Particle Powered Air Quality Sensor Logging to Google Docs



  • Hey All,

    I recently completed a project to simplify air quality measurements throughout my home. It uses a CCS811 (TVOC + C02), Si7021 (Humidity and Temp) and a HPMA115S0 (PM2.5 and PM10)

    I did base this off of a more manual DIY project here. If you're interested in simple though, continue on!

    Gather the Goods
    0_1554836630359_image.png

    Get everything together that you’ll need for this project.

    This includes:

    • A Particle Mesh board (Argon, Boron, Xenon). You can get them almost anywhere. Buying direct always works too. Note: if you're just starting out, the Argon is your best bet.
    • Particle^2 Air Quality Sensor.
    • Honeywell HPMA115S0 Particle Sensor.
    • Cable for HPMA115S0 Sensor. ( The last three you can get here. )

    The Leg Bones Connect to The ..
    Put everything together in the short few steps below:

    1. Attach the Particle to the Particle^2 board
      0_1554836644342_image.png

    2. Connect the HPM Particle sensor to the Particle^2 using the cable
      0_1554836653470_image.png

    3. Plug in USB!
      0_1554836659251_image.png

    Configure Google Docs Script

    1. Create a new Google Sheet
    2. Then click the Tools menu and click Script Editor
      0_1554836668088_image.png
    3. Create a new script
    4. Insert the below code into the script:
      //this is a function that fires when the webapp receives a POST request
       function doPost(e) {
    
         //Return if null
         if( e == undefined ) {
           Logger.log(“no data”);
           return HtmlService.createHtmlOutput(“need data”);
         }
    
         //Parse the JSON data
         var event = JSON.parse(e.postData.contents);
         var data = JSON.parse(event.data);
    
         //Get the last row without data
         var sheet = SpreadsheetApp.getActiveSheet();
         var lastRow = Math.max(sheet.getLastRow(),1);
         sheet.insertRowAfter(lastRow);
    
         //Get current timestamp
         var timestamp = new Date();
    
         //Insert the data into the sheet
         sheet.getRange(lastRow + 1, 1).setValue(event.published_at);
         sheet.getRange(lastRow + 1, 2).setValue(data.temperature);
         sheet.getRange(lastRow + 1, 3).setValue(data.humidity);
         sheet.getRange(lastRow + 1, 4).setValue(data.pm10);
         sheet.getRange(lastRow + 1, 5).setValue(data.pm25);
         sheet.getRange(lastRow + 1, 6).setValue(data.tvoc);
         sheet.getRange(lastRow + 1, 7).setValue(data.c02);
    
         SpreadsheetApp.flush();
         return HtmlService.createHtmlOutput(“post request received”);
       }
    

    Configure Webhook
    0_1554836676996_image.png

    1. Go to Publish and click Deploy as Web App
    2. Set Execute the app as yourself
    3. Then set Who has access to the app to Anyone, even anonymous. (Important: if you’re working with. mission critical data, you may want a more robust and custom solution. This allows anyone, if they have your web hook link to post data to that page!)
    4. Change the Project Version to new and deploy!
    5. Copy the Current App URL that the output provides.

    Configure Particle Cloud

    0_1554836686474_image.png

    1. In the Particle.io console, go to the Integrations section and Create a New Webhook
    2. Fill in the name of the event that get’s forwarded from the code (in this case it’s blob)
    3. Enter the Current App URL from the last step in the URL Box
    4. Set the request type to POST
    5. Set the request format to JSON
    6. Target the device you’ll be using (or leave it as is if you only have one device)
    7. Click save

    Beam me up

    0_1554836693406_image.png

    It’s time to program your board. Follow the steps below:

    1. Setup your Particle Account and Particle Mesh device. Use the Quickstart if you haven’t done this before.
    2. Download Particle Workbench and install if you haven’t already. Instructions here.
    3. Get the code here.
    4. Once the code is downloaded, open it with Visual Code (that you installed in Step 1)
    5. Login to Particle if you haven’t already (The fastest way is to hit Command + Shift + P to open the command window. Then start typing login)
    6. Publish to Particle Cloud - Again this uses the command window. Use the same Command + Shift + P as above and type Cloud Flash.
    7. Once you’ve found the Cloud Flash option, press enter.
    8. Your board should be programmed shortly. You can watch the LEDs for changes during this time. Once it’s glowing blue, you’re good to go!

    Last Step (I promise)

    1. In the Google sheet you can create a header in the first row with all the labels.
      0_1554836704903_image.png
    2. You should notice by now that new data is showing up in the sheet (if you set everything up correctly). Go back to the previous steps if you don’t see it.
    3. You can graph the data by selecting a full column and creating a new chart from it.
      0_1554836712512_image.png
    4. You can graph everything in one or in separate like I’ve done above.
      If everything is working and you have some pretty graphs, congrats!! If you’re ready to move on to the next step using an IoT service like Adafruit’s check out my full guide here.

    Conclusion
    I hope you've found this useful. Especially the bit about Google Docs. (It's changed my life that's for sure!!) Now it's on to bigger and better things like getting a battery optimized version running. Now that will be fun..


  • Plugin Developer

    Nice work.

    Does it use the temperature and humidity values to optimise the fine dust calculation?


  • Hardware Contributor

    @alowhum said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Nice work.

    Does it use the temperature and humidity values to optimise the fine dust calculation?

    No it doesn't.
    And by the way PM10 values are worthless, they are evaluated based on PM2.5 values. Meaning if you put the sensor in an environment with only 2.5-10 µm sized particles, it will say 0ug/m3.
    Not saying the sensor is bad, it's good but only for pm2.5. I suspect it's just a remake of a PMS5003 with longer lasting laser and fan.


  • Plugin Developer

    Wait, are you saying you believe the Honeywell device is a remake of the Plantower PMS5003?


  • Hardware Contributor

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Particle^2 Air Quality Sensor

    The CO2 measurement seems to be based on AMS CCS811. What is your experience with this sensor?

    I was comparing this sensor with Netatmo (+-50 ppm accuracy according to the website) and a MH-Z14A. Maybe you can tell me from my graph, if my sensor is broken and I should consider oredering another:

    0_1554993748723_co2-sensor-comparison.png



  • @alowhum Only used for TVOC. Though I think that algorithm is suspect. I've put a line in with AMS about it.

    @fotofieber are you running the sensor as-is or are you updating the environmental data as you run it? As I mention above, I've seen some weird results with the CCS811. (Lots of correlation with humidity and temperature) There are other TVOC/C02 sensors out there that I definitely want to check out and compare side-by-side. (right now I only have one data point which is the CCS811)



  • @FotoFieber btw which code are you using? Adafruit's library?



  • @nca78 said in Particle Powered Air Quality Sensor Logging to Google Docs:

    @alowhum said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Nice work.

    Does it use the temperature and humidity values to optimise the fine dust calculation?

    No it doesn't.
    And by the way PM10 values are worthless, they are evaluated based on PM2.5 values. Meaning if you put the sensor in an environment with only 2.5-10 µm sized particles, it will say 0ug/m3.
    Not saying the sensor is bad, it's good but only for pm2.5. I suspect it's just a remake of a PMS5003 with longer lasting laser and fan.

    I would have to agree with this observation thus far. The PM10 readings correlate 1:1 with the PM2.5. Good thing PM2.5 is what we really care about! For anyone who's curious, the sensor saturates at 1000µg/m3. Just had an interesting experience with that... 😬


  • Hardware Contributor

    @jaredwolff
    I am using the adafruit library and compensating temp/hum with the measurements of a SI7021. The results are really bad and I have ordered another CCS811 for comparison.

    void readCCS811(JsonObject &root)
    {
      static bool bFirst = true;
      static Adafruit_CCS811 sensor;
      if (bFirst)
      {
        DEBUG_PRINTLN("Initializing CCS811");
        if (!sensor.begin())
        {
          DEBUG_PRINTLN("CCS811 Initialization failed.");
        }
        else
        {
          sensor.setDriveMode(CCS811_DRIVE_MODE_IDLE);
          delay(10000);
          sensor.setDriveMode(CCS811_DRIVE_MODE_60SEC);
          bFirst = false;
        }
      }
      if (sensor.available())
      {
    
        // setEnvironmentalData(uint8_t humidity, double temperature);
        sensor.setEnvironmentalData(lasthum, lasttemp);
    
        if (!sensor.readData())
        {
          uint16_t lastppm = sensor.geteCO2();
          if (lastppm > 0)
          { 
            JsonObject rootCCS811 = root.createNestedObject("ccs811");
            rootCCS811["co2"] = lastppm;
            rootCCS811["tvoc"] = sensor.getTVOC();
          }
        }
        else
        {
          DEBUG_PRINTLN("CCS811 ERROR!");
        }
      }
    }
    


  • @fotofieber you're not alone in this. I've actually stopped setting the environmental data.

    I don't see as many random spikes as with. I've asked AMS about the frequency or when the data should be updated. I have a feeling it's supposed to be sparingly..



  • @fotofieber I've had some luck with removing the fraction portion of the temperature readings. It looks like the Adafruit code does use it. The suggested code from AMS does not use it.

    I'm also tooling around with saving the baseline. They suggest every 24h. That should help bring your readings back up to where they were in the event of a reset.


  • Hardware Contributor

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    @fotofieber I've had some luck with removing the fraction portion of the temperature readings. It looks like the Adafruit code does use it. The suggested code from AMS does not use it.

    Could you please share your code?

    There is an application note about update frequency on https://ams.com/documents/20143/36005/CCS811_AN000369_2-00.pdf/fb08da36-5b40-732b-39b0-62d2d9db5a3c

    It is recommended that the T+RH data is read from the ENS210 at the same frequency as the
    CCS811 generates eCO2 and TVOC outputs. For example in mode 3, 60 second mode, the
    application software should read the ENS210 data once every minute.

    The code in the application notes

    i2c_buff[0] = ((RH % 1000) / 100) > 7 ? (RH/1000 + 1)<<1 : (RH/1000)<<1;
    i2c_buff[1] = 0;
    if(((RH % 1000) / 100) > 2 && (((RH % 1000) / 100) < 8))
    {
    i2c_buff[0] |= 1;
    }
    

    looks quit different to the adafruit implementation:

    uint8_t hum_perc = humidity << 1;
    	
    // other code
    
    
    	uint8_t buf[] = {hum_perc, 0x00,
    		(uint8_t)((temp_conv >> 8) & 0xFF), (uint8_t)(temp_conv & 0xFF)};
    

    In the same document the handling of baseline is described. I think the adafruit code may be incomplete... 🙂

    I'll try the sparkfun lib, it hase baseline support and looks more like the programming note from aws.


  • Hardware Contributor

    The CCS81 seems to be much more complicated to handle than the MH-Z14A. There is an MCU on the sensor and you can make firmware upgrades which should reduce the burn in time. After burn in, you shoul save the actual baseline from time to time (e.g. every 24 hours) and restore it, when you reboot.

    My hacked code looks now much more complicated:

    void readCCS811(JsonObject &root)
    {
      static int loopCount = 0;
      static bool bFirst = true;
      static CCS811 myCCS811(CCS811_ADDR);
      JsonObject rootCCS811;
    
      loopCount++;
      if (bFirst)
      {
        DEBUG_PRINTLN("Initializing CCS811");
        CCS811Core::status returnCode = myCCS811.begin();
        DEBUG_PRINT("CCS811 begin exited with: ");
        printDriverError(returnCode);
        DEBUG_PRINTLN("");
    
        if (returnCode == CCS811Core::SENSOR_SUCCESS)
          bFirst = false;
    
        //This sets the mode to 60 second reads, and prints returned error status.
        returnCode = myCCS811.setDriveMode(3);
        DEBUG_PRINT("Mode request exited with: ");
        printDriverError(returnCode);
        DEBUG_PRINTLN("");
    
        if ((EEPROM.read(0) == 0xA5) && (EEPROM.read(1) == 0xB2))
        {
          DEBUG_PRINTLN("EEPROM contains saved data.");
          //The recovered baseline is packed into a 16 bit word
          unsigned int baselineToApply = ((unsigned int)EEPROM.read(2) << 8) | EEPROM.read(3);
          DEBUG_PRINT("Saved baseline: 0x");
          if (baselineToApply < 0x100)
            DEBUG_PRINT("0");
          if (baselineToApply < 0x10)
            DEBUG_PRINT("0");
          DEBUG_PRINT(baselineToApply, HEX);
          //This programs the baseline into the sensor and monitors error states
          CCS811Core::status errorStatus = myCCS811.setBaseline(baselineToApply);
          if (errorStatus == CCS811Core::SENSOR_SUCCESS)
          {
            DEBUG_PRINTLN("Baseline written to CCS811.");
          }
          else
          {
            printDriverError(errorStatus);
          }
        }
      }
    
      if (myCCS811.dataAvailable())
      {
    
        myCCS811.readAlgorithmResults();
        myCCS811.setEnvironmentalData(lasthum, lasttemp);
    
        uint16_t lastppm = myCCS811.getCO2();
    
        if (lastppm > 0)
        { // bis und mit 400 nur an der Initialisierung
          rootCCS811 = root.createNestedObject("ccs811");
          rootCCS811["co2"] = lastppm;
          rootCCS811["tvoc"] = myCCS811.getTVOC();
        }
      }
    
      // save Baseline every 24 hours
      if (loopCount >= 24 * 60)
      {
        // read baseline
        unsigned int baseline = myCCS811.getBaseline();
    
        rootCCS811["baseline"] = baseline;
    
        DEBUG_PRINTLN("baseline for this sensor: 0x");
        if (baseline < 0x100)
          DEBUG_PRINT("0");
        if (baseline < 0x10)
          DEBUG_PRINT("0");
        DEBUG_PRINTLN(baseline, HEX);
        //The baseline is saved (with valid data indicator bytes)
        EEPROM.write(0, 0xA5);
        EEPROM.write(1, 0xB2);
        EEPROM.write(2, (baseline >> 8) & 0x00FF);
        EEPROM.write(3, baseline & 0x00FF);
        EEPROM.commit();
    
        loopCount = 0;
      }
    }
    

    The results in the first 24 hours don't seem better. Hope they will getting better after 48 hours. 😞

    I am not really keen on programming a firmware upgrade program for the CCS811. The second sensor I ordered from aliexpress is hopefully better.



  • I have no experience with the MH-Z14A but compared to other comparable parts I think the CCS811 is a bit more simple to implement. (And less costly, despite it's $$$ price)

    Since my firmware improvements here (MSB for temp and humidity for saving the environmental data) seems to have helped tremendously. I have implemented the baseline save/restore but I haven't seen any crazy jumps or differences in operation. Maybe your MOX sensor is contaminated.

    I'm playing with some other sensors to see how they compare. I'll share my results here too.


  • Hardware Contributor

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    I have no experience with the MH-Z14A but compared to other comparable parts I think the CCS811 is a bit more simple to implement. (And less costly, despite it's $$$ price)

    The MH-Z14A is really simple to implement. Just send some characters over serial interface and get the CO2 value. You don't need to think about baselines and firmware versions. A cheap sensor is of no use, if you can't get correct readings. Maybe I am doing something wrong? 🙂

    But maybe you can share your code and I can get better results?

    The CCS811 I have here maybe cheap….
    0_1555968023025_sensor-comparison.png



  • @fotofieber after assembling and testing a few more boards. I've noticed that the fresh sensors, do need some time to "burn-in." I'm seeing wild values in the 1000's whereas the one I've been using for a few weeks is rock solid.

    Here's a capture of one I'm testing right now:

    0_1556208457191_Screen Shot 2019-04-25 at 12.07.09 PM.png

    The blue is the one that's been running for a while. The red is a fresh unused sensor.

    I haven't had a chance to play with the MH-Z14A. I'm currently doing an eval of all sensors that I can (easily) get my hands on to compare side by side.

    All the latest and greatest code for my project is located under the Beam me Up section in my original post above. #3 I think. Here's the link again though.


  • Hardware Contributor

    @jaredwolff
    Thx for the link to your sourcecode.
    How long is the time interval on the graph in your post?

    I tried to use drive mode 1 (measurement every second) with an average calculation for every minute. But it didn't get better... 😞

    I added now a MH-Z19B to the testbed.

    Awaiting still from aliexpress:
    SGP30
    MICS-VZ-89TE
    GY-MCU680V1 BME680
    Senseair S8-0053
    and another CCS811.
    0_1556312751563_IMG_3814.JPG



  • @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    How long is the time interval on the graph in your post?

    The interval was either 20 seconds or 2 minutes. My code defaults to 2 minutes. There's just no reason to be checking it that often.

    The CCS811 on the other hand takes a measurement every second. (I left it in the default mode) I just take the latest measurement when it's time to send the update to the server.

    Curious to see what conclusions you come to with your tests. I think we'll get there right around the same time!


  • Hardware Contributor

    @jaredwolff
    The MHZ19B is working out of the box without tuning. NDIR sensors seem to be easier to handle but are more power hungry.
    0_1556347989054_sensor-comparison co2.png
    In addition to the CO2 ppm, it has a temperature reading, which is not to bad:
    0_1556348218175_sensor-comparison temp.png
    The temperature of the BMP280 and ST7012 are quite high. They are on the same small pcb as the CCS811.



  • @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    The MHZ19B is working out of the box without tuning. NDIR sensors seem to be easier to handle but are more power hungry.

    Nice! Glad to see something working for you. The MHZ19B seems like a good option when you have the space. I wonder how it is long term.

    How many hours have you continuously run your CCS811? I'm seeing the fresh one I had normalize to zero over almost 24h of continuous running. (See the blue trace below for TVOC & C02)

    0_1556375221442_Screen Shot 2019-04-27 at 10.26.57 AM.png

    I'm also not surprised by the readings you're getting on temp. Unless you get a sensors that is specifically more precise you could get some significant deviations. I would expect ±1 °C from most sensors though..


  • Hardware Contributor

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Nice! Glad to see something working for you. The MHZ19B seems like a good option when you have the space.

    The MH-Z19B does use less space than the MH-Z14B. I thinkt the footprint is similar to my CCS811 PCB from aliexpress. But it is taller. I think the main argument against the MH-Z19B could be power consumption.

    I wonder how it is long term.

    I have some MH-Z14B working fine for more than two years. Accoriding to the datasheet, the MH-Z19B should last more than 15 years.

    How many hours have you continuously run your CCS811?

    More than two days. It didn't get better.

    I'm seeing the fresh one I had normalize to zero over almost 24h of continuous running. (See the blue trace below for TVOC & C02)

    I can't see the time on your graph. I only see 2019-0... would it be possible to show the time?

    The manufacturer has improved accuracy with the last firmware of the CCS811. Which version of firmware do you have on your CCS811?



  • @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    The manufacturer has improved accuracy with the last firmware of the CCS811. Which version of firmware do you have on your CCS811?

    Good question. According to my code: 1.1.0

    @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    I can't see the time on your graph. I only see 2019-0... would it be possible to show the time?

    Hmm. Yea they're full timestamps. Pretty useless huh? What are you using to create your graphs? That way we're looking at the same thing.

    On another note: I did get SPG30 and BME680 up and running. I ran the SPG30 while I was tinkering with the BME680. It's about 12 hours of data. (Sorry the x axis is not quite working out.)

    0_1556496951580_Screen Shot 2019-04-28 at 8.06.17 PM.png

    My initial impressions from the integration:

    SPG30 is about as easy as the CCS811. As you can see it has its own demons. It does require another power supply (1.8V typical for this part) And it can get power hungry if you run it tons (48mA when the heater is on).

    The BME680 is not so easy to integrate into the Particle platform. Mostly due to the added archive file (i.e. static library, i.e..a file). After tinkering with what they had I have it taking in and processing data. The only thing I really care about is the IAQ calculation which is not open source. It does some other calculations on the temperature and humidity if you choose to integrated it with a space heater. (or HVAC unit for that matter)


  • Hardware Contributor

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Hmm. Yea they're full timestamps. Pretty useless huh? What are you using to create your graphs? That way we're looking at the same thing.

    I am using grafana with influxdb (both in docker).

    @jaredwolff

    SPG30 is about as easy as the CCS811. As you can see it has its own demons. It does require another power supply (1.8V typical for this part) And it can get power hungry if you run it tons (48mA when the heater is on).

    Awaiting mine impatiently. 🙂 Power consumption is not a real problem in my usage scenario.

    @jaredwolff

    The BME680 is not so easy to integrate into the Particle platform. Mostly due to the added archive file (i.e. static library, i.e..a file).

    Do you build with platform.io? I only found instructions for the arduino ide...

    Temp and hum are measured on the heated sensor and must be calibrated to be useful according to some discussions I read.



  • @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    I am using grafana with influxdb (both in docker).

    I like it. It may make sense to have my own infrastructure in the future. But then again, I don't feel like dealing with it all. 😆

    @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Do you build with platform.io? I only found instructions for the arduino ide...

    I'm building using the Particle SDK on my machine. They can build Arduino libraries but can't quite include external/static libraries yet (As far as I can tell) out of the box. The Particle platform, in general, has been for convenience and getting to proof of concept (really) fast. Plus they're an awesome company.

    As for the data, I'm just pushing the data from the Particle platform into Google docs (as my original post described). It's great for short tests but longer data streams you definitely need a time-based database and some nice front end graphing capabilities. 😄

    Another update on the TVOC eval. Looks like the BME680 outputs on the same scale as the SPG30 and CCS811. (i.e. 500ppb == a reading of 500 IAQ on the BME680)

    0_1556567219754_chart.png

    (The timestamps are there if you click on the image itself. )

    @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Temp and hum are measured on the heated sensor and must be calibrated to be useful according to some discussions I read.

    I was thinking about this more considering the discrepancy I'm seeing in temperatures and humidity. If you're serious about the results and the accuracy of the temp & humidity it may require a 3rd temperature sensor with no heater inside.

    Supposedly the BME680 has a calibrated output but it hasn't fired up. I'll have to figure that out..


  • Hardware Contributor

    Firmware upgrade time!

    My CCS811 has bootloader version: 1000

    and had application version: 1100

    I upgraded to the newest firmware (2.0.1). Now waiting for another two days.... 🙂 Hope then I get reasonable results like you have....



  • @fotofieber yeehaw. I hope that fixes the craziness you were seeing. I'm curious if that will fix the early unreliable data I've been seeing too..



  • @FotoFieber if you check out my tvoc_test branch, I implemented the CCS811 update routine. I'm interested to see how it compares to the SPG30 and BME680..


  • Hardware Contributor

    @jaredwolff
    The update has brought a big improvement.
    I think one could derive airquality from the measurements, but the CO2 ppm value is still way off.
    0_1556686461628_sensor-comparison.png



  • @fotofieber that's great news! Pretty much what I've seen. I've stopped eC02 all together because it correlates 1:1 with TVOC on that part. Plus I don't know how actionable the C02 reading is. Does it indicate stale air? C02 is a byproduct of the VOCs? Maybe it's more useful for more industrial environments..

    Are you logging anything other than C02?


  • Hardware Contributor

    @jaredwolff
    CO2 is an indicator of air quality. I use it since years mainly with consumer devices from Netatmo. In my graphs you can see, when people are in the rooms consume the air, when they leave, when I open the windows...

    The CO2 measurement with NDIR-sensors seems much more reliable than what I see here from CCS811. They usually show quite good results just plugged in without calibration. They are easier to handle, because you don''t need to bother with handling basline (save and restore). And they don't need a temp/hum measurement to correct their values.

    Yesterday arrived another NDIR-Sensor (Senseair S8) and a SGP30. I am curious, how they perform. Hope I have the first results in two days.

    Are you logging anything other than C02?

    In general I have much more values I log (radioactivity, luminosity, window open/close, motion...)

    In this setup I log what I can get from the sensors.


  • Hardware Contributor

    This night was a complete fail for the CCS811 I have here:

    Fresh air at 20:00
    Sleep till 6:15 with closed windows
    -> NDIR sensors show, how air quality gets worse
    -> CCS811 shows, how the air quality gets better during sleep with closed window!
    Fresh air at 06:15

    WTF.... 🙂
    0_1556788324572_sensor-comparison.png


  • Hardware Contributor

    S8 readings seem quite goot. (NDIR)
    SGP30 😞 Will try with the adafruit library instead of the sparktech.
    0_1556954956512_sensor-comparison.png



  • @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    SGP30 Will try with the adafruit library instead of the sparktech.

    I have that one in the same branch I mentioned before if you need a working reference.

    I followed your lead on the Grafana + InfluxDB stuff. It was dead simple to setup.

    0_1557075343811_Screen Shot 2019-05-05 at 12.55.39 PM.png

    I just want to get HTTPS/SSL working. Pretty nifty little piece of software. 🙂


  • Hardware Contributor

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    I followed your lead on the Grafana + InfluxDB stuff. It was dead simple to setup.

    Yes, really simple. I use docker for grafana and influxdb.

    Your SGP30 CO2 ppm graph looks like mine... 😞

    I just want to get HTTPS/SSL working.

    I use an nginx-setup here for https.

    Pretty nifty little piece of software.

    Yepp! They are real software gems.



  • @fotofieber also, I compiled my conclusions about some of the smaller form factor TVOC/C02 sensors. It was inspired by everything we talked about here. Our back and forth conversation has been awesome. So I wanted to say thanks for the inspiration 🙂

    0_1557153919177_Screen Shot 2019-05-06 at 10.44.47 AM.png

    The above is a screenshot from the side-by-side data of the BME680, CCS811 and SGP30.

    The BME680 seemed impressive at first but I'm seeing a big difference in temperature and humidity. My thinking it's likely due to the heating elements inside keeping it a little less humid and a little more hot. (These are the compensated values by the way. The non-compensated values are even lower humidity and a hotter.)

    The SGP30 is a bit of a power hog but the TVOC readings seemed to align well with the response from the BME680.

    The CCS811, like we've seen throughout this thread, had some wacky responses using the 1.0.0 firmware. I haven't seen that since all of my CCS811 are up to date.

    It's a toss up between all three but I'd shy away from the CCS811. If anyone here plans on building a production device, the stock is not reliable enough. (Digikey and Mouser have been out of stock lately) I'm not sure if you'd have the same problem in the EU or how things are in Asia.

    Anyway my TLDR conclusions are here if anyone is interested. They include software implementation factors, hardware factors, availability factors and data output factors all rolled into one.



  • @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Your SGP30 CO2 ppm graph looks like mine...

    Also, Is your SGP30 plot the dark red one? Definitely not what I'd expect from this sensor. At first I thought it was the CCS811 as that one appears to be less reactive (at least in my testing)


  • Hardware Contributor

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    The BME680 seemed impressive at first but I'm seeing a big difference in temperature and humidity. My thinking it's likely due to the heating elements inside keeping it a little less humid and a little more hot. (These are the compensated values by the way. The non-compensated values are even lower humidity and a hotter.)

    I have tested several temperature sensors in the same setup and will use seperate HTU21D in my production devices anyway. So temperature and humidity would be no problem for me.

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Also, Is your SGP30 plot the dark red one? Definitely not what I'd expect from this sensor. At first I thought it was the CCS811 as that one appears to be less reactive (at least in my testing)

    Yes, it's is the dark red one. 😞
    Yesterday another CCS811 arrived. I will add it to my setup.

    My final setup drifts to:

    • HTU21D temp/hum
    • MHZ19B CO2
    • HC-SR501 (modified for 3.3V) motion
    • WS 2812B led stripes


  • @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    I have tested several temperature sensors in the same setup and will use seperate HTU21D in my production devices anyway. So temperature and humidity would be no problem for me.

    After someone on a different forum suggested, I actually switched it from continuous to low power mode and the temperature and humidity readings look better.

    0_1557233131908_Screen Shot 2019-05-07 at 8.45.03 AM.png

    (Red line is in the middle between before and after the change.)

    @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Yesterday another CCS811 arrived. I will add it to my setup.

    Nice, curious to see your results!


  • Hardware Contributor

    @jaredwolff 0_1557243066441_IMG_3835.jpg

    BME680 sensor mith MCU arrived. Hope I can read the chinese specification of the module.... 🙂 (What stand PS for?)



  • @fotofieber hmm I'm not sure. Can you send me more info about the board you got?


  • Hardware Contributor

    @jaredwolff
    Found something on https://de.aliexpress.com/item/GY-MCU680V1-BME680-Sensor-Module-Temperature-and-Humidity-Air-Pressure-Air-Quality-IAQ-MCU680-Module/32902672818.html?spm=a2g0x.10010108.1000016.1.3bc92080ZxA8fs&isOrigTitle=true

    When soldering the PS solder joint, the module is in the chip's own IIC mode, at which point the MCU does not participate in the operation and does not consume current. Can be used as a simple BME680 module.

    And in serial mode:
    https://playground.cmmakerclub.com/2018/12/esp32/วิธีการใช้งาน-gy-mcu680-กับ-esp32/

    I will try the I2C mode first.



  • @fotofieber I'm using I2C over here with great success. Let me know how it goes!


  • Hardware Contributor

    @jaredwolff
    Seems like I only get an IAQ value for the BME680 and no (e)CO2. Is this correct?



  • @fotofieber correct! No C02. There's also temp, humidity and pressure. Here's a little code to get up and running with their C++ library.


  • Hardware Contributor

    @jaredwolff
    Managed to compile Bosch arduino demo code on ESP32 on platformio after 3 hours. 😎

    But then....

    BSEC library version 1.4.7.3
    Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%], Static IAQ, CO2 equivalent, breath VOC equivalent
    BSEC error code : -2
    

    Maybe I give up here, as I really don't like to use binary code in my sensors....



  • @fotofieber integrating their static library is a PITA.

    What processor are you using exactly? That wold dictate which version of the BSEC you'd integrate.

    For Arduino, the library should handle the import of the .a file. If you're in any other environment you'll have to add a few lines:

    LIB_DEPS += $(USER_LIB_DIR)/libalgobsec.a
    LDFLAGS += -Wl,--whole-archive $(USER_LIB_DIR)/libalgobsec.a -Wl,--no-whole-archive
    

    I had to add these to the makefile in .particle/toolchains/deviceOS/1.2.0-beta.1/firmware-1.2.0-beta.1/modules/xenon/user-part for the Particle stuff to work.


  • Hardware Contributor

    @jaredwolff
    ESP32 is the platform I use.

    Linking is no problem (after trial and error of two hours 🙂 ).

    I seem to have made a call to the lib:

    BSEC library version 1.4.7.3
    

    Now adding DEBUG-Messages to the BSEC arduino library.



  • @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Linking is no problem (after trial and error of two hours ).

    Yea it took me a bit to figure that out too. 😬

    Have you fired up the standard I2C library to see if you can talk to the BME680? Or maybe throw a logic analyzer on it to maker sure it's communicating? I'd imaging the compiler would barf if you used the wrong static library. Bosch does have an ESP32 specific one.

    Unfortunately, I don't have any way of testing that here. Keep me posted, I'm curious as to why it's not working.


  • Hardware Contributor

    @jaredwolff
    The data is read correctly:

    temp 1883
    hum 54739
    press 94317
    gas resistance 118267
    call bsec_do_steps(..
    return of bsec_do_steps -2
    

    And -2 means:

     BSEC_E_DOSTEPS_VALUELIMITS = -2,                /*!< Value of input (physical) sensor signal passed to bsec_do_steps() is not in the valid range */
    

    I wish I had the source code of the lib....



  • @fotofieber the library does have an error I found earlier. Divide _data.temperature by 100.0f and _data.humidity by 1000.0f. This is in BSEC.cpp

    See below:

    /**
     * @brief Read data from the BME680 and process it
     */
    bool Bsec::readProcessData(int64_t currTimeNs, bsec_bme_settings_t bme680Settings)
    {
    	bme680Status = bme680_get_sensor_data(&_data, &_bme680);
    	if (bme680Status != BME680_OK) {
    		return false;
    	}
    
    	bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temp, Pres, Hum & Gas
    	uint8_t nInputs = 0, nOutputs = 0;
    
    	if (_data.status & BME680_NEW_DATA_MSK) {
    		if (bme680Settings.process_data & BSEC_PROCESS_TEMPERATURE) {
    			inputs[nInputs].sensor_id = BSEC_INPUT_TEMPERATURE;
    			inputs[nInputs].signal = _data.temperature/100.0f; // Need to divide by 100 for fp
    			inputs[nInputs].time_stamp = currTimeNs;
    			nInputs++;
    			/* Temperature offset from the real temperature due to external heat sources */
    			inputs[nInputs].sensor_id = BSEC_INPUT_HEATSOURCE;
    			inputs[nInputs].signal = _tempOffset;
    			inputs[nInputs].time_stamp = currTimeNs;
    			nInputs++;
    		}
    		if (bme680Settings.process_data & BSEC_PROCESS_HUMIDITY) {
    			inputs[nInputs].sensor_id = BSEC_INPUT_HUMIDITY;
    			inputs[nInputs].signal = _data.humidity/1000.0f; // Need to divide by 1000 for fp;
    			inputs[nInputs].time_stamp = currTimeNs;
    			nInputs++;
    		}
    		if (bme680Settings.process_data & BSEC_PROCESS_PRESSURE) {
    			inputs[nInputs].sensor_id = BSEC_INPUT_PRESSURE;
    			inputs[nInputs].signal = _data.pressure;
    			inputs[nInputs].time_stamp = currTimeNs;
    			nInputs++;
    		}
    		if (bme680Settings.process_data & BSEC_PROCESS_GAS) {
    			inputs[nInputs].sensor_id = BSEC_INPUT_GASRESISTOR;
    			inputs[nInputs].signal = _data.gas_resistance;
    			inputs[nInputs].time_stamp = currTimeNs;
    			nInputs++;
    		}
    	}
    
    

  • Hardware Contributor

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    ...
    inputs[nInputs].signal = _data.humidity/1000.0f; // Need to divide by 1000 for fp;
    ...

    WTF, they have a known bug in the library and we all have to discover it by ourselves?....

    How cool is that, you seem to have solved the problem I had.... 🙂

    BSEC library version 1.4.7.3
    Timestamp [ms], raw temperature [°C], pressure [hPa], raw relative humidity [%], gas [Ohm], IAQ, IAQ accuracy, temperature [°C], relative humidity [%], Static IAQ, CO2 equivalent, breath VOC equivalent
    End setup()
    279, 21.37, 94698.00, 57.66, 80982.00, 25.00, 0, 21.37, 57.66, 25.00, 500.00, 0.50
    3278, 21.21, 94700.00, 57.42, 111997.00, 25.00, 0, 21.15, 58.10, 25.00, 500.00, 0.50
    6278, 21.22, 94700.00, 57.25, 127972.00, 25.00, 0, 21.16, 57.80, 25.00, 500.00, 0.50
    9278, 21.22, 94702.00, 57.10, 135341.00, 25.00, 0, 21.16, 57.58, 25.00, 500.00, 0.50
    

    I hope I will have a graph in two days and I can compare the Bosch sensor to the NIDIR-Sensors...



  • @fotofieber I'm not sure they know.. haha I should tell them.

    Good luck and let me know how it goes!



  • They know about it. They keep their library up to date on Github:

    Here's the diff:

    https://github.com/BoschSensortec/BSEC-Arduino-library/commit/e9a10fe23739bb95650d2ab89ed37764a4ba3caf

    Here's the library link:

    https://github.com/BoschSensortec/BSEC-Arduino-library

    You probably downloaded it from the website just like I did.

    I'll have to update my repo and point it to this as a submodule.


  • Hardware Contributor

    @jaredwolff
    I downloaded the binaries from the Bosch site and the source library from the github repo.

    In the binaries archive is an arduino library with an example with the error, you found.... The github repo has no binaries and I couldn't get it up with the binary.

    The binary distribution of essential code makes it more complicated than it could be...

    The integration in platformio is not to complicated in my code. I only had to add (after investigating for some hours)

    build_flags =   -Llib/BSEC/src/esp32/
                    -lalgobsec
    


  • @FotoFieber how goes the testing?

    The BME680 and the SGP30 both correlate in their readings with temperature. This means when the temperature goes up and down, i've seen the TVOC reading go up and down as well. Hardly useful for a sensor that is supposed to tell you if your air is bad or not.

    Take a look at the screenshot below:

    0_1560869706305_image.png

    You can see that both sensors react wildly to temperature. Whereas the CCS811 has a bump but not significantly. If I go by the scales in the data sheets for the BME680 and SGP30, the room that these sensors are in require immediate venting.

    Even right now, the SGP30 sensor is half way to the danger zone. 😵

    Danger zone!

    0_1560869685735_image.png

    While testing that, I also threw everything together into an enclosure. Even added GPS:

    0_1560869778746_image.png

    So it sits up in the kitchen and chirps at me when I burn my food. I switch on my air purifier and the particulate level goes down pretty quick!


  • Hardware Contributor

    Thank you for the feedback @jaredwolff, that is very useful.
    Do you confirm that you use the BSEC library for the BME680 and not direct values from the sensor ?



  • @nca78 I am using the BSEC library. I’m using the compensated humidity and temperature so I’m sure if that. I may have to take a second look at the code for both sensors. I may have mucked something up!


  • Hardware Contributor

    @jaredwolff
    My experiments with VOC sensors were all not satisfactory.

    The NDIR-sensors reported more or less the same as the netatmo devices and I will therefore stick with them. Apart from that, using the NDIR-sensors in arduino is much easier and you don't have to store baselines or link precompiled code.


  • Hardware Contributor

    @fotofieber said in Particle Powered Air Quality Sensor Logging to Google Docs:

    @jaredwolff
    My experiments with VOC sensors were all not satisfactory.

    The NDIR-sensors reported more or less the same as the netatmo devices and I will therefore stick with them. Apart from that, using the NDIR-sensors in arduino is much easier and you don't have to store baselines or link precompiled code.

    Of course sensors measuring CO2 will give better results than sensors trying to guess the CO2 levels by measuring something else.
    But the power consumption is way too high, my hope was to be able to have a battery (li-ion) powered sensor able to run the BME680 in low power settings for a few months and just use it as a warning on when you need to ventilate a room. Unfortunately it seems to not even be fit for this limited use case 😞



  • @nca78 I mean, you can run it on a battery. Just need a really big one! 😬

    Because of the internal heater it does make it hard to integrate into a battery powered application.

    I haven’t measured the low power mode on the BME. What were you getting @Nca78


  • Hardware Contributor

    @jaredwolff said in Particle Powered Air Quality Sensor Logging to Google Docs:

    I haven’t measured the low power mode on the BME. What were you getting @Nca78

    With 5mn interval it's supposed to use only 90uA, it's good enough for a li-ion battery of a reasonable size.



  • @nca78 agreed. It totally depends on the application. On a 225mA button cell that may not work especially if it has to last a year or two!



  • So @jaredwolff & @FotoFieber what sensor would you suggest to use for measuring air quality using an Arduino (nano/uno), with the option to make it battery powered in the future. From my understanding this will remove the BME from the list due to memory/computing requirements. What are your suggestions?



  • Hey @Sebex

    After running my setup for more than 8 months here are a few suggestions:

    1. If you care about particulates then the PM2.5 sensor works wonders. I've been using the HPMA115S0. It uses UART which you should be able to use with any Arduino variant.
    2. If you're more concerned with chemicals, a MOx sensor like the CCS811 is still my choice.

    The CCS811 is available as development boards from Adafruit and Sparkfun. The HPMA115S0 can be purchased from Arrow, Mouser and Digikey.

    I actually developed an all-in-one for Featherwing board. You can check that out for inspiration as well.


  • Hero Member

    Regarding the bme680, has anyone yet figured out the correct amount of pre-heating that should be applied to it, or is that still unknown? See https://forum.mysensors.org/topic/7788/bosch-bme680-sensor/15?_=1578489395821 .



  • @jaredwolff thanks. I noticed that for the CSS811 there's no mysensor sketch example, any suggestions for a good guide to build one myself?

    Something else I wondered is adding multiple sensors to 1 pin. I want to combine the CCS811 with the Si7021 that I am running now on an Arduino. Perhaps I don't necessarily need to use the same pins but lets say you have running X amount of sensors that it becomes inevitable to use a similar pin. Is it possible to share pins in arduino sketches, if so how does this work? Or is every value sent by the sensor tagged. Couldn't find the answer anywhere on the forum.


  • Hardware Contributor

    @Sebex said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Perhaps I don't necessarily need to use the same pins

    Both the sensors you quote are using I2C. So they both use the same 2 pins (SDA, SCL) to communicate. You can put many I2C sensors on those same pins, they each have an address to know which sensor is receiving/sending data to the master (here, your arduino).
    Look for a tutorial on I2C first.



  • @NeverDie

    I've set up the BME680 to use low power mode. I saw that the temperature readings were much higher in normal mode. Here's the init:

      // Begin BME680 work
      #ifdef HAS_BME680
      bsec.begin(BME680_I2C_ADDR_PRIMARY, Wire);
      checkIaqSensorStatus();
    
      // Set up BME680 sensors
      bsec_virtual_sensor_t sensorList[7] = {
        BSEC_OUTPUT_RAW_TEMPERATURE,
        BSEC_OUTPUT_RAW_PRESSURE,
        BSEC_OUTPUT_RAW_HUMIDITY,
        BSEC_OUTPUT_RAW_GAS,
        BSEC_OUTPUT_IAQ,
        BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
        BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY
      };
    
      bsec.updateSubscription(sensorList, 7, BSEC_SAMPLE_RATE_LP); //BSEC_SAMPLE_RATE_LP
      checkIaqSensorStatus();
      #endif
    

    @Sebex I agree with @Nca78, you can look into how I2C works. The cool thing is you can add up to 255 sensors as long as they have different addresses. (or if you do some tricky hardware stuff for devices with the same address) Unfortunately I only have implementations for my Featherwing.



  • @Nca78 said in Particle Powered Air Quality Sensor Logging to Google Docs:

    @Sebex said in Particle Powered Air Quality Sensor Logging to Google Docs:

    Perhaps I don't necessarily need to use the same pins

    Both the sensors you quote are using I2C. So they both use the same 2 pins (SDA, SCL) to communicate. You can put many I2C sensors on those same pins, they each have an address to know which sensor is receiving/sending data to the master (here, your arduino).
    Look for a tutorial on I2C first.

    Thanks I get it now 😄



Suggested Topics

27
Online

11.2k
Users

11.1k
Topics

112.5k
Posts