Compare commits

...

3 Commits
2.4.3 ... 2.4.4

5 changed files with 64 additions and 856 deletions

View File

@ -10,6 +10,7 @@ Kits (including a pre-soldered version) are available: https://www.airgradient.c
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
"Arduino-SHT" by Johannes Winkelmann Version 1.2.2
Configuration:
Please set in the code below the configuration parameters.
@ -30,8 +31,10 @@ MIT License
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <U8g2lib.h>
#include "SHTSensor.h"
AirGradient ag = AirGradient();
SHTSensor sht;
U8G2_SSD1306_64X48_ER_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); //for DIY BASIC
@ -78,6 +81,8 @@ long val;
void setup()
{
Serial.begin(115200);
sht.init();
sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM);
u8g2.setBusClock(100000);
u8g2.begin();
updateOLED();
@ -88,7 +93,7 @@ void setup()
updateOLED2("Warm Up", "Serial#", String(ESP.getChipId(), HEX));
ag.CO2_Init();
ag.PMS_Init();
ag.TMP_RH_Init(0x44);
//ag.TMP_RH_Init(0x44);
}
@ -124,9 +129,19 @@ void updateTempHum()
{
if (currentMillis - previousTempHum >= tempHumInterval) {
previousTempHum += tempHumInterval;
TMP_RH result = ag.periodicFetchData();
temp = result.t;
hum = result.rh;
if (sht.readSample()) {
Serial.print("SHT:\n");
Serial.print(" RH: ");
Serial.print(sht.getHumidity(), 2);
Serial.print("\n");
Serial.print(" T: ");
Serial.print(sht.getTemperature(), 2);
Serial.print("\n");
temp = sht.getTemperature();
hum = sht.getHumidity();
} else {
Serial.print("Error in readSample()\n");
}
Serial.println(String(temp));
}
}

View File

