OneWire (also written 1-Wire) is a communication protocol designed by Dallas Semiconductor (now Maxim Integrated / Analog Devices). It allows multiple devices to share a single data wire plus a ground return, making it one of the simplest bus protocols you will encounter. The most common OneWire device in ESP32 projects is the DS18B20 temperature sensor, but the protocol is also used by iButton keys, EEPROMs, and battery monitors.
🔗How It Works
OneWire is a master-slave protocol. The ESP32 acts as the bus master and controls all communication. Slave devices (sensors) only respond when the master addresses them. Data travels in both directions over the same wire -- the master pulls the line low to send commands, and slaves pull it low to send data back.
Every OneWire device has a unique 64-bit ROM address programmed at the factory. This address consists of:
| Bytes | Field | Purpose |
|---|---|---|
| 1 | Family code | Identifies the device type (e.g., 0x28 = DS18B20) |
| 6 | Serial number | Unique identifier |
| 1 | CRC | Error checking |
Because each device has a unique address, you can connect many devices to the same bus and talk to each one individually.
🔗Bus Topology
graph LR
VCC[3.3V] --- R[4.7 kΩ pull-up]
R --- DATA[Data line]
ESP32[ESP32 GPIO] --- DATA
DATA --- S1[DS18B20 #1]
DATA --- S2[DS18B20 #2]
DATA --- S3[DS18B20 #3]
S1 --- GND1[GND]
S2 --- GND2[GND]
S3 --- GND3[GND]All devices share the same data line. The bus only requires two connections to each device: data and ground. Power can come from a separate VCC wire (three-wire mode) or from the data line itself (parasitic power mode).
🔗The Pull-Up Resistor
A $4.7\,\text{k}\Omega$ pull-up resistor between the data line and VCC is essential. OneWire uses an open-drain bus -- devices communicate by pulling the line low, and the pull-up resistor returns it to a high state when released. Without this resistor, the bus stays in an undefined state and communication fails completely.
| Bus length | Recommended pull-up |
|---|---|
| Short (< 1 m) | $4.7\,\text{k}\Omega$ (standard) |
| Medium (1--20 m) | $4.7\,\text{k}\Omega$ |
| Long (20--100 m) | $2.2\,\text{k}\Omega$ to $3.3\,\text{k}\Omega$ (stronger pull-up needed) |
Tip: Many DS18B20 breakout boards include a pull-up resistor on the PCB. Check before adding a second one -- two pull-up resistors in parallel lower the effective resistance and can cause problems.
🔗Parasitic Power vs External VCC
The OneWire protocol supports two power modes:
| Mode | Wires needed | How it works | Limitations |
|---|---|---|---|
| External VCC (recommended) | 3 (VCC, Data, GND) | Device powered by VCC pin | None -- reliable in all conditions |
| Parasitic power | 2 (Data, GND) | Device charges internal capacitor from data line | Unreliable above $100\,\text{°C}$, limits number of devices on bus, timing-sensitive |
Parasitic power is useful when running long cable lengths with only two conductors, but for most ESP32 projects, external VCC is simpler and more reliable.
🔗ESP32 Pin Selection
OneWire is a software protocol -- it does not require dedicated hardware peripherals. You can use any GPIO pin with one exception:
| Pin type | GPIOs | OneWire compatible? |
|---|---|---|
| General purpose | 0--33 (most) | Yes |
| Input-only | 34, 35, 36, 39 | No -- these pins cannot be driven low by the ESP32 |
GPIO 4 is a common choice because it has no secondary function that might conflict.
🔗Timing
OneWire communication is timing-critical. All operations begin with the master pulling the data line low for a precise duration.
| Operation | Duration | Notes |
|---|---|---|
| Reset pulse | $480\,\mu\text{s}$ minimum | Master pulls low; devices respond with presence pulse |
| Write "0" | $60$--$120\,\mu\text{s}$ low | Master holds line low |
| Write "1" | $1$--$15\,\mu\text{s}$ low, then release | Short pulse, line returns high |
| Read slot | $60\,\mu\text{s}$ total | Master initiates, slave drives data |
| Temperature conversion (12-bit) | 750 ms | Sensor is busy; bus reads 0 until done |
The $750\,\text{ms}$ conversion time at 12-bit resolution is the bottleneck in most projects. Lower resolutions are faster:
| Resolution | Increment | Conversion time |
|---|---|---|
| 9-bit | $0.5\,\text{°C}$ | ~$94\,\text{ms}$ |
| 10-bit | $0.25\,\text{°C}$ | ~$188\,\text{ms}$ |
| 11-bit | $0.125\,\text{°C}$ | ~$375\,\text{ms}$ |
| 12-bit | $0.0625\,\text{°C}$ | ~$750\,\text{ms}$ |
🔗Code Example: Discover Devices on the Bus
This sketch scans the OneWire bus and prints the 64-bit ROM address of every device it finds. This is useful when you have multiple sensors and need to know which address belongs to which physical device.
#include <OneWire.h>
#define ONE_WIRE_PIN 4
OneWire bus(ONE_WIRE_PIN);
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("Scanning OneWire bus...\n");
byte address[8];
int count = 0;
while (bus.search(address)) {
count++;
Serial.printf("Device %d: ", count);
for (int i = 0; i < 8; i++) {
if (address[i] < 0x10) Serial.print("0");
Serial.print(address[i], HEX);
if (i < 7) Serial.print(":");
}
// Check CRC
if (OneWire::crc8(address, 7) != address[7]) {
Serial.println(" (CRC ERROR)");
} else {
// Identify device type by family code
switch (address[0]) {
case 0x28: Serial.println(" (DS18B20)"); break;
case 0x10: Serial.println(" (DS18S20)"); break;
case 0x22: Serial.println(" (DS1822)"); break;
default: Serial.println(" (Unknown)"); break;
}
}
}
bus.reset_search();
Serial.printf("\nFound %d device(s).\n", count);
}
void loop() {
// Nothing to do here
}Upload this sketch, open the Serial Monitor at 115200 baud, and it will list every OneWire device connected to GPIO 4 along with its address and type.
🔗Common Issues
| Problem | Cause | Fix |
|---|---|---|
| No devices found | Missing pull-up resistor | Add $4.7\,\text{k}\Omega$ between data and VCC |
| No devices found | Using input-only pin (34--39) | Switch to a general-purpose GPIO |
| Intermittent reads / CRC errors | Wire too long or poor connections | Use shorter cable, stronger pull-up, or shielded wire |
| Reads $-127\,\text{°C}$ | Sensor not responding | Check wiring; ensure pull-up is present |
| Reads $85\,\text{°C}$ | Reading before conversion completes | Wait at least $750\,\text{ms}$ after requesting temperature |
| Parasitic power fails | Current draw too high during conversion | Switch to external VCC power |
Cable length: OneWire can theoretically work over distances up to ~$100\,\text{m}$, but this requires a strong pull-up ($2.2\,\text{k}\Omega$ or lower), good quality cable, and external VCC. For reliable operation, keep runs under $20\,\text{m}$.
🔗Arduino Libraries
| Library | Author | Purpose |
|---|---|---|
| OneWire | Paul Stoffregen | Low-level OneWire protocol (bus scan, read, write) |
| DallasTemperature | Miles Burton | High-level API for DS18B20/DS18S20 sensors (wraps OneWire) |
Install both via the Arduino Library Manager.
🔗Used In
The following pages on this site use the OneWire protocol:
- DS18B20 Temperature Sensor -- wiring, code, and project examples using OneWire
- Room Temperature Monitor -- complete project reading DS18B20 sensors over OneWire