From 4bb434562fdeebe65a39c56ac6d7eac4ed438c0f Mon Sep 17 00:00:00 2001 From: achim Date: Sat, 11 Jun 2022 16:18:21 +0200 Subject: [PATCH] new examples --- examples/DIY_BASIC/DIY_BASIC.ino | 229 +++++++++++++++++++++++++++++ examples/DIY_PRO/DIY_PRO.ino | 242 +++++++++++++++++++++++++++++++ library.properties | 2 +- 3 files changed, 472 insertions(+), 1 deletion(-) create mode 100644 examples/DIY_BASIC/DIY_BASIC.ino create mode 100644 examples/DIY_PRO/DIY_PRO.ino diff --git a/examples/DIY_BASIC/DIY_BASIC.ino b/examples/DIY_BASIC/DIY_BASIC.ino new file mode 100644 index 0000000..8048862 --- /dev/null +++ b/examples/DIY_BASIC/DIY_BASIC.ino @@ -0,0 +1,229 @@ +/* +This is the code for the AirGradient DIY Air Quality Sensor with an ESP8266 Microcontroller. + +It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi. + +For build instructions please visit https://www.airgradient.com/diy/ + +The codes needs the following libraries installed: +“WifiManager by tzapu, tablatronix” tested with version 2.0.11-beta +"ESP8266 and ESP32 OLED driver for SSD1306 displays by ThingPulse, Fabrice Weinberg" tested with Version 4.1.0 + +Configuration: +Please set in the code below which sensor you are using and if you want to connect it to WiFi. + +If you have any questions please visit our forum at https://forum.airgradient.com/ + +If you are a school or university contact us for a free trial on the AirGradient platform. +https://www.airgradient.com/schools/ + +MIT License + +*/ + + +#include +#include +#include +#include +#include +#include +#include "SSD1306Wire.h" + +AirGradient ag = AirGradient(); + +SSD1306Wire display(0x3c, SDA, SCL); + +unsigned long currentMillis = 0; + +const int oledInterval = 5000; +unsigned long previousOled = 0; + +const int sendToServerInterval = 10000; +unsigned long previoussendToServer = 0; + +const int co2Interval = 5000; +unsigned long previousCo2 = 0; +int Co2 = 0; + +const int pm25Interval = 5000; +unsigned long previousPm25 = 0; +int pm25 = 0; + +const int tempHumInterval = 2500; +unsigned long previousTempHum = 0; +float temp = 0; +int hum = 0; +int displaypage = 0; + +String APIROOT = "http://hw.airgradient.com/"; + +// set to true to switch PM2.5 from ug/m3 to US AQI +boolean inUSaqi = true; + +// set to true to switch from Celcius to Fahrenheit +boolean inF = true; + +// set to true if you want to connect to wifi. The display will show values only when the sensor has wifi connection +boolean connectWIFI=true; + + +void setup() +{ + Serial.begin(115200); + + display.init(); + display.flipScreenVertically(); + + if (connectWIFI) { + connectToWifi(); + } + + showTextRectangle("Init", String(ESP.getChipId(), HEX), true); + + ag.CO2_Init(); + ag.PMS_Init(); + ag.TMP_RH_Init(0x44); +} + + +void loop() +{ + currentMillis = millis(); + updateOLED(); + updateCo2(); + updatePm25(); + updateTempHum(); + sendToServer(); +} + +void updateCo2() +{ + if (currentMillis - previousCo2 >= co2Interval) { + previousCo2 += co2Interval; + Co2 = ag.getCO2_Raw(); + Serial.println(String(Co2)); + } +} + +void updatePm25() +{ + if (currentMillis - previousPm25 >= pm25Interval) { + previousPm25 += pm25Interval; + pm25 = ag.getPM2_Raw(); + Serial.println(String(pm25)); + } +} + +void updateTempHum() +{ + if (currentMillis - previousTempHum >= tempHumInterval) { + previousTempHum += tempHumInterval; + TMP_RH result = ag.periodicFetchData(); + temp = result.t; + hum = result.rh; + Serial.println(String(temp)); + } +} + +void updateOLED() { + if (currentMillis - previousOled >= oledInterval) { + previousOled += oledInterval; + +switch (displaypage) { + case 0: + if (inUSaqi) { + showTextRectangle("AQI", String(PM_TO_AQI_US(pm25)), false); + } else { + showTextRectangle("PM2", String(pm25), false); + } + displaypage = 1; + break; + case 1: + showTextRectangle("CO2", String(Co2), false); + displaypage = 2; + break; + case 2: + if (inF) { + showTextRectangle("F", String((temp * 9 / 5) + 32), false); + } else { + showTextRectangle("C", String(temp), false); + } + displaypage = 3; + break; + case 3: + showTextRectangle("Hum", String(hum)+"%", false); + displaypage = 0; + break; + } + } +} + +void showTextRectangle(String ln1, String ln2, boolean small) { + display.clear(); + display.setTextAlignment(TEXT_ALIGN_LEFT); + if (small) { + display.setFont(ArialMT_Plain_16); + } else { + display.setFont(ArialMT_Plain_24); + } + display.drawString(32, 16, ln1); + display.drawString(32, 38, ln2); + display.display(); +} + +void sendToServer() { + if (currentMillis - previoussendToServer >= sendToServerInterval) { + previoussendToServer += sendToServerInterval; + String payload = "{\"wifi\":" + String(WiFi.RSSI()) + + ", \"rco2\":" + String(Co2) + + ", \"pm02\":" + String(pm25) + + ", \"atmp\":" + String(temp) + + ", \"rhum\":" + String(hum) + + "}"; + + if(WiFi.status()== WL_CONNECTED){ + Serial.println(payload); + String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(), HEX) + "/measures"; + Serial.println(POSTURL); + WiFiClient client; + HTTPClient http; + http.begin(client, POSTURL); + http.addHeader("content-type", "application/json"); + int httpCode = http.POST(payload); + String response = http.getString(); + Serial.println(httpCode); + Serial.println(response); + http.end(); + } + else { + Serial.println("WiFi Disconnected"); + } + } +} + +// Wifi Manager + void connectToWifi() { + WiFiManager wifiManager; + //WiFi.disconnect(); //to delete previous saved hotspot + String HOTSPOT = "AIRGRADIENT-" + String(ESP.getChipId(), HEX); + wifiManager.setTimeout(120); + if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) { + Serial.println("failed to connect and hit timeout"); + delay(3000); + ESP.restart(); + delay(5000); + } +} + +// Calculate PM2.5 US AQI +int PM_TO_AQI_US(int pm02) { + if (pm02 <= 12.0) return ((50 - 0) / (12.0 - .0) * (pm02 - .0) + 0); + else if (pm02 <= 35.4) return ((100 - 50) / (35.4 - 12.0) * (pm02 - 12.0) + 50); + else if (pm02 <= 55.4) return ((150 - 100) / (55.4 - 35.4) * (pm02 - 35.4) + 100); + else if (pm02 <= 150.4) return ((200 - 150) / (150.4 - 55.4) * (pm02 - 55.4) + 150); + else if (pm02 <= 250.4) return ((300 - 200) / (250.4 - 150.4) * (pm02 - 150.4) + 200); + else if (pm02 <= 350.4) return ((400 - 300) / (350.4 - 250.4) * (pm02 - 250.4) + 300); + else if (pm02 <= 500.4) return ((500 - 400) / (500.4 - 350.4) * (pm02 - 350.4) + 400); + else return 500; +}; diff --git a/examples/DIY_PRO/DIY_PRO.ino b/examples/DIY_PRO/DIY_PRO.ino new file mode 100644 index 0000000..33d5cbf --- /dev/null +++ b/examples/DIY_PRO/DIY_PRO.ino @@ -0,0 +1,242 @@ +/* +This is the code for the AirGradient DIY Air Quality Sensor with an ESP8266 Microcontroller. + +It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi. + +For build instructions please visit https://www.airgradient.com/diy/ + +Instructions on using the TVOC sensor (SGP30) instead of the Temperature / Humidity sensor (SHT3x). + +https://www.airgradient.com/resources/tvoc-on-airgradient-diy-sensor/ + +The codes needs the following libraries installed: +“WifiManager by tzapu, tablatronix” tested with version 2.0.11-beta +“U8g2” by oliver tested with version 2.32.15 +“SGP30” by Rob Tilaart tested with Version 0.1.5 + +Configuration: +Please set in the code below which sensor you are using and if you want to connect it to WiFi. + +If you have any questions please visit our forum at https://forum.airgradient.com/ + +If you are a school or university contact us for a free trial on the AirGradient platform. +https://www.airgradient.com/schools/ + +MIT License + +*/ + + +#include +#include +#include +#include +#include + +#include "SGP30.h" +#include + +AirGradient ag = AirGradient(); +SGP30 SGP; +U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); + +unsigned long currentMillis = 0; + +const int oledInterval = 5000; +unsigned long previousOled = 0; + +const int sendToServerInterval = 10000; +unsigned long previoussendToServer = 0; + +const int tvocInterval = 1000; +unsigned long previousTVOC = 0; +int TVOC = 0; + +const int co2Interval = 5000; +unsigned long previousCo2 = 0; +int Co2 = 0; + +const int pm25Interval = 5000; +unsigned long previousPm25 = 0; +int pm25 = 0; + +const int tempHumInterval = 2500; +unsigned long previousTempHum = 0; +float temp = 0; +int hum = 0; + +String APIROOT = "http://hw.airgradient.com/"; + +// set to true to switch PM2.5 from ug/m3 to US AQI +boolean inUSaqi = true; + +// set to true to switch from Celcius to Fahrenheit +boolean inF = true; + +// set to true if you want to connect to wifi. The display will show values only when the sensor has wifi connection +boolean connectWIFI=true; + + +void setup() +{ + Serial.begin(115200); + + u8g2.begin(); + updateOLED(); + + if (connectWIFI) { + connectToWifi(); + } + + updateOLED2("Warming up the", "sensors.", ""); + + Serial.println(SGP.begin()); + SGP.GenericReset(); + + ag.CO2_Init(); + ag.PMS_Init(); + ag.TMP_RH_Init(0x44); +} + + +void loop() +{ + currentMillis = millis(); + updateTVOC(); + updateOLED(); + updateCo2(); + updatePm25(); + updateTempHum(); + sendToServer(); +} + +void updateTVOC() +{ + if (currentMillis - previousTVOC >= tvocInterval) { + previousTVOC += tvocInterval; + SGP.measure(true); + TVOC = SGP.getTVOC(); + Serial.println(String(TVOC)); + } +} + +void updateCo2() +{ + if (currentMillis - previousCo2 >= co2Interval) { + previousCo2 += co2Interval; + Co2 = ag.getCO2_Raw(); + Serial.println(String(Co2)); + } +} + +void updatePm25() +{ + if (currentMillis - previousPm25 >= pm25Interval) { + previousPm25 += pm25Interval; + pm25 = ag.getPM2_Raw(); + Serial.println(String(pm25)); + } +} + +void updateTempHum() +{ + if (currentMillis - previousTempHum >= tempHumInterval) { + previousTempHum += tempHumInterval; + TMP_RH result = ag.periodicFetchData(); + temp = result.t; + hum = result.rh; + Serial.println(String(temp)); + } +} + +void updateOLED() { + if (currentMillis - previousOled >= oledInterval) { + previousOled += oledInterval; + String ln1; + String ln2; + if (inUSaqi) { + ln1 = "CO2:" + String(Co2) + " AQI:" + String(PM_TO_AQI_US(pm25)); + } else { + ln1 = "CO2:" + String(Co2) + " PM:" + String(pm25); + } + + if (inF) { + ln2 = "F:" + String((temp* 9 / 5) + 32) + " H:" + String(hum)+"%"; + } else { + ln2 = "C:" + String(temp) + " H:" + String(hum)+"%"; + } + + String ln3 = "TVOC:" + String(TVOC) ; + updateOLED2(ln1, ln2, ln3); + } +} + +void updateOLED2(String ln1, String ln2, String ln3) { + char buf[9]; + u8g2.firstPage(); + u8g2.firstPage(); + do { + u8g2.setFont(u8g2_font_t0_16_tf); + u8g2.drawStr(1, 10, String(ln1).c_str()); + u8g2.drawStr(1, 30, String(ln2).c_str()); + u8g2.drawStr(1, 50, String(ln3).c_str()); + } while ( u8g2.nextPage() ); +} + +void sendToServer() { + if (currentMillis - previoussendToServer >= sendToServerInterval) { + previoussendToServer += sendToServerInterval; + String payload = "{\"wifi\":" + String(WiFi.RSSI()) + + ", \"rco2\":" + String(Co2) + + ", \"pm02\":" + String(pm25) + + ", \"tvoc\":" + String(TVOC) + + ", \"atmp\":" + String(temp) + + ", \"rhum\":" + String(hum) + + "}"; + + if(WiFi.status()== WL_CONNECTED){ + Serial.println(payload); + String POSTURL = APIROOT + "sensors/airgradient:" + String(ESP.getChipId(), HEX) + "/measures"; + Serial.println(POSTURL); + WiFiClient client; + HTTPClient http; + http.begin(client, POSTURL); + http.addHeader("content-type", "application/json"); + int httpCode = http.POST(payload); + String response = http.getString(); + Serial.println(httpCode); + Serial.println(response); + http.end(); + } + else { + Serial.println("WiFi Disconnected"); + } + } +} + +// Wifi Manager + void connectToWifi() { + WiFiManager wifiManager; + //WiFi.disconnect(); //to delete previous saved hotspot + String HOTSPOT = "AG-" + String(ESP.getChipId(), HEX); + updateOLED2("To setup connect", "to Wifi Hotspot", HOTSPOT); + wifiManager.setTimeout(120); + if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) { + Serial.println("failed to connect and hit timeout"); + delay(3000); + ESP.restart(); + delay(5000); + } +} + +// Calculate PM2.5 US AQI +int PM_TO_AQI_US(int pm02) { + if (pm02 <= 12.0) return ((50 - 0) / (12.0 - .0) * (pm02 - .0) + 0); + else if (pm02 <= 35.4) return ((100 - 50) / (35.4 - 12.0) * (pm02 - 12.0) + 50); + else if (pm02 <= 55.4) return ((150 - 100) / (55.4 - 35.4) * (pm02 - 35.4) + 100); + else if (pm02 <= 150.4) return ((200 - 150) / (150.4 - 55.4) * (pm02 - 55.4) + 150); + else if (pm02 <= 250.4) return ((300 - 200) / (250.4 - 150.4) * (pm02 - 150.4) + 200); + else if (pm02 <= 350.4) return ((400 - 300) / (350.4 - 250.4) * (pm02 - 250.4) + 300); + else if (pm02 <= 500.4) return ((500 - 400) / (500.4 - 350.4) * (pm02 - 350.4) + 400); + else return 500; +}; diff --git a/library.properties b/library.properties index 00d9417..a633f0c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=AirGradient Air Quality Sensor -version=1.4.2 +version=1.5.0 author=AirGradient maintainer=AirGradient sentence=ESP8266 library for an air quality sensor featuring PM2.5, CO2, Temperature and Humidity with OLED display.