Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

1-Wire Bus

Hardware revision note: 1-Wire requires hw-rev2 firmware. On v1 hardware, 1-Wire endpoints return OneWireError::Unsupported.

Pico de Gallo provides 1-Wire bus support through the RP2350’s PIO (Programmable I/O) state machine hardware. The 1-Wire data pin is on GPIO 16, configured in open-drain mode.

Operations

OperationDescription
ResetResets the bus and detects device presence
ReadReads N bytes from the bus
WriteWrites raw bytes to the bus
Write PullupWrites bytes then applies strong pullup for parasitic-power devices
SearchStarts a new ROM search and returns the first device
Search NextContinues the current ROM search

DS18B20 Temperature Sensor Example

The DS18B20 is the most popular 1-Wire device. Here’s how to read its temperature using each interface.

Protocol Refresher

  • Skip ROM (0xCC): addresses all devices (single-device bus)
  • Convert T (0x44): starts temperature conversion (needs 750ms with strong pullup for parasitic power)
  • Read Scratchpad (0xBE): reads 9 bytes of sensor data
  • Temperature is in bytes 0–1 (signed 16-bit, little-endian, 1/16°C resolution)

CLI

# 1. Discover devices on the bus
gallo onewire search

# 2. Reset the bus
gallo onewire reset

# 3. Start temperature conversion with 750ms strong pullup
gallo onewire write-pullup --data cc44 --duration 750

# 4. Reset again before reading
gallo onewire reset

# 5. Send Read Scratchpad command
gallo onewire write --data ccbe

# 6. Read 9-byte scratchpad
gallo onewire read --len 9

# Parse temperature from the first 2 bytes:
# e.g., bytes [50, 01] → 0x0150 = 336 → 336 / 16.0 = 21.0°C

Rust Library

#![allow(unused)]
fn main() {
use pico_de_gallo_lib::PicoDeGallo;

async fn read_ds18b20_temperature(gallo: &PicoDeGallo) -> f32 {
    // Reset bus, check presence
    let present = gallo.onewire_reset().await.unwrap();
    assert!(present, "No device on bus");

    // Skip ROM + Convert Temperature, strong pullup for 750ms
    gallo.onewire_write_pullup(&[0xCC, 0x44], 750).await.unwrap();

    // Reset again
    gallo.onewire_reset().await.unwrap();

    // Skip ROM + Read Scratchpad
    gallo.onewire_write(&[0xCC, 0xBE]).await.unwrap();

    // Read 9-byte scratchpad
    let data = gallo.onewire_read(9).await.unwrap();

    // Temperature is in bytes 0–1 (little-endian, 12-bit signed fixed-point)
    let raw = i16::from_le_bytes([data[0], data[1]]);
    raw as f32 / 16.0
}
}

C (FFI)

#include "pico_de_gallo.h"
#include <stdio.h>

float read_ds18b20(PicoDeGallo *gallo) {
    bool present;
    gallo_onewire_reset(gallo, &present);
    if (!present) {
        fprintf(stderr, "No device on bus\n");
        return -999.0f;
    }

    // Skip ROM + Convert T with 750ms strong pullup
    uint8_t convert_cmd[] = {0xCC, 0x44};
    gallo_onewire_write_pullup(gallo, convert_cmd, 2, 750);

    // Reset before reading
    gallo_onewire_reset(gallo, &present);

    // Skip ROM + Read Scratchpad
    uint8_t read_cmd[] = {0xCC, 0xBE};
    gallo_onewire_write(gallo, read_cmd, 2);

    // Read 9-byte scratchpad
    uint8_t buf[9];
    uint16_t out_len;
    gallo_onewire_read(gallo, buf, 9, &out_len);

    // Temperature from bytes 0–1
    int16_t raw = (int16_t)(buf[0] | (buf[1] << 8));
    return raw / 16.0f;
}

HAL

#![allow(unused)]
fn main() {
use pico_de_gallo_hal::Hal;

fn read_ds18b20_blocking(hal: &Hal) -> f32 {
    let ow = hal.onewire();

    let present = ow.reset().unwrap();
    assert!(present, "No device on bus");

    ow.write_pullup(&[0xCC, 0x44], 750).unwrap();
    ow.reset().unwrap();
    ow.write(&[0xCC, 0xBE]).unwrap();
    let data = ow.read(9).unwrap();

    let raw = i16::from_le_bytes([data[0], data[1]]);
    raw as f32 / 16.0
}
}

Bus Scanning

To enumerate all devices on the 1-Wire bus:

gallo onewire search

Output:

Found 2 device(s):
  1: ROM ID 0x28FF123456780012 (family 0x28)
  2: ROM ID 0x28FF9ABCDE340056 (family 0x28)

The family code 0x28 identifies DS18B20 sensors. Each ROM ID is a unique 64-bit address: family code (1 byte) + serial number (6 bytes) + CRC (1 byte).

Hardware Setup

Connect a DS18B20 (or other 1-Wire device) to GPIO 16 with a 4.7kΩ pull-up resistor to 3.3V:

3.3V ──┬── 4.7kΩ ──┬── GPIO 16 (data)
       │            │
       │          DS18B20
       │            │
      GND ─────── GND

For parasitic power mode (no separate VDD), use the write-pullup command which drives the data line high after sending commands to supply power through the bus itself.