AirSense: a DIY, cheap, air quality sensor

This post summarises the results of an experience that has been going on for more than a couple of years now.

When I moved to Oxford, the committee of the residential area I live in sent an email expressing some concerns about the consequences of a local developments on air quality. As a good neighbour, and maker, I proposed them to build an air quality sensor to monitor the situation.

I was aware of several initiatives of DIY air quality sensors, like the famous Air quality egg, so I thought that I could try to emulate one of them.

I didn’t know at that time where I was getting myself into. It turns out that building a device is quite simple, but validating it is completely another story.

Let’s try to explain it in a simple way.


Mine is surely not the first attempt to build a DIY air quality sensor. There are some good guides online, I have particularly appreciated these sources:

In order to understand the legislative framework in Europe, I suggest to have a look at this very nice HandBook about EU air quality legislation.

Finally, the local authorities of Oxfordshire publish a very handy chart with historic measurements of air quality: see the Oxfordshire air quality reference website.


Air quality is an umbrella word that identifies a whole bunch of pollutants. To be in line with the EU legislation, I have decided to measure the following quantities:

  • Temperature and humidity
  • Noise level
  • Concentration of particulates
  • Concentration of nitrogen dioxide

the sensor should be able to save data on a SD card, it should be operated on batteries or line power and should be placed outdoor.


to simplify its development, I have decided to use Seedstudio’s GROVE system, which allows plugging sensors to an Arduino board without any soldering. these are the components I have used:

The total price was about 115€.

If you want to replicate this experiment, check the current offer of Grove-compatible sensors on Seedstudio, because the offer for air quality is growing constantly!

While all Grove-compatible devices didn’t need soldering, the MICS 2714 board was a bit trickier. The component is sold for very little, but it’s hard to solder by an amateur. So I have bought a board with pins that makes the job easier (but costs 5 times the original price).

Be aware that Mics has released some new components that measure other gases too like the Mics 4514 or the Mics 6814 and there are reference boards or products for Arduino too.

Advanced materials (and why they are needed)

Making the long story short: this experiment has allowed me to involve other parties including the Oxford City Council, the Network for clean air UK and some people from Ricardo, the official provider of air quality monitoring for Oxford.

Thanks to their help and sponsorship, I was able to also integrate two more advanced sensors:

Both are chemical sensors for nitrogen dioxide with electronic analog front-ends (the circuitry needed to interface them with a micro-controller). These are more expensive devices (200 to 300 € when including the interfacing electronics), but are based on a much more solid technology than the Mics 2714. The Mics sensor is a metal-oxide sensor. It is simpler to produce but it is less accurate and, most problematically, it is more sensitive to interference (e.g. humidity) and tends to drift over time. The other 2 sensors are chemical sensors and should be more accurate and more stable over time.

So I have decided to combine all these modules together in one device and plugged all of them to an Arduino.

Building the device

Building the device was very simple. All sensors are plug-and-play except the Mics 2714 that required a bit of soldering. I used the reference design provided with the datasheet and this is how it appears:


Mics 2714 interfacing board

This was connected to ground, 5V and one of the analog pins of Arduino.

The SD card reader wasn’t Grove-compatible either, but examples of how to connect it are easy to find.

At the end this is how the device looks like if we don’t include the “advanced” sensors.


Sensors connected to the Grove shield

To this, I added an LED that to give some feedback if everything is working OK and a little computer fan, to suck air in from outside and to keep temperature under control.

The advanced sensors were also easy to install. They are both powered with the 5V output of Arduino and their measurement pins (1 for the SPEC sensor and 2 for the Alphasense sensor) where connected to 3 analog pins of the Arduino.

For what regards the casing, I used a plastic food box. The box is sealed and doesn’t allow rain to come in (good for placing it outdoor). I made two openings on the box so that air could be exchanged with the outside and to avoid overheating. In order to lay all the components I took a piece of cardboard and made holes in it, then I tied the components to the cardboard using some metal wire. The Arduino board was placed inside a plastic cup so that if the box gets some water in it, the electronics is protected anyway.

