Desk CO₂ Monitor: ESP32-C3, SCD41 and E-Paper

A CO₂ meter that sits on the desk, wakes every few minutes, takes one reading and goes back to sleep. No backlight, no fan, no cloud account: an e-paper panel holds the last number without drawing anything, and the battery is meant to last long enough that charging it is a rare event rather than a habit.

This page is a test record for the site build — the structure is real, the build is not finished. Every number below is either quoted from a datasheet, with the source linked at the end, or marked as still to be measured.

What it does

Parts

QtyPartWhy this one
1ESP32-C3 module board with USB-CSingle RISC-V core is plenty for one sensor and one panel, and the chip has native USB — no serial adapter on the board.
1Sensirion SCD41True NDIR CO₂, not a VOC sensor guessing at it. Single-shot mode is what makes the sleep cycle possible.
12.9″ e-paper panel, SPI, 296 × 128Holds the last frame with no power. A reading that updates every few minutes does not need anything faster.
118650 cell + protection boardCheap, replaceable, and standard enough that anyone repeating this already has one.
24.7 kΩ resistorsI²C pull-ups, if the sensor breakout does not carry its own.
1Printed enclosure, FDMTwo parts, no supports. Vents on the back so the sensor sees room air and not its own board.
The whole bill of materials. Nothing here is hard to source.

How it goes together

  1. Wire the SCD41 to the I²C pins and the panel to the SPI pins. Keep the sensor away from the regulator — its own heat lands in the temperature reading.
  2. Check the sensor answers on the bus before anything else. If the scan finds nothing, it is the pull-ups or the wiring, never the firmware.
  3. Flash the firmware and confirm one full cycle on USB power: wake, read, draw, sleep.
  4. Only then move to the cell. A build that misbehaves on battery is much harder to read than one that misbehaves on a bench supply.
  5. Print the enclosure, fit the panel behind its window, and leave the vents clear.

Firmware

The whole loop is four steps, and the interesting part is that there is no loop at all: deep sleep resets the chip, so every wake starts at the top.

// Pins and timing, in one place so the rest of the sketch never hardcodes them.
#define SDA_PIN        6
#define SCL_PIN        7
#define EPD_CS_PIN     10
#define EPD_DC_PIN     3
#define SLEEP_SECONDS  300

void setup() {
  Wire.begin(SDA_PIN, SCL_PIN);

  // Single shot: the sensor is powered up, measured once, and left alone.
  scd4x.measureSingleShot();
  scd4x.readMeasurement(co2, temperature, humidity);

  drawPanel(co2, temperature, humidity);

  esp_sleep_enable_timer_wakeup(SLEEP_SECONDS * 1000000ULL);
  esp_deep_sleep_start();
}

void loop() {
  // Never reached: deep sleep restarts the chip at setup().
}
Why the panel keeps a shadow of the previous reading

E-paper does not repaint a pixel, it moves particles, and a partial refresh only moves the ones it has to. Do that a few dozen times and the digits that stopped changing leave a faint outline behind. The fix is a full refresh — slower, and it flashes the whole panel black and white — every so many partial ones. How often is a judgement call: too rare and the ghosting stays, too often and the display blinks at you all day.


Numbers

FigureValueWhere it comes from
CO₂ measurement range400–5000 ppmSCD4x datasheet
CO₂ accuracy±75 ppm at 400–1000 ppmSCD4x datasheet
CPU32-bit RISC-V, single core, up to 160 MHzESP32-C3 datasheet
SRAM400 KB, plus 8 KB RTC FAST retained in deep sleepESP32-C3 datasheet
Programmable GPIOs22ESP32-C3 datasheet
Deep-sleep current, chip only5 µA typical, RTC timer and RTC memory onESP32-C3 datasheet
Deep-sleep current, whole boardto be measureddepends on the module’s regulator and USB bridge
Battery life on one 18650to be measuredfollows from the board current above
Full panel refresh timeto be measuredpanel and driver dependent
Datasheet figures are quoted; everything that depends on this particular build is still open.

The chip datasheet tells you what the silicon does in deep sleep. It says nothing about the regulator, the USB bridge and the status LED your board vendor put next to it — and on a build like this, those three are the entire battery life.

Sources