Close

The BME680 that ran 3 °C hot, and the twin experiment that proved it

A project log for SensorStation3

Open-source ESP32 CYD environmental station: T/H/pressure/CO2eq on a touchscreen, MQTT (HA autodiscovery, ThingsBoard, Domoticz), OTA

viacheslavViacheslav a day ago0 Comments

The project didn't start with air quality at all. The first working version used a BME280 — just temperature, humidity, dew point, pushed to a server. That was enough to make me want something more universal, something that would also make sense in a living room or an office. Which meant air quality, and I remembered a BME680 sitting in an old box labeled "climate sensors."

I wired it up and extended my BMP/BME driver component to read it, including the sensor's gas resistance (VOC). The station samples everything every 500 ms, and in the first pass I read gas resistance at that same rate. The dashboard immediately started showing about 3 °C more than the same room used to read with the BME280.

Trust, but verify with a twin. A constant +3 °C smelled like self-heating rather than a bad sensor, but I didn't want to guess. So I built an identical second station — same firmware, BME280 instead — and ran both side by side on the desk. The twin confirmed it: the BME680 unit read almost exactly 3 °C higher, consistently. Not drift, not calibration. Heat.

Why: the BME680's gas sensor works by firing an internal hotplate to a few hundred °C on every gas reading, millimeters from the temperature element on the same die. Reading gas resistance every 500 ms meant firing that heater constantly.

Fix, round one. I cut the VOC sampling rate by 10x, keeping temperature/humidity/pressure at 500 ms. That helped a lot — but the BME680 was still running 0.5–0.7 °C above the reference. Here's the detail that explains that residual: the station writes every reading into a 60-entry ring buffer and displays the average of the last 30 seconds. That averaging smooths the heat spike from every tenth gas reading into what looks like a steady bias instead of a visible spike — great for a readable display, bad for spotting the real cause.

At this point I added a ±5 °C temperature offset setting for the BME680, adjustable right on the touchscreen. Useful to have regardless — but papering over self-heating with an offset felt like the wrong fix, and the raw VOC numbers still didn't look particularly realistic.

Fix, round two: BSEC. I'd used a BME680 with Bosch's BSEC library years ago on an Orange Pi Zero — it worked, but the integration experience left mixed impressions. Still, BSEC is where Bosch put the actual sensor know-how: heater scheduling, compensation, IAQ processing. I downloaded BSEC 2.6.1.0 and wired it into the project. (It's proprietary, so it's not bundled in the repo — the README explains how to drop it in, and the firmware still builds fine without it.) After the switch, the twin stations finally agreed with each other, and I stopped needing to compare two displays every time I walked past.

What's still bugging me: the CO2-equivalent numbers from BSEC still don't fully convince me. I've ordered SCD41 sensors and dug an old MH-Z19 out of a parts bin to compare against real NDIR CO2 — that comparison will be the next log.

Discussions