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.
Viacheslav
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.