With my new addiction, I made the the mistake ??? to install Home Assistant, and wanted a thermometer and didn’t have any temperature sensor. But I remembered that the RP2040-Zeros in my drawer and the fact that they had internal temperature sensor.

After a short internet search I found learnembeddedsystems’ blog especially the article titled “RP2040’s On-Board Temperature Sensor”.

Code

Pico-SDK Installation

After opening the Pico-SDK Quick-Start Guide, I realised that their just was a AUR package, so after running yay -S pico-sdk and setting up the build environment i was done.

The Temperature Sensor

float get_temp() {
    const float conversion_factor = 3.3f / (1<<12);
    return 27 - (adc_read() * conversion_factor - 0.706) / 0.001721 + OFFSET;
}

This is a direct reference to the learnembeddedsystems blog and the RP2040 Datasheet temperature formula. $$ T = \frac{V - 0.706}{0.001721} $$ I calculated an offset using a real thermometer, after waiting for the chip to warm up and figured out that a $-5.5^{\circ}\mathrm{C}$ offset gave me a good enough estimation on my board.

Home Assistant Configuration

After struggling with Home Assistant config and reading the documentation, I came up with this configuration.yaml.

# Raw sensor data
sensor:
  - platform: serial
    serial_port: /dev/ttyACM0
    baudrate: 115200
    name: pico_temperature_raw
    value_template: "{{ value | trim | float(0) }}"

# Treated data
template:
  - sensor:
      - name: "Pico Temperature"
        unique_id: pico_temperature
        unit_of_measurement: "°C"
        device_class: temperature
        state: "{{ states('sensor.pico_temperature_raw') | float | round(1) }}"

# Do not record the raw data
recorder:
  exclude:
    entities:
      - sensor.pico_temperature_raw

Temperature History Temperature History - 24/01/2026

Extras

After finishing the main the main features I added two more :)

Colored LED

float get_temp_frac(float temp, float lower, float upper) {
    return (temp - lower) / (upper - lower);
}

uint32_t color_from_temp(float temp) {
    float t;

    uint8_t r;
    uint8_t g;
    uint8_t b;

    if (temp < TEMP_LOW) {
        t = get_temp_frac(temp, TEMP_LOWER, TEMP_LOW);
        r = 255 * (1 - t);
        g = 255 * (1 - t);
        b = 255;
    }
    else if (temp < TEMP_NORMAL) {
        t = get_temp_frac(temp, TEMP_LOW, TEMP_NORMAL - TEMP_LOW);
        r = 0;
        g = 255 * t;
        b = 255 * (1 - t);
    }
    else if (temp < TEMP_HIGH) {
        t = get_temp_frac(temp,- TEMP_NORMAL, TEMP_HIGH);
        r = 255 * t;
        g = 255 * (1 - t);
        b = 0;
    }
    else {
        r = 255;
        g = 0;
        b = 0;
    }

    return ((uint32_t) r << 8) | ((uint32_t) g << 16) | (uint32_t) b;
}

void update_led(float temp, bool cicle, PIO pio, uint sm) {
    uint32_t color = 0;

    if (temp <= TEMP_HIGH || cicle) {
            color = color_from_temp(temp);
    }
    pio_sm_put_blocking(pio, sm, color << 8u);
}

As the RP2040-Zero has a built in WS2812 LED, I decided to make it’s color transition depending on the temperature:

Temperature Color
$0^{\circ}\mathrm{C}$ White
$10^{\circ}\mathrm{C}$ Blue
$20^{\circ}\mathrm{C}$ Green
$30^{\circ}\mathrm{C}$ Red
$\gt30^{\circ}\mathrm{C}$ Blinking Red

Rack Mount

I also made a rack mount for the RP2040-Zero, to nourish my homelabing addiction :) RP2040-Zero Rack Mount 3D Model RP2040-Zero Rack Mount 3D Model - 25/01/2026 RP2040-Zero Rack Mount Photo RP2040-Zero Rack Mount - 25/01/2026

Download: STL Source: FreeCad

Sources and Inspiration: