The Arduino temp sensor DS18B20 is the industry standard for digital temperature measurement in embedded DIY projects. Unlike analog thermistors that require complex Steinhart-Hart equation math and suffer from voltage reference drift, the DS18B20 outputs a fully calibrated digital value over Maxim’s 1-Wire protocol. You get 9-bit to 12-bit resolution, a unique 64-bit serial ROM embedded in every single chip, and the ability to daisy-chain dozens of sensors on a single microcontroller GPIO pin.

However, the 1-Wire protocol is notoriously unforgiving regarding timing and pull-up resistor values. If your pull-up is too weak, or if you misunderstand the sensor's Power-On Reset (POR) state, your serial monitor will spit out garbage data or lock up entirely. This guide provides the exact wiring topologies, production-ready C++ code with error handling, and a decision-tree for debugging the most common 1-Wire bus failures.

DS18B20 Specifications and Operating Modes

Before wiring the sensor, you must understand its timing constraints and power delivery options. The DS18B20 does not stream data continuously; it requires a specific conversion command, followed by a mandatory wait period that scales with your chosen resolution.

Sensor Specification Sheet

ParameterValueEngineering Notes
Operating Voltage3.0V to 5.5VCan be powered directly from ESP32 (3.3V) or Arduino (5V) VCC pins.
Temperature Range-55°C to +125°CAccuracy is ±0.5°C only between -10°C and +85°C. Degrades to ±2°C at extremes.
Conversion Time (9-bit)93.75 ms0.5°C resolution. Fastest mode, ideal for rapid environmental logging.
Conversion Time (12-bit)750.0 ms0.0625°C resolution. Default POR state. Mandatory wait time before reading.
Standby Current1.0 µA (max)Negligible battery drain during idle states.
Active Current1.5 mA (typ)Spikes during the analog-to-digital conversion phase.

External Power vs. Parasitic Power Mode

The DS18B20 can be wired in two distinct topologies. Your wiring choice dictates how you must initialize the DallasTemperature library in your code.

FeatureExternal Power Mode (3-Wire)Parasitic Power Mode (2-Wire)
WiringVDD to 5V/3.3V, GND to GND, Data to GPIOVDD tied to GND, GND to GND, Data to GPIO
Power DeliveryDedicated power railHarvests power from the data line via internal capacitor
Pull-up Resistor4.7kΩ standard4.7kΩ standard, plus a "strong pull-up" MOSFET for conversions
ReliabilityHighly reliable over long cable runsProne to brownouts during 12-bit conversions on long cables
Best Use CaseBreadboards, standard indoor projectsSealed waterproof probes where only 2 wires can pass through a gland

Parts List and Pin Mapping

This build targets the Arduino Uno R3 (ATmega328P) operating at 5V logic. If you are migrating to an ESP32 later in this guide, you will need a logic level shifter or a dedicated 3.3V pull-up to avoid damaging the ESP32's GPIO pins.

Bill of Materials (BOM)

  • Microcontroller: Arduino Uno R3 (or compatible ATmega328P clone)
  • Sensor: Waterproof DS18B20 Probe (Stainless steel tube, PVC jacketed cable). Note: The MAX31820 is the modern, drop-in replacement from Analog Devices and works identically.
  • Resistor: 4.7kΩ (1/4W, 5% tolerance) pull-up resistor
  • Hardware: Half-size breadboard, male-to-male jumper wires
  • Estimated Cost: $12 - $18 (excluding the microcontroller)
⚠️ Counterfeit Warning: The market is flooded with fake DS18B20 sensors. Clones often share the exact same 64-bit ROM address, which completely breaks multi-drop bus configurations, or they fail the internal CRC check under electrical noise. For mission-critical or multi-sensor arrays, source your sensors from authorized distributors like DigiKey, Mouser, or verified makers like Adafruit (PID 381) and SparkFun (SEN-11050).

Pin Mapping Table (External Power Mode)

Waterproof probes typically use a three-wire color code. Always verify with a multimeter if your probe uses non-standard colors.

