The DS18B20 is the easiest way to read a real temperature on an Arduino or ESP32: one data pin, a sealed stainless probe you can drop in water, and as many sensors as you like on the same wire. There is exactly one thing that catches people out, and it is a 4.7k resistor.
What the DS18B20 is
The DS18B20 is a digital temperature sensor from Dallas/Maxim. In the version most people buy, the chip is potted inside a 304 stainless steel probe on a length of cable, which makes it IP67 waterproof and safe to put in a fish tank, a fermenter, a hot water cylinder or a bucket of soil.
Because it is digital, there is no analogue voltage to convert and no calibration to do. You ask it for a temperature and it hands back a number in degrees Celsius. It speaks a protocol called 1-Wire, which needs a single GPIO pin no matter how many sensors you connect, because every DS18B20 has a unique 64-bit address burned in at the factory.
- -55 to +125Degrees C range
- ±0.5°CAccuracy, -10 to 85
- 1 pinFor any number
- 3.0-5.5VSupply
What you need
- 1x DS18B20 waterproof probe, in 1m, 3m or 5m
- 1x 4.7kΩ resistor, which is not included in the probe. Grab one from a resistor kit, or skip it entirely with the DS18B20 adapter module, which has one already fitted
- An Arduino or ESP32 board, a breadboard and some jumper wires
The 4.7k pull-up, and why nothing works without it
1-Wire is an open-drain bus. The sensor can only pull the data line low; it has no way to drive it high again. Something has to do that for it, and that something is a resistor between the data wire and the supply. Without it the line never returns high, the microcontroller never sees a valid response, and you get one of two numbers instead of a temperature:
| You see | What it means |
|---|---|
| 85.00 | The sensor's power-on default value. It powered up but never completed a conversion, so you are reading the factory register. |
| -127.00 | No communication at all. The library could not find a device on the bus. |
Both usually mean the same thing: no pull-up, or the pull-up is on the wrong pin. Fit a 4.7kΩ resistor between the yellow data wire and the red supply wire and both numbers turn into a real temperature.
If you would rather not fiddle with a loose resistor, the DS18B20 adapter module is a small breakout with the 4.7k already fitted and screw terminals for the probe wires. It turns this whole section into a non-issue.
Wiring it up
The probe has three wires. They are the same on the 1m, 3m and 5m versions.
| Wire | Goes to |
|---|---|
| Red | VCC (3.3V or 5V) |
| Black | GND |
| Yellow | Data (any GPIO) |
- Red to 5V on an Arduino Uno, or 3.3V on an ESP32. Do not feed 5V into an ESP32 pin.
- Black to GND.
- Yellow to a data pin. Pin 2 on an Arduino Uno, or GPIO4 on an ESP32 are good defaults.
- Fit the 4.7kΩ resistor between the yellow wire and the red wire. On a breadboard, that is one leg in the data row and one leg in the supply row.
On an ESP32, pull up to 3.3V, not 5V. The pull-up sets the voltage the data line rises to, so a 5V pull-up puts 5V on a 3.3V pin. Also avoid the strapping pins (GPIO0, 2, 12 and 15 on a WROOM-32) for the data line, since a sensor holding them at boot can stop the board starting.
The code
Two libraries do the work. In the Arduino IDE, open Tools → Manage Libraries and install OneWire by Paul Stoffregen and DallasTemperature by Miles Burton. Then upload this:
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2 // yellow wire. Use 4 on an ESP32.
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
void setup() {
Serial.begin(9600);
sensors.begin();
}
void loop() {
sensors.requestTemperatures();
float tempC = sensors.getTempCByIndex(0);
if (tempC == DEVICE_DISCONNECTED_C) {
Serial.println("No probe found. Check the wiring and the 4.7k pull-up.");
} else {
Serial.print(tempC);
Serial.println(" C");
}
delay(1000);
}
Open the Serial Monitor at 9600 baud and you should see the room temperature once a second. Hold the probe in your hand and watch it climb.
On an ESP32 with native USB (the C3, C6, H2, S2 and S3 boards), set Tools → USB CDC On Boot → Enabled before uploading or the Serial Monitor stays blank.
Several probes on one pin
This is the DS18B20's best trick. Wire every probe's red to red, black to black and yellow to yellow, use a single 4.7k pull-up for the whole bus, and read them by index:
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 2
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
void setup() {
Serial.begin(9600);
sensors.begin();
Serial.print(sensors.getDeviceCount());
Serial.println(" probes found");
}
void loop() {
sensors.requestTemperatures();
for (int i = 0; i < sensors.getDeviceCount(); i++) {
Serial.print("Probe ");
Serial.print(i);
Serial.print(": ");
Serial.print(sensors.getTempCByIndex(i));
Serial.println(" C");
}
delay(2000);
}
The catch with index numbers is that they follow bus order, not the order you plugged them in, and they can shift if you add a probe later. For anything permanent, read each sensor's unique address once with sensors.getAddress(), write those addresses into your sketch, and call getTempC(address) instead. Then "the probe in the tank" stays the probe in the tank.
Raspberry Pi
No library needed. Enable 1-Wire in raspi-config, or add dtoverlay=w1-gpio to /boot/config.txt and reboot. Wire the yellow data line to GPIO4 (physical pin 7), red to 3.3V, black to GND, with the same 4.7k pull-up. Each probe then appears as a folder under /sys/bus/w1/devices/ starting with 28-, and cat on the w1_slave file inside gives you the reading in thousandths of a degree.
Troubleshooting
| Symptom | Fix |
|---|---|
| Reads 85.00 | Missing or wrong pull-up, or the supply is not connected properly. Check the 4.7k sits between data and VCC. |
| Reads -127.00 | No device on the bus. Check the data wire is on the pin your sketch names, and that GND is shared. |
| Readings jump around on a long cable | Use twisted pair or Cat5 with data and ground as one pair, and try dropping the pull-up to 3.3k or 2.2k. Keep the run away from mains cable and motor leads. |
| Only some probes appear | Usually a marginal bus. Shorten the run, drop the pull-up value, or split long chains onto separate pins. |
| Nothing on the Serial Monitor | Check the baud rate is 9600. On a native-USB ESP32, enable USB CDC On Boot. |
| Board will not boot with the probe attached | The data wire is on a strapping pin. Move it to GPIO4 on an ESP32. |
You may also see parasite power mentioned, where the sensor runs from the data line and only two wires are used. It works, but it is fussy about timing and pull-up strength. With a three-wire probe in your hand there is no reason to bother.
Which cable length?
All three are the same sensor. Only the cable differs, so pick the run between the probe and your controller.
| Length | Best for |
|---|---|
| 1m | Benchtop work, small tanks, fermenters, anything within reach of the board |
| 3m | Most fixed installs, where the controller is on a wall nearby |
| 5m | Controller across the room, outside, or in a different cabinet |
The probe itself is IP67 and handles full submersion. For a permanent install, try to keep the point where the cable leaves the water above the waterline.
-
DS18B20 Waterproof Probe
from $4.69
View probe
-
DS18B20 Adapter Module
$2.99
Pull-up included
-
Resistor Kit, 600pc
$11.99
Includes 4.7k
-
Dupont Jumper Wires, 40pc
$4.45
View wires
Wiring this on a breadboard for the first time? Breadboard Basics covers how the rows and rails connect. Not sure which board to pair it with? See Which ESP32 board should you buy.
Get the probe
Sealed stainless DS18B20 in 1m, 3m or 5m, shipped from New Zealand. Add the adapter module and the pull-up is already sorted.
