Compare commits

..

6 Commits
2.4.0 ... 2.4.2

Author SHA1 Message Date
c53517cadf Updated outdoor C3 example 2023-04-13 15:03:31 +07:00
6314e52770 Updated indoor examples 2023-04-13 09:33:26 +07:00
43f599a0a7 Corrected Arduino JSON version 2023-03-22 15:55:16 +07:00
cfc37d2d96 Added example for PCB v4.2 2023-03-11 06:53:37 +07:00
693d1f78aa Adjusted license to CC BY-SA 2023-03-09 07:35:49 +07:00
ef802593a6 Updated default display orientation 2023-02-26 16:57:08 +07:00
14 changed files with 689 additions and 41 deletions

View File

@ -17,7 +17,8 @@ https://www.airgradient.com/
Kits with all required components are available at https://www.airgradient.com/open-airgradient/shop/
MIT License
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
#include <AirGradient.h>

View File

@ -21,7 +21,8 @@ If you have any questions please visit our forum at https://forum.airgradient.co
If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/
MIT License
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
#include <AirGradient.h>

View File

@ -85,9 +85,7 @@ void setup()
if (connectWIFI) {
connectToWifi();
}
updateOLED2("Warming", "up the", "sensors");
updateOLED2("Warm Up", "Serial#", String(ESP.getChipId(), HEX));
ag.CO2_Init();
ag.PMS_Init();
ag.TMP_RH_Init(0x44);
@ -207,9 +205,9 @@ void sendToServer() {
WiFiManager wifiManager;
//WiFi.disconnect(); //to delete previous saved hotspot
String HOTSPOT = "AG-" + String(ESP.getChipId(), HEX);
updateOLED2("Connect", "Wifi", HOTSPOT);
updateOLED2("Connect", "Wifi AG-", String(ESP.getChipId(), HEX));
delay(2000);
wifiManager.setTimeout(60);
wifiManager.setTimeout(90);
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
updateOLED2("Booting", "offline", "mode");
Serial.println("failed to connect and hit timeout");

View File

@ -14,7 +14,7 @@ If you have any questions please visit our forum at https://forum.airgradient.co
If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/
License: CC BY-NC 4.0 Attribution-NonCommercial 4.0 International
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
#include "PMS.h"

View File

@ -0,0 +1,242 @@
/*
Important: This code is only for the DIY OUTDOOR OPEN AIR Presoldered Kit with the ESP-C3.
It is a high quality outdoor air quality sensor with dual PM2.5 modules and can send data over Wifi.
Kits 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
“pms” by Markusz Kakl version 1.1.0 (needs to be patched for 5003T model)
For built instructions and how to patch the PMS library: https://www.airgradient.com/open-airgradient/instructions/diy-open-air-presoldered-v11/
If you have any questions please visit our forum at https://forum.airgradient.com/
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
#include "PMS.h"
#include <HardwareSerial.h>
#include <Wire.h>
#include <HTTPClient.h>
#include <WiFiManager.h>
#define DEBUG true
HTTPClient client;
PMS pms1(Serial0);
PMS::DATA data1;
PMS pms2(Serial1);
PMS::DATA data2;
float pm1Value=0;
int pm1Position = 0;
float pm2Value=0;
int pm2Position = 0;
float temp_pm1 = 0;
float hum_pm1 = 0;
float temp_pm2 = 0;
float hum_pm2 = 0;
unsigned long currentMillis = 0;
const int pm1Interval = 5000;
unsigned long previousPm1 = 0;
const int pm2Interval = 5000;
unsigned long previousPm2 = 0;
String APIROOT = "http://hw.airgradient.com/";
bool ledOn = false;
int loopCount = 0;
int averageCount = 10;
void debug(String msg) {
if (DEBUG)
Serial.print(msg);
}
void debug(int msg) {
if (DEBUG)
Serial.print(msg);
}
void debugln(String msg) {
if (DEBUG)
Serial.println(msg);
}
void debugln(int msg) {
if (DEBUG)
Serial.println(msg);
}
void switchLED(boolean ledON) {
if (ledON) {
digitalWrite(10, HIGH);
} else {
digitalWrite(10, LOW);
}
}
void IRAM_ATTR isr() {
debugln("pushed");
}
void postToServer(String postfix, int pm25,float tem, float hum) {
String payload = "{\"wifi\":" + String(WiFi.RSSI())
+ ", \"pm02\":" + String(pm25)
+ ", \"atmp\":" + String(tem/10)
+ ", \"rhum\":" + String(hum/10)
+ ", \"boot\":" + loopCount
+ "}";
if(WiFi.status()== WL_CONNECTED){
switchLED(true);
String url = APIROOT + "sensors/airgradient:" + getNormalizedMac() + postfix + "/measures";
debugln(url);
debugln(payload);
client.setConnectTimeout(5 * 1000);
client.begin(url);
client.addHeader("content-type", "application/json");
int httpCode = client.POST(payload);
debugln(httpCode);
client.end();
resetWatchdog();
switchLED(false);
}
else {
debug("post skipped, not network connection");
}
loopCount++;
}
void countdown(int from) {
debug("\n");
while (from > 0) {
debug(String(from--));
debug(" ");
delay(1000);
}
debug("\n");
}
// select board LOLIN C3 mini to flash
void setup() {
if (DEBUG) {
Serial.begin(115200);
// see https://github.com/espressif/arduino-esp32/issues/6983
Serial.setTxTimeoutMs(0); // <<<====== solves the delay issue
}
debug("starting ...");
// default hardware serial, PMS connector on the right side of the C3 mini on the Open Air
Serial0.begin(9600);
// second hardware serial, PMS connector on the left side of the C3 mini on the Open Air
Serial1.begin(9600, SERIAL_8N1, 0, 1);
// led
pinMode(10, OUTPUT);
// push button
pinMode(9, INPUT_PULLUP);
attachInterrupt(9, isr, FALLING);
pinMode(2, OUTPUT);
digitalWrite(2, LOW);
// give the PMSs some time to start
countdown(3);
connectToWifi();
switchLED(false);
}
void resetWatchdog() {
digitalWrite(2, HIGH);
delay(20);
digitalWrite(2, LOW);
}
void loop() {
if(WiFi.status()== WL_CONNECTED) {
if (pms1.readUntil(data1, 2000)) {
pm1Value=pm1Value+data1.PM_AE_UG_2_5;
temp_pm1=temp_pm1+data1.AMB_TMP;
hum_pm1=hum_pm1+data1.AMB_HUM;
debugln("PMS 1 measurement "+String(pm1Position)+": "+String(data1.PM_AE_UG_2_5)+"ug/m3");
pm1Position++;
if (pm1Position==averageCount) {
pm1Value = pm1Value / averageCount;
temp_pm1 = temp_pm1 / averageCount;
hum_pm1 = hum_pm1 / averageCount;
postToServer("-1", pm1Value, temp_pm1,hum_pm1);
pm1Position=0;
pm1Value=0;
}
} else {
debugln("PMS 1 does't respond");
}
if (pms2.readUntil(data2, 2000)) {
pm2Value=pm2Value+data2.PM_AE_UG_2_5;
temp_pm2=temp_pm2+data2.AMB_TMP;
hum_pm2=hum_pm2+data2.AMB_HUM;
debugln("PMS 2 measurement "+String(pm2Position)+": "+String(data2.PM_AE_UG_2_5)+"ug/m3");
pm2Position++;
if (pm2Position==averageCount) {
pm2Value = pm2Value / averageCount;
temp_pm2 = temp_pm2 / averageCount;
hum_pm2 = hum_pm2 / averageCount;
postToServer("-2", pm2Value, temp_pm2, hum_pm2);
pm2Position=0;
pm2Value=0;
}
} else {
debugln("PMS 2 does't respond");
}
}
countdown(2);
}
// Wifi Manager
void connectToWifi() {
WiFiManager wifiManager;
switchLED(true);
//WiFi.disconnect(); //to delete previous saved hotspot
String HOTSPOT = "AG-" + String(getNormalizedMac());
wifiManager.setTimeout(180);
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
switchLED(false);
Serial.println("failed to connect and hit timeout");
delay(6000);
}
}
String getNormalizedMac() {
String mac = WiFi.macAddress();
mac.replace(":", "");
mac.toLowerCase();
return mac;
}

View File

@ -19,7 +19,7 @@ If you have any questions please visit our forum at https://forum.airgradient.co
If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/
MIT License
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/

View File

@ -5,7 +5,7 @@ This is the code for the AirGradient DIY PRO Air Quality Sensor with an ESP8266
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/
Build Instructions: https://www.airgradient.com/open-airgradient/instructions/diy-pro-v37/
Kits (including a pre-soldered version) are available: https://www.airgradient.com/open-airgradient/kits/
@ -23,7 +23,7 @@ If you have any questions please visit our forum at https://forum.airgradient.co
If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/
License: CC BY-NC 4.0 Attribution-NonCommercial 4.0 International
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
@ -51,15 +51,15 @@ NOxGasIndexAlgorithm nox_algorithm;
// time in seconds needed for NOx conditioning
uint16_t conditioning_s = 10;
// for persistent saving and loading
int addr = 0;
// for peristent saving and loading
int addr = 4;
byte value;
// Display bottom right
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
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);
//U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R2, /* reset=*/ U8X8_PIN_NONE);
// CONFIGURATION START
@ -108,7 +108,7 @@ unsigned long previousTempHum = 0;
float temp = 0;
int hum = 0;
int buttonConfig=0;
int buttonConfig=4;
int lastState = LOW;
int currentState;
unsigned long pressedTime = 0;
@ -117,7 +117,6 @@ unsigned long releasedTime = 0;
void setup() {
Serial.begin(115200);
Serial.println("Hello");
u8g2.setBusClock(100000);
u8g2.begin();
//u8g2.setDisplayRotation(U8G2_R0);
@ -144,7 +143,7 @@ void setup() {
connectToWifi();
}
updateOLED2("Warming up the", "sensors.", "");
updateOLED2("Warming Up", "Serial Number:", String(ESP.getChipId(), HEX));
sgp41.begin(Wire);
ag.CO2_Init();
ag.PMS_Init();
@ -256,6 +255,9 @@ void setConfig() {
inF = true;
inUSAQI = true;
}
// to do
// if (buttonConfig == 8) {
// updateOLED2("CO2", "Manual", "Calibration");
@ -398,19 +400,8 @@ void sendToServer() {
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());
updateOLED2("90s to connect", "to Wifi Hotspot", HOTSPOT);
wifiManager.setTimeout(90);
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
updateOLED2("booting into", "offline mode", "");
@ -418,9 +409,6 @@ void sendToServer() {
delay(6000);
}
Serial.println("Parameter 2:");
Serial.println(parameter.getValue());
}
// Calculate PM2.5 US AQI

