DIY Workshop Air Quality Monitor with the Particle Photon 2 and Grafana

Why Track Air Quality in a Workshop?

CO₂ builds up fast in closed spaces. A few hours of power tool use, a gas heater running in the background, or just poor ventilation can push concentrations well above where they start affecting concentration and comfort — and you usually won’t notice until you’re already feeling it. Cheap sensors and a single development board are enough to build a monitor that gives you an actual number to act on.

The Particle Photon 2 is a natural fit for this kind of build. It has dual-band Wi-Fi (2.4GHz and 5GHz) and BLE 5.3 built in, runs a 200MHz Arm Cortex-M33, and sits in a Feather form factor with a wide ecosystem of compatible shields and breakout boards. It also connects to Particle’s cloud out of the box, which handles authentication and device management so you can focus on the sensor side. Note: the original Photon is discontinued — the Photon 2 is the current hardware.

Choosing Your Sensors

CO₂: Get a Real NDIR Sensor

A lot of inexpensive breakouts labelled "CO₂ sensor" are actually MOS (metal oxide semiconductor) devices. They measure VOCs and estimate equivalent CO₂ concentration — they’re not measuring CO₂ directly. The readings are noisy and environment-dependent. For a workshop monitor, you want a true NDIR or photoacoustic sensor.

The Sensirion SCD40 is a popular pick in the maker community. It uses photoacoustic sensing (a variant of NDIR), communicates over I²C, and fits on standard breakout boards. It costs noticeably more than MOS alternatives, but the readings mean something. ASHRAE guidelines put comfortable indoor CO₂ somewhere in the 600–900 ppm range; 1000 ppm is a reasonable alert threshold for a workspace.

Temperature and Humidity

The Bosch BME280 handles temperature, humidity, and barometric pressure on a single I²C breakout. It’s well-documented and has libraries for every major platform. The Sensirion SHT31 is a slightly cleaner choice if you only need temp and humidity and want a tighter accuracy spec without paying for the pressure measurement.

If you go with the SCD40, it has onboard temperature and humidity sensing built in — one fewer component to wire. The catch: self-heating inside a sealed enclosure can push its temperature reading a couple of degrees high. If that matters for your use case, mount a separate temperature sensor outside any enclosure and use that reading instead.

Wiring It Together

Both sensors use I²C. On the Photon 2, the I²C bus is on D0 (SDA) and D1 (SCL). Multiple I²C devices share the same two lines, so you run SDA and SCL from the Photon 2 to both sensors in parallel. The SCD40 defaults to address 0x62; the BME280 defaults to 0x76 (or 0x77 depending on the SDO pin on your specific breakout). No address conflict.

Before writing any sensor library code, run a basic I²C address scan to confirm both sensors are detected. Most breakout boards include the pull-up resistors the bus requires — but not all of them do. If the scan returns nothing, that is the first thing to check.

Particle Firmware Basics

Particle’s firmware environment is a modified Arduino framework. Libraries for the SCD4x family and the BME280 are in Particle’s library browser. You can install them through Particle Workbench (the VS Code extension) or directly in the Web IDE.

The publishing pattern that makes Particle useful here is Particle.publish(). You send a named event with a JSON string payload, and Particle’s cloud receives it. From there you configure a webhook in the Particle Console to forward that payload to whatever back-end you want — a Google Sheet, a custom API endpoint, or a time-series database. The free plan is generous for hobbyist use. Just don’t publish every second; air quality changes slowly enough that once per minute is plenty, and high-frequency publishing will eat into event limits.

Getting Data into Grafana

The Particle Console’s live event stream is useful for debugging but gives you nothing historical. For trends, you need time-series storage. Two common setups:

  • Particle Webhook → InfluxDB → Grafana. Configure a webhook in the Particle Console to POST your event payload to an InfluxDB write endpoint. Run InfluxDB and Grafana in Docker on a home server or small VM. Grafana then connects to InfluxDB as a data source and you build panels from there. This is the most flexible option.
  • Particle Webhook → ThingsBoard. ThingsBoard’s self-hosted community edition handles device dashboards without needing a separate visualization layer. Less customizable than Grafana, but significantly faster to get running from scratch.

The InfluxDB route has one gotcha that trips people up: Particle webhooks use Mustache templating to build the outgoing request body, and InfluxDB’s line protocol is strict about spacing and comma placement. A malformed write fails silently from the Particle Console side — you won’t see an error there. If data stops arriving, check InfluxDB’s own write API response logs directly to see the actual error.

Making the Alert Actually Useful

A dashboard you have to remember to look at is only marginally better than no dashboard. Once data is flowing, add a Grafana alert rule on the CO₂ panel — threshold at 1000 ppm, routed to your phone via Pushover or a Slack channel. That turns a passive display into something that actually gets your attention when the shop needs fresh air.

Placement and Enclosure

Placement matters more than most people expect. Mount the sensor at breathing height in the middle of the space, not up near the ceiling and not directly under an HVAC vent. CO₂ doesn’t distribute instantly and evenly — a corner near the floor reads differently from where you actually are.

A printed enclosure is fine, but CO₂ sensors need airflow — vent it on at least two sides. Keep the Photon 2 away from the sensors if you can; microcontroller heat is small but measurable if everything is packed into a tight box.

Power: the Photon 2 draws well under 100mA at idle with Wi-Fi connected. Any decent USB phone charger runs it indefinitely without a second thought.

Sources

Similar Posts