Sensors lie. Not dramatically. Not intentionally. They just drift, and over six months a cheap DHT22 reading a comfortable 21°C can be reading an actual 22.3°C, and your "turn on the AC at 23" automation becomes "turn on the AC at 24.3." If you think this doesn't matter, you've never gotten into bed on a summer evening and argued with your partner about whether the thermostat is accurate.
I have six Home Assistant + ESPHome DIY sensors around the apartment. I logged every reading for 180 days against a calibrated reference (a $300 lab-grade logger borrowed for six months from a friend who is a meteorologist). This is the drift report. Part of the rig.
The sensors
- S1–S3 — ESP32 dev boards with DHT22 sensors, in the living room, bedroom, closet-rack.
- S4 — ESP32 + BME280 (temperature, humidity, pressure) on the kitchen counter.
- S5 — ESP32 + SCD40 (CO2 sensor, NDIR) in the office.
- S6 — ESP32 + PMS5003 (particulate PM2.5 and PM10) in the office near the window.
Total hardware cost: about $52. Total time to flash ESPHome firmware and integrate with Home Assistant: 35 minutes.
The drift — headline numbers
| Sensor | Metric | Month 1 avg error | Month 6 avg error | Drift rate |
|---|---|---|---|---|
| S1 (DHT22, living room) | Temperature | ±0.4°C | ±1.3°C | ~0.15°C/month |
| S2 (DHT22, bedroom) | Temperature | ±0.3°C | ±1.1°C | ~0.13°C/month |
| S3 (DHT22, closet-rack) | Temperature | ±0.5°C | ±1.8°C | ~0.22°C/month (hot env) |
| S4 (BME280, kitchen) | Temperature | ±0.2°C | ±0.4°C | ~0.03°C/month |
| S5 (SCD40, office) | CO2 | ±30 ppm | ±45 ppm | ~2.5 ppm/month |
| S6 (PMS5003, office) | PM2.5 | ±2 μg/m³ | ±8 μg/m³ | ~1 μg/m³/month |
Takeaway: DHT22 is a scam at the edges
If all you need is a temperature indicator that shows "roughly 21 degrees or roughly 24 degrees," the DHT22 is fine. If you're automating cooling/heating decisions on a 1-degree threshold, it's not.
The BME280 drifted 3–4x less than the DHT22 in the same environment. The cost difference is about $2. For every new sensor I build now, I buy BME280s exclusively.
The closet-rack sensor (S3) drifted hardest because it lives in a 28–32°C environment most of the day — heat is harder on capacitive humidity elements than people realize.
The automations that broke
1. "Turn on AC at 23°C" fired at 24.3°C in month 6. Partner noticed. This is the one that started me caring.
2. "Air quality alert if PM2.5 > 35" triggered false positives after month 4 as the PMS5003 drifted high. Filed under "cried wolf" and ignored.
3. "Humidifier on when bedroom humidity < 38%" ran constantly in the dry winter because S2's humidity reading was off by about 7 percentage points. Humidifier ran 14 hours/day for a week before I noticed the tank needed refilling every day. Refill friction finally tipped me off.
Calibration — how I fixed it
Every two months I now run a "calibration run": put all six sensors next to the reference logger for 24 hours, dump the data, fit a linear offset per sensor, update the Home Assistant sensor filter. My ESPHome snippet:
sensor:
- platform: bme280
temperature:
name: "Kitchen Temperature"
filters:
- offset: -0.4 # calibration offset, Feb 2026
- sliding_window_moving_average:
window_size: 10
send_every: 10
- platform: dht
model: DHT22
pin: GPIO2
temperature:
name: "Living Room Temperature"
filters:
- offset: -1.1 # calibration offset, Feb 2026 (drifted high)
- sliding_window_moving_average:
window_size: 15
send_every: 15
The moving-average filter matters almost as much as the offset. Raw DHT22 readings jitter ±0.3°C from sample to sample. Averaging over 15 samples at 15s each gives me a reading every four minutes that's actually stable.
The lesson I wish I'd internalized sooner
"It's smart home, it should be accurate" is the wrong mental model. The right one is: "it's an array of cheap sensors, and the software job is to treat them like cheap sensors." Build calibration into your workflow. Log raw readings against a reference every six months. Don't build automations with 1-unit thresholds on 3-unit-accuracy sensors.
The investment that paid off most was the $0 one: being willing to admit the sensors were wrong.
For the full stack including how the HA LXC container is set up: The self-hosting stack I actually use in 2026.
# issues (0)
$ no issues filed yet. be the first — the form is below.