A local-only CO₂ / air quality monitor and TTS notification speaker for Home Assistant, hidden inside a geometric planter. No cloud. No subscription. No screen — just light and voice.
Built on ESPHome · Sensirion SCD40 (true NDIR) · M5Stack AtomS3 Lite (ESP32-S3) · Firmware: MIT licensed
The idea in one sentence: your air quality device should tell you when to open a window — and look good enough to sit next to your books while doing it. Even kids get it: red = open the window. And even kids can build it: this design was tested by my sons (10 and 13) and our neighbor's family — every step they stumbled on, we made simpler.
Everything you need to build a fully working sensor:
- ✅
firmware/murco_v1.4.5.yaml— complete, battle-tested ESPHome config (58 compilations later…), MIT licensed - ✅ Bill of materials with sourcing notes (below)
- ✅ Wiring / pinout reference
- ✅ Quick-start flashing guide
- ✅ Home Assistant TTS automation example
- ✅ Lessons learned — the stuff that cost us evenings, free for you
What's not here: the 3D-printed geometric shell (STL), the illustrated 10-chapter build manual, and email support. Those live in the murCO Starter Kit → — it's how a father-and-sons project funds itself. The brain is free. The beauty is the product.
| Feature | How it works |
|---|---|
| 🟢🟠🔴 CO₂ at a glance | LED color by ppm (ASHRAE/REHVA thresholds). Standard 3-zone or sensitive 4-zone mode |
| 🗣 It talks | TTS speaker as a native HA media_player — announce CO₂ alerts, doorbells, anything |
| 🌡 Climate report | Long-press the button → temperature as color + optional voice report |
| 💧 Plant watering tracker | Blue pulse when your Tillandsia is thirsty (or disable it) |
| 🌙 Day / night brightness | Automatic, fully configurable hours and levels |
| 📡 No display? No problem | 4× click and murCO blinks out the last octet of its IP address in colors (green = hundreds, orange = tens, blue = units) |
| 📶 Wi-Fi watchdog | Magenta pulse when the connection drops — reconnects automatically |
| 📶 BLE proxy | Bonus: extends your HA Bluetooth range |
| 🏠 100 % local | ESPHome native API, encrypted, auto-discovered by HA. Web UI included — works without HA too |
| Part | Note |
|---|---|
| M5Stack AtomS3 Lite | ESP32-S3 in a finished case — see below why |
| Sensirion SCD40 module | True NDIR CO₂ + temp + humidity. An SCD41 works too — same scd4x platform, no YAML changes needed. Planning to add the murCO shell later? Get the soldered 22×14 mm SCD40 breakout — the shell's internal mount is designed for that exact board size (larger boards like Adafruit/Qwiic modules won't fit). Verified sourcing links are included in the Starter Kit. |
| MAX98357A I2S amplifier | Optional — only if you want the TTS speaker |
| Small 4Ω speaker (~2–3 W) | Optional, pairs with the amp |
| Grove cable / dupont wires | I2C hookup |
| USB-C cable + 5V supply | Power |
All parts are commonly available (AliExpress, Mouser, local distributors).
Because murCO is built to be a first project anyone can actually finish — that's the whole philosophy, and the board choice follows it:
- No soldering iron needed. Grove connector for I2C, USB-C for power. If you can plug in cables, you can build this. (Our 10- and 13-year-old test builders confirm.)
- The whole UX runs on stock hardware. The button (1×/2×/4×/6× click functions) and the RGB LED indicator are already in the Atom — nothing to add, nothing to wire wrong.
- Fixed form factor. The murCO shell is engineered around the Atom's exact dimensions — airflow, LED diffusion, cable routing. Known hardware is what makes "works first time" a promise instead of a hope.
Hardcore DIY folks: the YAML ports to any ESP32-S3 with pin adjustments — everything is commented. Go wild.
SCD40 → AtomS3 Lite (via Grove connector):
| SCD40 pin | AtomS3 pin | Grove wire |
|---|---|---|
| VDD | 5V | red |
| GND | GND | black |
| SDA | GPIO 1 | yellow |
| SCL | GPIO 2 | white |
MAX98357A amplifier → AtomS3 Lite (optional — TTS speaker; Dupont female-male cables, ~10 cm):
| MAX98357A pin | AtomS3 pin |
|---|---|
| VIN | 3V3 (top left) |
| GND | G (right column) |
| BCLK | G5 |
| LRC | G6 |
| DIN | G7 |
| Speaker + / − | your 4Ω speaker |
Onboard (nothing to wire): RGB LED = GPIO 35, button = GPIO 41 — both built into the Atom.
That's it — one Grove cable for the sensor, 5 wires if you want it to talk. No soldering needed.
Easy path — no ESPHome setup needed:
- Download
murco_v1.4.5_EN.factory.binfrom Releases - Open web.esphome.io in Chrome/Edge, connect the Atom via a data USB cable
- Click "Prepare for first use", then Install → select the downloaded .bin
- Connect to the
murCO Planter SetupWi-Fi AP →192.168.4.1→ enter your Wi-Fi - Home Assistant discovers it automatically — when asked for the encryption key, use:
lrzDKyTwxe+CjHKL8mYaP7FwV8zvfTGlpSesyjRAgKU= - Done. Green light = breathe easy.
Maker path — compile it yourself:
- Grab
firmware/murco_v1.4.5.yamlandfirmware/partitions_murco_8mb.csv - Put the CSV where the YAML's
board_build.partitionspath points — or adjust the path to your setup - Generate your own API encryption key (the YAML ships with a placeholder)
- Compile in your ESPHome dashboard, flash, adopt in HA. Every section of the YAML is commented — bend it to your will.
Full web interface at http://murcoplanter-xxxxx.local — calibration, thresholds, brightness, all of it. Works standalone without HA.
The speaker shows up in HA as a media player. From there, one small automation:
alias: murCO CO2 Alert
triggers:
- platform: numeric_state
entity_id: sensor.murco_planter_XXXXXX_murco_co2
above: 1500
for:
minutes: 5
actions:
- action: tts.speak
target:
entity_id: tts.google_translate_en_com
data:
message: "CO2 is getting high. Please open a window."
media_player_entity_id: media_player.murco_planter_XXXXXX_murco_speaker
mode: singleDoorbell announcements, laundry-done, "the plant is thirsty" — anything HA knows, murCO can say.
Things that cost us evenings across 58 firmware compilations:
- The SCD40 self-heats inside an enclosure. Sealed next to electronics, it reads 3–6 °C above ambient. The firmware ships with a configurable temperature offset (default 6.0 °C) — calibrate yours against a reference thermometer and adjust in 0.5 °C steps.
- The temperature offset needs a restart to fully apply. The SCD4x takes the new offset on the next boot — the firmware handles writing it, just restart after changing.
- Never calibrate CO₂ indoors. Forced recalibration sets the sensor to ~420 ppm reference — do it outside, after 10+ minutes of stabilization, or all your readings shift wrong.
- LED logic + alerts + effects = recursion traps. The LED state machine (CO₂ color, watering pulse, temperature blinks, critical alert loop) runs as a
mode: restartscript so overlapping triggers can't stack — if you extend it, keep it that way. - I2S audio on the AtomS3: BCLK 5, LRCLK 6, DOUT 7 with an external DAC (
dac_type: external, mono) — works reliably with the MAX98357A.
I wanted precise, local CO₂ data in Home Assistant — no cloud, no subscription. The prototype worked, but it was a mess of wires. My father, a mechanical engineer who spent his career designing industrial machinery, engineered the enclosure. My brother designed the polygonal shell. Then the build guide went through the toughest QA there is: my sons (10 and 13) and the neighbor's family built their own murCOs, and every step that confused them got rewritten. Months of walks and late evenings later, murCO is what it is: three people, one device. Built by a family, for yours.
This repo gets you a working sensor on your desk. The murCO Starter Kit gets you the thing on the hero photo:
- 🧊 All STL files — the geometric shell + internal mounts, designed around this exact hardware (airflow, LED diffusion, speaker cavity)
- 📖 Illustrated 10-chapter manual — refined by watching real families build it: my sons (10 and 13) and our neighbor's kids were the toughest QA team. From printed parts to a running device without googling anything.
- 🌿 Plant guide (yes, it's also a real planter — Tillandsia air plants, no soil)
- 💬 Email support from the person who wrote the firmware
€23 at murco.design · works out to ~€60 all-in including parts — compare that to $150+ consumer monitors that phone home.
Can I use a different ESP32 board? Yes, with pin adjustments — the YAML is commented. The AtomS3 Lite is just the neatest fit for the shell (see "Why the AtomS3" above).
Does it work without Home Assistant? Fully. Built-in web UI has every control. HA adds history graphs, automations and TTS.
Manual CO₂ calibration? Rarely needed (automatic self-calibration is on), but one button in the web UI — outdoors only.
Why CO₂ only, no PM2.5? Deliberate choice: for the daily "should I ventilate" question, CO₂ answers it, and it keeps the device small and affordable. PM is on the roadmap for v2.
Fahrenheit? Home Assistant converts automatically based on your unit settings. The device web UI and threshold sliders are °C for now.
Why not just buy an AirGradient or Apollo AIR-1?. Both are great — genuinely. But they look like measuring instruments, and I wanted something that earns its spot on the living room shelf. murCO is for the living room, not the utility closet. (Also: it talks, and my kids built one.) If you need PM2.5 or a proven ecosystem, try one of those — they're excellent. If you want it beautiful, talking, and built together with your kids, that's murCO.
A Zigbee version? Not planned for v1 — murCO is built around ESPHome's native API (and the TTS speaker needs the horsepower anyway). If you'd want one, open an issue and tell us — we're counting.
License? Firmware is MIT — use it, modify it, ship it, just keep the attribution. The murCO name and logo, the shell design (STL files) and the build manual are proprietary and not covered by the MIT license.
If this saved you an evening, a ⭐ helps others find it. Useful beyond that? You can buy us a beer 🍺 — or better, get the shell and give this sensor a home.
Made by family · murco.design · claim your spot on the murCO world map

