Build

Bedroom CO₂ monitor

For your room, your classroom or your boat.

These parts on their own: $151.

  • 10-Port Motherboard×1
  • USB-C×1
  • CO₂ Sensor×1
  • Screen×1
  • Light Grid×1

Smart Home · Wi-Fi · Bluetooth

What it does

  1. 1The screen shows the CO₂ level in the room in ppm.
  2. 2The light grid glows warm while the air is fine and turns red when it is time to open a window.

How to build it

  1. 1Slide the screen into ports 2 and 3.
  2. 2Slide the light grid into port 5.
  3. 3Slide the CO₂ sensor into port 6.
  4. 4Slide the USB-C into port 10 and plug the cable into your computer.
  5. 5Plug it in and press Upload to board.

Uploading works from Chrome or Edge on a computer. Open this page there with the board plugged in.

On the board

Front

  • 2+3ScreenThe ppm and a gauge
  • 5Light GridGreen, amber above 1000 ppm, red above 1500
  • 6CO₂ SensorReads the air

Back

  • 10USB-CPower and programming

The code

co2.cpp · 80 linesDownload
// CO2 monitor — small (10-port) board, CO2 sensor (SCD40), Screen, Light Grid.
// The screen shows the ppm with a gauge; the grid is green while the air is fine, amber above 1000 ppm, red above 1500.
// Nothing to press. The sensor needs about a minute after power-on before its first reading.
#include <Arduino.h>
#include "drivers/i2c_software.h"
#include "modules/air_quality/scd40.h"
#include "modules/display/st7735_tft.h"
#include "modules/led/neopixel.h"

ST7735_TFT    screen(SCR_SCLK, SCR_CS, SCR_MOSI, SCR_DC);
SoftwareI2C   bus(CO2_SDA, CO2_SCL);
SCD40         co2(&bus);
NeoPixelGrid  grid(GRID_A, GRID_B);

static const uint16_t AMBER_ABOVE = 1000, RED_ABOVE = 1500, GAUGE_MAX = 2000;
static uint16_t rgb(uint8_t r, uint8_t g, uint8_t b) { return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); }

enum Air { FINE, STUFFY, BAD, WAITING };
Air airOf(uint16_t ppm) { return ppm == 0 ? WAITING : ppm > RED_ABOVE ? BAD : ppm > AMBER_ABOVE ? STUFFY : FINE; }
uint16_t inkOf(Air a) { return a == BAD ? rgb(255, 70, 60) : a == STUFFY ? rgb(255, 180, 40) : a == FINE ? rgb(90, 210, 110) : rgb(120, 120, 120); }

uint16_t lastPpm = 0; bool sensorOk = false; uint32_t lastDraw = 0, bootAt = 0; bool pulse = false;

void lights(Air a) {
…