@ -14,6 +14,7 @@ The codes needs the following libraries installed:
“U8g2” by oliver tested with version 2.32.15
"Sensirion I2C SGP41" by Sensation Version 0.1.0
"Sensirion Gas Index Algorithm" by Sensation Version 3.2.1
"Arduino-SHT" by Johannes Winkelmann Version 1.2.2
Configuration:
Please set in the code below the configuration parameters.
@ -35,6 +36,7 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
#include <WiFiClient.h>
#include <EEPROM.h>
#include "SHTSensor.h"
//#include "SGP30.h"
#include <SensirionI2CSgp41.h>
@ -48,6 +50,8 @@ AirGradient ag = AirGradient();
SensirionI2CSgp41 sgp41;
VOCGasIndexAlgorithm voc_algorithm;
NOxGasIndexAlgorithm nox_algorithm;
SHTSensor sht;
// time in seconds needed for NOx conditioning
uint16_t conditioning_s = 10;
@ -108,7 +112,7 @@ unsigned long previousTempHum = 0;
float temp = 0;
int hum = 0;
int buttonConfig=4;
int buttonConfig=0;
int lastState = LOW;
int currentState;
unsigned long pressedTime = 0;
@ -118,23 +122,28 @@ void setup() {
Serial.begin(115200);
Serial.println("Hello");
u8g2.begin();
sht.init();
sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM);
//u8g2.setDisplayRotation(U8G2_R0);
EEPROM.begin(512);
delay(500);
buttonConfig = String(EEPROM.read(addr)).toInt();
if (buttonConfig>3) buttonConfig=0;
delay(400);
setConfig();
Serial.println("buttonConfig: "+String(buttonConfig));
updateOLED2("Press Button", "Now for", "Config Menu");
delay(2000);
pinMode(D7, INPUT_PULLUP);
currentState = digitalRead(D7);
if (currentState == HIGH)
if (currentState == LOW)
{
updateOLED2("Entering", "Config Menu", "");
delay(3000);
lastState = LOW;
lastState = HIGH;
setConfig();
inConf();
}
@ -164,20 +173,26 @@ void inConf(){
setConfig();
currentState = digitalRead(D7);
if(lastState == LOW && currentState == HIGH) {
if (currentState){
Serial.println("currentState: high");
} else {
Serial.println("currentState: low");
}
if(lastState == HIGH && currentState == LOW) {
pressedTime = millis();
}
else if(lastState == HIGH && currentState == LOW) {
else if(lastState == LOW && currentState == HIGH) {
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if( pressDuration < 1000 ) {
buttonConfig=buttonConfig+1;
if (buttonConfig>7) buttonConfig=0;
if (buttonConfig>3) buttonConfig=0;
}
}
if (lastState == HIGH && currentState == HIGH){
if (lastState == LOW && currentState == LOW){
long passedDuration = millis() - pressedTime;
if( passedDuration > 4000 ) {
// to do
@ -208,43 +223,23 @@ void inConf(){
void setConfig() {
if (buttonConfig == 0) {
updateOLED2("Temp. in C", "PM in ug/m3", "Display Top");
u8g2.setDisplayRotation(U8G2_R2);
inF = false;
inUSAQI = false;
} else if (buttonConfig == 1) {
updateOLED2("Temp. in C", "PM in US AQI", "Display Top");
u8g2.setDisplayRotation(U8G2_R2);
inF = false;
inUSAQI = true;
} else if (buttonConfig == 2) {
updateOLED2("Temp. in F", "PM in ug/m3", "Display Top");
u8g2.setDisplayRotation(U8G2_R2);
inF = true;
inUSAQI = false;
} else if (buttonConfig == 3) {
updateOLED2("Temp. in F", "PM in US AQI", "Display Top");
u8g2.setDisplayRotation(U8G2_R2);
inF = true;
inUSAQI = true;
} else if (buttonConfig == 4) {
updateOLED2("Temp. in C", "PM in ug/m3", "Display Bottom");
updateOLED2("Temp. in C", "PM in ug/m3", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0);
inF = false;
inUSAQI = false;
}
if (buttonConfig == 5) {
updateOLED2("Temp. in C", "PM in US AQI", "Display Bottom");
if (buttonConfig == 1) {
updateOLED2("Temp. in C", "PM in US AQI", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0);
inF = false;
inUSAQI = true;
} else if (buttonConfig == 6) {
updateOLED2("Temp. in F", "PM in ug/m3", "Display Bottom");
} else if (buttonConfig == 2) {
updateOLED2("Temp. in F", "PM in ug/m3", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0);
inF = true;
inUSAQI = false;
} else if (buttonConfig == 7) {
updateOLED2("Temp. in F", "PM in US AQI", "Display Bottom");
} else if (buttonConfig == 3) {
updateOLED2("Temp. in F", "PM in US AQI", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0);
inF = true;
inUSAQI = true;
@ -314,9 +309,20 @@ void updateTempHum()
{
if (currentMillis - previousTempHum >= tempHumInterval) {
previousTempHum += tempHumInterval;
TMP_RH result = ag.periodicFetchData();
temp = result.t;
hum = result.rh;
if (sht.readSample()) {
Serial.print("SHT:\n");
Serial.print(" RH: ");
Serial.print(sht.getHumidity(), 2);
Serial.print("\n");
Serial.print(" T: ");
Serial.print(sht.getTemperature(), 2);
Serial.print("\n");
temp = sht.getTemperature();
hum = sht.getHumidity();
} else {
Serial.print("Error in readSample()\n");
}
Serial.println(String(temp));
}
}

View File

@ -1,310 +0,0 @@
/*
This is the code for the AirGradient DIY PRO Air Quality Sensor with an ESP8266 Microcontroller with the SGP40 TVOC module from AirGradient.
It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi.
Build Instructions: https://www.airgradient.com/open-airgradient/instructions/diy-pro/
Kits (including a pre-soldered version) are available: https://www.airgradient.com/open-airgradient/kits/
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
"Sensirion I2C SGP41" by Sensation Version 0.1.0
"Sensirion Gas Index Algorithm" by Sensation Version 3.2.1
Configuration:
Please set in the code below the configuration parameters.
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/
MIT License
*/
#include <AirGradient.h>
#include <WiFiManager.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
//#include "SGP30.h"
#include <SensirionI2CSgp41.h>
#include <NOxGasIndexAlgorithm.h>
#include <VOCGasIndexAlgorithm.h>
#include <U8g2lib.h>
AirGradient ag = AirGradient();
SensirionI2CSgp41 sgp41;
VOCGasIndexAlgorithm voc_algorithm;
NOxGasIndexAlgorithm nox_algorithm;
// time in seconds needed for NOx conditioning
uint16_t conditioning_s = 10;
// Display bottom right
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// Replace above if you have display on top left
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R2, /* reset=*/ U8X8_PIN_NONE);
// CONFIGURATION START
//set to the endpoint you would like to use
String APIROOT = "http://hw.airgradient.com/";
// set to true to switch from Celcius to Fahrenheit
boolean inF = false;
// set to true if you want to connect to wifi. You have 60 seconds to connect. Then it will go into an offline mode.
boolean connectWIFI=true;
// CONFIGURATION END
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;
int NOX = 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;
void setup()
{
Serial.begin(115200);
u8g2.setBusClock(100000);
u8g2.begin();
updateOLED();
if (connectWIFI) {
connectToWifi();
}
updateOLED2("Warming up the", "sensors.", "");
sgp41.begin(Wire);
ag.CO2_Init();
ag.PMS_Init();
ag.TMP_RH_Init(0x44);
}
void loop()
{
currentMillis = millis();
updateTVOC();
updateOLED();
updateCo2();
updatePm25();
updateTempHum();
sendToServer();
}
void updateTVOC()
{
uint16_t error;
char errorMessage[256];
uint16_t defaultRh = 0x8000;
uint16_t defaultT = 0x6666;
uint16_t srawVoc = 0;
uint16_t srawNox = 0;
uint16_t defaultCompenstaionRh = 0x8000; // in ticks as defined by SGP41
uint16_t defaultCompenstaionT = 0x6666; // in ticks as defined by SGP41
uint16_t compensationRh = 0; // in ticks as defined by SGP41
uint16_t compensationT = 0; // in ticks as defined by SGP41
delay(1000);
compensationT = static_cast<uint16_t>((temp + 45) * 65535 / 175);
compensationRh = static_cast<uint16_t>(hum * 65535 / 100);
// 3. Measure SGP4x signals
if (conditioning_s > 0) {
// During NOx conditioning (10s) SRAW NOx will remain 0
error = sgp41.executeConditioning(compensationRh, compensationT, srawVoc);
conditioning_s--;
} else {
// Read Measurement
error = sgp41.measureRawSignals(compensationRh, compensationT, srawVoc,
srawNox);
}
if (error) {
Serial.print("Error trying to execute measureRawSignals(): ");
errorToString(error, errorMessage, 256);
Serial.println(errorMessage);
} else {
Serial.print("SRAW_VOC:");
Serial.print(srawVoc);
Serial.print("\t");
Serial.print("SRAW_NOx:");
Serial.println(srawNox);
}
if (currentMillis - previousTVOC >= tvocInterval) {
previousTVOC += tvocInterval;
TVOC = voc_algorithm.process(srawVoc);
NOX = nox_algorithm.process(srawNox);
// TVOC = sgp40.getVoclndex();
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 ln3;
String ln1 = "PM:" + String(pm25) + " CO2:" + String(Co2);
// String ln2 = "AQI:" + String(PM_TO_AQI_US(pm25)) + " TVOC:" + String(TVOC);
String ln2 = "TVOC:" + String(TVOC) + " NOX:" + String(NOX);
if (inF) {
ln3 = "F:" + String((temp* 9 / 5) + 32) + " H:" + String(hum)+"%";
} else {
ln3 = "C:" + String(temp) + " H:" + String(hum)+"%";
}
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())
+ (Co2 < 0 ? "" : ", \"rco2\":" + String(Co2))
+ (pm25 < 0 ? "" : ", \"pm02\":" + String(pm25))
+ (TVOC < 0 ? "" : ", \"tvoc_index\":" + String(TVOC))
+ (NOX < 0 ? "" : ", \"nox_index\":" + String(NOX))
+ ", \"atmp\":" + String(temp)
+ (hum < 0 ? "" : ", \"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("60s to connect", "to Wifi Hotspot", HOTSPOT);
wifiManager.setTimeout(60);
WiFiManagerParameter custom_text("<p>This is just a text paragraph</p>");
wifiManager.addParameter(&custom_text);
WiFiManagerParameter parameter("parameterId", "Parameter Label", "default value", 40);
wifiManager.addParameter(&parameter);
Serial.println("Parameter 1:");
Serial.println(parameter.getValue());
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
updateOLED2("booting into", "offline mode", "");
Serial.println("failed to connect and hit timeout");
delay(6000);
}
Serial.println("Parameter 2:");
Serial.println(parameter.getValue());
}
// 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;
};

View File

@ -1,248 +0,0 @@
/*
This is the code for the AirGradient DIY PRO 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.
Build Instructions: https://www.airgradient.com/open-airgradient/instructions/diy-pro/
Kits (including a pre-soldered version) are available: https://www.airgradient.com/open-airgradient/kits/
IMPORTANT: If you use SGP30 modules, you need to remove the Pull up resistors to make it work.
See https://www.airgradient.com/open-airgradient/instructions/tvoc-on-airgradient-diy-sensor/
If you want to use TVOC we strongly recommend you use the AirGradient SGP4x module available in our online shop.
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 the configuration parameters.
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/
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
#include <AirGradient.h>
#include <WiFiManager.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include "SGP30.h"
#include <U8g2lib.h>
AirGradient ag = AirGradient();
SGP30 SGP;
// Display bottom right
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// Replace above if you have display on top left
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R2, /* reset=*/ U8X8_PIN_NONE);
// CONFIGURATION START
//set to the endpoint you would like to use
String APIROOT = "http://hw.airgradient.com/";
// set to true to switch from Celcius to Fahrenheit
boolean inF = false;
// set to true if you want to connect to wifi. You have 60 seconds to connect. Then it will go into an offline mode.
boolean connectWIFI=true;
// CONFIGURATION END
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;
void setup()
{
Serial.begin(115200);
u8g2.setBusClock(100000);
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 ln3;
String ln1 = "PM:" + String(pm25) + " CO2:" + String(Co2);
String ln2 = "AQI:" + String(PM_TO_AQI_US(pm25)) + " TVOC:" + String(TVOC);
if (inF) {
ln3 = "F:" + String((temp* 9 / 5) + 32) + " H:" + String(hum)+"%";
} else {
ln3 = "C:" + String(temp) + " H:" + String(hum)+"%";
}
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())
+ (Co2 < 0 ? "" : ", \"rco2\":" + String(Co2))
+ (pm25 < 0 ? "" : ", \"pm02\":" + String(pm25))
+ (TVOC < 0 ? "" : ", \"tvoc\":" + String(TVOC))
+ ", \"atmp\":" + String(temp)
+ (hum < 0 ? "" : ", \"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("60s to connect", "to Wifi Hotspot", HOTSPOT);
wifiManager.setTimeout(60);
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
updateOLED2("booting into", "offline mode", "");
Serial.println("failed to connect and hit timeout");
delay(6000);
}
}
// 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;
};

View File

@ -1,255 +0,0 @@
/*
This is the code for the AirGradient DIY PRO Air Quality Sensor with an ESP8266 Microcontroller with the SGP40 TVOC module from AirGradient.
It is a high quality sensor showing PM2.5, CO2, Temperature and Humidity on a small display and can send data over Wifi.
Build Instructions: https://www.airgradient.com/open-airgradient/instructions/diy-pro/
Kits (including a pre-soldered version) are available: https://www.airgradient.com/open-airgradient/kits/
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
“DFRobot_SGP40” by DFRobot tested with Version 1.0.3
Configuration:
Please set in the code below the configuration parameters.
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/
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
#include <AirGradient.h>
#include <WiFiManager.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
//#include "SGP30.h"
#include <DFRobot_SGP40.h>
#include <U8g2lib.h>
AirGradient ag = AirGradient();
DFRobot_SGP40 sgp40;
// Display bottom right
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// Replace above if you have display on top left
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R2, /* reset=*/ U8X8_PIN_NONE);
// CONFIGURATION START
//set to the endpoint you would like to use
String APIROOT = "http://hw.airgradient.com/";
// set to true to switch from Celcius to Fahrenheit
boolean inF = false;
// set to true if you want to connect to wifi. You have 60 seconds to connect. Then it will go into an offline mode.
boolean connectWIFI=true;
// CONFIGURATION END
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;
void setup()
{
Serial.begin(115200);
u8g2.setBusClock(100000);
u8g2.begin();
updateOLED();
if (connectWIFI) {
connectToWifi();
}
updateOLED2("Warming up the", "sensors.", "");
sgp40.begin();
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;
TVOC = sgp40.getVoclndex();
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 ln3;
String ln1 = "PM:" + String(pm25) + " CO2:" + String(Co2);
String ln2 = "AQI:" + String(PM_TO_AQI_US(pm25)) + " TVOC:" + String(TVOC);
if (inF) {
ln3 = "F:" + String((temp* 9 / 5) + 32) + " H:" + String(hum)+"%";
} else {
ln3 = "C:" + String(temp) + " H:" + String(hum)+"%";
}
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())
+ (Co2 < 0 ? "" : ", \"rco2\":" + String(Co2))
+ (pm25 < 0 ? "" : ", \"pm02\":" + String(pm25))
+ (TVOC < 0 ? "" : ", \"tvoc_index\":" + String(TVOC))
+ ", \"atmp\":" + String(temp)
+ (hum < 0 ? "" : ", \"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("60s to connect", "to Wifi Hotspot", HOTSPOT);
wifiManager.setTimeout(60);
WiFiManagerParameter custom_text("<p>This is just a text paragraph</p>");
wifiManager.addParameter(&custom_text);
WiFiManagerParameter parameter("parameterId", "Parameter Label", "default value", 40);
wifiManager.addParameter(&parameter);
Serial.println("Parameter 1:");
Serial.println(parameter.getValue());
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
updateOLED2("booting into", "offline mode", "");
Serial.println("failed to connect and hit timeout");
delay(6000);
}
Serial.println("Parameter 2:");
Serial.println(parameter.getValue());
}
// 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;
};