Probe Wire ColorDS18B20 Pin NameArduino Uno R3 ConnectionNotes
RedVDD (Pin 3)5V PinProvides dedicated power to the internal ADC.
BlackGND (Pin 1)GND PinCommon ground reference.
Yellow (or White)DQ (Pin 2)Digital Pin 21-Wire data line. Requires 4.7kΩ pull-up to 5V.

Step-by-Step Wiring and Compilable Code

Physical Wiring Steps

  1. Insert the 4.7kΩ resistor into the breadboard, bridging the 5V rail and the row designated for Digital Pin 2.
  2. Connect the sensor's Red wire to the 5V rail.
  3. Connect the sensor's Black wire to the GND rail.
  4. Connect the sensor's Yellow (Data) wire to the same row as one leg of the 4.7kΩ resistor, and run a jumper from that row to the Arduino's Digital Pin 2.
  5. Double-check that the resistor is acting as a bridge between 5V and the Data line. Without this, the 1-Wire bus will float and fail.

Production-Ready C++ Code

This code requires the OneWire and DallasTemperature libraries (installable via the Arduino Library Manager). It includes robust error handling for the two most common DS18B20 failure states: the disconnected state (-127°C) and the Power-On Reset state (85°C).

#include <OneWire.h>
#include <DallasTemperature.h>

// Target Board: Arduino Uno R3 (ATmega328P)
// Hardware setup: External Power Mode (3-wire)
#define ONE_WIRE_BUS 2
#define SENSOR_RESOLUTION 12

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup() {
  Serial.begin(115200);
  while (!Serial); // Wait for serial monitor (native USB boards)
  
  Serial.println("Initializing DS18B20 1-Wire Bus...");
  sensors.begin();
  
  // Set resolution to 12-bit (default is 12, but explicit is better)
  // Note: 12-bit requires a 750ms conversion delay
  sensors.setResolution(SENSOR_RESOLUTION);
  
  // Disable blocking delays if you want to do other tasks during conversion
  // sensors.setWaitForConversion(false);
}

void loop() {
  // Command all sensors on the bus to perform a temperature conversion
  sensors.requestTemperatures();
  
  // Read the first sensor found on the bus (Index 0)
  float tempC = sensors.getTempCByIndex(0);
  
  // ERROR HANDLING: Check for physical disconnection
  if (tempC == DEVICE_DISCONNECTED_C) { // Evaluates to -127.0
    Serial.println("ERROR: Sensor disconnected or bus shorted (-127.00 C).");
  }
  // ERROR HANDLING: Check for Power-On Reset (POR) artifact
  else if (tempC == 85.0) {
    Serial.println("ERROR: Read POR default (85.00 C). Conversion failed or brownout occurred.");
  }
  // Valid reading
  else {
    Serial.print("Temperature: ");
    Serial.print(tempC, 2);
    Serial.println(" °C");
  }
  
  delay(1000); // 1 second polling interval
}

Debugging: Exact Error Strings and Failure Modes

When a 1-Wire bus fails, it rarely fails silently. The DallasTemperature library returns specific sentinel values, and the OneWire library outputs distinct console strings during ROM searches. Here is how to diagnose them.

🔧 The First Three Things to Check When It Fails:
  1. Measure the Pull-Up Resistor: Use a multimeter in continuity/resistance mode (power off) to verify exactly 4.7kΩ (±5%) between the Data pin and VCC. A missing or blown pull-up is the cause of 80% of 1-Wire failures.
  2. Verify VDD Wiring (External vs Parasitic): If you are using Parasitic mode but left the VDD pin floating, the sensor will brownout during the 12-bit conversion. Ensure VDD is tied to GND for parasitic, or tied to 5V for external.
  3. Check Pin Definitions vs Physical Wiring: Confirm that #define ONE_WIRE_BUS 2 in your code matches the physical wire plugged into Digital Pin 2, not Analog Pin 2 (which is A2 / D16 on the Uno).

Symptom 1: Serial Monitor prints "No more addresses." or "Device not found"

This occurs during the sensors.begin() ROM search phase. The microcontroller sends a search command, but no sensor pulls the bus low to acknowledge.

  • Cause 1 (Most Likely): Missing or incorrect pull-up resistor. The data line is floating high, so the sensor's open-drain transistor cannot register a logic LOW.
  • Cause 2: Broken data wire inside the waterproof probe's PVC jacket. Perform a continuity test from the probe tip to the bare wire ends.
  • Cause 3: Counterfeit sensor with a corrupted ROM table. The OneWire CRC check fails silently in some library versions, dropping the device from the bus.

