thermo

Guide

How to calibrate Xiaomi LYWSD03MMC thermometers

Five cheap Bluetooth thermometers in one room will show five different numbers. Here's why, what the pvvx firmware lets you fix, and how to fix a whole houseful at once without buying a reference instrument.

What the firmware can correct

The pvvx ATC_MiThermometer firmware converts each raw sensor value with a straight line, one for temperature and one for humidity:

temperature = raw × k_T + z_T
humidity    = raw × k_H + z_H

Out of the box k and z are the sensor datasheet's formula. Calibrating means changing them. That gives two knobs per quantity: the offset shifts the line, the gain tilts it. There's no curve, so a correction is always "multiply a little, then add a little". Both are written to flash over Bluetooth (command 0x25). The factory values come back with 0x26, or x in thermo.

Offset versus gain: an offset shifts a device's reading line up or down by the same amount everywhere; a gain tilts it so the error grows with distance from one point offset same error everywhere:one place is enough gain error grows with distance:needs two temperatures
An offset is visible anywhere. A gain error is only visible if you compare at two temperatures far enough apart.

Calibrating without a reference: consensus

If the thermometers sit in the same air, any disagreement between them is sensor error. So you can fit each device against the others. thermo takes the median of every other device as the reference, fits a gain and offset per device, and then shifts the whole set so that the gains average 1 and the offsets average 0. Each device ends up agreeing with the group's average.

Before: eight devices scattered around the true value; after: all on the group average, one outlier excluded from the average before after outlier: not written group average
Agreement is not the same as accuracy. If every sensor reads 0.3 °C high, comparing them can't tell. But the average of eight is usually better than any single one.

Want absolute humidity? Put the thermometers in a sealed box with a dish of table salt wetted into a thick slush. The air above saturated NaCl settles at 75.3 %RH at room temperature (magnesium chloride: about 33 %RH). It's the classic cheap hygrometer check.

The procedure

  1. Side by side, at least 2 hours.

    A few centimetres apart, not touching, away from radiators, sun, laptop exhaust and people. Keep thermo running and the computer awake: only live adverts are used.

  2. Move them all at once, at least 3 hours.

    Somewhere at least 5 °C warmer or colder: outside in the shade, a cold room, a garage. thermo ignores the first hour after a big change while the cases catch up. It also drops readings above 95 %RH, so avoid fog and rain.

  3. Press c and choose the window.

    Tab picks the start or end, ← → move it by 15 minutes (Shift: one hour). The chart shades what's left out. Check that two phases were found and that the gain columns show numbers, then press Enter and y.

thermo calibration screen with a window from Wednesday 20:54 to Thursday 12:00, per-device temperature and humidity offsets with bars, fitted gains, and a chart with the excluded time shaded
A real run with 8 devices: disagreement went from 0.078 to 0.012 °C and from 1.76 to 0.40 %RH. The temperature span (15.8–21.6 °C) was wide enough for gains. The humidity span (58–68 %RH) only allowed offsets.

Which range should you calibrate in?

For temperature, the width of the range matters more than where it sits. A gain fitted over 16–22 °C is practically as good at 25 °C as one fitted over 18–25 °C. The extra error a few degrees past the fitted range is around a hundredth of a degree. A wider span such as 8–22 °C (an afternoon outside) pins the gain down even better. These sensors are close to linear, so a gain fitted on a wide span holds well beyond it. thermo only fits a gain when the steady data spans at least 5 °C and the gain is clearly different from 1. Otherwise it writes only the offset.

Humidity is different. Humidity sensors are less linear, and outdoor air in autumn sits at 80–90 %RH while a heated home in winter sits at 30–45 %. A gain fitted between 60 and 90 % and used at 35 % reaches far outside its data. Calibrate humidity near where you live, add a dry point such as a magnesium chloride box, or settle for offsets. They matter most anyway. thermo asks for at least a 15 %RH span before fitting a humidity gain.

LYWSD03MMC units ship with different sensors. In one batch of eight, five had SHT4x-style factory coefficients (12500; −600) and three had SHT3x-style ones (10000; 0), and the two groups disagreed by more at high humidity than at low. thermo logs each device's old and new coefficients in calibrations.csv, and cargo run -p atc --example probe -- <MAC> prints them for one device.

How the fit works

All of this is plain, unit-tested Rust in crates/calibration, with no Bluetooth involved.

  1. Resample every device to 5-minute bins. Bluetooth reception is lossy, and finer bins would be mostly empty.
  2. Keep only steady data. A bin counts if, over 30 minutes, neither the group median nor the device moved more than 0.75 °C / 3.5 %RH, and the group didn't jump by 2 °C / 10 %RH in the hour before. Slow drifts, like a room cooling in the evening, are fine.
  3. Fit each device against the median of the others with a robust Huber regression. An extra term absorbs case lag: devices responded up to six minutes apart, which during a slow drift looks like a fake offset.
  4. Reject outliers. With four or more devices, one whose correction has a robust z-score above 3.5 is left out of the average, and nothing is written to it. Whatever set it apart probably skews both its temperature and humidity.
  5. Anchor the set so gains average 1 and offsets 0, then compose onto each device's current coefficients (k′ = a·k, z′ = a·z + 100·b). The new values are read back to verify and logged. Calibrating again later builds on the last calibration.

The full write-up, including the firmware commands and what was found on real hardware, is in docs/calibration.md.

Two things learned on the way

Install thermo