BMP 280/388 sensor readings accuracy

When using the BMP 280 type sensor for measuring air pressure in HA, is the Bosch compensation built into the final value?

The values I’m seeing from two modules (within 1 mbar of each other) are a long way off the local values published for atmospheric pressure in this area, from multiple sources.

Around 20mbar low in a nominal range of 950 to 1050mbar.

There is a compensation calculation published in the Bosch data sheet, but is this used?

Compensation of what? Did you apply it?

What do you even mean. Like it is an sensor, and in what? ESPHome? Or some comemercial product? If yes what it is?

The BMP280 / BMP388 modules are sensors used within ESPHome with an ESP32.

These particular sensors provide temperature and pressure value readings, useable within HA. (There are some variations which give other data, eg Humidiy).

I had two BMP280s running on a single ESP32 for some time, and never really used the pressure values. The temperature values I compared with other devices and seem ok. The pressure values appear to have a significant offset. As noted above. I’ve only recently taken an interest in using the pressure.

So, checking the manufactures data sheet, it includes data on how compensation should be applied using the individual sensor offsets.

There is an array of 11 ‘compensation trim parameters’, given within the Bmp register map for pressure relating to the individual BMP sensor. (Another array of 10 values for temperature).

I can’t believe it’s up to a user to fetch these parameters and use them in a lambda?

I’ve looked in an associated file I’ve found in the ESPHome docs, where they seemed to be declared, but I’ve no idea if they are actually being used in a calculation to provide compensation.

I’ve just switched out one BMP280 for a BMP388 and the T&P values from each read similar.
(Are within limits).

But the pressure values seem too far out to be correct.

Looks like it is.

Note that barometric pressure varies with altitude and local weather conditions.

Segal’s law is an adage that states:

A man with a watch knows what time it is. A man with two watches is never sure.[1]

If you are comparing to figures from weather bureaus you need to apply a MSL calculation:

It differs on your location - but this is mine:

      - unit_of_measurement: hPa
        default_entity_id: sensor.outside_pressure_msl
        icon: mdi:gauge
        name: Outside Air Pressure MSL
        state: >
          {{ '%0.1f'|format(((states('sensor.outside_air_pressure')|float * (1 - (0.0065 * 175) / (states('sensor.outside_temperature')
            | float + (0.0065 * 175) + 273.15)) ** -5.257) | round(1)) - 1)  }}

That’s similar to what I’ve found above. But where is the calculation that uses those values and applies it to the raw sensor reading?
I couldn’t understand that bit.

(Altitude here is around 100m AMSL. Which as far as I can make out, has less than 1% effect on a reading).

(Would a man with three watches be less sure of the time, than a man only having two?)

I just think that man with 2358 watches will be less sure how much he has them.

Well you can create a template sensor on the ESP if that’s where you are reading it. Mine is a weather station so I had to create a template sensor in HA.

Ahh. That looks conclusive then.
Thanks.

It’s in a .cpp file.
I didn’t know where to look, to be honest.
I found the .h file, which I related to above.

So…
The thick plottens…

Maybe. I am at 175m. This is the result of a filter I applied to a BMP280:

[10:07:22.355][D][man_cave:043]: Raw pressure: 991.57
[10:07:22.355][S][sensor]: 'Man Cave Temperature' >> 15.0 °C
[10:07:22.355][S][sensor]: 'Man Cave Air Pressure' >> 1012.3 hPa
sensor:
  - platform: bmp280_i2c
    temperature:
      name: "Man Cave Temperature"
      id: man_cave_temperature
      oversampling: 16x
    pressure:
      name: "Man Cave Air Pressure"
      filters:
        - lambda: |-
            ESP_LOGD("man_cave", "Raw pressure: %.2f", x);
            // Correct station pressure to Mean Sea Level (MSL),
            // compensated using measured temperature.
            // Rutherglen, VIC elevation: 175 m AMSL
            const float altitude = 175.0;     // metres AMSL
            const float lapse_rate = 0.0065;  // K/m, standard atmosphere
            float temp_k = id(man_cave_temperature).state + 273.15;
            float mean_temp_k = temp_k + (lapse_rate * altitude) / 2.0;
            return x * exp((9.80665 * altitude) / (287.05 * mean_temp_k));
    address: 0x76
    update_interval: 60s

Do that before you try and start comparing with reported local stations.

EDIT: My local BOM station doesn’t report air pressure, but the next closest (25 km) does, it comes at at a reasonable match:

Screenshot 2026-09-05 at 10.14.47

The hPa values you show in your calculation are similar to what I have here at the moment, as raw and expected value. It looks like it could just be that calculation I’m missing then. That’s definitely more than 1%.

Thanks for that.
I’ll try including it.

I wonder why that wasn’t included as a configurable option in the HA BMP xxx component?

EDIT:-
I’ve just added it into the project and it’s definately the fix.

Thanks.