The sketch used on the Arduino was also really straight-forward. After start-up, the used ADC pins are sampled, the dust ratio is computed for 30 seconds (see reference code), the temperature and humidity are taken from the DHT sensor (see reference code) and all the values are logged in a file on the SD card together with the timestamp (see millis). Then the board waits for other 30 seconds, so that, in total, a sample of each quantity is taken every minute.

Characterisation and calibration

Now we need to convert the raw data, as measured by the ADC of the Arduino, into actual quantities (concentrations, decibels etc.), and this is where the things get very complicated.

All manufacturers of the sensors provide a datasheet with some graphs you can use to do this conversion, but unfortunately, these are not always to be trusted 100% because of differences in the produced components or because of drifts. For this reason I have decided to perform a characterisation campaign myself.

Sound characterisation

The idea here is to convert the raw samples read by the microphone into decibels. As a reference, I have bought an inexpensive, second-hand decibel monitor (about 15 € on eBay). Then, at home, I connected my laptop to my stereo and put on some white noise generator as this one. On Arduino, I measure the maximum and minimum values of the input from the microphone (the amplitude) for a period of few seconds.

The procedure is simple: I start the noise on the laptop, I start the Arduino sketch and I print the amplitude on the screen while I note down the reference decibel on the external device. I repeat this operation several times at different volumes and I note down the numbers on Excel.

Here’s the result:


Relationship between the amplitude (difference between maximum and minimum) and the reference sound intensity.

You can see that there is clearly a relationship between the amplitude and the decibels and, not surprisingly, it’s logaritmic.

NO2 characterisation: 1st attempt

The idea here is to locate my sensor next to a reference one (so that they “sniff” the same air) and to compare what is measured against the reference. To have enough points, I decided to take a measurement of at least 24 hours and in a place with enough traffic so that the range of concentrations is as wide as possible.

The first characterisation campaign was launched in September 2015. I contacted the Oxford City Council Air Quality officer, who, very kindly, let me locate my sensor on top of the official one in a busy street in the centre of the city. My sensor was few centimetres apart from the inlet of the official monitor, so it should have measured the same air!


Airsense placed next to the official City Council’s monitor inlet.

The problem I encountered was energy supply. My device was by far not optimised and there was no plug on top of the cabinet containing the official monitor. I tried different combinations of battery supplies (even with 10 9V batteries in parallel!) and, eventually, I found a cheap 5000 mAh battery bank that would let run my device for 35 hours.


Useless set of 10 9V batteries in parallel.

I left my sensor gathering data for about a day and then I downloaded the official monitor’s data from the official website. The monitor provides hourly averages, so I had, in total, about 24 samples only. Here is how the Mics 2714 data looks like compared with the NO2 reference:


NO2 official measurements (1 hour average) versus raw data of the Mics 2714 sensor (1 hour averages)

There’s no clear trend or relationship between the signals. Definitely, the number of samples is too small and we need to do something more clever.

NO2 characterisation: 2nd attempt

A year passed, and I managed to liaise with both a new City Council officer and a person who could help me getting raw data from the official monitors. Together we set-up a new data collection campaign. This time the monitor would provide minute-by-minute samples and we found a way to bring an electricity cable from inside the cabinet to the top (so no power limitations any more!). Then we left the devices collecting data for about a week.

This is how raw data appear (warning: big and messy graph! select the plots on the right of the chart).

The reference signals are NO, NO2 and NOX. All the others are raw data as measured by the Arduino ADC (except temperature, humidity and dust).

Worth mentioning, is that signals are not aligned in time (some start or end earlier and there is no sample-by-sample alignment) and they are quite noisy too. So we need to a) align them and b) try to reduce the noise a bit.

