DS18B20 reads 85 °C or -127 °C? Here's why
A DS18B20 that reports 85 °C hasn't measured anything; that is its power-on value, and -127 °C means no probe is connected. How the tank monitor's firmware and ESPHome drop both, and the wire to check when the probe is stuck at 85.

The DS18B20 is the easy sensor in a water-quality monitor. It is a waterproof stainless probe, the probe and its cable can go fully underwater, and it is accurate to ±0.5 °C out of the box with no calibration maths. So when the tank card suddenly says the water is 85 °C, or -127 °C, it is tempting to blame the probe, the board or the tank heater.
None of those is the cause. Both numbers are the sensor telling you it has no reading. This post covers what each one means, how the Smart Turtle Tank firmware keeps them off your graphs, and where to look when the probe will not stop saying 85.
The trap: two numbers that look like readings
The DS18B20 is a digital sensor. It talks over a single wire using a protocol called 1-Wire and sends the temperature as a number rather than as a voltage. That is why it is the accurate one, and also why it can hand you a perfectly formatted number that has nothing to do with the water.
There are two of these:
| Value | What it actually means |
|---|---|
| 85 °C | The power-on value, before the first conversion finishes. The sensor never got a successful read. |
| -127 °C | What the Dallas library returns when the probe is not connected. |
Neither is a temperature. If your code passes them through, the server stores them like any other reading, and your graph and alerts treat them as real. The book's alert rule fires when the water goes under 73 °F or over 85 °F, so a fake 85 °C sails straight past the upper limit and sets off an alert for water that is fine.
The fix in the firmware
The Smart Turtle Tank firmware reads the probe once per sample with the OneWire and DallasTemperature libraries (in platformio.ini they are paulstoffregen/OneWire and milesburton/DallasTemperature). The probe sits on D4:
#define TEMP_PIN D4 // GPIO6, DS18B20 DAT (adapter has the pull-up)
And this is the part of the sample loop that does the rejecting:
temp.requestTemperatures(); // ~750 ms at 12-bit
float t = temp.getTempCByIndex(0);
if (t > -100 && t != 85.0f) { accT += t; nT++; } // drop -127 and 85
Line by line:
temp.requestTemperatures()tells the DS18B20 to measure. At 12-bit resolution that takes about 750 ms, and the call waits for it.getTempCByIndex(0)reads the first (and only) probe on the wire.- The
ifthrows away -127 (no probe) and exactly 85.0 (the power-on value), and counts only good reads innT.
Every five minutes (ten samples) the firmware averages the good samples into one reading. When there were none, the temperature field is sent as null. A null on the graph is honest; a fake 85 °C would page you.
The server backs this up. Its validation accepts t only as null or between -5 and 50 °C, so anything else is rejected with a 400 and never reaches history.
The fix in ESPHome
If you would rather run the probe through ESPHome and Home Assistant, the same rejection is two filter lines on the dallas_temp sensor:
one_wire:
- platform: gpio
pin: GPIO6 # XIAO D4
sensor:
- platform: dallas_temp
name: "Tank water temperature"
update_interval: 30s
filters:
- filter_out: 85.0
- filter_out: -127.0
one_wire: sets up the 1-Wire bus on GPIO6, which is the XIAO's D4, and the dallas_temp sensor finds the probe on it. The two filter_out lines drop the 85 °C power-on value and the -127 °C unplugged value, the same job the PlatformIO firmware does.
Stuck at 85: check the wiring, not the code
Filtering keeps the bad values off the graph, but it does not fix them. If the temperature field stays null, or the raw value keeps coming back as 85 or -127, the sensor is not getting a clean read. The book's troubleshooting puts it plainly: an 85 °C reading usually means a loose DAT wire.
The probe has three wires that screw into a small adapter board, matched by the printed letters:
- Red to VCC
- Yellow to DAT
- Black to GND
Then three jumpers connect the adapter to the XIAO:
- The + rail (3V3) to the adapter's VCC pin.
- The - rail (GND) to the adapter's GND pin.
- XIAO D4 to the adapter's DAT pin.
Two details catch people here. First, the pins on your adapter may be in a different order than any picture you are following, so go by the printed letters, not by position. Second, the adapter belongs on 3V3, not 5V. Its VCC comes from the + rail, which is fed by the XIAO's 3V3 pin, so the signal on DAT stays under the 3.3 V the XIAO's pins can take.
You also do not need to add a resistor. The DS18B20 needs a 4.7 kΩ pull-up on its data line, and the kit's adapter board already has it built in.
Once the probe reads, the only adjustment left is a one-time offset. Put the DS18B20 and a reference aquarium thermometer in the same cup of water for five minutes; the difference is temp_offset_c, a setting on the server. Expect a few tenths of a degree, since the probe is rated ±0.5 °C.
Checklist
- Probe wires screwed into the adapter by letter: red to VCC, yellow to DAT, black to GND, each one tugged gently.
- Adapter VCC from the 3V3 (+) rail, GND from the - rail, DAT to XIAO D4.
- No extra pull-up resistor; the adapter has the 4.7 kΩ one.
- Only the metal probe and its cable go in the water. The adapter board stays dry, with the cable hanging in a U-shaped drip loop below the electronics.
- Firmware drops
-127and exactly85.0and sendsnullwhen there was no good read. - In ESPHome,
filter_out: 85.0andfilter_out: -127.0are on thedallas_tempsensor. - Still null or stuck at 85? Re-seat the DAT, VCC and GND wires and confirm the adapter is on 3V3.
- Probe reading for real? Set
temp_offset_conce against a reference thermometer.


