#include #include /////////////////////////////////////////////////////////////////// // Set your SSID & Pass for initial configuration #include "configuration.h" // application configuration /////////////////////////////////////////////////////////////////// #include "webserver.h" #include "tm1650.h" #include "SparkFun_Alphanumeric_Display.h" #include "AHTxx.h" HT16K33 display; /** DHT22 */ #define DHT22_PIN 2 DHTesp dht; TempAndHumidity th; Timer readTemperatureProcTimer; void onTimer_readDHT22(); Timer procTimer, procRTimer; Timer displayTimer, tmpTimer; Timer showHighTimer, showLowTimer; Timer dotTimer; // Sensors values ahtxx_t sensorData; String StrCF; // Time values time_t Time, NTPLastUpdate; DateTime dt; float SensorT, SensorH, SensorHI, SensorCR; void GetData(void); void connectOk(const String& SSID, MacAddress bssid, uint8_t channel); void connectFail(const String& ssid, MacAddress bssid, WifiDisconnectReason reason); void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway); void showWatch(void); void showTime(void); void dotOff(void); void showTemperature(void); void showHumidity(void); void showError(void); void shiftStringLeft(void); // NTP Client void onNtpReceive(NtpClient& client, time_t timestamp); NtpClient ntpClient("ntp.time.in.ua", 1500, onNtpReceive); // every 15 min void init(void) { spiffs_mount(); // Mount file system, in order to work with files Serial.begin(SERIAL_BAUD_RATE); // 115200 by default Serial.systemDebugOutput(false); // Debug output to serial Serial.println("Wall Segment Clock"); ActiveConfig = loadConfig(); // set timezone hourly difference to UTC SystemClock.setTimeZone(ActiveConfig.AddTZ); WifiStation.config(ActiveConfig.NetworkSSID, ActiveConfig.NetworkPassword); WifiStation.enable(true); WifiAccessPoint.enable(false); WifiEvents.onStationConnect(connectOk); WifiEvents.onStationDisconnect(connectFail); WifiEvents.onStationGotIP(gotIP); // initialize I2C Wire.pins(4, 5); Wire.begin(); // BIG digits TM1650_Init(); // Low 14-Seg LED output if (display.begin(DEFAULT_ADDRESS) == false) { Serial.println("HT16K33 device did not acknowledge!"); } else { if (display.initialize() != false) { Serial.println("HT16K33 displays acknowledged. Init OK"); } else { Serial.println("HT16K33 displays acknowledged. Init FAIL"); } } display.print("1234"); tmpTimer.initializeMs(500, shiftStringLeft).start(); // refresh big led displayTimer.initializeMs(1000, showWatch).start(); /* AHTxx Sensor */ // AHTxx_Init(); // procTimer.initializeMs(2000, GetData).start(); /* DHT22 */ dht.setup(DHT22_PIN, DHTesp::DHT22); readTemperatureProcTimer.initializeMs(30000, onTimer_readDHT22).start(); // every so often. } void showWatch(void) { static time_t oldTime; Time = SystemClock.now(); dt.setTime(Time); /* * Now, in dt we have: * int8_t Hour; * int8_t Minute; * int8_t Second; * int16_t Milliseconds; * int8_t Day; * int8_t DayofWeek; -- Sunday is day 0 * int8_t Month; // Jan is month 0 * int16_t Year; // Full Year numer */ if (oldTime != Time) { // New Second oldTime = Time; showTime(); if (dt.Second == 0x00) { Serial.printf("Time: %02d:%02d:00\r\n", dt.Hour, dt.Minute); } } } /* * Выводим текущее время [HH MM] на верхние индикаторы */ void showTime(void) { static uint8_t oldHour = 0xFF, oldMinute = 0xFF; if (oldMinute != dt.Minute) { oldMinute = dt.Minute; // ... if (oldHour != dt.Hour) { oldHour = dt.Hour; // ... } // new hour } // new minute TM1650_Out(dt.Hour/10, dt.Hour%10, dt.Minute/10, dt.Minute%10); TM1650_DotSet(Dig_2); TM1650_DotSet(Dig_3); dotTimer.initializeMs(500, dotOff); dotTimer.startOnce(); } void dotOff(void) { TM1650_DotRes(Dig_2); TM1650_DotRes(Dig_3); } /* * Show temperature, small indicators */ void showTemperature(void) { SensorT = th.temperature; uint8_t a, b; a = (uint8_t)th.temperature / 10; b = (uint8_t)th.temperature % 10; TM1650_Out(a, b, 0, 0); TM1650_Out3(Sym_o); TM1650_Out4(Sym_C); } /* * Show humidity, small indicators */ void showHumidity(void) { SensorH = th.humidity; uint8_t a, b; a = (uint8_t)th.humidity / 10; b = (uint8_t)th.humidity % 10; TM1650_Out(a, b, 0, 0); TM1650_Out3(Sym_Off); TM1650_Out4(Sym_H); } /* * Show error, small indicators */ void showError(void) { TM1650_DotRes(Dig_2); TM1650_Out1(Sym_E); TM1650_Out2(Sym_r); TM1650_Out3(Sym_r); TM1650_Out4(Sym_Off); } /* * Выводим дату на верхние индикаторы [DD MM] */ void showDate(void) { // ... } /** * @brief Get data from Temperature/Humidity Sensor. */ void GetData(void) { static bool st = false; AHTxx_GetData(&sensorData); if (sensorData.Error != St_OK) { Serial.println("Sensor: Data error!"); return; } th.temperature = (float)sensorData.Temperature / 10.0; th.humidity = (float)sensorData.Humidity / 10.0; if (st) { st = !st; showTemperature(); } else { st = !st; showHumidity(); } Serial.printf("Humidity: %d.%d %%; Temperature: %d.%d *C\r\n", sensorData.Humidity/10, sensorData.Humidity%10, sensorData.Temperature/10, sensorData.Temperature%10); } void connectOk(const String& SSID, MacAddress bssid, uint8_t channel) { debugf("connected"); WifiAccessPoint.enable(false); } void gotIP(IpAddress ip, IpAddress netmask, IpAddress gateway) { Serial.print("Got IP address: "); Serial.println(ip); // Restart main screen output procTimer.restart(); displayTimer.restart(); // start NTP Client there? startWebServer(); } void connectFail(const String& ssid, MacAddress bssid, WifiDisconnectReason reason) { debugf("connection FAILED: %s", WifiEvents.getDisconnectReasonDesc(reason).c_str()); WifiAccessPoint.config("ClockConfig", "", AUTH_OPEN); WifiAccessPoint.enable(true); // Stop main screen output procTimer.stop(); displayTimer.stop(); Serial.println("WiFi ClockConfig"); Serial.println(WifiAccessPoint.getIP()); startWebServer(); WifiStation.disconnect(); WifiStation.connect(); } /** * @brief NTP Client */ void onNtpReceive(NtpClient& client, time_t timestamp) { SystemClock.setTime(timestamp, eTZ_UTC); NTPLastUpdate = SystemClock.now(); Serial.println("*** Time synchronized OK! ***"); // DEBUG } void onTimer_readDHT22() { //* try different reading methods (Adafruit compatible) vs improved */ static bool toggle = false; toggle = !toggle; float humidity = 0; float temperature = 0; Serial << _F("TickCount=") << RTC.getRtcNanoseconds() / 1000000 << endl; if(toggle) { Serial.println(_F("Read using Adafruit API methods")); humidity = dht.getHumidity(); temperature = dht.getTemperature(); th.humidity = humidity; th.temperature = temperature; // check if returns are valid, if they are NaN (not a number) then something went wrong! if(dht.getStatus() == DHTesp::ERROR_NONE) { Serial << _F("\tHumidity: ") << humidity << _F("% Temperature: ") << temperature << " °C" << endl; } else { Serial << _F("Failed to read from DHT: ") << dht.getStatus() << endl; } } else { //* improved reading method Serial.println(_F("\r\n" "Read using new API methods")); th = dht.getTempAndHumidity(); humidity = th.humidity; temperature = th.temperature; if(dht.getStatus() == DHTesp::ERROR_NONE) { Serial << _F("\tHumidity: ") << th.humidity << _F("% Temperature: ") << th.temperature << " °C" << endl; } else { Serial << _F("Failed to read from DHT: ") << dht.getStatus() << endl; } } // Other goodies: // // Heatindex is the perceived temperature taking humidity into account // More: https://en.wikipedia.org/wiki/Heat_index // Serial << _F("Heatindex: ") << dht.computeHeatIndex(temperature, humidity) << " °C" << endl; // // Dewpoint is the temperature where condensation starts. // Water vapors will start condensing on an object having this temperature or below. // More: https://en.wikipedia.org/wiki/Dew_point // Serial << _F("Dewpoint: ") << dht.computeDewPoint(temperature, humidity) << " °C" << endl; // // Determine thermal comfort according to http://epb.apogee.net/res/refcomf.asp // ComfortState cf; Serial << _F("Comfort is at ") << dht.getComfortRatio(cf, temperature, humidity) << " %, ("; switch(cf) { case Comfort_OK: Serial.print(_F("OK")); break; case Comfort_TooHot: Serial.print(_F("Too Hot")); break; case Comfort_TooCold: Serial.print(_F("Too Cold")); break; case Comfort_TooDry: Serial.print(_F("Too Dry")); break; case Comfort_TooHumid: Serial.print(_F("Too Humid")); break; case Comfort_HotAndHumid: Serial.print(_F("Hot And Humid")); break; case Comfort_HotAndDry: Serial.print(_F("Hot And Dry")); break; case Comfort_ColdAndHumid: Serial.print(_F("Cold And Humid")); break; case Comfort_ColdAndDry: Serial.print(_F("Cold And Dry")); break; default: Serial.print(_F("Unknown:")); Serial.print(cf); break; } Serial.println(')'); } void shiftStringLeft(void) { display.shiftLeft(); }