PRO v9 (C3 Version), added LED config

This commit is contained in:
Achim
2023-10-10 06:42:58 +07:00
parent d4225896fe
commit dee5b77d2a

View File

@ -1,16 +1,25 @@
#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>
@ -32,7 +41,7 @@ PMS pms1(Serial0);
PMS::DATA data1; PMS::DATA data1;
S8_UART* sensor_S8; S8_UART * sensor_S8;
S8_sensor sensor; S8_sensor sensor;
// time in seconds needed for NOx conditioning // time in seconds needed for NOx conditioning
@ -56,12 +65,14 @@ boolean inUSAQI = false;
// Display Position // Display Position
boolean displayTop = true; 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. // 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; boolean connectWIFI = true;
int loopCount = 0; int loopCount = 0;
unsigned long currentMillis = 0; unsigned long currentMillis = 0;
const int oledInterval = 5000; const int oledInterval = 5000;
@ -91,34 +102,26 @@ unsigned long previousTempHum = 0;
float temp = 0; float temp = 0;
int hum = 0; int hum = 0;
int buttonConfig=0; int buttonConfig = 0;
int lastState = LOW; int lastState = LOW;
int currentState; int currentState;
unsigned long pressedTime = 0; unsigned long pressedTime = 0;
unsigned long releasedTime = 0; unsigned long releasedTime = 0;
void setup() { void setup() {
if (DEBUG) { if (DEBUG) {
Serial.begin(115200); Serial.begin(115200);
// see https://github.com/espressif/arduino-esp32/issues/6983 // see https://github.com/espressif/arduino-esp32/issues/6983
Serial.setTxTimeoutMs(0); // <<<====== solves the delay issue Serial.setTxTimeoutMs(0); // <<<====== solves the delay issue
}
Wire.begin(I2C_SDA, I2C_SCL);
pixels.begin();
pixels.clear();
for(int i=0; i<11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 255, 255));
pixels.show();
delay(100);
} }
Serial1.begin(9600, SERIAL_8N1, 0, 1); Wire.begin(I2C_SDA, I2C_SCL);
Serial0.begin(9600); pixels.begin();
pixels.clear();
Serial.println("Hello"); Serial1.begin(9600, SERIAL_8N1, 0, 1);
u8g2.begin(); Serial0.begin(9600);
u8g2.begin();
updateOLED2("Warming Up", "Serial Number:", String(getNormalizedMac())); updateOLED2("Warming Up", "Serial Number:", String(getNormalizedMac()));
sgp41.begin(Wire); sgp41.begin(Wire);
@ -126,38 +129,27 @@ void setup() {
sht.init(Wire); sht.init(Wire);
sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM); sht.setAccuracy(SHTSensor::SHT_ACCURACY_MEDIUM);
//init Watchdog
pinMode(2, OUTPUT);
digitalWrite(2, LOW);
sensor_S8 = new S8_UART(Serial1); sensor_S8 = new S8_UART(Serial1);
// Check if S8 is available
sensor_S8->get_firmware_version(sensor.firm_version);
int len = strlen(sensor.firm_version);
if (len == 0) {
debugln("SenseAir S8 CO2 sensor not found!");
}
// Show basic S8 sensor info
// debugln(">>> SenseAir S8 NDIR CO2 sensor <<<");
// sensor.sensor_id = sensor_S8->get_sensor_ID();
EEPROM.begin(512); EEPROM.begin(512);
delay(500); delay(500);
// push button
pinMode(9, INPUT_PULLUP);
// push button buttonConfig = String(EEPROM.read(addr)).toInt();
pinMode(9, INPUT_PULLUP); if (buttonConfig > 3) buttonConfig = 0;
buttonConfig = String(EEPROM.read(addr)).toInt();
if (buttonConfig>3) buttonConfig=0;
delay(400); delay(400);
setConfig(); setConfig();
Serial.println("buttonConfig: "+String(buttonConfig)); Serial.println("buttonConfig: " + String(buttonConfig));
updateOLED2("Press Button", "Now for", "Config Menu"); updateOLED2("Press Button", "Now for", "Config Menu");
delay(2000); delay(2000);
// pinMode(D7, INPUT_PULLUP);
currentState = digitalRead(9); currentState = digitalRead(9);
if (currentState == LOW) if (currentState == LOW) {
{
updateOLED2("Entering", "Config Menu", ""); updateOLED2("Entering", "Config Menu", "");
delay(3000); delay(3000);
lastState = HIGH; lastState = HIGH;
@ -165,14 +157,13 @@ buttonConfig = String(EEPROM.read(addr)).toInt();
inConf(); inConf();
} }
countdown(3); countdown(3);
if (connectWIFI) if (connectWIFI) {
{ connectToWifi();
connectToWifi();
} }
sendPing(); sendPing();
updateOLED2("Warming Up", "Serial Number:", String(getNormalizedMac())); updateOLED2("Warming Up", "Serial Number:", String(getNormalizedMac()));
} }
void loop() { void loop() {
@ -185,135 +176,129 @@ void loop() {
sendToServer(); sendToServer();
} }
void updateTVOC() void updateTVOC() {
{ uint16_t error;
uint16_t error; char errorMessage[256];
char errorMessage[256]; uint16_t defaultRh = 0x8000;
uint16_t defaultRh = 0x8000; uint16_t defaultT = 0x6666;
uint16_t defaultT = 0x6666; uint16_t srawVoc = 0;
uint16_t srawVoc = 0; uint16_t srawNox = 0;
uint16_t srawNox = 0; uint16_t defaultCompenstaionRh = 0x8000; // in ticks as defined by SGP41
uint16_t defaultCompenstaionRh = 0x8000; // in ticks as defined by SGP41 uint16_t defaultCompenstaionT = 0x6666; // 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 compensationRh = 0; // in ticks as defined by SGP41 uint16_t compensationT = 0; // in ticks as defined by SGP41
uint16_t compensationT = 0; // in ticks as defined by SGP41
delay(1000); delay(1000);
compensationT = static_cast<uint16_t>((temp + 45) * 65535 / 175); compensationT = static_cast < uint16_t > ((temp + 45) * 65535 / 175);
compensationRh = static_cast<uint16_t>(hum * 65535 / 100); compensationRh = static_cast < uint16_t > (hum * 65535 / 100);
if (conditioning_s > 0) { if (conditioning_s > 0) {
error = sgp41.executeConditioning(compensationRh, compensationT, srawVoc); error = sgp41.executeConditioning(compensationRh, compensationT, srawVoc);
conditioning_s--; conditioning_s--;
} else { } else {
error = sgp41.measureRawSignals(compensationRh, compensationT, srawVoc, error = sgp41.measureRawSignals(compensationRh, compensationT, srawVoc,
srawNox); srawNox);
} }
if (currentMillis - previousTVOC >= tvocInterval) { if (currentMillis - previousTVOC >= tvocInterval) {
previousTVOC += tvocInterval; previousTVOC += tvocInterval;
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() {
{ if (currentMillis - previousCo2 >= co2Interval) {
if (currentMillis - previousCo2 >= co2Interval) { previousCo2 += co2Interval;
previousCo2 += co2Interval; Co2 = sensor_S8 -> get_co2();
Co2 = sensor_S8->get_co2(); Serial.println(String(Co2));
Serial.println(String(Co2)); setRGBledCO2color(Co2);
} }
} }
void updatePm() void updatePm() {
{ if (currentMillis - previousPm >= pmInterval) {
if (currentMillis - previousPm >= pmInterval) { previousPm += pmInterval;
previousPm += pmInterval; if (pms1.readUntil(data1, 2000)) {
if (pms1.readUntil(data1, 2000)) {
pm01 = data1.PM_AE_UG_1_0; pm01 = data1.PM_AE_UG_1_0;
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;
}
} }
}
} }
void updateTempHum() void updateTempHum() {
{ if (currentMillis - previousTempHum >= tempHumInterval) {
if (currentMillis - previousTempHum >= tempHumInterval) { previousTempHum += tempHumInterval;
previousTempHum += tempHumInterval;
if (sht.readSample()) { if (sht.readSample()) {
temp = sht.getTemperature(); temp = sht.getTemperature();
hum = sht.getHumidity(); hum = sht.getHumidity();
} else { } else {
Serial.print("Error in readSample()\n"); Serial.print("Error in readSample()\n");
} }
} }
} }
void updateOLED() { void updateOLED() {
if (currentMillis - previousOled >= oledInterval) { if (currentMillis - previousOled >= oledInterval) {
previousOled += oledInterval; previousOled += oledInterval;
String ln3; String ln3;
String ln1; String ln1;
if (inUSAQI) { if (inUSAQI) {
ln1 = "AQI:" + String(PM_TO_AQI_US(pm25)) + " CO2:" + String(Co2); ln1 = "AQI:" + String(PM_TO_AQI_US(pm25)) + " CO2:" + String(Co2);
} else { } else {
ln1 = "PM:" + String(pm25) + " CO2:" + String(Co2); ln1 = "PM:" + String(pm25) + " CO2:" + String(Co2);
} }
String ln2 = "TVOC:" + String(TVOC) + " NOX:" + String(NOX); String ln2 = "TVOC:" + String(TVOC) + " NOX:" + String(NOX);
if (inF) { if (inF) {
ln3 = "F:" + String((temp* 9 / 5) + 32) + " H:" + String(hum)+"%"; ln3 = "F:" + String((temp * 9 / 5) + 32) + " H:" + String(hum) + "%";
} else { } else {
ln3 = "C:" + String(temp) + " H:" + String(hum)+"%"; ln3 = "C:" + String(temp) + " H:" + String(hum) + "%";
} }
updateOLED2(ln1, ln2, ln3); updateOLED2(ln1, ln2, ln3);
} }
} }
void inConf() {
void inConf(){
setConfig(); setConfig();
currentState = digitalRead(9); currentState = digitalRead(9);
if (currentState){ if (currentState) {
Serial.println("currentState: high"); Serial.println("currentState: high");
} else { } else {
Serial.println("currentState: low"); Serial.println("currentState: low");
} }
if(lastState == HIGH && currentState == LOW) { if (lastState == HIGH && currentState == LOW) {
pressedTime = millis(); pressedTime = millis();
} } else if (lastState == LOW && currentState == HIGH) {
else if(lastState == LOW && currentState == HIGH) {
releasedTime = millis(); releasedTime = millis();
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 > 3) buttonConfig = 0;
} }
} }
if (lastState == LOW && currentState == LOW){ if (lastState == LOW && currentState == LOW) {
long passedDuration = millis() - pressedTime; long passedDuration = millis() - pressedTime;
if( passedDuration > 4000 ) { if (passedDuration > 4000) {
updateOLED2("Saved", "Release", "Button Now"); updateOLED2("Saved", "Release", "Button Now");
delay(1000); delay(1000);
updateOLED2("Rebooting", "in", "5 seconds"); updateOLED2("Rebooting", "in", "5 seconds");
delay(5000); delay(5000);
EEPROM.write(addr, char(buttonConfig)); EEPROM.write(addr, char(buttonConfig));
EEPROM.commit(); EEPROM.commit();
delay(1000); delay(1000);
ESP.restart(); ESP.restart();
} }
} }
@ -322,44 +307,43 @@ void inConf(){
inConf(); inConf();
} }
void setConfig() { void setConfig() {
if (buttonConfig == 0) { if (buttonConfig == 0) {
updateOLED2("Temp. in C", "PM in ug/m3", "Long Press Saves"); updateOLED2("Temp. in C", "PM in ug/m3", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0); u8g2.setDisplayRotation(U8G2_R0);
inF = false; inF = false;
inUSAQI = false; inUSAQI = false;
} }
if (buttonConfig == 1) { if (buttonConfig == 1) {
updateOLED2("Temp. in C", "PM in US AQI", "Long Press Saves"); updateOLED2("Temp. in C", "PM in US AQI", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0); u8g2.setDisplayRotation(U8G2_R0);
inF = false; inF = false;
inUSAQI = true; inUSAQI = true;
} else if (buttonConfig == 2) { } else if (buttonConfig == 2) {
updateOLED2("Temp. in F", "PM in ug/m3", "Long Press Saves"); updateOLED2("Temp. in F", "PM in ug/m3", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0); u8g2.setDisplayRotation(U8G2_R0);
inF = true; inF = true;
inUSAQI = false; inUSAQI = false;
} else if (buttonConfig == 3) { } else if (buttonConfig == 3) {
updateOLED2("Temp. in F", "PM in US AQI", "Long Press Saves"); updateOLED2("Temp. in F", "PM in US AQI", "Long Press Saves");
u8g2.setDisplayRotation(U8G2_R0); u8g2.setDisplayRotation(U8G2_R0);
inF = true; inF = true;
inUSAQI = true; inUSAQI = true;
} }
} }
void switchLED(boolean ledON) { void switchLED(boolean ledON) {
if (ledON) { if (ledON) {
digitalWrite(10, HIGH); digitalWrite(10, HIGH);
} else { } else {
digitalWrite(10, LOW); digitalWrite(10, LOW);
} }
} }
void sendPing(){ void sendPing() {
String payload = "{\"wifi\":" + String(WiFi.RSSI()) String payload = "{\"wifi\":" + String(WiFi.RSSI()) +
+ ", \"boot\":" + loopCount ", \"boot\":" + loopCount +
+ "}"; "}";
} }
void updateOLED2(String ln1, String ln2, String ln3) { void updateOLED2(String ln1, String ln2, String ln3) {
@ -367,49 +351,48 @@ void updateOLED2(String ln1, String ln2, String ln3) {
u8g2.firstPage(); u8g2.firstPage();
u8g2.firstPage(); u8g2.firstPage();
do { do {
u8g2.setFont(u8g2_font_t0_16_tf); u8g2.setFont(u8g2_font_t0_16_tf);
u8g2.drawStr(1, 10, String(ln1).c_str()); u8g2.drawStr(1, 10, String(ln1).c_str());
u8g2.drawStr(1, 30, String(ln2).c_str()); u8g2.drawStr(1, 30, String(ln2).c_str());
u8g2.drawStr(1, 50, String(ln3).c_str()); u8g2.drawStr(1, 50, String(ln3).c_str());
} while ( u8g2.nextPage() ); } while (u8g2.nextPage());
} }
void sendToServer() { void sendToServer() {
if (currentMillis - previoussendToServer >= sendToServerInterval) { if (currentMillis - previoussendToServer >= sendToServerInterval) {
previoussendToServer += sendToServerInterval; previoussendToServer += sendToServerInterval;
String payload = "{\"wifi\":" + String(WiFi.RSSI()) String payload = "{\"wifi\":" + String(WiFi.RSSI()) +
+ (Co2 < 0 ? "" : ", \"rco2\":" + String(Co2)) (Co2 < 0 ? "" : ", \"rco2\":" + String(Co2)) +
+ (pm01 < 0 ? "" : ", \"pm01\":" + String(pm01)) (pm01 < 0 ? "" : ", \"pm01\":" + String(pm01)) +
+ (pm25 < 0 ? "" : ", \"pm02\":" + String(pm25)) (pm25 < 0 ? "" : ", \"pm02\":" + String(pm25)) +
+ (pm10 < 0 ? "" : ", \"pm10\":" + String(pm10)) (pm10 < 0 ? "" : ", \"pm10\":" + String(pm10)) +
+ (pm03PCount < 0 ? "" : ", \"pm003_count\":" + String(pm03PCount)) (pm03PCount < 0 ? "" : ", \"pm003_count\":" + String(pm03PCount)) +
+ (TVOC < 0 ? "" : ", \"tvoc_index\":" + String(TVOC)) (TVOC < 0 ? "" : ", \"tvoc_index\":" + String(TVOC)) +
+ (NOX < 0 ? "" : ", \"nox_index\":" + String(NOX)) (NOX < 0 ? "" : ", \"nox_index\":" + String(NOX)) +
+ ", \"atmp\":" + String(temp) ", \"atmp\":" + String(temp) +
+ (hum < 0 ? "" : ", \"rhum\":" + String(hum)) (hum < 0 ? "" : ", \"rhum\":" + String(hum)) +
+ ", \"boot\":" + loopCount ", \"boot\":" + loopCount +
+ "}"; "}";
if(WiFi.status()== WL_CONNECTED){ if (WiFi.status() == WL_CONNECTED) {
Serial.println(payload); Serial.println(payload);
String POSTURL = APIROOT + "sensors/airgradient:" + String(getNormalizedMac()) + "/measures"; String POSTURL = APIROOT + "sensors/airgradient:" + String(getNormalizedMac()) + "/measures";
Serial.println(POSTURL); Serial.println(POSTURL);
WiFiClient client; WiFiClient client;
HTTPClient http; HTTPClient http;
http.begin(client, POSTURL); http.begin(client, POSTURL);
http.addHeader("content-type", "application/json"); http.addHeader("content-type", "application/json");
int httpCode = http.POST(payload); int httpCode = http.POST(payload);
String response = http.getString(); String response = http.getString();
Serial.println(httpCode); Serial.println(httpCode);
Serial.println(response); Serial.println(response);
http.end(); http.end();
resetWatchdog(); resetWatchdog();
loopCount++; loopCount++;
} } else {
else { Serial.println("WiFi Disconnected");
Serial.println("WiFi Disconnected"); }
} }
}
} }
void countdown(int from) { void countdown(int from) {
@ -423,46 +406,45 @@ void countdown(int from) {
} }
void resetWatchdog() { void resetWatchdog() {
digitalWrite(2, HIGH); Serial.println("Watchdog reset");
delay(20); digitalWrite(2, HIGH);
digitalWrite(2, LOW); delay(20);
digitalWrite(2, LOW);
} }
// Wifi Manager // Wifi Manager
void connectToWifi() { void connectToWifi() {
WiFiManager wifiManager; WiFiManager wifiManager;
switchLED(true); switchLED(true);
//WiFi.disconnect(); //to delete previous saved hotspot //WiFi.disconnect(); //to delete previous saved hotspot
String HOTSPOT = "AG-" + String(getNormalizedMac()); String HOTSPOT = "AG-" + String(getNormalizedMac());
wifiManager.setTimeout(180); wifiManager.setTimeout(180);
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
if (!wifiManager.autoConnect((const char * ) HOTSPOT.c_str())) {
switchLED(false); switchLED(false);
Serial.println("failed to connect and hit timeout"); Serial.println("failed to connect and hit timeout");
delay(6000); delay(6000);
} }
} }
void debug(String msg) { void debug(String msg) {
if (DEBUG) if (DEBUG)
Serial.print(msg); Serial.print(msg);
} }
void debug(int msg) { void debug(int msg) {
if (DEBUG) if (DEBUG)
Serial.print(msg); Serial.print(msg);
} }
void debugln(String msg) { void debugln(String msg) {
if (DEBUG) if (DEBUG)
Serial.println(msg); Serial.println(msg);
} }
void debugln(int msg) { void debugln(int msg) {
if (DEBUG) if (DEBUG)
Serial.println(msg); Serial.println(msg);
} }
String getNormalizedMac() { String getNormalizedMac() {
@ -472,6 +454,68 @@ String getNormalizedMac() {
return mac; return mac;
} }
void setRGBledCO2color(int co2Value) {
if (co2Value < 800) setRGBledColor('g');
if (co2Value >= 800 && co2Value < 1000) setRGBledColor('y');
if (co2Value >= 1000 && co2Value < 1500) setRGBledColor('o');
if (co2Value >= 1500 && co2Value < 2000) setRGBledColor('r');
if (co2Value >= 2000 && co2Value < 3000) setRGBledColor('p');
if (co2Value >= 3000 && co2Value < 10000) setRGBledColor('b');
}
void setRGBledColor(char color) {
if (useRGBledBar) {
//pixels.clear();
switch (color) {
case 'g':
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(0, 255, 0));
delay(100);
pixels.show();
}
break;
case 'y':
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 255, 0));
delay(100);
pixels.show();
}
break;
case 'o':
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 128, 0));
delay(100);
pixels.show();
}
break;
case 'r':
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(255, 0, 0));
delay(100);
pixels.show();
}
break;
case 'p':
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(153, 0, 153));
delay(100);
pixels.show();
}
break;
case 'b':
for (int i = 0; i < 11; i++) {
pixels.setPixelColor(i, pixels.Color(102, 0, 0));
delay(100);
pixels.show();
}
break;
default:
// if nothing else matches, do the default
// default is optional
break;
}
}
}
// Calculate PM2.5 US AQI // Calculate PM2.5 US AQI
int PM_TO_AQI_US(int pm02) { int PM_TO_AQI_US(int pm02) {