#include #include #include #include #include #include #include // https://github.com/tzapu/WiFiManager WiFiManager wm; #include const char* debug = "debug"; const char* server = "mqtt.iot"; const char* s_will = "died"; const char* s_ready = "ready"; const char* s_sens = "zero MHZ"; WiFiClient espClient; PubSubClient client(espClient); char co[28]; char tmp[28]; char hum[28]; char sta[21]; uint8_t MAC_array[6]; char MAC_char[21]; char buffer[60]; bool pubsub = false; MHZ19 myMHZ19; Adafruit_AHTX0 aht; // x38 #if defined mydisplay #include LiquidCrystal_I2C lcd(0x27, 20, 4); #define DEGREE_SYMBOL 0xDF //degree symbol from LCD ROM byte user_value1[8] ={ B11111, B11111, B00000, B00000, B00000, B00000, B00000, B00000 }; byte user_value2[8] ={ B00000, B00000, B00000, B00000, B00000, B00000, B11111, B11111 }; byte user_value3[8] ={ B11111, B11111, B00000, B00000, B00000, B00000, B11111, B11111 }; byte user_value4[8] ={ B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; byte user_value5[8] ={ B00000, B00000, B00011, B00011, B00011, B00011, B00000, B00000 }; byte user_value6[8] ={ B00000, B00000, B11000, B11000, B11000, B11000, B00000, B00000 }; byte plus_minus_icon[8] = {0x00, 0x04, 0x0E, 0x04, 0x00, 0x0E, 0x00, 0x00}; const uint8_t numbers[][6] = { { 3, 0, 3, 3, 1, 3 }, { 0, 3, 160, 1, 3, 1 }, { 2, 2, 3, 3, 1, 1 }, { 2, 2, 3, 1, 1, 3 }, { 3, 1, 3, 160, 160, 3 }, { 3, 2, 2, 1, 1, 3 }, { 3, 2, 2, 3, 1, 3 }, { 0, 0, 3, 160, 160, 3 }, { 3, 2, 3, 3, 1, 3 }, { 3, 2, 3, 1, 1, 3 }, { 160, 160, 160, 160, 160, 160 } }; void myprint(int x, const uint8_t num[6]) { yield(); lcd.setCursor(x,0); yield(); lcd.write(num[0]); yield(); lcd.write(num[1]); yield(); lcd.write(num[2]); yield(); lcd.setCursor(x,1); yield(); lcd.write(num[3]); yield(); lcd.write(num[4]); yield(); lcd.write(num[5]); } void numprint(int num) { if(num >= 10000) { myprint(0, numbers[num / 10000 % 10]); } else { myprint(0, numbers[10]); } if(num >= 1000) { myprint(4, numbers[num / 1000 % 10]); } else { myprint(4, numbers[10]); } if(num >= 100) { myprint(8, numbers[num / 100 % 10]); } else { myprint(8, numbers[10]); } if(num >= 10) { myprint(12, numbers[num / 10 % 10]); } else { myprint(12, numbers[10]); } if(num >= 0) { myprint(16, numbers[num / 1 % 10]); } else { myprint(16, numbers[10]); } } #endif void callback(char* topic, byte* payload, unsigned int length) { if(topic[14] == 's') { if((char)payload[0] == 'r' && (char)payload[1] == 'e' && (char)payload[2] == 's' && (char)payload[3] == 'e' && (char)payload[4] == 't') { #if defined mydisplay lcd.setCursor(0,1); lcd.print(F("reset")); #endif WiFi.forceSleepBegin(); ESP.wdtFeed(); ESP.restart(); while(true) { yield(); } } if((char)payload[0] == 'c' && (char)payload[1] == 'a' && (char)payload[2] == 'l' && (char)payload[3] == 'i' && (char)payload[4] == 'b') { myMHZ19.calibrate(); client.publish(sta,s_sens); } } } unsigned long tick = 0; int sec = 20; bool sensor = false; void setup() { Serial.begin(9600); WiFi.mode(WIFI_STA); unsigned int i; WiFi.macAddress(MAC_array); for (i = 0; i < sizeof(MAC_array); ++i){ sprintf(MAC_char,"%s%02x",MAC_char,MAC_array[i]); } sprintf(co,"/%s/co2",MAC_char); sprintf(sta,"/%s/status",MAC_char); sprintf(tmp,"/%s/temperature",MAC_char); sprintf(hum,"/%s/humidity",MAC_char); client.setServer(server, 1883); client.setCallback(callback); wm.setConfigPortalBlocking(false); wm.setDebugOutput(false); if(wm.autoConnect("CO2sensor")){ pubsub = true; client.connect(MAC_char, sta, 0, false, s_will); client.subscribe(sta,1); client.publish(debug,MAC_char); IPAddress ip = WiFi.localIP(); sprintf(buffer,"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); client.publish(sta,buffer); client.publish(sta, server); client.publish(sta, PROJECT); client.publish(sta,s_ready); } Wire.begin(0,2); // 00-sda,02-sdl #if defined mydisplay lcd.init(); lcd.noBacklight(); lcd.clear(); lcd.backlight(); lcd.print(F("CO2 monitor starting")); #endif myMHZ19.begin(Serial); myMHZ19.setRange(2000); myMHZ19.autoCalibration(false); #if defined mydisplay lcd.setCursor(0,1); lcd.print(F("CO2 sensor started")); #endif sensor = aht.begin(); #if defined mydisplay lcd.setCursor(0,2); lcd.print(F("aht sensor started")); lcd.createChar(0, user_value1); lcd.createChar(1, user_value2); lcd.createChar(2, user_value3); lcd.createChar(3, user_value4); lcd.createChar(4, user_value5); lcd.createChar(5, user_value6); lcd.createChar(6, plus_minus_icon); lcd.setCursor(0,3); lcd.print(F("lcd font loaded")); #endif ESP.wdtEnable(WDTO_8S); tick = millis(); } bool clear = true; int value; sensors_event_t humidity, temp; void loop() { ESP.wdtFeed(); wm.process(); pubsub = WiFi.isConnected(); if(pubsub) { ESP.wdtFeed(); yield(); if(client.connected()) { client.loop(); } else { client.connect(MAC_char, sta, 0, false, s_will); client.subscribe(sta,1); client.publish(sta,__FILE__); IPAddress ip = WiFi.localIP(); sprintf(buffer,"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); client.publish(sta,buffer); } } if(millis() - tick >= 1000) { tick = millis(); sec--; if(sec<0) sec = 5; if(sec == 5) { if(clear) { #if defined mydisplay lcd.clear(); #endif clear = false; } value = myMHZ19.getCO2(); #if defined mydisplay numprint(value); #endif if(pubsub) { sprintf(buffer,"%d", (int) value); client.publish(co,buffer); } if(sensor) { aht.getEvent(&humidity, &temp); if(pubsub) { dtostrf(temp.temperature,4,2,buffer); client.publish(tmp,buffer); sprintf(buffer,"%d", (int) humidity.relative_humidity); client.publish(hum,buffer); } #if defined mydisplay lcd.setCursor(0,2); lcd.print(temp.temperature); lcd.print(F(" ")); lcd.write(6); lcd.print(F("0.3")); lcd.write(DEGREE_SYMBOL); lcd.print(F("C ")); lcd.setCursor(0,3); lcd.print((int) humidity.relative_humidity); lcd.print(F(" ")); lcd.write(6); lcd.print(F("2% ")); #endif } } } delay(100); }