This is the first of two logs about the software needed for the SniffingTrinket project. Because I guess that a general Arduino library for the MQ135 might be of use for other projects, I decided to split the software in a dedicated library and a sketch specifically for the SniffingTrinket. So, this is solely about the MQ135 lib, which, btw. you can find in my GitHub.
First, some theory: My interest in those cheap gas sensors was sparked by a video from Ben Krasnow who takes a look at a cheap breathalyzer with a very similar sensor. He links a paper in his blog post that goes into the theory of the operation of these sensors. In short, they consist of a heated piece of tin dioxide (doped with other stuff) that changes resistance as it reacts with the ambient gas (the heat accelerates the chemical reaction). There are several versions of these sensor, sensitive to several gas types. However, no sensor material is sensitive to a single gas only! I did some more research and found in principle two sensor of immediate interest to me: The MQ135 for "air quality" and the MQ811 for CO2. The MQ811 is much more expensive (30$ compared to 3$).
The datasheet claims that the MQ135 is sensitive for CO2, Alkohol, Benzene, NOx, NH3 and the Fig 3 shows the change in resistance depending on the concentration of these gases in the ambient air in ppm (of the total gas volume). It turns out the the general sensitivity is the roughly same for all the gases. This is where you think: Wait a minute! CO2 is the 4th most abundant trace gas in the earths atmosphere with about 400ppm concentration (N2, O2, and Ar are on place 1-3). All of the other gases the sensor detects are much less common than CO2 and luckily so, as they are harmful. This means, in a normal atmosphere the sensor mostly detects CO2 and with the right calibration we can use it as a cheap replacement for the MQ811 (which by the way is also sensitive to other gases). Turns out, somebody already hat a go at this: I will leave you with great explanation of David Gironi for the details, but mostly he just extracts data from the figures in the datasheet, throws some math at the problem and cross-checks the results with a different kind of sensor for CO2.
The Library I have written basically just implements his approach for the Arduino. It's pretty easy to use. Copy it to your Arduino library folder and put
#include "MQ135.h" MQ135 gasSensor = MQ135(ANALOGPIN);
to your sketch. ANALOGPIN is the ADC input for the sensor readings (refer to the post with the SniffingTrinket schematic for explanation).
Before you can use the sensor, it has to be calibrated. For this, connect the sensor to your circuit and leave it powered on for 12-24 h to burn it in. Then put it into outside air, preferably at 20°C/35% rel. hum. (humidity is not so crucial). Read out the calibration value as such
float rzero = gasSensor.getRZero();
Wait until the value has somewhat settled (30min-1h). Remember, this is an ADC measurement so you might not want to wait some time between reading the sensor and also do some averaging. Once you have determined your RZero, put it into the MQ135.h. Note: Different sensors will likely have different RZero!
#define RZERO 76.63
Congrats, you have calibrated the sensor and can now read the CO2 ppm value in your sketch
float ppm = gasSensor.getPPM();The library also provides functions to apply the temperature/humidity correction that is shown in Fig 4 of the datasheet, but I do not trust the datasheet there, so this should not be used for the moment.
If you want to know more, look at the code. I tried to make it very readable and self explaining and provided lots of comments. If you do not understand something, ask: I will happily explain it.