#include #include #include /////////////////////////////////////////////////////////////////// // Set your SSID & Pass for initial configuration #include "../include/configuration.h" // application configuration /////////////////////////////////////////////////////////////////// #include "max7219.h" #include "webserver.h" DHT dht(DHT_PIN, DHT22); Timer procTimer, procRTimer; Timer displayTimer, tmpTimer; Timer showHighTimer, showLowTimer; Timer brightTimer; // Sensors values float SensorT, SensorH, SensorHI, SensorCR; String StrCF; // Time values time_t Time, NTPLastUpdate; DateTime dt; void process(void); void connectOk(void); void connectFail(void); void showWatch(void); void showTime(void); void showTemperature(void); void showHumidity(void); void setBright(void); // NTP Client void onNtpReceive(NtpClient& client, time_t timestamp); NtpClient ntpClient("ntps1-0.cs.tu-berlin.de", 300, onNtpReceive); void init() { 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); WifiStation.waitConnection(connectOk, 20, connectFail); // We recommend 20+ seconds for connection timeout at start // DHT sensor start dht.begin(); // опрос датчиков -- раз в минуту? procTimer.initializeMs(60000, process).start(); process(); // 7-segment output MAX7219_Init(); tmpTimer.initializeMs(10, MAX7219_FillMinus).startOnce(); brightTimer.initializeMs(1000, setBright).start(); // обновление экрана два раза в секунду displayTimer.initializeMs(500, showWatch).start(); } void showWatch() { static uint8_t old_si = 0xFF; static time_t oldTime; Time = SystemClock.now(); dt.setTime(Time); /* * теперь в dt у нас следующее: * 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 */ uint8_t si = dt.Second / 5; /* * 0 - Temp * 1 - Humidity * 2 - Temp * 3 - Humidity * 4 - Temp * 5 - Humidity * 6 - Temp * 7 - Humidity * 8 - Temp * 9 - Humidity * 10 - Temp * 11 - Humidity */ if (oldTime == Time) { // Старая секунда // time the same, output blank for [HH MM] MAX7219_writeData(MAX7219_DIGIT2, SYM_BLANK); /* if (si != 5 || si != 11) { MAX7219_writeData(MAX7219_DIGIT2, SYM_BLANK); } */ } else { // Новая секунда oldTime = Time; // Запланируем обновление индикаторов showHighTimer.initializeMs(10, showTime).startOnce(); switch(dt.Second / 15) { case 0: MAX7219_writeData(MAX7219_DIGIT2, SYM_Minus); break; case 1: MAX7219_writeData(MAX7219_DIGIT2, SYM_Minus2L); break; case 2: MAX7219_writeData(MAX7219_DIGIT2, SYM_Minus2H); break; case 3: MAX7219_writeData(MAX7219_DIGIT2, SYM_Minus3); break; } if (old_si != si) { old_si = si; switch (si) { case 0: showLowTimer.initializeMs(20, showTemperature).startOnce(); break; case 1: showLowTimer.initializeMs(20, showHumidity).startOnce(); break; case 2: showLowTimer.initializeMs(20, showTemperature).startOnce(); break; case 3: showLowTimer.initializeMs(20, showHumidity).startOnce(); break; case 4: showLowTimer.initializeMs(20, showTemperature).startOnce(); break; case 5: showLowTimer.initializeMs(20, showHumidity).startOnce(); break; case 6: showLowTimer.initializeMs(20, showTemperature).startOnce(); break; case 7: showLowTimer.initializeMs(20, showHumidity).startOnce(); break; case 8: showLowTimer.initializeMs(20, showTemperature).startOnce(); break; case 9: showLowTimer.initializeMs(20, showHumidity).startOnce(); break; case 10: showLowTimer.initializeMs(20, showTemperature).startOnce(); break; case 11: showLowTimer.initializeMs(20, showHumidity).startOnce(); break; } } } } /* * Выводим текущее время [HH MM] на верхние индикаторы */ void showTime(void) { static uint8_t oldHour = 0xFF, oldMinute = 0xFF; if (oldMinute != dt.Minute) { oldMinute = dt.Minute; MAX7219_writeData(MAX7219_DIGIT3, dt.Minute / 10); MAX7219_writeData(MAX7219_DIGIT4, dt.Minute % 10); if (oldHour != dt.Hour) { oldHour = dt.Hour; // уберём ведущий ноль у часов if (dt.Hour < 10) { MAX7219_writeData(MAX7219_DIGIT0, MAX7219_CHAR_BLANK); } else { MAX7219_writeData(MAX7219_DIGIT0, dt.Hour / 10); } MAX7219_writeData(MAX7219_DIGIT1, dt.Hour % 10); } } } /* * Выводим температуру на нижние индикаторы */ void showTemperature(void) { MAX7219_writeData(MAX7219_DIGIT5, SYM_Temp); MAX7219_writeData(MAX7219_DIGIT6, (int) (SensorT) / 10); MAX7219_writeData(MAX7219_DIGIT7, (int) (SensorT) % 10); } /* * Выводим влажность на нижние индикаторы */ void showHumidity(void) { MAX7219_writeData(MAX7219_DIGIT5, SYM_H_SM); MAX7219_writeData(MAX7219_DIGIT6, (int) (SensorH) / 10); MAX7219_writeData(MAX7219_DIGIT7, (int) (SensorH) % 10); } /* * Выводим дату на верхние индикаторы [DD MM] */ /* void showDate(void) { MAX7219_writeData(MAX7219_DIGIT0, dt.Day/10); MAX7219_writeData(MAX7219_DIGIT1, dt.Day%10); MAX7219_writeData(MAX7219_DIGIT2, SYM_Minus); MAX7219_writeData(MAX7219_DIGIT3, dt.Month/10); MAX7219_writeData(MAX7219_DIGIT4, dt.Month%10); MAX7219_writeData(MAX7219_DIGIT6, (uint8_t)(dt.DayofWeek / 10)); MAX7219_writeData(MAX7219_DIGIT7, (uint8_t)(dt.DayofWeek % 10)); } */ /* * Автоматическая регулировка яркости индикаторов */ void setBright(void) { // приведём к диапазону 0-16 uint8_t bright = (1024 - system_adc_read()) >> 6; // переведём диапазон значений 9-16/1 в 1-15/2 if (bright > 8) { bright = ( (bright - 9) * 2 ) + 1; } else { bright = 1; } MAX7219_writeData(MAX7219_MODE_INTENSITY, bright); } /* * Читаем данные с DHT22, в случае неудачи -- данные остануться старыми. * меня это полностью устраивает. */ void process() { TempAndHumidity th; ComfortState cf; static int8_t status; if (dht.readTempAndHumidity(th)) { status = 0; SensorT = th.temp; SensorH = th.humid; SensorHI = dht.getHeatIndex(); SensorCR = dht.getComfortRatio(cf); switch (cf) { case Comfort_OK: StrCF = "OK"; break; case Comfort_TooHot: StrCF = "Too Hot"; break; case Comfort_TooCold: StrCF = "Too Cold"; break; case Comfort_TooDry: StrCF = "Too Dry"; break; case Comfort_TooHumid: StrCF = "Too Humid"; break; case Comfort_HotAndHumid: StrCF = "Hot And Humid"; break; case Comfort_HotAndDry: StrCF = "Hot And Dry"; break; case Comfort_ColdAndHumid: StrCF = "Cold And Humid"; break; case Comfort_ColdAndDry: StrCF = "Cold And Dry"; break; default: StrCF = "Unknown"; break; } } else { /* * В случае, если от датчика ничего не получили, запустим повторный опрос через * 10 секунд, но не более 5 раз подряд. */ if (status < 6) { status++; procRTimer.initializeMs(10000, process).startOnce(); } } } void connectOk() { WifiAccessPoint.enable(false); Serial.print("I'm connecteed. IP: "); Serial.println(WifiStation.getIP().toString()); startWebServer(); } /* * в случае неудачи подключения поднимаем точку доступа без авторизации */ void connectFail() { WifiAccessPoint.config("MeteoConfig", "", AUTH_OPEN); WifiAccessPoint.enable(true); // Stop main screen output procTimer.stop(); displayTimer.stop(); Serial.println("WiFi MeteoConfig"); Serial.println(WifiAccessPoint.getIP()); startWebServer(); WifiStation.waitConnection(connectOk); // Wait connection } /* * NTP Client */ void onNtpReceive(NtpClient& client, time_t timestamp) { SystemClock.setTime(timestamp, eTZ_UTC); NTPLastUpdate = SystemClock.now(); Serial.println("*** Time synchronized OK! ***"); // DEBUG }