We can also already notice that some signals present some similar trends (the Mics signal notably) and other seem to be completely unrelated (the SPEC signal for example). So I have computed the correlation among all these inputs and outputs. These are the results:

Signal NO2 NOx NO
Mics 0.44 0.46 0.43
SPEC -0.01 -0.00 -0.01
Alpha1 0.15 0.15 0.11
Alpha2 -0.02 0.01 0.09
Alpha (1-2) 0.17 0.19 0.19
MQ2 0.09 0.09 0.08
Dust 0.05 0.04 0.04
Temp -0.03 -0.03 -0.02
Hum -0.00 0.04 0.06

You can see that the Mics signal is the only one that has a decent correlation.

Note: it is important to note down the exact time when the experiment starts as measured by both your device and the official monitor, otherwise then it’s impossible to align them!

In order to do sample-by-sample comparisons, I have created a little program in JavaScript (running on nodeJS) that aligns the samples and interpolates them when the timestamps do not match. In total, I had 8154 aligned samples per signal.

Then I have:
  1. Taken the 30 minutes averages of the signal to remove (some) noise. This brings down the number of samples to 273 per signal.
  2. Regressed different combinations of signals with different combinations of their powers (up to the 3rd) against the reference NO2 (I used this simple regression library).
  3. Compared the regressed signal with reference (all of it, thus no training-test distinction, with obvious possibility of overfitting). As metrics I have computed the average, median and maximum absolute error and the correlation between the regressed signal and the reference
These are the main findings:
  • The cheap metal-oxide Mics 2714 sensor, after regression, obtains an average absolute error of 3.82 ppb and correlates with the reference signal 0.7.
  • If we add temperature and humidity to the model, the error remains about the same (3.62 ppb), but the correlation goes up to 0.75 (maybe because effects from humidity are partially compensated?).
  • The Alphasense signal, taken at pin 1 alone, has an average error of 4.62 ppb and correlates 0.55 with the reference.
  • If we add humidity and temperature to the Alphasense signal, error becomes 3.81 ppb and correlation 0.69.
  • If we regress Mics, Alphasense, humidity and temperature all together we get a very interesting 2.76 ppb error and 0.87 (!!!) correlation.
The rest of the sensors (dust, SPEC, MQ2) didn’t add anything interesting.
This is how the best regressed signal (Alphasense + Mics + humidity + temperature up to the 3d power) looks like against the reference. Not too bad, but we are of course risking over-fitting here.

Best regressed signal vs reference (click to see interactive graph)

I have also tried with other de-noising methods, like a moving average, or averages over shorter and longer periods of time. The results change slightly, but not substantially.


In conclusion:
  • Building a DIY air quality sensor is relatively easy and inexpensive, but needs to be calibrated or it will provide measurements that are not meaningful.
  • The cheap, metal-oxide Mics 2714 sensor seems to be promising, but it is affected by interference (likely humidity or maybe other gases too).
  • The Alphasense device performed worse than expected, but combined with the metal-oxide sensor creates a very good estimator.
  • The SPEC sensor, as used here, provides only noise.

Future work

I would need to perform another data collection campaign. The aim would be to confirm these findings and to check that the Mics sensor doesn’t drift over time.
Also, I want to use a 24 bits ADC with the Alphasense and the SPEC sensor next time. Especially with the Alphasense, you see that the range of values is small and it’s possible that some information is lost in the quantisation noise.
I also want to try this adapted MICS sensor sold by Seedstudio. It is based on the MiCS-6814, and, by looking at the datasheet, it seems that it embeds the same NO2 sensor used in the 2714, plus it adds 2 others. It would be cheaper than my approach and would be super simple to install.
Ah, and I would still have to validate the dust sensor too.
Future-future work:
Probably more advanced machine learning techniques would lead to even better results. There might be information hidden in non linear transformations, or derivatives of these signals, who knows?
But the more ML approach we take the more we would need to corroborate the results.
I will keep you updated with more experiments and results on this blog !

One comment

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s