Portable Air-Quality Monitor
← Project Index Portable Air-Quality Monitor

Portable Air-Quality Monitor

A handheld indoor air-quality logger built on a Pimoroni Explorer board running MicroPython -; TVOC sensing, CSV logging, and seaborn visualizations of workplace walk-throughs. A particulate/dust sensor was the next piece to wire in.

Active Started: 2026 Updated: 2026

Overview

A pocket-sized device you can carry through a building to see what the air is actually doing. It reads total volatile organic compounds, CO2, and formaldehyde off a UART sensor, pairs that with temperature/humidity/pressure and ambient light, draws it all on a little color screen, and logs every reading to a CSV on flash so the walk-through can be replayed and plotted later.

Background

The Pimoroni Explorer is a tidy RP2350 board with a built-in display, buttons, and Qwiic/ STEMMA connectors -; exactly the kind of thing you want for a "walk around and measure stuff" gadget that doesn't need a laptop tethered to it. The goal was a logger you could hold in one hand during a workplace walk-through and trust to capture a clean trace, warts and all, for offline analysis.

How It Works

It's a single-file MicroPython event loop. A Waveshare TVOC sensor talks over UART at 115200 8N1, streaming 11-byte frames once a second; the firmware parses them (header 0xFE, footer 0x16, a checksum over the payload bytes) into TVOC ppm, CO2 ppm, formaldehyde ppb, and a 1-;4 air-quality level. The sensor's heater needs 5V, so it's powered off the Explorer's servo rail while the logic lines stay 3.3V-safe, and the first ~120 seconds are flagged as warmup so the unreliable early readings can be filtered out downstream.

A Pimoroni Multi-Sensor Stick on I2C adds a BME280 (temp/humidity/pressure) and an LTR559 (lux/proximity). The UI is four pages you cycle with the X/Y buttons -; a TVOC dashboard with a 60-second sparkline and peak tracker, an environment page with plain-English descriptions ("temperate", "fair"), a light page on a log scale, and a dust/PM2.5 page. Buttons toggle logging, reset peaks, and re-baseline the dust sensor.

Logging appends one row every five seconds to /aq_log.csv on internal flash, with a warmup flag so the noisy first two minutes can be dropped in analysis:

# header written once; one row every LOG_INTERVAL_S = 5s
elapsed_s, warmup, tvoc_ppm, co2_ppm, ch2o_ppb, level,
temp_c, humidity_pct, pressure_hpa, lux, proximity,
pm25_ugm3, dust_voltage

# e.g.  44,1,0.348,539,2,2,22.56,52.1,986.46,4.98,0,0.9,0.2621

The CSVs are pulled off over Thonny and plotted offline with seaborn -; the warmup flag exists specifically so those first two minutes can be excluded from the charts. (The plotting lives outside this repo; the firmware's job is just to capture a clean trace.)

Current Status

TVOC, environment, and light are all working and logging. The dust sensor that was billed as "next" is already done -; a Sharp GP2Y1010AU0F optical dust sensor on an ADC pin, with datasheet pulse timing (drive the IR LED, wait 280µs, sample for 40µs), 10-sample averaging, a zero-dust baseline auto-calibrated over the first 30 seconds in clean air, and conversion through to US EPA AQI. The README still documents the older three-page build, so it's one revision behind the code.

  • Four-page firmware (air_monitor_4.py) is the current build; dust/PM2.5 is integrated and has real captured logs.
  • README documents the three-page version -; due for an update.
  • Warmup flagging keeps the first ~120s of TVOC data out of the analysis.