DIY Air Quality Sensor

My folks live out in the woods, and are grappling with the the recent wildfires in California that have resulted from the displacement of indigenous peoples, a century of wildfire suppression, and climate change. My Grandpa and Mom are asthmatic, and it’s important for the family to know what the air quality is outside as the many fires burn through the season. The problem is that we can’t say for certain what the air quality is at their exact location, because they live far away from publicly available sensors.

I wanted to make an air quality sensor that could provide real-time data to me and my family on our phones. PurpleAir sensors seem cool, but as of this writing they are $229. I was convinced that I could build something similar for much cheaper.

Because I planned to integrate some more sensors and functionality eventually, I decided to set up a homeassistant server on a raspberry pi, and build a sensor that connected to homeassistant. The result is an extensible, cheap, air quality sensor that my family and I use to monitor air quality from our phones, which can be set to send alerts when the AQI crosses certain thresholds.

This project was heavily based on Pieter Brinkman’s tutorial

Table of Contents

  1. Supplies
  2. The AQI Sensor
  3. Homeassistant Server

An exhaustive list of all materials used in this project (total = $77, $61 of which is the raspberry pi home server)

Supplies

Tools

The Sensor

aqi-materials1.jpeg

Wiring

PMS5003

Pastedimage20240619142006.png

To connect the PMS5003 you must clip the ends and solder one end of dupont wire onto the wires coming out of the sensor.

Then we connect the other ends of the dupont wires to the corresponding pins on the ESP32 board. Don’t mind the DHT22 humidity sensor yet

DHT22 Humidity Sensor

Pastedimage20240619143426.png

Wire it up with the socket-socket dupont connectors, no soldering needed here. The picture at the end of the previous section shows what it looks like wired up.

Software

I’m assuming you have a unix system (linux or mac) open Terminal or some other terminal emulator.

I use pip as a python package manager. It should be installed by default with python3

download the esphome package

pip install esphome

Now we’re going to make a .yaml configuration file that will be used to flash the software onto the sensor.

Here’s my air-quality.yaml

esphome:
  name: airquality
  platform: ESP32
  board: nodemcu-32s

# Enable logging
logger:

# Enable Home Assistant API
api:

ota:
  password: ""

wifi:
  ssid: "WIFI NAME"
  password: "WIFI PASSWORD"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Airquality Fallback Hotspot"
    password: "PASSWORD"

captive_portal:

uart:
  tx_pin: GPIO17 
  rx_pin: GPIO16 
  baud_rate: 9600

sensor:
  - platform: pmsx003
    type: PMSX003
    pm_1_0:
      name: "Particulate Matter <1.0µm Concentration"
    pm_2_5:
      name: "Particulate Matter <2.5µm Concentration"
    pm_10_0:
      name: "Particulate Matter <10.0µm Concentration"
  - platform: dht
    pin: GPIO19 #D19 #D4
    temperature:
      name: "Air quality meter Temperature"
    humidity:
      name: "Air quality meter Humidity"
    update_interval: 60s

switch:
  - platform: gpio
    pin: 
      number: GPIO21
    id: pms_set
    name: "Start measuring"
  
interval:
  - interval: 120s
    then:
      - switch.turn_on: pms_set
      - delay: 20s
      - switch.turn_off: pms_set
esphome air-quality.yaml run

It compiled, but I received the following error

INFO Successfully compiled program.
INFO Resolving IP address of barntank_sensor.local
ERROR Error resolving IP address of barntank_sensor.local. Is it connected to WiFi?
ERROR (If this error persists, please set a static IP address: https://esphome.io/components/wifi.html#manual-ips)
ERROR Error resolving IP address: Error resolving address with mDNS: Did not respond. Maybe the device is offline., [Errno 8] nodename nor servname provided, or not known

After about an hour of trouble shooting I realized it was because the microUSB cable I was using does not transfer data, it only charges devices, which is the case with some cheap cables. After replacing the cable with another microUSB I had lying around, it worked.

It’s gonna compile and take a few minutes. When prompted, select the option to flash over ‘serial’ i.e. USB.

If you change the configuration and flash it again you can use the following command to flash it over wifi

esphome water.yaml run --upload-port XX.XX.XX.XX

where xx.xx.xx.xx is the IP address of the sensor (the IP of the sensor is reported after you flash it over USB the first time. Might be worth writing it down.)

Flash/update the software on the sensor as often as you change the .yaml configuration. Now the sensor should be set up

Homeassistant Server

This part is pretty easy, but opens up pandora’s box. There are so many things you can do. But to integrate our sensor it’s pretty easy.

So we’re gonna install Home Assistant on a raspberry pi 4. You can install Home Assistant software on a bunch of different machines/computers, but raspberry pis are cheap and effective.

You’re going to start by taking your microSD card and using the microSD converter and plugging it into your computer.

Once you’ve got the microSD in, follow this tutorial for installing Home Assistant. It says to use Balena Etcher but you can also use Raspberry Pi Imager, which is what I used.

Once you set up home assistant it may tell you that there is a device discovered. If not, you can add it manually under Settings > Devices & Services > Add Integration > ESPHome Enter the ip address of the sensor under in the ‘host’ field. And now it’s added!

Go to the Overview dashboard tab in the sidebar. Edit the dashboard by clicking the pencil in the top right Click Add Card in the bottom right Search by entity

And add the card once you’ve identified the sensor or set of sensors you would like to add. Now you can customize how to display the sensor data in your Home Assistant dashboard!

I use the following custom card configuration to show PM2.5 as AQI categories

type: gauge
entity: sensor.particulate_matter_2_5um_concentration_2
needle: true
min: 0
max: 300
segments:
  - from: 0
    color: '#00e400'
    label: Good
  - from: 12
    color: '#ffff00'
    label: Moderate
  - from: 35.5
    color: '#ff7e00'
    label: Unhealthy for sensitive groups
  - from: 55.5
    color: '#ff0000'
    label: Unhealthy
  - from: 150.5
    color: '#8f3f97'
    label: Very Unhealthy
  - from: 250.5
    color: '#800000'
    label: Hazardous
name: Air Quality (PM2.5)

You can edit a card in the dashboard and click Show code editor in the bottom left and paste it in

Conclusion

I put it in a box and drilled some holes in it and mounted it on the side of my grandparent’s shed. So far so good.

IMG_97162.jpg
IMG_9713.jpg