Advertisement
CuriousScientist

Arduino air quality, CCS811, BME280, Dust sensor

May 23rd, 2020
173
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //If you found this code useful, please subscribe to my channel: https://www.youtube.com/c/CuriousScientist?sub_confirmation=1
  2. //It took several hours for me to prepare everything, but subscription is just a click for you. Thank you!
  3. //This code belongs to the following tutorial video: https://youtu.be/6w7Js9SOPwM
  4.  
  5. //Info: GP2Y1010AU0F Dust sensor
  6. //The dust sensor reaches the maximum output pulse 0.28 ms after the LED was turned on
  7. //This sensor is based on voltage measurement
  8. //CCS811 is a thermometer-VOC meter and uses a premade library -I2C
  9. //BME280 is a thermometer, humidity and pressure sensor - I2C
  10. //OLED: any OLED display can be used, this particular tutorial uses the 128x32 type - I2C
  11.  
  12. //OLED Libraries
  13. #include "SSD1306Ascii.h"
  14. #include "SSD1306AsciiAvrI2c.h"
  15. #define I2C_ADDRESS 0x3C //Address
  16. #define RST_PIN -1 //For OLED with no reset pin
  17. SSD1306AsciiAvrI2c display;
  18.  
  19. #include <Wire.h>
  20.  
  21. //VOC sensor
  22. #include "Adafruit_CCS811.h" //We load the library for the gas sensor
  23. #include <Adafruit_Sensor.h>
  24. #include <Adafruit_BME280.h>
  25. Adafruit_CCS811 ccs;
  26.  
  27. //BME280
  28. Adafruit_BME280 bme; // I2C
  29. //Use these #define lines if you want to use it with SPI
  30. //#define BME_SCK 13
  31. //#define BME_MISO 12
  32. //#define BME_MOSI 11
  33. //#define BME_CS 10
  34. #define SEALEVELPRESSURE_HPA (1013.25)
  35.  
  36. //-------------------------------------------
  37. //variables
  38. float co2Amount; //Amount (ug/m^3) of CO2
  39. float CCSTemp; //temperature measured by the CCS811
  40.  
  41. //Dust sensor
  42. int dustmeasurePin = A3; //The output of the dust sensor is connected to A3 (AD converter pin)
  43. int dustLEDPin = 2; //The IR pin inside the dust sensor is connected to D2 (digital output pin)
  44. float outBits = 0; //AD-converter raw output
  45. float dustDensity = 0; //dust density, based on the formula
  46.  
  47. //BME280  - Temperature, humidity and pressure sensor.
  48. float BME280Temp;
  49. float BME280Humidity;
  50. float BME280Pressure;
  51. float BME280Altitude;
  52.  
  53. unsigned long delayTime; //delaytime for BME280 library
  54.  
  55. //String for storing the formatted output data (serial port)
  56. String outputData;
  57.  
  58. void setup()
  59. {
  60.     Serial.begin(9600); //Start serial
  61.  
  62.     Serial.println("*Dust and VOC sensor"); //Print message. I use '*' to tell the receiver software that this is not a measurement data
  63.  
  64.   //CCS
  65.     if(!ccs.begin()) //if we are not able to start the VOC sensor, print the following message
  66.     {
  67.         Serial.println("* Failed to start sensor! Please check your wiring.");
  68.         while(1); //And hold the code here
  69.     }
  70.    
  71.     while(!ccs.available());
  72.   //endofCCS
  73.  
  74.     float temp = ccs.calculateTemperature(); //calculate the temperature
  75.     ccs.setTempOffset(temp - 25.0); //set the offset using the  
  76.   //BME280
  77.    unsigned status;
  78.    status = bme.begin(0x76);
  79.    if (!status) {
  80.         Serial.println("*Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
  81.         Serial.print("*SensorID was: 0x"); Serial.println(bme.sensorID(),16);
  82.         Serial.print("*        ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
  83.         Serial.print("*   ID of 0x56-0x58 represents a BMP 280,\n");
  84.         Serial.print("*        ID of 0x60 represents a BME 280.\n");
  85.         Serial.print("*        ID of 0x61 represents a BME 680.\n");
  86.         while (1) delay(10);
  87.     }    
  88.     delayTime = 1000;
  89.    //endofBME280
  90.  
  91.   //OLED part
  92.   #if RST_PIN >= 0
  93.   display.begin(&Adafruit128x32, I2C_ADDRESS, RST_PIN);
  94.   #else // RST_PIN >= 0
  95.   display.begin(&Adafruit128x32, I2C_ADDRESS);
  96.   #endif // RST_PIN >= 0
  97.   //Call oled.setI2cClock(frequency) to change from the default frequency.
  98.  
  99.   display.setFont(System5x7);
  100.   display.set1X();
  101.   display.clear();
  102.   //--endofOLED----
  103.  
  104.   pinMode(dustLEDPin,OUTPUT); //the pin for the dust sensor's LED is set as an output
  105. }
  106.  
  107. void loop()
  108. {
  109.   //we do this part outside of the serial as well, since we need to measure anyway if we want to see the info on the OLED
  110.        measureDust();
  111.        delay(500);
  112.        measureVOCs();
  113.        delay(500);
  114.        MeasureBME280();
  115.        delay(500);
  116.        //Printing the data on the OLED
  117.        refreshOLED();
  118.        delay(1000);
  119.   //
  120.  
  121.   //We only enter this part, if we sent a character "S" to the serial
  122.   //The printing can be stopped by sending an "N"
  123.     if (Serial.available() > 0) //if there's something on the serial
  124.     {
  125.     char commandCharacter = Serial.read(); //we use characters (letters) for controlling the switch-case
  126.  
  127.         switch (commandCharacter)
  128.         {
  129.           case 'S': //S: start
  130.  
  131.           while(Serial.read() != 'N') //while we don't send N through the serial, the following functions are looping:
  132.           {        
  133.        measureDust();
  134.        delay(500);
  135.        measureVOCs();
  136.        delay(500);
  137.        MeasureBME280();
  138.        delay(500);
  139.        //Printing the data on the OLED
  140.        refreshOLED();
  141.        delay(1000);
  142.              printFormattedData();     //prints the pre-formatted line on the serial port
  143.        
  144.           }
  145.           break;
  146.  
  147.           default:
  148.               //
  149.           break;
  150.           }    
  151.   }
  152. }
  153.  
  154. void measureDust()
  155. {
  156.   digitalWrite(dustLEDPin,LOW); //turn ON the LED
  157.  
  158.   delayMicroseconds(280); // wait 0.28 ms = 280 us
  159.  
  160.   outBits = analogRead(dustmeasurePin); //measure the peak of the output pulse  
  161.  
  162.   digitalWrite(dustLEDPin,HIGH); //turn OFF the LED    
  163.  
  164.   /*
  165.   If you want to get the converted data on the Arduino terminal,
  166.   //uncomment this part and replace the outbits to dustDensity in printFormattedData()
  167.  
  168.   dustDensity = 1000* ( 0.17 * ((5.0 / 1024) * outBits) - 0.1); //dust density in ug/m^3
  169.   */
  170.  
  171. }
  172.  
  173. void measureVOCs()
  174. {
  175.     if(ccs.available()) //If we can communicate with the VOC sensor
  176.     {
  177.         if(!ccs.readData()) //if we are not reading (i.e. the devide is available)
  178.         {
  179.             co2Amount = ccs.geteCO2(); //read CO2
  180.             ccs.getTVOC(); //read temperature
  181.             CCSTemp = ccs.calculateTemperature(); //calculate temperature
  182.         }
  183.         else
  184.         {
  185.             Serial.println("ERROR!"); //Print error message
  186.             while(1); //wait here
  187.         }
  188.     }
  189. }
  190.  
  191. void printFormattedData() //Formatting the output so the receiver software can process it
  192. {  
  193.                            
  194.   outputData = (String)CCSTemp +  '\t' + (String)BME280Temp + '\t' + (String)bme.readHumidity() + '\t' + (String)BME280Pressure + '\t'
  195.   + (String)outBits + '\t' + (String)co2Amount; //for the output
  196.   Serial.println(outputData); //print the formatted line
  197.  
  198.   //Format on serial output: Temp1 (CCS) /tab/ Temp2 (BME) /tab/ Humidity /tab/ Pressure /tab/ Dust /tab/ CO2 /newline/
  199.  
  200.   //outBits can be replaced to dustDensity to print the converted data instead of the raw data.  
  201.   //dustDensity = 1000* ( 0.17 * ((5.0 / 1024) * outBits) - 0.1); //dust density in ug/m^3
  202. }
  203.  
  204. void MeasureBME280()
  205. {
  206. //Reading all the available values from the BME280 chip
  207. BME280Temp = bme.readTemperature();
  208. BME280Humidity = bme.readHumidity();
  209. BME280Pressure = bme.readPressure() / 100.0F;
  210. BME280Altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);  
  211. }
  212.  
  213. void refreshOLED()
  214. {
  215.   //128x32 OLED
  216.   //1st line of the OLED
  217.   display.clear();  
  218.   display.setCursor(0, 0);
  219.   display.print("T: ");
  220.   display.print(BME280Temp);
  221.   display.print("C  H: ");
  222.   display.print(BME280Humidity);
  223.   display.println("%");
  224.  
  225.   //2nd line
  226.   display.setCursor(0, 1);
  227.   display.print("P: ");
  228.   display.print(BME280Pressure);
  229.   display.print(" A: ");
  230.   display.print(BME280Altitude);
  231.   display.println("m");
  232.    
  233.   //3rd line
  234.   display.setCursor(0, 2);
  235.   display.print("CO2: ");
  236.   display.print(co2Amount);  
  237.   display.print(" ppm");
  238.  
  239.   //4th line
  240.   display.setCursor(0, 3);
  241.   display.print("D: ");
  242.   display.print(1000* ( 0.17 * ((5.0 / 1024) * outBits) - 0.1));
  243.   display.println(" ug/m3");  
  244.  
  245. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement