Compare commits

..

8 Commits

Author SHA1 Message Date
0458adb949 Added missing pms library to instructions 2024-01-06 09:14:40 +07:00
f51203f754 Added config menu item to switch off LED bar 2023-12-13 18:37:36 +07:00
33520c18fe Fixed persistent WiFi issue 2023-11-25 08:37:56 +07:00
91563ef836 Updated Wifi connection issue in v9 2023-11-21 07:23:36 +07:00
feec04f42b fixed typo in comment 2023-11-10 08:24:20 +07:00
36fd7774f6 added example for Open Air O-1PST version 2023-11-01 13:59:06 +07:00
e0d0bb6e3b improved error handling 2023-10-24 14:01:54 +07:00
9b0d6dbcdd updated 2023-10-23 19:01:46 +07:00
5 changed files with 575 additions and 118 deletions

View File

@ -0,0 +1,339 @@
/*
Important: This code is only for the AirGradient ONE Open Air Version with TVOC and CO2 sensor.
It is a high quality sensor measuring PM2.5, CO2, TVOC, NOx, Temperature and Humidity and can send data over Wifi.
Build Instructions: https://www.airgradient.com/open-airgradient/instructions/
Kits (including a pre-soldered version) are available: https://www.airgradient.com/
The codes needs the following libraries installed:
“WifiManager by tzapu, tablatronix” tested with version 2.0.11-beta
"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
“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/
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 "PMS.h"
#include <HardwareSerial.h>
#include <Wire.h>
#include "s8_uart.h"
#include <HTTPClient.h>
#include <WiFiManager.h>
#include <SensirionI2CSgp41.h>
#include <NOxGasIndexAlgorithm.h>
#include <VOCGasIndexAlgorithm.h>
#define DEBUG true
#define I2C_SDA 7
#define I2C_SCL 6
HTTPClient client;
SensirionI2CSgp41 sgp41;
VOCGasIndexAlgorithm voc_algorithm;
NOxGasIndexAlgorithm nox_algorithm;
PMS pms1(Serial0);
PMS::DATA data1;
S8_UART * sensor_S8;
S8_sensor sensor;
// time in seconds needed for NOx conditioning
uint16_t conditioning_s = 10;
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;
// use RGB LED Bar
//boolean useRGBledBar = 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;
int loopCount = 0;
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 = -1;
int NOX = -1;
const int co2Interval = 5000;
unsigned long previousCo2 = 0;
int Co2 = 0;
const int pmInterval = 5000;
unsigned long previousPm = 0;
int pm25 = -1;
int pm01 = -1;
int pm10 = -1;
int pm03PCount = -1;
float temp;
int hum;
//const int tempHumInterval = 2500;
//unsigned long previousTempHum = 0;
void setup() {
if (DEBUG) {
Serial.begin(115200);
// see https://github.com/espressif/arduino-esp32/issues/6983
Serial.setTxTimeoutMs(0); // <<<====== solves the delay issue
}
Wire.begin(I2C_SDA, I2C_SCL);
Serial1.begin(9600, SERIAL_8N1, 0, 1);
Serial0.begin(9600);
sgp41.begin(Wire);
//init Watchdog
pinMode(2, OUTPUT);
digitalWrite(2, LOW);
sensor_S8 = new S8_UART(Serial1);
delay(500);
// push button
pinMode(9, INPUT_PULLUP);
countdown(3);
if (connectWIFI) {
WiFi.begin("airgradient", "cleanair");
int retries = 0;
while ((WiFi.status() != WL_CONNECTED) && (retries < 15)) {
retries++;
delay(500);
Serial.print(".");
}
if (retries > 14) {
Serial.println(F("WiFi connection FAILED"));
connectToWifi();
}
if (WiFi.status() == WL_CONNECTED) {
sendPing();
Serial.println(F("WiFi connected!"));
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
}
}
void loop() {
currentMillis = millis();
updateTVOC();
updateCo2();
updatePm();
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);
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;
if (error) {
TVOC = -1;
NOX = -1;
//Serial.println(String(TVOC));
} else {
TVOC = voc_algorithm.process(srawVoc);
NOX = nox_algorithm.process(srawNox);
//Serial.println(String(TVOC));
}
}
}
void updateCo2() {
if (currentMillis - previousCo2 >= co2Interval) {
previousCo2 += co2Interval;
Co2 = sensor_S8 -> get_co2();
//Serial.println(String(Co2));
}
}
void updatePm() {
if (currentMillis - previousPm >= pmInterval) {
previousPm += pmInterval;
if (pms1.readUntil(data1, 2000)) {
pm01 = data1.PM_AE_UG_1_0;
pm25 = data1.PM_AE_UG_2_5;
pm10 = data1.PM_AE_UG_10_0;
pm03PCount = data1.PM_RAW_0_3;
temp = data1.AMB_TMP;
hum = data1.AMB_HUM;
} else {
pm01 = -1;
pm25 = -1;
pm10 = -1;
pm03PCount = -1;
temp = -10001;
hum = -10001;
}
}
}
void sendPing() {
String payload = "{\"wifi\":" + String(WiFi.RSSI()) +
", \"boot\":" + loopCount +
"}";
}
void sendToServer() {
if (currentMillis - previoussendToServer >= sendToServerInterval) {
previoussendToServer += sendToServerInterval;
String payload = "{\"wifi\":" + String(WiFi.RSSI()) +
(Co2 < 0 ? "" : ", \"rco2\":" + String(Co2)) +
(pm01 < 0 ? "" : ", \"pm01\":" + String(pm01)) +
(pm25 < 0 ? "" : ", \"pm02\":" + String(pm25)) +
(pm10 < 0 ? "" : ", \"pm10\":" + String(pm10)) +
(pm03PCount < 0 ? "" : ", \"pm003_count\":" + String(pm03PCount)) +
(TVOC < 0 ? "" : ", \"tvoc_index\":" + String(TVOC)) +
(NOX < 0 ? "" : ", \"nox_index\":" + String(NOX)) +
", \"atmp\":" + String(temp/10) +
(hum < 0 ? "" : ", \"rhum\":" + String(hum/10)) +
", \"boot\":" + loopCount +
"}";
if (WiFi.status() == WL_CONNECTED) {
Serial.println(payload);
String POSTURL = APIROOT + "sensors/airgradient:" + String(getNormalizedMac()) + "/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();
resetWatchdog();
loopCount++;
} else {
Serial.println("WiFi Disconnected");
}
}
}
void countdown(int from) {
debug("\n");
while (from > 0) {
debug(String(from--));
debug(" ");
delay(1000);
}
debug("\n");
}
void resetWatchdog() {
Serial.println("Watchdog reset");
digitalWrite(2, HIGH);
delay(20);
digitalWrite(2, LOW);
}
// Wifi Manager
void connectToWifi() {
WiFiManager wifiManager;
//WiFi.disconnect(); //to delete previous saved hotspot
String HOTSPOT = "AG-" + String(getNormalizedMac());
wifiManager.setTimeout(180);
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
Serial.println("failed to connect and hit timeout");
delay(6000);
}
}
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);
}
String getNormalizedMac() {
String mac = WiFi.macAddress();
mac.replace(":", "");
mac.toLowerCase();
return mac;
}

View File

@ -1,5 +1,5 @@
/* /*
Important: This code is only for the DIY PRO PCB Version 3.7 that has a push button mounted. Important: This code is only for the DIY PRO PCB Version 4.2 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. This is the code for the AirGradient DIY PRO Air Quality Sensor with an ESP8266 Microcontroller with the SGP40 TVOC module from AirGradient.

View File

@ -12,6 +12,7 @@ The codes needs the following libraries installed:
“U8g2” by oliver tested with version 2.32.15 “U8g2” by oliver tested with version 2.32.15
"Sensirion I2C SGP41" by Sensation Version 0.1.0 "Sensirion I2C SGP41" by Sensation Version 0.1.0
"Sensirion Gas Index Algorithm" by Sensation Version 3.2.1 "Sensirion Gas Index Algorithm" by Sensation Version 3.2.1
“pms” by Markusz Kakl version 1.1.0
"Arduino-SHT" by Johannes Winkelmann Version 1.2.2 "Arduino-SHT" by Johannes Winkelmann Version 1.2.2
"Adafruit NeoPixel" by Adafruit Version 1.11.0 "Adafruit NeoPixel" by Adafruit Version 1.11.0
@ -28,17 +29,29 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
*/ */
#include "PMS.h" #include "PMS.h"
#include <HardwareSerial.h> #include <HardwareSerial.h>
#include <Wire.h> #include <Wire.h>
#include "s8_uart.h" #include "s8_uart.h"
#include <HTTPClient.h> #include <HTTPClient.h>
#include <WiFiManager.h> #include <WiFiManager.h>
#include <Adafruit_NeoPixel.h> #include <Adafruit_NeoPixel.h>
#include <EEPROM.h> #include <EEPROM.h>
#include "SHTSensor.h" #include "SHTSensor.h"
#include <SensirionI2CSgp41.h> #include <SensirionI2CSgp41.h>
#include <NOxGasIndexAlgorithm.h> #include <NOxGasIndexAlgorithm.h>
#include <VOCGasIndexAlgorithm.h> #include <VOCGasIndexAlgorithm.h>
#include <U8g2lib.h> #include <U8g2lib.h>
#define DEBUG true #define DEBUG true
@ -100,8 +113,8 @@ unsigned long previoussendToServer = 0;
const int tvocInterval = 1000; const int tvocInterval = 1000;
unsigned long previousTVOC = 0; unsigned long previousTVOC = 0;
int TVOC = 0; int TVOC = -1;
int NOX = 0; int NOX = -1;
const int co2Interval = 5000; const int co2Interval = 5000;
unsigned long previousCo2 = 0; unsigned long previousCo2 = 0;
@ -109,15 +122,15 @@ int Co2 = 0;
const int pmInterval = 5000; const int pmInterval = 5000;
unsigned long previousPm = 0; unsigned long previousPm = 0;
int pm25 = 0; int pm25 = -1;
int pm01 = 0; int pm01 = -1;
int pm10 = 0; int pm10 = -1;
int pm03PCount = 0; int pm03PCount = -1;
const int tempHumInterval = 2500; const int tempHumInterval = 5000;
unsigned long previousTempHum = 0; unsigned long previousTempHum = 0;
float temp = 0; float temp;
int hum = 0; int hum;
int buttonConfig = 0; int buttonConfig = 0;
int lastState = LOW; int lastState = LOW;
@ -142,9 +155,11 @@ void setup() {
updateOLED2("Warming Up", "Serial Number:", String(getNormalizedMac())); updateOLED2("Warming Up", "Serial Number:", String(getNormalizedMac()));
sgp41.begin(Wire); sgp41.begin(Wire);
delay(300);
sht.init(Wire); sht.init(Wire);
sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM); //sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM);
delay(300);
//init Watchdog //init Watchdog
pinMode(2, OUTPUT); pinMode(2, OUTPUT);
@ -159,10 +174,19 @@ void setup() {
pinMode(9, INPUT_PULLUP); pinMode(9, INPUT_PULLUP);
buttonConfig = String(EEPROM.read(addr)).toInt(); buttonConfig = String(EEPROM.read(addr)).toInt();
if (buttonConfig > 3) buttonConfig = 0; if (buttonConfig > 7) buttonConfig = 0;
delay(400); delay(400);
setConfig(); setConfig();
Serial.println("buttonConfig: " + String(buttonConfig)); Serial.println("buttonConfig: " + String(buttonConfig));
updateOLED2("Press Button", "for LED test &", "offline mode");
delay(2000);
currentState = digitalRead(9);
if (currentState == LOW) {
ledTest();
return;
}
updateOLED2("Press Button", "Now for", "Config Menu"); updateOLED2("Press Button", "Now for", "Config Menu");
delay(2000); delay(2000);
currentState = digitalRead(9); currentState = digitalRead(9);
@ -174,12 +198,13 @@ void setup() {
inConf(); inConf();
} }
countdown(3); if (connectWIFI) connectToWifi();
if (WiFi.status() == WL_CONNECTED) {
if (connectWIFI) {
connectToWifi();
}
sendPing(); sendPing();
Serial.println(F("WiFi connected!"));
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
updateOLED2("Warming Up", "Serial Number:", String(getNormalizedMac())); updateOLED2("Warming Up", "Serial Number:", String(getNormalizedMac()));
} }
@ -220,10 +245,17 @@ void updateTVOC() {
if (currentMillis - previousTVOC >= tvocInterval) { if (currentMillis - previousTVOC >= tvocInterval) {
previousTVOC += tvocInterval; previousTVOC += tvocInterval;
if (error) {
TVOC = -1;
NOX = -1;
Serial.println(String(TVOC));
} else {
TVOC = voc_algorithm.process(srawVoc); TVOC = voc_algorithm.process(srawVoc);
NOX = nox_algorithm.process(srawNox); NOX = nox_algorithm.process(srawNox);
Serial.println(String(TVOC)); Serial.println(String(TVOC));
} }
}
} }
void updateCo2() { void updateCo2() {
@ -242,6 +274,11 @@ void updatePm() {
pm25 = data1.PM_AE_UG_2_5; pm25 = data1.PM_AE_UG_2_5;
pm10 = data1.PM_AE_UG_10_0; pm10 = data1.PM_AE_UG_10_0;
pm03PCount = data1.PM_RAW_0_3; pm03PCount = data1.PM_RAW_0_3;
} else {
pm01 = -1;
pm25 = -1;
pm10 = -1;
pm03PCount = -1;
} }
} }
} }
@ -255,6 +292,8 @@ void updateTempHum() {
hum = sht.getHumidity(); hum = sht.getHumidity();
} else { } else {
Serial.print("Error in readSample()\n"); Serial.print("Error in readSample()\n");
temp = -10001;
hum = -10001;
} }
} }
} }
@ -302,7 +341,7 @@ void inConf() {
long pressDuration = releasedTime - pressedTime; long pressDuration = releasedTime - pressedTime;
if (pressDuration < 1000) { if (pressDuration < 1000) {
buttonConfig = buttonConfig + 1; buttonConfig = buttonConfig + 1;
if (buttonConfig > 3) buttonConfig = 0; if (buttonConfig > 7) buttonConfig = 0;
} }
} }
@ -328,26 +367,52 @@ void inConf() {
void setConfig() { void setConfig() {
Serial.println("in setConfig"); Serial.println("in setConfig");
if (buttonConfig == 0) { if (buttonConfig == 0) {
updateOLED2("Temp. in C", "PM in ug/m3", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0); u8g2.setDisplayRotation(U8G2_R0);
updateOLED2("T:C, PM:ug/m3", "LED Bar: on", "Long Press Saves");
inF = false; inF = false;
inUSAQI = false; inUSAQI = false;
} useRGBledBar = true;
if (buttonConfig == 1) { } else if (buttonConfig == 1) {
updateOLED2("Temp. in C", "PM in US AQI", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0); u8g2.setDisplayRotation(U8G2_R0);
updateOLED2("T:C, PM:US AQI", "LED Bar: on", "Long Press Saves");
inF = false; inF = false;
inUSAQI = true; inUSAQI = true;
useRGBledBar = true;
} else if (buttonConfig == 2) { } else if (buttonConfig == 2) {
updateOLED2("Temp. in F", "PM in ug/m3", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0); u8g2.setDisplayRotation(U8G2_R0);
updateOLED2("T:F PM:ug/m3", "LED Bar: on", "Long Press Saves");
inF = true; inF = true;
inUSAQI = false; inUSAQI = false;
useRGBledBar = true;
} else if (buttonConfig == 3) { } else if (buttonConfig == 3) {
updateOLED2("Temp. in F", "PM in US AQI", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0); u8g2.setDisplayRotation(U8G2_R0);
updateOLED2("T:F PM:US AQI", "LED Bar: on", "Long Press Saves");
inF = true; inF = true;
inUSAQI = true; inUSAQI = true;
useRGBledBar = true;
} else if (buttonConfig == 4) {
updateOLED2("T:C, PM:ug/m3", "LED Bar: off", "Long Press Saves");
inF = false;
inUSAQI = false;
useRGBledBar = false;
} else if (buttonConfig == 5) {
u8g2.setDisplayRotation(U8G2_R0);
updateOLED2("T:C, PM:US AQI", "LED Bar: off", "Long Press Saves");
inF = false;
inUSAQI = true;
useRGBledBar = false;
} else if (buttonConfig == 6) {
u8g2.setDisplayRotation(U8G2_R0);
updateOLED2("T:F PM:ug/m3", "LED Bar: off", "Long Press Saves");
inF = true;
inUSAQI = false;
useRGBledBar = false;
} else if (buttonConfig == 7) {
u8g2.setDisplayRotation(U8G2_R0);
updateOLED2("T:F PM:US AQI", "LED Bar: off", "Long Press Saves");
inF = true;
inUSAQI = true;
useRGBledBar = false;
} }
} }
@ -369,7 +434,6 @@ void updateOLED2(String ln1, String ln2, String ln3) {
} while (u8g2.nextPage()); } while (u8g2.nextPage());
} }
void updateOLED3() { void updateOLED3() {
char buf[9]; char buf[9];
u8g2.firstPage(); u8g2.firstPage();
@ -378,19 +442,19 @@ void updateOLED3() {
u8g2.setFont(u8g2_font_t0_16_tf); u8g2.setFont(u8g2_font_t0_16_tf);
if (inF) { if (inF) {
if (temp > -10001) { if (temp > -10001) {
float tempF = (temp * 9 / 5) + 32; float tempF = (temp * 9 / 5) + 32;
sprintf (buf, "%.1f°F", tempF); sprintf(buf, "%.1f°F", tempF);
} else { } else {
sprintf (buf, "-°F"); sprintf(buf, "-°F");
} }
u8g2.drawUTF8(1, 10, buf); u8g2.drawUTF8(1, 10, buf);
} else { } else {
if (temp > -10001) { if (temp > -10001) {
sprintf (buf, "%.1f°C", temp); sprintf(buf, "%.1f°C", temp);
} else { } else {
sprintf (buf, "-°C"); sprintf(buf, "-°C");
} }
u8g2.drawUTF8(1, 10, buf); u8g2.drawUTF8(1, 10, buf);
} }
@ -407,7 +471,6 @@ if (inF) {
// there might also be single digits, not considered, sprintf might actually support a leading space // there might also be single digits, not considered, sprintf might actually support a leading space
} }
u8g2.drawLine(1, 13, 128, 13); u8g2.drawLine(1, 13, 128, 13);
u8g2.setFont(u8g2_font_t0_12_tf); u8g2.setFont(u8g2_font_t0_12_tf);
u8g2.drawUTF8(1, 27, "CO2"); u8g2.drawUTF8(1, 27, "CO2");
@ -425,8 +488,7 @@ if (inF) {
u8g2.drawStr(48, 27, "PM2.5"); u8g2.drawStr(48, 27, "PM2.5");
u8g2.setFont(u8g2_font_t0_22b_tf); u8g2.setFont(u8g2_font_t0_22b_tf);
if (inUSAQI) {
if (inUSAQI) {
if (pm25 >= 0) { if (pm25 >= 0) {
sprintf(buf, "%d", PM_TO_AQI_US(pm25)); sprintf(buf, "%d", PM_TO_AQI_US(pm25));
} else { } else {
@ -525,6 +587,7 @@ void connectToWifi() {
WiFiManager wifiManager; WiFiManager wifiManager;
//WiFi.disconnect(); //to delete previous saved hotspot //WiFi.disconnect(); //to delete previous saved hotspot
String HOTSPOT = "AG-" + String(getNormalizedMac()); String HOTSPOT = "AG-" + String(getNormalizedMac());
updateOLED2("180s to connect", "to Wifi Hotspot", HOTSPOT);
wifiManager.setTimeout(180); wifiManager.setTimeout(180);
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) { if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
Serial.println("failed to connect and hit timeout"); Serial.println("failed to connect and hit timeout");
@ -561,12 +624,12 @@ String getNormalizedMac() {
} }
void setRGBledCO2color(int co2Value) { void setRGBledCO2color(int co2Value) {
if (co2Value < 800) setRGBledColor('g'); if (co2Value >= 300 && co2Value < 800) setRGBledColor('g');
if (co2Value >= 800 && co2Value < 1000) setRGBledColor('y'); if (co2Value >= 800 && co2Value < 1000) setRGBledColor('y');
if (co2Value >= 1000 && co2Value < 1500) setRGBledColor('o'); if (co2Value >= 1000 && co2Value < 1500) setRGBledColor('o');
if (co2Value >= 1500 && co2Value < 2000) setRGBledColor('r'); if (co2Value >= 1500 && co2Value < 2000) setRGBledColor('r');
if (co2Value >= 2000 && co2Value < 3000) setRGBledColor('p'); if (co2Value >= 2000 && co2Value < 3000) setRGBledColor('p');
if (co2Value >= 3000 && co2Value < 10000) setRGBledColor('b'); if (co2Value >= 3000 && co2Value < 10000) setRGBledColor('z');
} }
void setRGBledColor(char color) { void setRGBledColor(char color) {
@ -576,42 +639,63 @@ void setRGBledColor(char color) {
case 'g': case 'g':
for (int i = 0; i < 11; i++) { for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(0, 255, 0)); pixels.setPixelColor(i, pixels.Color(0, 255, 0));
delay(100); delay(30);
pixels.show(); pixels.show();
} }
break; break;
case 'y': case 'y':
for (int i = 0; i < 11; i++) { for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 255, 0)); pixels.setPixelColor(i, pixels.Color(255, 255, 0));
delay(100); delay(30);
pixels.show(); pixels.show();
} }
break; break;
case 'o': case 'o':
for (int i = 0; i < 11; i++) { for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 128, 0)); pixels.setPixelColor(i, pixels.Color(255, 128, 0));
delay(100); delay(30);
pixels.show(); pixels.show();
} }
break; break;
case 'r': case 'r':
for (int i = 0; i < 11; i++) { for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 0, 0)); pixels.setPixelColor(i, pixels.Color(255, 0, 0));
delay(100); delay(30);
pixels.show();
}
break;
case 'b':
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 255));
delay(30);
pixels.show();
}
break;
case 'w':
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 255, 255));
delay(30);
pixels.show(); pixels.show();
} }
break; break;
case 'p': case 'p':
for (int i = 0; i < 11; i++) { for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(153, 0, 153)); pixels.setPixelColor(i, pixels.Color(153, 0, 153));
delay(100); delay(30);
pixels.show(); pixels.show();
} }
break; break;
case 'b': case 'z':
for (int i = 0; i < 11; i++) { for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(102, 0, 0)); pixels.setPixelColor(i, pixels.Color(102, 0, 0));
delay(100); delay(30);
pixels.show();
}
break;
case 'n':
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
delay(30);
pixels.show(); pixels.show();
} }
break; break;
@ -623,6 +707,40 @@ void setRGBledColor(char color) {
} }
} }
void ledTest() {
updateOLED2("LED Test", "running", ".....");
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 0, 0));
delay(30);
pixels.show();
}
delay(500);
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(0, 255, 0));
delay(30);
pixels.show();
}
delay(500);
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 255));
delay(30);
pixels.show();
}
delay(500);
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 255, 255));
delay(30);
pixels.show();
}
delay(500);
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
delay(30);
pixels.show();
}
delay(500);
}
// Calculate PM2.5 US AQI // Calculate PM2.5 US AQI
int PM_TO_AQI_US(int pm02) { int PM_TO_AQI_US(int pm02) {
if (pm02 <= 12.0) return ((50 - 0) / (12.0 - .0) * (pm02 - .0) + 0); if (pm02 <= 12.0) return ((50 - 0) / (12.0 - .0) * (pm02 - .0) + 0);

View File

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