Two-Part, Four-Wire Air Quality Meter Shows How It’s Done

The Bosch BME680 is a super-capable environmental sensor, and [Random Nerd Tutorials] has married it to the ESP32 to create an air quality meter that serves as a great tutorial on not just getting the sensor up and running, but also in setting up a simple (and optional) web server to deliver the readings. It’s a great project that steps through everything from beginning to end, including how to install the necessary libraries and how to program the ESP32, so it’s the perfect weekend project for anyone who wants to learn.

The BME680 is a small part that communicates over SPI or I2C and combines gas, pressure, temperature, and humidity sensors. The gas sensor part detects a wide range of volatile organic compounds (VOCs) and contaminants, including carbon monoxide, which makes it a useful indoor air quality sensor. It provides only a relative measurement (lower resistance corresponds to lower air quality) so for best results it should be calibrated against a known source.

The tutorial uses the Arduino IDE with an add-on to support the ESP32, and libraries from Adafruit. Unfamiliar with such things? The tutorial walks through the installation of both. There’s a good explanation of the source code, and guidance on entering setup values (such as local air pressure, a function of sea level) for best results.

Once the software is on the ESP32, the results can be read from the serial port monitor. By going one step further, the ESP32 can run a small web server (using ESPAsyncWebServer) to serve the data to any device wirelessly. It’s a well-written tutorial that covers every element well, and complements this other BME680-based air quality meter that uses MQTT and Raspberry Pi.

