#include #include "LiquidCrystal_I2C.h" #include "WiFiSettings.h" #include "ArduinoJson.h" #include #include #include #include "wifiFix.h" String weather_lat = ""; String weather_long = ""; String weather_apikey = ""; String weather_final_url = ""; SCD4x scd4x; LiquidCrystal_I2C LCD(0x27,2,1,0,4,5,6,7,3,POSITIVE); WiFiClient* wifi = new WiFiClientFixed(); HTTPClient* http = new HTTPClient(); #define PIN_LED_GREEN 25 #define PIN_LED_YELLOW 33 #define PIN_LED_RED 32 int backlightState = HIGH; volatile bool interruptFired = false; unsigned long lastInterrupt = 0; unsigned long lastUpdated = 0; unsigned long lastWeatherUpdate = 0; bool weatherUpdateSuccess = false; int lastWeatherPressure = 0; int avgAtmosphericPressure = 1013; unsigned const int updateTimer = 5000; unsigned const int interruptTimer = 500; void led(int red, int green, int yellow) { analogWrite(PIN_LED_RED, red); analogWrite(PIN_LED_GREEN, green); analogWrite(PIN_LED_YELLOW, yellow); } void IRAM_ATTR BacklightToggle() { if (!interruptFired) interruptFired = true; } void UpdateWeatherData() { if (lastWeatherUpdate != 0 && millis() - lastWeatherUpdate < 60000) { return; } lastWeatherUpdate = millis(); Serial.print("Attempting to get weather data from "); Serial.println(weather_final_url); http->begin(*wifi, weather_final_url); int httpResponseCode = http->GET(); if (httpResponseCode == 200) { String payload = http->getString(); http->end(); Serial.println(payload); StaticJsonDocument<1024> doc; DeserializationError error = deserializeJson(doc, payload.c_str()); if (error) { weatherUpdateSuccess = false; lastWeatherPressure = avgAtmosphericPressure; } float coord_lon = doc["coord"]["lon"]; // 3.45 float coord_lat = doc["coord"]["lat"]; // 1.23 JsonObject weather_0 = doc["weather"][0]; int weather_0_id = weather_0["id"]; // 804 const char* weather_0_main = weather_0["main"]; // "Clouds" const char* weather_0_description = weather_0["description"]; // "overcast clouds" const char* weather_0_icon = weather_0["icon"]; // "04d" const char* base = doc["base"]; // "stations" JsonObject main = doc["main"]; float main_temp = main["temp"]; // 301.92 float main_feels_like = main["feels_like"]; // 306.28 float main_temp_min = main["temp_min"]; // 301.92 float main_temp_max = main["temp_max"]; // 301.92 int main_pressure = main["pressure"]; // 1012 int main_humidity = main["humidity"]; // 75 int main_sea_level = main["sea_level"]; // 1012 int main_grnd_level = main["grnd_level"]; // 1012 int visibility = doc["visibility"]; // 10000 JsonObject wind = doc["wind"]; float wind_speed = wind["speed"]; // 4.71 int wind_deg = wind["deg"]; // 219 float wind_gust = wind["gust"]; // 4.52 int clouds_all = doc["clouds"]["all"]; // 100 long dt = doc["dt"]; // 1684079803 long sys_sunrise = doc["sys"]["sunrise"]; // 1684042647 long sys_sunset = doc["sys"]["sunset"]; // 1684086466 int timezone = doc["timezone"]; // 0 int id = doc["id"]; // 0 const char* name = doc["name"]; // nullptr int cod = doc["cod"]; // 200 lastWeatherPressure = main_pressure; weatherUpdateSuccess = true; Serial.println(String("Got pressure: ") + lastWeatherPressure); } else { http->end(); lastWeatherPressure = avgAtmosphericPressure; weatherUpdateSuccess = false; Serial.println(String("Failed getting pressure (Error code: ") + httpResponseCode + String("), using avg atmospheric pressure: ") + lastWeatherPressure); } } void UpdateSensorCompensation(){ if (weatherUpdateSuccess) { scd4x.setAmbientPressure(lastWeatherPressure * 100); // It wants the data in Pascal! } } void setup() { Serial.begin(115200); LCD.begin(16, 2); LCD.clear(); LCD.setBacklight(backlightState); LCD.print("WiFi init..."); SPIFFS.begin(true); WiFiSettings.hostname = "co2-scd4x-"; weather_apikey = WiFiSettings.string("OpenWeatherMap API key", "hskjdfghjkdfhgyuw"); weather_lat = WiFiSettings.string("Location: latitude", "1.23"); weather_long = WiFiSettings.string("Location: longitude", "3.45"); weather_final_url = "http://api.openweathermap.org/data/2.5/weather?lat=" + weather_lat + "&lon=" + weather_long + "&appid=" + weather_apikey; WiFiSettings.connect(); scd4x.enableDebugging(); if (!scd4x.begin(Wire)) { Serial.println("Could not find SCD4x? Check wiring"); LCD.clear(); LCD.print("SCD4x not found"); LCD.setCursor(0, 1); LCD.print("Check wiring"); while (true); } scd4x.stopPeriodicMeasurement(); LCD.setCursor(0, 0); LCD.print("SCD4x SELF TEST "); if (!scd4x.performSelfTest()) { Serial.println("SCD4x self test failed"); LCD.setCursor(0, 1); LCD.print("FAIL"); while (true); } scd4x.setAutomaticSelfCalibrationEnabled(true); LCD.setCursor(0, 1); LCD.print("PASS"); delay(1000); Serial.println("SCD4x init:"); char mySerial[16]; scd4x.getSerialNumber(mySerial); Serial.print("Serial no: "); Serial.println(mySerial); LCD.setCursor(6, 0); LCD.print("SERIAL # "); LCD.setCursor(0, 1); LCD.print(mySerial); delay(1000); Serial.print("Altitude: "); Serial.println(scd4x.getSensorAltitude()); Serial.print("Self-cal enabled: "); Serial.println(scd4x.getAutomaticSelfCalibrationEnabled() ? "Yes" : "No"); Serial.print("Temperature Offset: "); Serial.println(scd4x.getTemperatureOffset()); UpdateWeatherData(); UpdateSensorCompensation(); scd4x.startPeriodicMeasurement(); pinMode(23, INPUT_PULLUP); attachInterrupt(23, BacklightToggle, FALLING); LCD.clear(); } void loop() { if (interruptFired) { if (millis() - lastInterrupt > interruptTimer || lastInterrupt == 0) { backlightState = !backlightState; Serial.printf("Setting backlight to %i \n", backlightState); LCD.setBacklight(backlightState); lastInterrupt = millis(); } interruptFired = false; } if (millis() - lastUpdated > updateTimer || lastUpdated == 0) { lastUpdated = millis(); } else { return; } UpdateWeatherData(); UpdateSensorCompensation(); int co2 = scd4x.getCO2(); float temp = scd4x.getTemperature(); float rh = scd4x.getHumidity(); LCD.setCursor(0, 0); LCD.print(temp, 1); LCD.print((char)223); // Degree symbol (º) LCD.print("C "); LCD.setCursor(9, 0); LCD.print(rh, 1); LCD.print("%rH"); LCD.setCursor(0, 1); LCD.print(co2); LCD.print("ppm "); LCD.setCursor(9, 1); if (weatherUpdateSuccess) LCD.print(lastWeatherPressure); else LCD.print("----"); LCD.print("hPa"); Serial.print(co2); Serial.print(" ppm, "); Serial.print(temp); Serial.print(" ºC, "); Serial.print(rh); Serial.println(" %rH"); if (co2 < 1000) led(0, 1, 0); else if (co2 < 1500) led(0, 0, 5); else led(5, 0, 0); }