From a09da9b3ed690a195ea906bdd97bd5fc702bb38b Mon Sep 17 00:00:00 2001 From: gunner47 Date: Mon, 14 Oct 2019 16:18:45 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D0=B2=D1=8B=D0=B2=D0=BE=D0=B4=20=D0=B2=D1=80=D0=B5?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D0=B8=20=D0=BF=D0=BE=20=D0=B7=D0=B0=D0=BF?= =?UTF-8?q?=D1=80=D0=BE=D1=81=D1=83=20=D0=B8/=D0=B8=D0=BB=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B8=D0=BE=D0=B4=D0=B8=D1=87=D0=B5=D1=81=D0=BA?= =?UTF-8?q?=D0=B8;=20=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=B7=D0=B0=D0=BF=D1=83=D1=81=D0=BA=20?= =?UTF-8?q?=D0=B2=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC=D0=B5=20ESP=5FMODE=20?= =?UTF-8?q?=3D=200,=20=D0=B5=D1=81=D0=BB=D0=B8=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B2=D0=BE=D0=BC=20=D0=B7=D0=B0=D0=BF=D1=83?= =?UTF-8?q?=D1=81=D0=BA=D0=B5=20=D0=B2=20=D1=80=D0=B5=D0=B6=D0=B8=D0=BC?= =?UTF-8?q?=D0=B5=20ESP=5FMODE=20=3D=201=20=D0=BD=D0=B5=20=D0=B1=D1=8B?= =?UTF-8?q?=D0=BB=D0=B8=20=D0=B2=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D1=8B=20?= =?UTF-8?q?=D0=B8=D0=BC=D1=8F=20=D0=B8=20=D0=BF=D0=B0=D1=80=D0=BE=D0=BB?= =?UTF-8?q?=D1=8C=20WiFi=20=D1=81=D0=B5=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- firmware/GyverLamp_v1.4/Constants.h | 4 +- firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino | 26 ++++-- firmware/GyverLamp_v1.4/button.ino | 9 +- firmware/GyverLamp_v1.4/effects.ino | 2 +- firmware/GyverLamp_v1.4/runningText.ino | 97 ++++++++++++++++++++-- firmware/GyverLamp_v1.4/time.ino | 3 +- 6 files changed, 124 insertions(+), 17 deletions(-) diff --git a/firmware/GyverLamp_v1.4/Constants.h b/firmware/GyverLamp_v1.4/Constants.h index 26ed21e..89069a6 100644 --- a/firmware/GyverLamp_v1.4/Constants.h +++ b/firmware/GyverLamp_v1.4/Constants.h @@ -11,7 +11,7 @@ uint8_t espMode = ESP_MODE; // ESP_MODE може #define ESP_RESET_ON_START (false) // true - если при старте нажата кнопка (или кнопки нет!), сохранённые настройки будут сброшены; false - не будут #define ESP_HTTP_PORT (80U) // номер порта, который будет использоваться во время первой утановки имени WiFi сети (и пароля), к которой потом будет подключаться лампа в режиме WiFi клиента (лучше не менять) #define ESP_UDP_PORT (8888U) // номер порта, который будет "слушать" UDP сервер во время работы лампы как в режиме WiFi точки доступа, так и в режиме WiFi клиента (лучше не менять) -#define ESP_CONN_TIMEOUT (6U) // время в секундах (ДОЛЖНО БЫТЬ МЕНЬШЕ 8, иначе сработает WDT), которое ESP будет пытаться подключиться к WiFi сети, после его истечения автоматически развернёт WiFi точку доступа +#define ESP_CONN_TIMEOUT (7U) // время в секундах (ДОЛЖНО БЫТЬ МЕНЬШЕ 8, иначе сработает WDT), которое ESP будет пытаться подключиться к WiFi сети, после его истечения автоматически развернёт WiFi точку доступа #define ESP_CONF_TIMEOUT (300U) // время в секундах, которое ESP будет ждать ввода SSID и пароля WiFi сети роутера в конфигурационном режиме, после его истечения ESP перезагружается #define GENERAL_DEBUG // если строка не закомментирована, будут выводиться отладочные сообщения #define WIFIMAN_DEBUG (true) // вывод отладочных сообщений при подключении к WiFi сети: true - выводятся, false - не выводятся; настройка не зависит от GENERAL_DEBUG @@ -36,6 +36,8 @@ const uint8_t AP_STATIC_IP[] = {192, 168, 4, 1}; // статичес #define GMT (3) // часовой пояс (москва 3) #define NTP_ADDRESS ("ntp2.colocall.net") // сервер времени #define NTP_INTERVAL (30UL * 60UL * 1000UL) // интервал синхронизации времени (30 минут) +#define PRINT_TIME (0U) // 0U - не выводить время бегущей строкой; 1U - вывод времени каждый час; 2U - каждый час + каждые 30 минут; 3U - каждый час + каждые 15 минут + // 4U - каждый час + каждые 10 минут; 5U - каждый час + каждые 5 минут; 6U - каждый час + каждую минуту // --- ВНЕШНЕЕ УПРАВЛЕНИЕ -------------- #define USE_MQTT (false) // true - используется mqtt клиент, false - нет diff --git a/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino b/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino index 20737d2..660a820 100644 --- a/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino +++ b/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino @@ -87,6 +87,11 @@ - * при переключении рабочего режима лампы WiFi точка доступа/WiFi клиент семикратным кликом по кнопке (перед перезагрузкой) - 3 стандартных вспышки красным - Уменьшен таймаут подключения к WiFi сети до 6 секунд; вызвано увеличившейся продолжительностью работы функции setup(), она в сумме должна быть меньше 8 секунд - Оптимизирован код + --- 14.10.2019 + - Если при первом старте в режиме WiFi клиента запрашиваемые имя и пароль WiFi сети не введены за отведённый таймаут (5 минут), лампа перезагрузится в режиме точки доступа + - Добавлен вывод времени бегущей строкой: + - * по запросу - шестикратному клику - текущее время белым цветом; + - * периодически - определяется константой PRINT_TIME в Constants.h - от раза в час (красным цветом) до раза в минуту (синим цветом) с яркостью текущего эффекта как при включенной, так и при выключенной матрице */ // Ссылка для менеджера плат: @@ -133,6 +138,8 @@ NTPClient timeClient(ntpUDP, NTP_ADDRESS, GMT * 3600, NTP_INTERVAL); #endif timerMinim timeTimer(3000); +bool ntpServerAddressResolved = false; +uint32_t lastTimePrinted = 0U; #ifdef ESP_USE_BUTTON GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); @@ -200,6 +207,7 @@ void setup() { Serial.begin(115200); Serial.println(); + ESP.wdtEnable(WDTO_8S); // TELNET @@ -209,12 +217,10 @@ void setup() { handleTelnetClient(); delay(100); + ESP.wdtFeed(); } #endif - ESP.wdtDisable(); - //ESP.wdtEnable(WDTO_8S); - // КНОПКА #if defined(ESP_USE_BUTTON) @@ -227,6 +233,7 @@ void setup() wifiManager.resetSettings(); // сброс сохранённых SSID и пароля при старте с зажатой кнопкой, если разрешено LOG.println(F("Настройки WiFiManager сброшены")); } + ESP.wdtFeed(); #endif #endif @@ -304,7 +311,14 @@ void setup() if (WiFi.status() != WL_CONNECTED) { - LOG.println(F("Время ожидания ввода SSID и пароля от WiFi сети или подключения к WiFi сети превышено\nПерезагрузка модуля")); + LOG.println(F("Время ожидания ввода SSID и пароля от WiFi сети или подключения к WiFi сети превышено\nЛампа будет перезагружена в режиме WiFi точки доступа!\n")); + + espMode = (espMode == 0U) ? 1U : 0U; + EepromManager::SaveEspMode(&espMode); + + LOG.printf_P(PSTR("Рабочий режим лампы изменён и сохранён в энергонезависимую память\nНовый рабочий режим: ESP_MODE = %d, %s\nРестарт...\n"), + espMode, espMode == 0U ? F("WiFi точка доступа") : F("WiFi клиент (подключение к роутеру)")); + showWarning(CRGB::Red, 250U, 250U); // мигание красным цветом 0,25 секунды (1 раз) - ожидание ввода SSID'а и пароля WiFi сети прекращено, перезагрузка ESP.restart(); } @@ -312,6 +326,7 @@ void setup() LOG.print(F("IP адрес: ")); LOG.println(WiFi.localIP()); } + ESP.wdtFeed(); LOG.printf_P(PSTR("Порт UDP сервера: %u\n"), localPort); Udp.begin(localPort); @@ -320,6 +335,7 @@ void setup() // NTP #ifdef USE_NTP timeClient.begin(); + ESP.wdtFeed(); #endif @@ -330,6 +346,7 @@ void setup() mqttClient = new AsyncMqttClient(); MqttManager::setupMqtt(mqttClient, inputBuffer, &sendCurrent); // создание экземпляров объектов для работы с MQTT, их инициализация и подключение к MQTT брокеру } + ESP.wdtFeed(); #endif @@ -401,5 +418,4 @@ void loop() #endif ESP.wdtFeed(); // пнуть собаку - yield(); // обработать все "служебные" задачи: wdt, WiFi подключение и т.д. (?) } diff --git a/firmware/GyverLamp_v1.4/button.ino b/firmware/GyverLamp_v1.4/button.ino index f46a646..f8ae719 100644 --- a/firmware/GyverLamp_v1.4/button.ino +++ b/firmware/GyverLamp_v1.4/button.ino @@ -84,16 +84,21 @@ void buttonTick() #endif } - if (ONflag && clickCount == 5U) // вывод IP на лампу + if (clickCount == 5U) // вывод IP на лампу { if (espMode == 1U) { loadingFlag = true; - while(!fillString(WiFi.localIP().toString().c_str())) delay(1); + while(!fillString(WiFi.localIP().toString().c_str(), CRGB::White)) { delay(1); ESP.wdtFeed(); } loadingFlag = true; } } + if (clickCount == 6U) // вывод текущего времени бегущей строкой + { + printTime(thisTime, true); + } + if (ONflag && clickCount == 7U) // смена рабочего режима лампы: с WiFi точки доступа на WiFi клиент или наоборот { espMode = (espMode == 0U) ? 1U : 0U; diff --git a/firmware/GyverLamp_v1.4/effects.ino b/firmware/GyverLamp_v1.4/effects.ino index d6b9350..595c0e5 100644 --- a/firmware/GyverLamp_v1.4/effects.ino +++ b/firmware/GyverLamp_v1.4/effects.ino @@ -229,7 +229,7 @@ void rainbowDiagonalRoutine() for (uint8_t j = 0U; j < HEIGHT; j++) { float twirlFactor = 3.0F * (modes[EFF_RAINBOW_DIAG].Scale / 100.0F); // на сколько оборотов будет закручена матрица, [0..3] - CRGB thisColor = CHSV(constrain((uint8_t)(hue + (float)(WIDTH / HEIGHT * i + j * twirlFactor) * (float)(255 / maxDim)), 0, 255), 255, 255); + CRGB thisColor = CHSV((uint8_t)(hue + (float)(WIDTH / HEIGHT * i + j * twirlFactor) * (float)(255 / maxDim)), 255, 255); drawPixelXY(i, j, thisColor); } } diff --git a/firmware/GyverLamp_v1.4/runningText.ino b/firmware/GyverLamp_v1.4/runningText.ino index 0016e99..4ed9fd7 100644 --- a/firmware/GyverLamp_v1.4/runningText.ino +++ b/firmware/GyverLamp_v1.4/runningText.ino @@ -9,14 +9,16 @@ #define LET_WIDTH (5U) // ширина буквы шрифта #define LET_HEIGHT (8U) // высота буквы шрифта #define SPACE (1U) // пробел -#define LETTER_COLOR (CRGB::White) // цвет букв +#define LETTER_COLOR (CRGB::White) // цвет букв по умолчанию + // --- ДЛЯ РАЗРАБОТЧИКОВ --------------- int16_t offset = WIDTH; uint32_t scrollTimer = 0LL; -bool fillString(const char* text) + +bool fillString(const char* text, CRGB letterColor) { if (!text || !strlen(text)) { @@ -36,13 +38,13 @@ bool fillString(const char* text) uint8_t i = 0, j = 0; while (text[i] != '\0') { - if ((uint8_t)text[i] > 191) // работаем с русскими буквами! + if ((uint8_t)text[i] > 191) // работаем с русскими буквами { i++; } else { - drawLetter(text[i], offset + j * (LET_WIDTH + SPACE)); + drawLetter(text[i], offset + j * (LET_WIDTH + SPACE), letterColor); i++; j++; } @@ -60,7 +62,88 @@ bool fillString(const char* text) return false; } -void drawLetter(uint8_t letter, int8_t offset) + +void printTime(uint32_t thisTime, bool onDemand) // периодический вывод времени бегущей строкой; onDemand - по требованию, вывод текущего времени; иначе - вывод времени по расписанию +{ + #if defined(USE_NTP) && defined(PRINT_TIME) // вывод, только если используется синхронизация времени и если заказан его вывод бегущей строкой + if (espMode != 1U || !ntpServerAddressResolved) // вывод только в режиме WiFi клиента и только, если имя сервера времени разрезолвлено + { + return; + } + + CRGB letterColor = CRGB::Black; + bool needToPrint = false; + + #if (PRINT_TIME >= 1U) // вывод только каждый час (красным цветом) + if (thisTime % 60U == 0U) + { + needToPrint = true; + letterColor = CRGB::Red; + } + #endif + + #if (PRINT_TIME == 2U) // вывод каждый час (красным цветом) + каждые 30 минут (синим цветом) + if (thisTime % 60U != 0U && thisTime % 30U == 0U) + { + needToPrint = true; + letterColor = CRGB::Blue; + } + #endif + + #if (PRINT_TIME == 3U) // вывод каждый час (красным цветом) + каждые 15 минут (синим цветом) + if (thisTime % 60U != 0U && thisTime % 15U == 0U) + { + needToPrint = true; + letterColor = CRGB::Blue; + } + #endif + + #if (PRINT_TIME == 4U) // вывод каждый час (красным цветом) + каждые 10 минут (синим цветом) + if (thisTime % 60U != 0U && thisTime % 10U == 0U) + { + needToPrint = true; + letterColor = CRGB::Blue; + } + #endif + + #if (PRINT_TIME == 5U) // вывод каждый час (красным цветом) + каждые 5 минут (синим цветом) + if (thisTime % 60U != 0U && thisTime % 5U == 0U) + { + needToPrint = true; + letterColor = CRGB::Blue; + } + #endif + + #if (PRINT_TIME == 6U) // вывод каждый час (красным цветом) + каждую минуту (синим цветом) + if (thisTime % 60U != 0U) + { + needToPrint = true; + letterColor = CRGB::Blue; + } + #endif + + if (onDemand) + { + letterColor = CRGB::White; + } + + if ((needToPrint && thisTime != lastTimePrinted) || onDemand) + { + lastTimePrinted = thisTime; + char stringTime[10U]; + sprintf_P(stringTime, PSTR("-> %u:%02u"), (uint8_t)((thisTime - thisTime % 60U) / 60U), (uint8_t)(thisTime % 60U)); + loadingFlag = true; + FastLED.setBrightness(modes[currentMode].Brightness); + delay(1); + while (!fillString(stringTime, letterColor)) { delay(1); ESP.wdtFeed(); } + loadingFlag = true; + } + + #endif +} + + +void drawLetter(uint8_t letter, int8_t offset, CRGB letterColor) { uint8_t start_pos = 0, finish_pos = LET_WIDTH; @@ -100,7 +183,7 @@ void drawLetter(uint8_t letter, int8_t offset) { if (thisBit) { - leds[getPixelNumber(offset + i, TEXT_HEIGHT + j)] = LETTER_COLOR; + leds[getPixelNumber(offset + i, TEXT_HEIGHT + j)] = letterColor; } else { @@ -111,7 +194,7 @@ void drawLetter(uint8_t letter, int8_t offset) { if (thisBit) { - leds[getPixelNumber(i, offset + TEXT_HEIGHT + j)] = LETTER_COLOR; + leds[getPixelNumber(i, offset + TEXT_HEIGHT + j)] = letterColor; } else { diff --git a/firmware/GyverLamp_v1.4/time.ino b/firmware/GyverLamp_v1.4/time.ino index d8999d9..e2fe23c 100644 --- a/firmware/GyverLamp_v1.4/time.ino +++ b/firmware/GyverLamp_v1.4/time.ino @@ -13,7 +13,6 @@ #define RESOLVE_TIMEOUT (1500UL) // таймаут ожидания подключения к интернету в миллисекундах (1,5 секунды) uint64_t lastResolveTryMoment = 0UL; bool timeSynched = false; -bool ntpServerAddressResolved = false; IPAddress ntpServerIp = {0, 0, 0, 0}; static CHSV dawnColor = CHSV(0, 0, 0); // цвет "рассвета" static CHSV dawnColorMinus1 = CHSV(0, 0, 0); // для большей плавности назначаем каждый новый цвет только 1/10 всех диодов; каждая следующая 1/10 часть будет "оставать" на 1 шаг @@ -61,6 +60,8 @@ void timeTick() thisTime = timeClient.getHours() * 60 + timeClient.getMinutes(); uint32_t thisFullTime = timeClient.getHours() * 3600 + timeClient.getMinutes() * 60 + timeClient.getSeconds(); + printTime(thisTime, false); + // проверка рассвета if (alarms[thisDay].State && // день будильника thisTime >= (uint16_t)constrain(alarms[thisDay].Time - pgm_read_byte(&dawnOffsets[dawnMode]), 0, (24 * 60)) && // позже начала