34 thoughts on “Two-Part, Four-Wire Air Quality Meter Shows How It’s Done

  1. Humidity to 2 decimal places! Can anyone really tell the difference between 59.44% and 59.45% humidity? Why do designers lose the forest for the trees? How meaningful is to most people to know the temperature to 1/100th of a degree C?
    I appreciate the technical tutorial, and I thank Random Nerd for this. This is not a comment against him. I just wish that we all would emphasize meaning over numbers.

    1. It’s useful if you want to see at a first glance, if a value is stable or if it is changing. It is also useful to judge how much noise your measurement system is exposed to.

      I used to make temperature measurements by vastly oversampling a thermocouple, which moved the usable resolution down to 0.01 K. You could basically tell, by looking at the graph for 3-4s, that someone was standing near my test rig, because temperature increased.

    2. Better to have it and not need it, than need it and not have it. For 98% of applications it’s probably not useful. That other 2% will eat it right up.

      I use very small pressure differentials in my house to determine whether I need to open a window (to equalize pressure) to prevent radon from accumulating in my basement, and to determine if I’m about to have a flow reversal in my chimney. I have a blower plumbed into my basement so I can force the correct direction of flow in my chimney, but I don’t want to drag in cold air from the outside all the time and wastefully run a blower. Measuring small pressure differences is useful for this application.

      Small humidity? Not sure. I don’t have a need to measure humidity changes that small, but I’m sure someone will find it useful. Detecting water leaks maybe? Quickly catching someone having a shower and turning on an automated bathroom fan or dehumidifier? Indirectly measuring the rate of change of clothes drying and turn on/off a heating element in a clothes dryer so it can operate more efficiently? There are lots of potential applications.

      1. – I’m after the same idea with chimney flow – but with a damper on the exhaust of an air exchanger instead. I’d be interested in any details you’d like to share – did you use a BMExxx or other, and/or other issues you ran into? Between stack effect of pressure inside the house, and effects of any wind increasing/decreasing pressure on the sensor outside if near the building, I’ve been debating how well it would actually work out…

        1. I tried a couple BMP180s, then BME280s. Those kinda worked with some fiddling. I’m using a small low pressure differential sensor now with a small 1/4″ poly tube that runs to the outside. Just do that instead. Way easier and no messing around trying to get sensor values to match up. Really I should have a few of these things plumbed to different sides of the house for exactly the reason you just said; wind. That adds a whole other layer of complexity.

          1. Thanks! – Good to know! – Yeah, I was heading down a similar path it sounds – tentatively had planned on a few locations outside with BME280’s, and a pair in the house, to try to normalize readings. After seeing readings from a handful of BME280–>arduino micro–>rs485 adapters back to a central controller, I’d started to looking into the differential pressure sensor route to simplify exactly what you said about calibration/matching, but the project went by the wayside. It’s back on the front burner now that I actually have an operating woodstove though – if you have any suggestions / part #’s on a differential sensor, feel free to share!

        2. I couldn’t reply to your other comment so I’ll leave my response here. I have a little MPXV7002DP that seems to do the trick. It does -2 kPa to +2 kPa on a 5v analog output. Cheap. Works. Readily available. What more could you want?

          Just make sure you order the DP version if you want two ports. It comes in two versions, which may or may not work out for you depending on what you want. I like being able to hook up two tubes.

    3. It is the default “String s = String(floatvalue);” stuff the Arduino String class does.

      Because everything goes into this really novel hack and nothing into the science behind it.

    4. It is not unheard of to use statistical analysis on the results, so increased precision is good. It certainly isn’t bad; would having less precision cause the part to cost less, or not?

      Even just an indoor/outdoor temperature sensor, the more precision I have, the faster results I get, and I can more easily compare two different fan configurations to see which one cools faster. With enough precision I can see results even before my regular room thermometer has showed a 0.1 degree temperature change.

      1. That’s the advantage of Bosch sensors.
        The tolerances are so tight in the legit ones that almost all of the cheap ones are still within the range people would use them at for something like a weather station.

        Got two BME280’s that with testing along with certified sensors are JUST outside some of the tolerances listed in the data sheet.

        Sure as hell beat the DHT11 & DHT22 despite the prices.

      2. The module doesn’t matter that much in this case, compared to the IC.

        Bosch basically owns the automotive market for these type of sensors, and is the top player in the scientific instruments, too. But the automotive stuff has to be really robust. That’s why these things can do much better than the specs in more normal settings.

        Even a cheap module will be better than hand soldering it. If I dead bug one of these onto a proto board, it works fine, no layout issues. The stray inductance and capacitance doesn’t really matter because you’re ready a steady value, so you just have to match the wire lengths and you’re there.

        1. After playing with quite a few other humidity sensors that failed in various ways, i moved to BME280, ebay modules. So far so good.
          However, it needs more time to really say how they will behave, they are running for <1 year so far. I do agree that the cost is justifiable, the BME280 is quite a good price.

          My concern about ready made modules from various sources is less about being a bit out of spec and more about being defective in ways that are not easy to figure out quickly. But for that i will still have to wait and see how these sensors behave over time.

  2. The air quality part of the 680 is a scam. It doesn’t measure what you’d expect, it’s only fully supported using a closed source library (which probably is closed exactly to reveal it’s a scam) and it randomly stops working.

    I have yet to find a part that is both a good price and does reliably supply the real air quality.

    1. There is some info (guesswork? fantasy?) about the sensor working in

      The more I read about Quality of Air the more it reminds me of 風水 / 风水, homeopathy and other voodoo. So to me the binary blob was the final showstopper.

      On the other hand, looking at some of those hacks published here, precise measurements seem to be not that important. “Feeling the value is right” is good enough.

      My weather stations forcecast module displays “same as yesterday”. Has about 75% accuracy. Feels good enough for me.

      1. I initially wanted to applaud the guy for reverse-engineering and open-sourcing the closed blob from Bosch, but then he added all that corporate stuff at the bottom.

        From my own trials at reverse-engineering the IAQ algorithm, it’s not as simple as it looks on his charts. They have non-linear mappings between the variables, since I have a feeling they are interconnected. Similar as to using a cheap TDS meter and the same water has a different purity as it goes up in temperature.

        Anyway, about three years ago Bosch had no IAQ blob for ESP32 and ESP8266, at least now they provide one.

        1. How do you mean corporate stuff? I’d welcome an open source implementation (which would also work good, of course).

          And no, the algorithm is certainly not simple. It will very probably even keep some history.

          If the code of the binary blob is as awful as their open source code, I’d “hesitate” to use it.

    2. It’s also a metal oxide sensor, making the “VOC” reading totally useless in any sort of quantitative since it has wildly differing levels of sensitivity to a ton different VOCs and can’t distinguish between them.

      1. If it is sensitive to some VOCs and not others, then it is quite useful for quantitative analysis of the VOCs that it can detect.

        Is it a “healthy air detector,” or something like that? No. It only detects what it detects, and other stuff not.

        The vast majority of situations where you’d be using a sensor like this to detect VOCs you would be near a specific source of VOCs and you can simply calibrate the sensitivity to your application; something you’d have to do anyway.

        1. The problem is that it’s sensitive to a *wide range of common VOCs*, and the sensitivity varies by *orders of magnitude*. So a very tiny amount of one VOC it’s extremely sensitive to (e.g., ammonia from someone using Windex) might give you an elevated reading, while a VOC that it’s got a low sensitivity (like CO2) would take a much higher concentration. You never really know which case you’re looking at and in my experience there are enough contaminants in a typical household that the readings vary wildly.

          I agree that they can be useful in a couple scenarios, however. First is if you have a single known VOC and no others that might confound the signal. The second is as a very rough indicator of “there is *something* in the air” versus not.

          One major limitation of the BME680 is that you don’t have the option to calibrate it to a specific VOC in the proprietary library as far as I remember and you’re stuck with their sensitivity curves. You can get the raw resistance values, but then you have to do your own temperature and humidity compensation as well as determine the sensitivity curves yourself.

  3. I recently setup one of these sensors. To get a useful air quality value you need to install the proprietary precompiled Bosch library. It’s a little bit of a pain to setup since the Arduino IDE wasn’t really made to link against static libraries. It’s also closed source. Without the library all you get is a resistance value which isn’t very useful. It constantly changes with humidity and other environmental factors which the Bosch library compensates for.

  4. The 680 only provides a resistance value which changes with air quality (sensitive to a wide range of volatile organic components) and is not useful for absolute measurements. The closed source library with its proprietary algorithm can give you a proper air quality measurement by using this resistance value together with other parameter like heating temperature, heating duration, humidity and aging.
    Someone with proper test equipment should try to reverse engineer this algorithm…

    Meanwhile I use the SGPC3 from Sensirion.

    1. I’ve been screaming seemingly forever about how “VOC” readings from this type of metal oxide sensor are totally useless for what most people want (and how “equivalent CO2” readings many of these provide are even more meaningless), but of course it’s futile. The only time these sensors give meaningful values are in a controlled laboratory with a single known VOC.

      In something like a household environment, AT BEST the readings from the BME280 can distinguish between “clean air” and “there is *something* in the air”.

        1. True. But VOC sensors can still be useful if you only want to detect anomalies or changes from “normal” behaviors. In my application long-term stability and repeatability is more important. All of those metal oxide sensors change with age and all have some way of compensating this drift. Sensirion does this on-chip while Bosch requires this precompiled binary.

          As the BME680 allows to manually adjust heating temperature and duration, we could in principle adjust the sensitivity of the metal oxide layer to different kind of chemical components and adapt do application specific use-cases. But sadly the calibration procedure and drift compensation algorithms are kept secret.

          1. Exactly that. I do not mind if the compensation needs to be done in software. The IC may not be powerful enough to do it properly. But then, at least, release the specifications on how to do it. Closed source means to be there are things we cannot know, not because they’re “trade secrets” (those are reverse engineered pretty quickly by the competitors), but because they’re not telling us the truth in some way. Comparable to GPU’s where the drivers are only closed source, because the drivers mask ommisions and errata in the sillicon. And of course promises from the marketing department that can’t be actually met.

        1. It’s all marketing.

          Once I went ahead and drowned the sensor in CO2 (I own cylinders with the stuff for carbonisation of water). There was NO difference in the reading.

          1. MOX sensors are particularly insensitive to CO2; most of them are *technically sensitive to it, but at several orders of magnitude lower sensitivity versus other common VOCs. You really want an NDIR sensor for measuring CO2. Sensirion makes a really nice NDIR sensor (the SCD30) but it’s a little spendy at ~$60, while you can get the probably-not-something-you-want-to-bet-your-life-on but still perfectly adequate MH-Z19 sensors for ~$15-20 from the usual Chinese sources.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.