What is wrong with my EQP AQI Computation?

I have a Flex located outdoors directly next to a uRad Smoggie. I believe both use the same pm2.5 sensor. And sometimes I even get the same particle count :slight_smile:

But the Smoggie does not compute/report the US EPA AQI - only the raw pm2.5 count. I want to compute the AQI so I can easily compare both results.

Here is the code I use to calculate the AQI (this follows suggested code elsewhere here and from Google search AI) -

// Standard US EPA PM2.5 Breakpoints (Concentration Low, Concentration High, AQI Low, AQI High)
double[][] BREAKPOINTS = {
{0.0, 9.0, 0, 50},
{9.1, 35.4, 51, 100},
{35.5, 55.4, 101, 150},
{55.5, 125.4, 151, 200},
{125.5, 225.4, 201, 300},
{225.5, 325.4, 301, 500},
{325.5, 504.4, 501, 600} // Extended range if needed
};

int calculatePm25Aqi(double pm25Concentration) {
// Truncate to 1 decimal place
double cp = Math.floor(pm25Concentration * 10.0) / 10.0;

if (cp < 0.0) return 0;
if (cp > 504.4) return 500; // Cap at maximum AQI

for (double[] bp : BREAKPOINTS) {
double bpLo = bp[0];
double bpHi = bp[1];
double iLo = bp[2];
double iHi = bp[3];

if (cp >= bpLo && cp <= bpHi) {
double aqi = ((iHi - iLo) / (bpHi - bpLo)) * (cp - bpLo) + iLo;
return (int) Math.round(aqi);
}
}
return 500;
}

All of this seems reasonable to me. But as you can see in the screenshot below, the result coming from this computation for my outside Smoggie does NOT quite match that shown for the Purple widget - even though the pm2.5 values are identical (5).

At first I tried replacing the call to Math.round() with Math.floor() and Math.ceil() as this seems the mostly likely possible difference in an otherwise pretty well understood computation. the results from Math.floor() is closer to that shown for the Purple widget but it is still higher.

Can anyone suggest why these values do not match? Thanks