murCO: From 2000 ppm in my kids' bedroom to a planter that tells them to open the window

The wake-up call

It wasn't a gadget idea. It was my kids' bedroom in November.

The air in there was noticeably bad in the mornings — that heavy, stale feeling you can't quite prove. So I built a rough CO₂ logger and left it running overnight. By morning it was past 2000 ppm. Every night, in the room where my two sons sleep.

And here's the thing an adult forgets: kids don't open windows. An adult walks into a stuffy room and opens one on instinct. A 10-year-old plays, does homework, sleeps, and never once thinks about air. They're in that room most of the day.

I also learned something that changed the design: in my overnight tests, leaving a window tilted open barely changed the CO₂ level — actually opening it wide for a few minutes made a much bigger difference.

So the question wasn't "what's the ppm value". The question was: is it time to open the window, and for how long?

That's a question a child can answer — if the answer is a color, not a number.

That's the whole product in one sentence:

Green means fine. Red means open the window.

No numbers, no app, no reading required. And since I go to bed later than my kids, I can air out their room while they sleep and close it again when the CO₂ drops.

Why build instead of buy

I looked at what's out there first:

I wanted local data in Home Assistant, no subscriptions, and a device my family wouldn't want to hide.

Three principles I refused to break

1. No soldering

If my sons (10 and 13) can't build it, the project failed.

That's why it runs on an M5Stack AtomS3 Lite: Grove connector, onboard button and RGB LED, USB-C. Everything plugs in.

2. Real CO₂, not estimated

Sensirion SCD40 — true NDIR.

If the number isn't trustworthy, the color isn't either.

3. It has to look like it belongs in a living room

Not "Arduino project on a shelf".

An object.

The enclosure: 15 printed iterations and a five-round war with one button

V0 was an Atom and an SCD40 on my desk, wires everywhere. It worked perfectly and looked like a crime scene.

V1 — my father, a retired mechanical engineer who spent his career designing industrial machinery, couldn't leave it alone. He made a proper box. Functional, well built... and a box.

V2 — on a walk it hit me: make it something people actually want. The first attempt was a planter with printed bamboo stalks on top. Better, but dead. It needed something alive.

V3 — then I found Tillandsia, the air plant. No soil, no mess, absorbs water through its leaves. Suddenly the thing had a soul.

The polygonal shell my brother designed was finished around the fourth major iteration.

Then the actual fun began: fitting the hardware inside.

The sensor and the Atom were easy.

The button was not.

It had to sit flush with the geometric shell, let the LED light through, and physically press the Atom's button underneath. We went through five versions and several mechanisms.

What finally worked: springs harvested from ballpoint pens, so the button returns on its own.

Cheap, ugly-clever, perfect.

And then it stopped pressing at all.

Cause: we had mounted the Atom higher up — partly for looks, partly so its heat wouldn't sit right on top of the sensor — and under finger pressure the Atom itself flexed in its holder.

Rigid enough to look right, springy enough to eat the press.

That took another round to solve.

Total: 15 printed and tested STL versions.

The firmware: 57 versions, mostly because of things I couldn't have predicted

While my father iterated the enclosure, I iterated the code.

The CO₂ part worked early. Everything after that came from actually living with the device.

"When do I water the plant?"

I added a watering tracker: it counts days since the last watering, double-click the button to reset, and a slider lets you set the interval.

Lovely.

For testing I set the interval to two days so I wouldn't have to wait.

Two days is not the right interval.

The first Tillandsia rotted. RIP.

The manual now recommends 5–14 days depending on your home.

Learned the hard way.

"That LED is too bright at night."

I added separate day and night brightness sliders.

Then I noticed the colors were wrong in the dark: below about 23% brightness, the warning colors stopped being distinguishable from each other.

So the minimum brightness is now capped at 23%.

Below that, the device lies to you.

"What is that flashing?!"

My wife, at night.

The night dimming worked beautifully, and then the blue water-me pulse lit up the entire bedroom at full attention.

Now watering alerts are suppressed during night hours — nobody waters a plant at 2 a.m. — and the alert waits for morning at night-appropriate brightness.

"It lost its IP address. What is it now?"

4× click and the device blinks its last IP octet in colors — green for hundreds, orange for tens, blue for units, white flashes as intro and outro.

Works with no app, no router login, no scanner.

"I want to know the temperature without opening anything."

Long-press gives a climate report: LED color for temperature, and with the MAX98357A amp + a small speaker it can say the values out loud through Home Assistant TTS.

Which led to an honest limitation:

The speech requires Home Assistant.

The audio path is driven from HA's media_player side, and getting fully standalone speech working on the Atom was beyond what I could get working.

So audio is a bonus for HA users, not a base feature.

"What if the Wi-Fi is down and it can't tell me anything?"

The LED pulses magenta when the connection to the router is lost, and stops the moment it's back.

"The temperature is too high."

The SCD40 sits inside an enclosure next to live electronics and self-heats.

In my build, measured against a reference thermometer, mine needed a 6 °C correction.

Since every build and every room differs, it's a user-adjustable slider rather than a hard-coded value.

The correction also needs a restart to fully take effect.

"Three colors aren't enough. I want an earlier warning."

I added a Sensitive mode with a fourth zone — yellow — which can be switched on if desired.

Real-world testing

Then I gave units to neighbours and family — four households.

Their feedback rewrote the manual.

One neighbour's family built one from my first written instructions and took it apart so thoroughly that we rebuilt it together as a picture guide: every step they stumbled on, we made simpler.

His 9-year-old now asks me when these will be for sale.

That was probably the best validation of the whole project.

What I'd tell anyone building with an SCD40

Open source

The firmware and electronics documentation are free.

The GitHub repository includes:

GitHub: https://github.com/Murco-design/murco-planter

If you want to build the planter exactly as shown here, the printable enclosure files and the illustrated step-by-step build manual are available at:

https://murco.design/

The idea is simple: the electronics side stays open; the printable design and the work that went into making it repeatable fund the project.

Questions I'd genuinely like answered

1. CO₂ only?

CO₂ only was a deliberate choice — "should I ventilate" doesn't need PM2.5.

But everyone asks about PM.

Is it a real need, or just a spec-sheet reflex?

2. Zigbee?

Is it worth moving this kind of device to Zigbee, or is ESPHome + Wi-Fi — with a Bluetooth proxy as a bonus  the better home for it?

3. Display?

My father has already designed a display variant.

I just haven't written the firmware for it.

Honestly, I'm not sure it's needed: the LED exists precisely so you don't have to read anything, and Home Assistant already has the graphs.

Would a display add real value, or is color + voice enough?

Happy to answer anything — hardware, firmware, or how to survive co-designing a product with your own father. 🙂