Arduino-controlled Particulate Air Sensor

by imageguy in Circuits > Sensors

3659 Views, 24 Favorites, 0 Comments

Arduino-controlled Particulate Air Sensor

2021-09-21_09-19-21.jpg
2021-09-21_09-19-31.jpg
2021-09-21_09-19-36.jpg

Summer wildfire smoke has been a summer problem for a while where I live in the western United States, and has been particularly bad this year. The daily question was "How bad is the air outside?" Or inside, for that matter. There are several sources for air quality data, but there are no sensors close to where I live to tell me the local conditions. Last year, I tried to guess based on visible haze, but this proved to be woefully inadequate.

This Instructable describes the device I made to measure my local particulate matter pollution. It's handheld and battery powered, so I can monitor either outside air, or the air inside the house. The device is also handy to take along if I'm traveling.

The device shows selected measurements on a 1.8" color display and will report the full set via serial port.

Supplies

You will need the following components:

Plantower PMS1003 particulate sensor (https://www.amazon.com/dp/B08DP2HBPN) (see Step 1)

Adafruit 1.8" Color TFT LCD Display with MicroSD Card Breakout - ST7735R (https://www.adafruit.com/product/358) The same display can be purchased without being mounted on a PCB - half the price, but you have to do some fine soldering.

Arduino Nano

60x40mm perfboard

Various male headers for the PCB

1 female 1x6 cable connector

2 female 1x10 cable connector

1 SPST switch, such as https://www.amazon.com/dp/B07B9RPLZD

9V battery

9V battery connector

A short piece of CAT5 cable, or 8 short thin wires to connect the display to the PCB.

2 60mm M3 screws

3 10mm M3 screws

2 M3 nuts

Tools:

Basic tools for electronics, such as soldering iron, wire stripers, crimper etc.

3D printer to make the housing (optional, you can design and make your housing in some other way)

Drill and a 7/64" or similar (3.75-3mm) drill bit.

Computer with Arduino IDE installed.

Measuring Air Quality

In general, "air quality" is designed to measure city pollution, so tracks particulates (2.5µm or less and 10µm or less), CO, ozone, nitrogen oxide and sulfur dioxide. For wildfire smoke pollution, we're interested in particulates, primarily 2.5µm or less particle size.

Particle concentrations are reported in µg per cubic meter. There are six categories of air quality, denoted by AQI (air quality index), based on the concentrations:

  • 0 - 50 - good : 0 - 12 µg/m^3
  • 51 - 100 - acceptable : 13 - 35 µg/m^3
  • 101 - 150 - unhealthy for sensitive groups : 36 - 55 µg/m^3
  • 151 - 200 - unhealthy : 56 - 140 µg/m^3
  • 201 - 300 - very unhealthy : 141 - 210 µg/m^3
  • 300+ - hazardous : 211+ µg/m^3

See the AirNow website for details. The regions are really delimited by measurements that are real numbers, but the sensor reports integers, so the above table rounds up or down, as required.

There are several sources for air quality data. Weather reports include air quality indicators, though these tend to lag, while smoke can arrive or leave quickly.

https://www.iqair.com/us/air-quality-map and https://map.purpleair.com/1/mAQI/a10/p604800/cC0#6.4/44.083/-120.116 show real time or frequently updated particulate matter data.

Plantower (a Chinese company) makes a widely used particulate sensor. The air is sucked in by a small fan and passed through a laser-illuminated cavity. It counts the particles illuminated by the laser. PMS1003 is the first generation sensor (10 in the model number) and can detect particles between 0.3µm and 2.5µm. It also reports data for 5µm and 10µm particle sizes, but those are estimated from the smaller particle measurements.

Adafruit sells Plantower PMS5003 sensor, the fifth generation of the Plantower particulate sensor. The box, fan and airflow have been changed, but the electronics and the interface remain the same. PMS5003 can be used instead of PMS1003, but the housing would have to be modified to accommodate the different form factor and location of the opening

A precise particulate sensor that is used in real weather stations runs to many thousands of dollars, while the device in this Instructable can be built for a $60 or so. For those who would buy rather than make, PurpleAir makes three particulate sensors with prices between $199 and $279. Two bigger models need permanent mounts and use twin PMS5003 sensors. The smallest model, designed for indoor use, uses a single PMS1003 sensor. PurpleAir sensors report their measurements via WiFi to PurpleAir online system, so their measurements are widely available online (see link above).

The sensor reports particle counts per 0.1L of air for particle sizes >0.3µm, >0.5µm, >1µm, >2.5µm, >5µm and >10µm (last two are estimated) and uses these counts to compute concentrations of 1µm, 2.5µm and 10µm size particles in µg/m^3. Two sets of concentrations are reported: CF=1 (standard particle) and ambient (under atmospheric environment).

A note in the manual says CF=1 should be used in the factory environment and "CF" apparently refers to "factory calibration". I used "under atmospheric environment" values and have seen other people do the same. See https://forums.adafruit.com/viewtopic.php?f=48&t=136528&p=767725#p767725 for an excellent writeup.

Plantower sensors are quite accurate. EPA did a study on the sensor and developed a correction formula (see attached PDF). I don't use it in my code, since they used CF=1 values. They found that Plantower returns higher values for a number of concentrations. However, CF=1 values in that range of concentrations are higher than the ambient values, so what we used is more accurate than uncorrected values analyzed by the EPA.

The values I get from my sensor are in decent agreement with the the values reported from surrounding official sensors.

When the sensor is turned on, the first few values reported will be much higher, until any accumulated dust is cleared out. It should settle down within 30 seconds or less.

Circuit Design

air_sensor_breadboard.png
air_sensor_schematic.png
air_sensor_pcb.png
2021-09-06_14-37-14.jpg
2021-09-07_13-15-20.jpg
2021-09-07_13-15-46.jpg

The circuit is simple enough that you don't really need a PCB - all the parts could be wired together directly. I chose to use a perfboard to provide a solid base for the Nano. The housing exposes Nano USB connector and this needs to be reasonably fixed so a cable can be inserted easily.

I used 40x60mm perfboard. I wanted for the USB to stick out a little, so I mounted the Nano across the shorter dimension. That meant that the perfboard was too narrow for the battery connection (VIN and GND pins). I cut out a piece of perfboard below these pins and just connected them to the battery and switch directly.

Since I can't upload a Fritzing part into Instructables, here's the part I used, found in my GitHub repository. It's just a 1x6 header with PMS1003 pins labeled.

https://github.com/imageguy/Fritzing_parts/blob/main/PMS1003.fzpz

PMS1003 comes with a ribbon cable. Rather than deal with the small connector, I cut it off and substituted a 1x6 female connector. Note that PMS1003 has 8 pins, but the pins 7 and 8 are not used.

The display has 10 pins, but only 8 are used. I made as short connector using a CAT5 cable. This was fine while I was prototyping the circuit, but I cut the casing off for the final assembly. The housing is tight, and the wires have to be flexible and very carefully folded to make everything fit.

I used the 9V battery connector I had in my stash and a DPDT switch that was left over from an old project. You only need a SPST switch, as long as it's the same size as the one listed under "Supplies" (I think the sizes are pretty standard, since these are the same size as the old switch I used). 9V + is connected to switch and the switch is connected to VIN on the Nano. 9V- is connected directly to GND on the Nano.

PMS1003 needs 5V for the fan, while the display needs 5V for both display and backlight. Nano 5V pin provides enough power for both. 3.3V pins that PMS1003 need to have set to HIGH are driven from the Nano 3.3V pin.

Downloads

Arduino

2021-09-12_13-21-02.jpg

The program displays ambient concentrations of PM1, PM2.5 and PM10 on the display. The background changes with the air quality as follows:

  1. good - white
  2. acceptable - yellow
  3. unhealthy for sensitive groups - orange
  4. unhealthy - red
  5. very unhealthy - magenta
  6. hazardous - black

The text is blue for white, yellow and orange backgrounds, white otherwise. These three particulate values are basically as much as can be fit on the screen to be legible at a glance. If the serial line is connected, the full measurements (CF=1 and ambient concentrations and particle counts) are reported.

The display color model is 18 bit RGB, but the interface libraries from Adafruit use uint16_t to specify the colors. Red and blue are given using 5 bits, while G uses 6 bits. The uint16_t value, expressed in bits is RRRR RGGG GGGB BBBB.

There is some logic in the sketch to parse the record incoming from the sensor. It should always be 32 bytes, but sometimes it's corrupted. My early prototype used ESP8266 ESP01 instead of Nano and the sensor was attached via hardware serial. It seemed to have no problems. On Nano, we use Software Serial and the records are sometimes corrupted. Additional logic takes care of that problem.

PMS1003 reports data in big endian format, so we have to switch to local byte order.

The sensor reports more often as the concentrations increase. The sketch reports and refreshes the display every 3 seconds.

Downloads

Housing

2021-09-17_12-37-03.jpg

The housing was designed in OpenSCAD. I'm attaching the source file. Feel free to make any changes you see fit. I've added ".txt" to the filename, since .scad files can't be uploaded into an instructable.

The source file has a "do_build" variable. If set to 1, it builds whatever is selected on the bottom for printing. Otherwise, it shows the whole device, including somewhat imprecise mockups of all the contents.

You don't need the source, unless you want to make changes. STL files are attached if you want to print the housing as designed.

I used PLA to make the housing, but almost any hard filament will do.

Note that the housing is not watertight.


Assembly

2021-09-17_12-29-08.jpg
2021-09-17_12-28-39.jpg
2021-09-17_12-18-05.jpg

Make sure the long M3 screws reach the nut openings in the top part of the housing, but are not too long.

Solder wires to the switch. One goes to the battery 9V+ and the other to Nano VIN pin. Another wire goes from the battery 9V- to the Nano GND pin. Make sure the wires are long enough. Use connectors to attach the wires leading switch, don't solder them to the battery or Nano or PCB.

Put the PMS1003 into the main compartment. Take the PCB shim and glue it to the bottom of the PCB base. The idea is that the PCB will be horizontal and in such a position that the Nano USB port is aligned with the hole. Once the glue is dry, put the PCB base in and the PCB, with the Nano in place on it. After aligning it so the USB is in the right place, drill two holes through the holes in the PCB base into the housing lower half. I used 7/64" drill bit, something like 3mm or a bit smaller can also be used.

While you have the glue open, dab a bit onto each of the M3 nuts and place them into the openings in the top part of the housing. Make sure the nuts are well aligned with the screw holes. Glue is just to hold the nuts there so they don't fall out during assembly.

Mark the position of the PCB on the PCB base and use the same bit to drill through both. A short M3 screw is used to attach the two pieces, positioned upside down. There is no need for a nut.

Push the switch through its opening and attach one wire to the battery and the the other to the Nano. Place the battery into the smaller compartment. Make sure that the ribbon cable goes across the PMS1003 and comes out on the other side of the PCB.

Put the PCB on its base in place and screw in the two remaining short M3 screws. Plug in the PMS1003 ribbon cable into the PCB.

Attach the connector to the display and position the display into its opening. Push the strut in so it holds the display in place. If the strut is too long (i.e., the housing bulges), trim it a little. Attach the display cable to the PCB header.

Make sure the various wires are routed properly (it's a tight fit) and close the housing. Thread the two M3 screws in from below and screw them in.

I found it helpful to turn the device on during this final step, so I can make sure no connection is broken while the housing is being closed.

There, you're done! I hope you didn't have too much trouble building this device and that you'll find it useful.