I built this DIY Air Quality Monitor to help me stay healthy and alert in my basement office.
I'm going to show you how you can do the same thing in this video, so let's get started!
This office is where I record all my YouTube videos and do all my work. It's in a corner
of my basement with no windows and one air vent; this one you see behind me.
I normally put this magnetic cover on it because it can be pretty distracting to have it open
during my recording. I never designed this office for YouTube,
but if I did, I would've put the vent somewhere else, definitely not right where you can see
it!
But I noticed something when I had the vent closed off all day.
Some afternoons I'd just start dragging. You know, like staring off into space not being
able to do much?
Okay, it never got quite that bad! But it was bad enough I could see a pattern. Every
afternoon I would get really sluggish, and I'd only feel better after going upstairs
a while. I came to realize how much indoor air quality
impacts my ability to think.
Specifically, high Carbon Dioxide levels can lead to fatigue and lower cognitive performance,
or even sick-building syndrome!
In a 2014 report, the EPA quantified CO2 levels that lead to sick-building syndrome, and there's
evidence that ventilation to help reduce CO2 and other contaminants in the air can also
reduce the spread of COVID-19 indoors.
So, it'd be good to better control my air quality. But it's hard to know if I'm doing
it right if I can't quantify the problem!
So initially I bought this TemTop air quality monitor. It monitors CO2 levels and even has
a battery so I can move it around my house easily.
I put it in my office for a few days, and found that if I was in the office long enough,
the CO2 levels would quickly go past the 'alarm' level and sometimes reach beyond 3000 parts
per million, unless I kept my vent open.
So I knew keeping the vent open is important, but I'm lazy. And I often forget to pop off
the magnetic cover after recording.
And the Temtop would work okay, but I'd rather have an unobtrusive device in my office measuring
the air quality and sending it to the Raspberry Pi I already use for monitoring other things,
using Prometheus and Grafana.
I initially looked into something like AirThings, but was turned off by the price; paying more
than 200 bucks for an Internet-connected monitor that I could only minimally control was a
no-go.
Then a few months ago, I spotted a Hacker News post about the AirGradient DIY monitor.
AirGradient's founder offered to send free PCBs to anyone who wanted to build the sensor,
so I took him up on the offer.
I got two PCBs, so I could build two sensors: one for my office down here in the basement,
and one to put centrally upstairs, so I could monitor the air in the main living space.
This one's been running in my office for a couple months, and it logs its data to a Raspberry
Pi in my rack, so I can view the data on a Grafana dashboard.
I'll put together the second board now so you can see how to do it. I'll also show you
how I customized the firmware so it reports its data to my Raspberry Pi.
First, I'll walk you through the parts that make up the sensor package.
The most important part for me was this SenseAir S8, which is a fairly accurate CO2 sensor.
It's also the most expensive part, coming in around $30.
Right behind that is the comparatively massive PM2.5 particulate matter sensor from Plantower.
It cost around $20, and comes with a little breakout wire.
Then there's a SHT30 temperature and humidity sensor. It's only a few bucks.
And then to integrate everything together and provide both a simple display and the
ability to transmit the sensor data over WiFi, there's a Wemos D1 Mini, which has an ESP8266
on it, and a Wemos OLED display shield, that goes right on top of the D1 Mini. Those guys
are both a couple bucks a piece.
All these components fit together nicely on the AirGradient PCB, with it's helpful silkscreen.
Now, I bought everything from AliExpress. And as a US resident, I was prepared for the
wait—it took some of the parts over a month to make it to my house. Shipping is weird,
especially how cheap it is, but I won't get into that geopolitical discussion. I had bought
a SenseAir S8 from a US supplier last year, and it cost over $60... but it came within
two days.
Anyways, we'll move on to the assembly next.
Before you ask, for the assembly I used a circuit board holder, helping hands, a small
breadboard, a small adjustable wire stripper, a flush cutter, and a Weller WES-51 soldering
station.
But you could get by with any old soldering iron, and you technically don't need everything
I used—I just use them because I'm really clumsy soldering, stripping, and snipping
without them! If you want to see the exact tools I used, there are links for all of em'
in the description.
AirGradient's website has a pretty good guide, but I can give a little more detail here,
since there are a couple tricky parts.
First, I soldered headers onto the OLED. You stick the headers in a breadboard, and set
the OLED on top, and put a little solder on each leg.
Next, I plugged the OLED into the tall headers it came with, and then soldered the WeMos
D1 directly onto those headers' long legs.
Finally, leaving a little bit of a gap between the D1 and the board, just using friction
to hold it in place, I soldered the OLED and D1 package onto the PCB where it's indicated.
Now that the brains of the board are done, I snipped a header to size and soldered the
header to the SHT30 temperature and humidity sensor. I used the breadboard to keep it steady.
I put the sensor in the right place on the PCB and soldered it in, using a piece of tape
to hold it in place while the board was upside-down.
Next I soldered headers to both sides of the SenseAir S8 CO2 sensor, making sure the pins
were going down, so when I plugged the sensor into the PCB, all the pins aligned correctly.
Then I put the sensor on the PCB, and again left a little room underneath. This sensor
is positioned with air flowing underneath it, so make sure you leave a little gap!
For the Plantower PM2.5 sensor, the installation is a bit finicky. I had to first cut the wire
it came with in half, then strip the ends of four of the wires using this guide on AirGradient's
site.
I ended up using my adjustable wrench stripper for this, because it can be a lot more precise
than my normal wire strippers. The wires in this cable are tiny and stranded, and that
makes them fragile and prone to pulling out if you use the wrong wire stripper.
I stuck the wires into the PCB where following AirGraident's instructions, and soldered them
in place. It helps to put a piece of tape across the tiny wires on the top side, otherwise
they might pull out.
Finally, I plugged the other end of the cable into the PM2.5 sensor, put some double-sided
tape on it, and stuck it on the board.
For the longer term, I might consider using some more permanent adhesive. There are screw
holes too, but I didn't have any tiny screws small enough for them.
The final work on the PCB was snipping any of the long leads with my flush cutter, then
cleaning off a little extra flux from the solder with alcohol.
All right, so we have this nice looking little board assembled, but it's not ideal for mounting
anywhere. Ideally, you'd want it vertical, in an area with some amount of air circulation,
so setting it flat on a desk isn't that useful.
Luckily, AirGradient also has a simple 3D printable case design, along with a wall mount
bracket.
I grabbed the STL files from their website, and printed both of them on my Ender 3; first
the wall bracket, and then the two halves of the case.
Once that was done, I slid the PCB in one half, and popped the other half on. It's a
friction fit, and it's not necessarily the best fit in the world, but it works great
after you put it in the wall mount holder, which kind of ties the whole package together.
There's just one last thing to do.
Nice.
At this point, we have a glorified sensor package, but when I plug it in... nothing
happens. That's because the WeMos D1 needs to be flashed with software to make it work.
The easiest way to flash the D1 is using Arduino IDE. I installed it using Homebrew on my Mac,
using the command you see here, but follow the official guide for whatever OS you use.
Next I had to tell the IDE to work with the D1.
Inside the IDE, I opened Preferences, added the ESP8266 to "Additional Boards Manager
URL", then opened the "Boards Manager..." setting and installed the latest version of
the board.
Finally I had to go to the ESP8266 menu and choose the right board version, in this case,
the WeMos D1 Mini, like you see on the screen.
If you want, you can upload a 'Blink' sketch and watch the little LED on the D1 blink to
make sure things are working.
But in my case, I wanted to upload the AirGradient sketch so I could start seeing the air quality
readings. The sketch from AirGradient requires two additional
libraries, the WifiManager by tablatronix, and the ESP8266 OLED driver by ThingPulse.
And at this point if you're feverishly taking notes, please know that I have all these steps,
in detail, in a blog post linked below. So go check that out when you're building your
own board!
Now it's time to install AirGradient's sketch. The easiest way is to go to the 'Manage Libraries'
menu, and search for "AirGradient". Install the latest version, and then choose this option
from the Examples menu.
It'll open up a sketch that makes all the sensors work, but at this point there are
a couple choices you can make:
You can choose whether or not you want WiFi enabled. If you just want to see what the
levels are on the built-in OLED, you can do that! Just set the Connect WiFi boolean to
false.
But in my case, I wanted it to send data to my Raspberry Pi, so I set it true.
Then, the APIROOT string is what the board will send the data to. The default sends sensor
data up to AirGradient's servers, but since I wanted to send the data to my Pi, I set
it to the Pi's address, and port 9926. I'll show how the Pi receives that data soon.
I've actually been tweaking the config a little on my board, and I'll be tracking those changes
in the GitHub repository I mention later.
Once everything's set how you like it, click the Upload button (that little right arrow
icon) to compile and upload the sketch to the D1.
After a minute or so, the OLED display should read "Init", and after a short delay it will
start printing the PM2.5, CO2, and Temperature and Humidity on the screen.
That is, unless you configured it to connect to WiFi. If you do that, it'll read 'Connect
to WiFi' until you connect to it from another computer. You have to connect to it's ad-hoc
network and set up your WiFi credentials so it can connect to your home WiFi network and
start sending data.
Once you do that, it takes a little time, but it should connect to WiFi and start posting
data to the APIROOT you set.
AirGradient offers a cloud-based dashboard for your sensor if you use the default address,
but like I said, I want my sensor data to stay on my local network, so I put in my Pi's
URL and used port 9926.
To make it so the Pi could actually receive the data on port 9926, I built a Docker container
image that I can run on the Pi on that port, using PHP. And that same image also exposes
a metrics endpoint so Prometheus can grab the data and store it in its database.
I released all this code like I do with all my projects. There's an open source AirGradient
Prometheus Exporter project up on GitHub, and it also has my sketch customizations in
it.
I also integrated those settings as an optional add-on in my Internet Pi project, so enabling
it is as easy as changing one setting in that project to 'true'.
I won't go into the details of the exporter or the Internet Pi project, but everything's
explained in detail in those project's README files, if you wanna run it on your own.
Now that I have the AirGradient DIY sensor pointed at the Docker container, and Prometheus
is logging the data from it, I can build these nice dashboards to monitor air quality over
time, and also set up alerts in Grafana so I can be notified when things like CO2 levels
are too high.
The data came in handy recently, when I had a window company come and replace my basement
windows. I noticed an odd odor in the basement even a couple hours after they were done.
And sure enough, the PM2.5 graph went the highest it's ever gone on my basement sensor.
I opened a window and put in a fan, and the level went down pretty quickly over the next
couple hours. If I didn't do that, the particulate matter would've slowly dispersed in my house.
I didn't like the idea of me and my family just breathing in all the rusty dust and chemicals
for the next week!
After using it a couple months now, the data coming from the sensors seems pretty reliable,
though I haven't done any lab-grade testing. The CO2 sensor needs a week or two before
it can self-calibrate to give more accurate data.
Even then, all these sensors have a little margin of error, and you might even run into
issues like the temperature sensor giving high readings because of it's location in
the case.
And regarding any absolute recommendations, or things like adding HEPA filtration—I
still don't do that, and I still haven't seen any hard evidence to point to any particular
thresholds for indoor air. Just that you should make sure you exchange outside air regularly.
The main thing I was looking for in this project was when CO2 levels were high, because I can
strongly correlate that to my brain's performance.
For a future upgrade to my air monitoring, I'd also like to add at least radon monitoring.
I already have this other monitor in my basement, and we have a radon fan that helps make sure
levels don't get dangerously high, but it would be nice to have that data logged too.
And heck, while I'm at it, a geiger counter would be neat. I'd be able to see when Red
Shirt Jeff's experiments get a little too wild.
But all in good time.
Until then, I'm Jeff Geerling!