Symptom 2: Constant "85.00 °C" Readings

85°C is not a random error; it is the hardcoded Power-On Reset (POR) value stored in the DS18B20's scratchpad register upon boot. If you read 85°C, it means you are reading the scratchpad before the sensor has successfully completed an analog-to-digital conversion.

  • Cause 1 (Most Likely): Parasitic power brownout. During a 12-bit conversion, the sensor draws up to 1.5mA. In parasitic mode, the 4.7kΩ pull-up resistor limits current too severely (I = V/R = 5V/4700Ω = ~1mA), causing the internal voltage to sag and the conversion to abort. Fix: Switch to external power mode, or implement a strong pull-up MOSFET circuit.
  • Cause 2: Code timing error. You called getTempCByIndex() immediately after requestTemperatures() without allowing the 750ms conversion time to elapse (if setWaitForConversion(false) is used).

Symptom 3: Constant "-127.00 °C" (DEVICE_DISCONNECTED_C)

The library explicitly returns -127°C when the OneWire bus returns a CRC mismatch or all bits read high (disconnected).

  • Cause 1: The sensor is physically unplugged or the data wire is severed.
  • Cause 2: Severe electrical noise (EMI) on the data line. If your probe cable runs parallel to AC mains or high-current DC motor lines, the noise will corrupt the 1-Wire timing pulses. Fix: Use shielded twisted-pair cable for the probe extension and tie the shield to GND at the microcontroller end only.

Extending the Build: Multi-Drop Buses and ESP32 Migration

Scaling Up: The 1-Wire Multi-Drop Bus

The true power of the DS18B20 is the multi-drop bus. Because every chip is laser-trimmed with a unique 64-bit ROM serial number, you can wire up to 100+ sensors in parallel on the exact same GPIO pin and 4.7kΩ pull-up resistor.

To read specific sensors in a multi-drop array, you must stop using getTempCByIndex(0), as the index order can shift during power cycles. Instead, extract the unique ROM address and query it directly:

DeviceAddress insideProbe = {0x28, 0xFF, 0x64, 0x1D, 0x86, 0x16, 0x03, 0x3F};
// Later in loop:
float temp = sensors.getTempC(insideProbe);

Reference: You can find your sensor's unique ROM address by running the DS18x20_Search example included in the DallasTemperature library.

Migrating to ESP32 (3.3V Logic)

If you are moving this project to an ESP32 DevKit V1 for WiFi/MQTT integration, you must adjust your hardware design. The ESP32 operates at 3.3V logic. While the DS18B20 can be powered by 3.3V, the 1-Wire protocol's rise times become marginal at lower voltages over long cable runs.

  • Pin Selection: Avoid ESP32 strapping pins (GPIO 0, 2, 12, 15) for the 1-Wire bus, as the pull-up resistor will interfere with the boot sequence. Use GPIO 4, 5, or 16.
  • Pull-up Voltage: Tie the 4.7kΩ pull-up resistor to the ESP32's 3V3 pin, not the 5V VIN pin. Pulling a 3.3V GPIO pin up to 5V will back-feed voltage into the ESP32's silicon, potentially destroying the GPIO pad over time.
  • Cable Length: At 3.3V, reliable 1-Wire communication drops to roughly 10-15 meters. For longer runs, power the DS18B20 VDD pin with 5V (from the ESP32 VIN), but use a bidirectional logic level shifter (like a BSS138 MOSFET circuit) on the data line to translate the 5V sensor signals down to 3.3V for the ESP32.

By respecting the strict timing requirements of the 1-Wire protocol and implementing proper error handling for the 85°C and -127°C edge cases, your Arduino temp sensor DS18B20 build will transition from a fragile breadboard experiment to a robust, deployment-ready environmental monitor.

Sources and Further Reading:
Analog Devices DS18B20 Official Datasheet
PJRC OneWire Library Documentation and Timing Analysis
Arduino Official 1-Wire Communication Guide