View File

@ -0,0 +1,418 @@
/*
Important: This code is only for the DIY PRO PCB Version 3.7 that has a push button mounted.
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-v37/
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/
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 <EEPROM.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;
// for peristent saving and loading
int addr = 4;
byte value;
// 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;
// PM2.5 in US AQI (default ug/m3)
boolean inUSAQI = false;
// Display Position
boolean displayTop = true;
// 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;
int buttonConfig=4;
int lastState = LOW;
int currentState;
unsigned long pressedTime = 0;
unsigned long releasedTime = 0;
void setup() {
Serial.begin(115200);
Serial.println("Hello");
u8g2.begin();
//u8g2.setDisplayRotation(U8G2_R0);
EEPROM.begin(512);
delay(500);
buttonConfig = String(EEPROM.read(addr)).toInt();
setConfig();
updateOLED2("Press Button", "Now for", "Config Menu");
delay(2000);
currentState = digitalRead(D7);
if (currentState == HIGH)
{
updateOLED2("Entering", "Config Menu", "");
delay(3000);
lastState = LOW;
inConf();
}
if (connectWIFI)
{
connectToWifi();
}
updateOLED2("Warming Up", "Serial Number:", String(ESP.getChipId(), HEX));
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 inConf(){
setConfig();
currentState = digitalRead(D7);
if(lastState == LOW && currentState == HIGH) {
pressedTime = millis();
}
else if(lastState == HIGH && currentState == LOW) {
releasedTime = millis();
long pressDuration = releasedTime - pressedTime;
if( pressDuration < 1000 ) {
buttonConfig=buttonConfig+1;
if (buttonConfig>7) buttonConfig=0;
}
}
if (lastState == HIGH && currentState == HIGH){
long passedDuration = millis() - pressedTime;
if( passedDuration > 4000 ) {
// to do
// if (buttonConfig==4) {
// updateOLED2("Saved", "Release", "Button Now");
// delay(1000);
// updateOLED2("Starting", "CO2", "Calibration");
// delay(1000);
// Co2Calibration();
// } else {
updateOLED2("Saved", "Release", "Button Now");
delay(1000);
updateOLED2("Rebooting", "in", "5 seconds");
delay(5000);
EEPROM.write(addr, char(buttonConfig));
EEPROM.commit();
delay(1000);
ESP.restart();
// }
}
}
lastState = currentState;
delay(100);
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");
u8g2.setDisplayRotation(U8G2_R0);
inF = false;
inUSAQI = false;
}
if (buttonConfig == 5) {
updateOLED2("Temp. in C", "PM in US AQI", "Display Bottom");
u8g2.setDisplayRotation(U8G2_R0);
inF = false;
inUSAQI = true;
} else if (buttonConfig == 6) {
updateOLED2("Temp. in F", "PM in ug/m3", "Display Bottom");
u8g2.setDisplayRotation(U8G2_R0);
inF = true;
inUSAQI = false;
} else if (buttonConfig == 7) {
updateOLED2("Temp. in F", "PM in US AQI", "Display Bottom");
u8g2.setDisplayRotation(U8G2_R0);
inF = true;
inUSAQI = true;
}
// to do
// if (buttonConfig == 8) {
// updateOLED2("CO2", "Manual", "Calibration");
// }
}
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);
if (conditioning_s > 0) {
error = sgp41.executeConditioning(compensationRh, compensationT, srawVoc);
conditioning_s--;
} else {
error = sgp41.measureRawSignals(compensationRh, compensationT, srawVoc,
srawNox);
}
if (currentMillis - previousTVOC >= tvocInterval) {
previousTVOC += tvocInterval;
TVOC = voc_algorithm.process(srawVoc);
NOX = nox_algorithm.process(srawNox);
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;
if (inUSAQI) {
ln1 = "AQI:" + String(PM_TO_AQI_US(pm25)) + " CO2:" + String(Co2);
} else {
ln1 = "PM:" + String(pm25) + " CO2:" + String(Co2);
}
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("90s to connect", "to Wifi Hotspot", HOTSPOT);
wifiManager.setTimeout(90);
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

@ -25,7 +25,7 @@ If you have any questions please visit our forum at https://forum.airgradient.co
If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/
MIT License
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/

View File

@ -20,7 +20,7 @@ If you have any questions please visit our forum at https://forum.airgradient.co
If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/
MIT License
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/

View File

@ -10,7 +10,7 @@ The codes needs the following libraries installed:
"WifiManager by tzapu, tablatronix" tested with Version 2.0.5-alpha
"Adafruit_ILI9341" tested with Version 1.5.10
"Adafruit GFX library" tested with Version 1.10.12 (often automatically installed with above ILI9341 library)
"ArduinoJSON" by Benoit Blanchon tested with Version 6.18.5
"ArduinoJSON" by Benoit Blanchon tested with Version 5.13.5
Configuration:
Please set in the code below (line 90-) if you want to display the PM2.5 values in US AQI and temperature in F.
@ -21,7 +21,7 @@ If you have any questions please visit our forum at https://forum.airgradient.co
If you are a school or university contact us for a free trial on the AirGradient platform.
https://www.airgradient.com/
MIT License
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
#include <WiFiManager.h>

View File

@ -17,7 +17,7 @@ https://www.airgradient.com/
Kits with all required components are available at https://www.airgradient.com/open-airgradient/shop/
MIT License
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
#include <AirGradient.h>

View File

@ -17,7 +17,7 @@ Kits with all required components are available at https://www.airgradient.com/o
If you have any questions please visit our forum at https://forum.airgradient.com/
MIT License
CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/
#include <AirGradient.h>

View File

@ -1,5 +1,5 @@
name=AirGradient Air Quality Sensor
version=2.4.0
version=2.4.2
author=AirGradient <support@airgradient.com>
maintainer=AirGradient <support@airgradient.com>
sentence=ESP8266 library for an air quality sensor featuring PM2.5, CO2, Temperature, TVOC and Humidity with OLED display.