Site Loader

Several years ago I took a Raspberry Pi 2 B+ and turned it into SLRPi – the SETI listener for Raspberry Pi. It was a custom build of Debian Jessie and a custom build of BOINC for the SETI project. You can read more about that effort here.

Earlier this year it was announced that this phase of the project was ending. After 20 years of collecting data it was time for them to do some data mining and look for interesting phenomenon. With a heavy heart (because I joined that project 20 years ago!) I decided to repurpose the Pi, but wasn’t sure what exactly to do with it. 2020 has without a doubt been a unique year, bringing with it a whole host of apocalyptic things like murder hornets, incessant hurricanes, raging wildfires, and who could forget COVID-19? Needless to say, it makes life as an asthmatic more challenging, and monitoring air quality has become crucial. The last thing folks like us need is a trip to the ER for lung related problems, when there’s a lung-eating virus out there! I purchased an indoor AQI monitor which has more than paid for itself so far. This combined with our Honeywell air cleaners keep the air inside of our home very clean. However, I do like going outside, and it’s nice to know if I should wear a normal mask, an N-95 respirator, or should I just stay indoors, take Robitussin and a breathing treatment and try again tomorrow?

This sparked my next project – OAQ. The Oszakiewski Air Quality sensor. Using the same Raspberry Pi 2 B+ with a new SD card running Raspberry OS I built a Python 3 script based on this article that connects to my other project – the Weather Station Widget for Android, which reports out real time weather data from my Ambient Weather sensor array out back as a widget on my Android phone. Currently I’m reading AQI data from an EPA station roughly 5 miles away. Not too bad, unless there’s a dust storm there but not by me. Or a fire there but not by me. I’m interested if I can open my windows, go for a walk, sit on the patio, etc. What’s my air quality like?

Raspberry Pi and Sensor

I started out installing the OS the traditional way, configuring WiFi, running updates, etc. The Pi already had a WiFi dongle from the SLRPi project which made this easier. Next I installed PySerial using the following terminal command:

pip3 install pyserial

This will install the Python 3 version of the serial libraries which are needed to talk to the USB ports. The SDS011 PM sensor I purchased separately plugs into the USB port, providing an easy interface to read from. This sensor will read PM2.5 and PM10 air quality levels. A separate sensor is required for Ozone (O3). I’ll work on that one later.

Once the serial libraries were installed I created a new python project and added the following code:

import serial, time, requests
from datetime import datetime
ser = serial.Serial('/dev/ttyUSB0')
headers = {'Content-Type' : 'application/json'}
while True:
    data = []
    for index in range(0,10):
        datum = ser.Read()
        data.append(datum)

    pmtwofive = int.from_bytes(b''.join(data[2:4]), byteorder='little') / 10
    pmten = int.from_bytes(b''.join(data[4:6]), byteorder='little') / 10
    body = {'pm25':pmtwofive,'pm10':pmten}
    response = requests.post(url='API_URL', headers=headers, json=body)
    print('PM2.5: ' + pmtwofive + ' PM10: ' + pmten)
    print(response.status_code)
    time.sleep(300)

The code first imports all necessary libraries, then establishes a connection to the USB port using a serial connection. Once connected it reads from that port as long as there’s something coming from it. The SDS011 sensor reads and reports in bytes of 10, which is why we’re reading each message from the port as a range(0,10). Once we have that chunk of data, we append it to the array we established initially (data = []). Now that we have the results as an array we need to parse it and convert the parsed pieces into integers. Array positions 2-4 is the PM2.5 value, and positions 4-6 is the PM10 value. By grabbing that, converting to an integer and dividing by 10 (again, because everything coming from the sensor is by tens), you end up with the real time sensor reading. Repeat for each for the other sensor value and you’ve got the readings!

I also ensured this loads every time the Pi restarts in case of power outages, moving the device around, etc.

API

The next step was to save it somewhere. Since I ultimately wanted to display this in my Android Weather Widget, I created a SQL table in my Azure SQL database to store the values in. Now I needed an API to push the data to. I built a .Net Core 3.1 Web API and pushed it to my Azure instance to handle these calls, and also for the weather widget to pull the data from. The API only has two endpoints: POST and GET. The POST accepts strongly-typed JSON data from the Pi and adds it to the database. The GET returns the most recent values from the database. Nice and simple!

Installation and Weatherproofing

Since this is an outdoor sensor, I wanted to make sure it can survive the weather. In Arizona it gets HOT, but it also rains on occasion and can get down to freezing at night in the winter. I already had a case for the Pi, but needed something for the SDS011 PM sensor. I found an unused Tupperware-style container with a locking lid that perfectly fit both devices side by side. I cut a hole in the front for the PM sensor laser, and another for the power cord for the Pi. You can see the result here:

Top view of Raspberry Pi and sensor
Top view of Pi and sensor. Sensor is plugged into the Pi via the USB port.
Front view of Raspberry Pi and sensor
Front view of closed case. PM sensor laser is in the bottom right.

Not elegant, but functional! Should allow enough air flow to keep the interior from overheating (low voltage anyway, shouldn’t have a problem with overheating) while allowing adequate air across the sensor.

Next Steps

Next I’ll purchase an Ozone (O3) sensor and attach that as well. Probably in a month or two. I’ll post here when that’s added with what was required and how it went.

Have you done something like this and have advice? See something that could have been done better? Interested in doing something similar? Let me know!

Update: I published a page on our family’s Health Metrics Management site where you can view the current sensor output, updated every 5 min.

Eric Oszakiewski

Eric Oszakiewski is a professional software developer based in Scottsdale, AZ with over 38 years of software development experience, and 13 years SharePoint experience. He is currently working as a .Net/SharePoint Platform Engineer for General Motors.

Leave a Reply