mirror of
https://github.com/gunner47/GyverLamp.git
synced 2025-08-07 09:00:30 +03:00
Добавлена возможность смены ESP_MODE без перепрошивки; доработан будильник; добавлена визуальная сигнализация красными и жёлтыми вспышками для некоторых действий/состояний; оптимизирован код, исправлены ошибки
This commit is contained in:
@@ -6,11 +6,12 @@
|
||||
// ============= НАСТРОЙКИ =============
|
||||
// --- ESP -----------------------------
|
||||
#define ESP_MODE (1U) // 0U - WiFi точка доступа, 1U - клиент WiFi (подключение к роутеру)
|
||||
uint8_t espMode = ESP_MODE; // ESP_MODE может быть сохранён в энергонезависимую память и изменён в процессе работы лампы без необходимости её перепрошивки
|
||||
#define ESP_USE_BUTTON // если строка не закомментирована, должна быть подключена кнопка (иначе ESP может регистрировать "фантомные" нажатия и некорректно устанавливать яркость)
|
||||
#define ESP_RESET_ON_START (false) // true - если при старте нажата кнопка (или кнопки нет!), сохранённые настройки будут сброшены; false - не будут
|
||||
#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 (7U) // время в секундах (ДОЛЖНО БЫТЬ МЕНЬШЕ 8, иначе сработает WDT), которое ESP будет пытаться подключиться к WiFi сети, после его истечения автоматически развернёт WiFi точку доступа
|
||||
#define ESP_CONN_TIMEOUT (6U) // время в секундах (ДОЛЖНО БЫТЬ МЕНЬШЕ 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
|
||||
@@ -111,5 +112,5 @@ bool telnetGreetingShown = false; // признак "
|
||||
#define FASTLED_ALLOW_INTERRUPTS (0U)
|
||||
#define FASTLED_ESP8266_RAW_PIN_ORDER
|
||||
|
||||
#define NUM_LEDS (WIDTH * HEIGHT)
|
||||
#define NUM_LEDS (uint16_t)(WIDTH * HEIGHT)
|
||||
#define SEGMENTS (1U) // диодов в одном "пикселе" (для создания матрицы из кусков ленты)
|
||||
|
@@ -55,7 +55,7 @@
|
||||
*
|
||||
* Не используются адреса:
|
||||
* 96-110 15 резерв, можно добавить ещё 5 эффектов
|
||||
* 142-196 55 если добавить ещё 5 эффектов, начальный адрес неиспользуемой памяти сдвинется с 142 на 147
|
||||
* 142-195 54 если добавить ещё 5 эффектов, начальный адрес неиспользуемой памяти сдвинется с 142 на 147
|
||||
*/
|
||||
|
||||
#include <EEPROM.h>
|
||||
@@ -64,6 +64,7 @@
|
||||
#define EEPROM_ALARM_START_ADDRESS (0U) // начальный адрес в EEPROM памяти для записи настроек будильников
|
||||
#define EEPROM_MODES_START_ADDRESS (21U) // начальный адрес в EEPROM памяти для записи настроек эффектов (яркость, скорость, масштаб)
|
||||
#define EEPROM_FAVORITES_START_ADDRESS (111U) // начальный адрес в EEPROM памяти для записи настроек режима избранных эффектов
|
||||
#define EEPROM_ESP_MODE (196U) // адрес в EEPROM памяти для записи режима работы модуля ESP (точка доступа/WiFi клиент)
|
||||
#define EEPROM_LAMP_ON_ADDRESS (197U) // адрес в EEPROM памяти для записи состояния лампы (вкл/выкл)
|
||||
#define EEPROM_FIRST_RUN_ADDRESS (198U) // адрес в EEPROM памяти для записи признака первого запуска (определяет необходимость первоначальной записи всех хранимых настроек)
|
||||
#define EEPROM_DAWN_MODE_ADDRESS (199U) // адрес в EEPROM памяти для записи времени до "рассвета"
|
||||
@@ -79,7 +80,7 @@
|
||||
class EepromManager
|
||||
{
|
||||
public:
|
||||
static void InitEepromSettings(ModeType modes[], AlarmType alarms[], bool* onFlag, uint8_t* dawnMode, int8_t* currentMode,
|
||||
static void InitEepromSettings(ModeType modes[], AlarmType alarms[], uint8_t* espMode, bool* onFlag, uint8_t* dawnMode, int8_t* currentMode,
|
||||
void (*readFavoritesSettings)(), void (*saveFavoritesSettings)())
|
||||
{
|
||||
// записываем в EEPROM начальное состояние настроек, если их там ещё нет
|
||||
@@ -104,6 +105,7 @@ class EepromManager
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
EEPROM.write(EEPROM_ESP_MODE, ESP_MODE);
|
||||
EEPROM.write(EEPROM_LAMP_ON_ADDRESS, 0);
|
||||
EEPROM.write(EEPROM_DAWN_MODE_ADDRESS, 0);
|
||||
EEPROM.write(EEPROM_CURRENT_MODE_ADDRESS, 0);
|
||||
@@ -127,6 +129,7 @@ class EepromManager
|
||||
|
||||
readFavoritesSettings();
|
||||
|
||||
*espMode = (uint8_t)EEPROM.read(EEPROM_ESP_MODE);
|
||||
*onFlag = (bool)EEPROM.read(EEPROM_LAMP_ON_ADDRESS);
|
||||
*dawnMode = EEPROM.read(EEPROM_DAWN_MODE_ADDRESS);
|
||||
*currentMode = EEPROM.read(EEPROM_CURRENT_MODE_ADDRESS);
|
||||
@@ -162,6 +165,12 @@ class EepromManager
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
static void SaveEspMode(uint8_t* espMode)
|
||||
{
|
||||
EEPROM.write(EEPROM_ESP_MODE, *espMode);
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
static void SaveOnFlag(bool* onFlag)
|
||||
{
|
||||
EEPROM.write(EEPROM_LAMP_ON_ADDRESS, *onFlag);
|
||||
|
@@ -74,6 +74,19 @@
|
||||
- Добавлено управление по протоколу MQTT
|
||||
- Исправлена ошибка выключения будильника кнопкой
|
||||
- Добавлена задержка в 1 секунду сразу после старта, в течение которой нужно нажать кнопку, чтобы очистить сохранённые параметры WiFi (если ESP_RESET_ON_START == true)
|
||||
--- 12.10.2019
|
||||
- Добавлена возможность сменить рабочий режим лампы (ESP_MODE) без необходимости перепрошивки; вызывается по семикратному клику по кнопке при включенной матрице; сохраняется в EEPROM
|
||||
- Изменён алгоритм работы будильника:
|
||||
- * обновление его оттенка/яркости происходит 1 раз в 3 секунды вместо 1 раза в минуту
|
||||
- * диоды разбиты на 6 групп, первой из которых назначается новый оттенок/яркость 1 раз в 3 секунды, вторая "отстаёт" на 1 шаг, третья - на 2 шага и т.д. (для большей плавности)
|
||||
- Добавлена визуальная сигнализация о некоторых важных действиях/состояниях лампы:
|
||||
- * при запуске в режиме WiFi клиента и ещё не настроенных параметрах WiFi сети (когда их нужно ввести) - 1 короткая (0,25 сек) вспышка жёлтым
|
||||
- * если лампа стартовала в режиме WiFi клиента с ненастроенными параметрами WiFi сети, и они не были введены за отведённый таймаут (перед перезагрузкой) - 1 короткая вспышка красным
|
||||
- * при переходе лампы в режим обновления по воздуху (OTA) по двум четырёхкратным кликам по кнопке или по кнопке OTA из android приложения - 2 стандартных (0,5 сек) вспышки жёлтым
|
||||
- * если лампа была переведена в режим OTA, но не дождалась прошивки за отведённый таймаут (перед перезагрузкой) - 2 стандартных вспышки красным
|
||||
- * при переключении рабочего режима лампы WiFi точка доступа/WiFi клиент семикратным кликом по кнопке (перед перезагрузкой) - 3 стандартных вспышки красным
|
||||
- Уменьшен таймаут подключения к WiFi сети до 6 секунд; вызвано увеличившейся продолжительностью работы функции setup(), она в сумме должна быть меньше 8 секунд
|
||||
- Оптимизирован код
|
||||
*/
|
||||
|
||||
// Ссылка для менеджера плат:
|
||||
@@ -126,7 +139,7 @@ GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN);
|
||||
#endif
|
||||
|
||||
#ifdef OTA
|
||||
OtaManager otaManager;
|
||||
OtaManager otaManager(&showWarning);
|
||||
OtaPhase OtaManager::OtaFlag = OtaPhase::None;
|
||||
#endif
|
||||
|
||||
@@ -159,7 +172,7 @@ AlarmType alarms[7];
|
||||
static const uint8_t dawnOffsets[] PROGMEM = {5, 10, 15, 20, 25, 30, 40, 50, 60}; // опции для выпадающего списка параметра "время перед 'рассветом'" (будильник); синхронизировано с android приложением
|
||||
uint8_t dawnMode;
|
||||
bool dawnFlag = false;
|
||||
long thisTime;
|
||||
uint32_t thisTime;
|
||||
bool manualOff = false;
|
||||
|
||||
int8_t currentMode = 0;
|
||||
@@ -212,10 +225,7 @@ void setup()
|
||||
if (digitalRead(BTN_PIN))
|
||||
{
|
||||
wifiManager.resetSettings(); // сброс сохранённых SSID и пароля при старте с зажатой кнопкой, если разрешено
|
||||
|
||||
#ifdef GENERAL_DEBUG
|
||||
LOG.println(F("Настройки WiFiManager сброшены"));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -224,25 +234,41 @@ void setup()
|
||||
// ЛЕНТА/МАТРИЦА
|
||||
FastLED.addLeds<WS2812B, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS)/*.setCorrection(TypicalLEDStrip)*/;
|
||||
FastLED.setBrightness(BRIGHTNESS);
|
||||
if (CURRENT_LIMIT > 0) FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT);
|
||||
if (CURRENT_LIMIT > 0)
|
||||
{
|
||||
FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT);
|
||||
}
|
||||
FastLED.clear();
|
||||
FastLED.show();
|
||||
|
||||
|
||||
// EEPROM
|
||||
EepromManager::InitEepromSettings( // инициализация EEPROM; запись начального состояния настроек, если их там ещё нет; инициализация настроек лампы значениями из EEPROM
|
||||
modes, alarms, &espMode, &ONflag, &dawnMode, ¤tMode,
|
||||
&(FavoritesManager::ReadFavoritesFromEeprom),
|
||||
&(FavoritesManager::SaveFavoritesToEeprom));
|
||||
LOG.printf_P(PSTR("Рабочий режим лампы: ESP_MODE = %d\n"), espMode);
|
||||
|
||||
|
||||
// WI-FI
|
||||
wifiManager.setDebugOutput(WIFIMAN_DEBUG); // вывод отладочных сообщений
|
||||
//wifiManager.setMinimumSignalQuality(); // установка минимально приемлемого уровня сигнала WiFi сетей (8% по умолчанию)
|
||||
if (ESP_MODE == 0) // режим WiFi точки доступа
|
||||
// wifiManager.setMinimumSignalQuality(); // установка минимально приемлемого уровня сигнала WiFi сетей (8% по умолчанию)
|
||||
if (espMode == 0U) // режим WiFi точки доступа
|
||||
{
|
||||
// wifiManager.setConfigPortalBlocking(false);
|
||||
WiFi.softAPConfig( // wifiManager.startConfigPortal использовать нельзя, т.к. он блокирует вычислительный процесс внутри себя, а затем перезагружает ESP, т.е. предназначен только для ввода SSID и пароля
|
||||
IPAddress(AP_STATIC_IP[0], AP_STATIC_IP[1], AP_STATIC_IP[2], AP_STATIC_IP[3]), // IP адрес WiFi точки доступа
|
||||
IPAddress(AP_STATIC_IP[0], AP_STATIC_IP[1], AP_STATIC_IP[2], 1), // первый доступный IP адрес сети
|
||||
IPAddress(255, 255, 255, 0)); // маска подсети
|
||||
|
||||
if (sizeof(AP_STATIC_IP))
|
||||
{
|
||||
LOG.println(F("Используется статический IP адрес WiFi точки доступа"));
|
||||
wifiManager.setAPStaticIPConfig( // wifiManager.startConfigPortal использовать нельзя, т.к. он блокирует вычислительный процесс внутри себя, а затем перезагружает ESP, т.е. предназначен только для ввода SSID и пароля
|
||||
IPAddress(AP_STATIC_IP[0], AP_STATIC_IP[1], AP_STATIC_IP[2], AP_STATIC_IP[3]), // IP адрес WiFi точки доступа
|
||||
IPAddress(AP_STATIC_IP[0], AP_STATIC_IP[1], AP_STATIC_IP[2], 1), // первый доступный IP адрес сети
|
||||
IPAddress(255, 255, 255, 0)); // маска подсети
|
||||
}
|
||||
|
||||
WiFi.softAP(AP_NAME, AP_PASS);
|
||||
|
||||
LOG.println(F("Режим WiFi точки доступа"));
|
||||
LOG.println(F("Старт в режиме WiFi точки доступа"));
|
||||
LOG.print(F("IP адрес: "));
|
||||
LOG.println(WiFi.softAPIP());
|
||||
|
||||
@@ -250,19 +276,22 @@ void setup()
|
||||
}
|
||||
else // режим WiFi клиента (подключаемся к роутеру, если есть сохранённые SSID и пароль, иначе создаём WiFi точку доступа и запрашиваем их)
|
||||
{
|
||||
LOG.println(F("Режим WiFi клиента"));
|
||||
if (WiFi.SSID())
|
||||
LOG.println(F("Старт в режиме WiFi клиента (подключение к роутеру)"));
|
||||
|
||||
if (WiFi.SSID().length())
|
||||
{
|
||||
LOG.print(F("Подключение WiFi сети: "));
|
||||
LOG.println(WiFi.SSID());
|
||||
LOG.printf_P(PSTR("Подключение к WiFi сети: %s\n"), WiFi.SSID().c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG.println(F("WiFi сеть не определена, запуск WiFi точки доступа для настройки параметров подключения к WiFi сети..."));
|
||||
showWarning(CRGB::Yellow, 250U, 250U); // мигание жёлтым цветом 0,25 секунды (1 раз) - нужно ввести параметры WiFi сети для подключения
|
||||
}
|
||||
|
||||
if (STA_STATIC_IP)
|
||||
if (sizeof(STA_STATIC_IP))
|
||||
{
|
||||
LOG.print(F("Сконфигурирован статический IP адрес: "));
|
||||
LOG.printf_P(PSTR("%u.%u.%u.%u\n"), STA_STATIC_IP[0], STA_STATIC_IP[1], STA_STATIC_IP[2], STA_STATIC_IP[3]);
|
||||
wifiManager.setSTAStaticIPConfig(
|
||||
IPAddress(STA_STATIC_IP[0], STA_STATIC_IP[1], STA_STATIC_IP[2], STA_STATIC_IP[3]), // статический IP адрес ESP в режиме WiFi клиента
|
||||
IPAddress(STA_STATIC_IP[0], STA_STATIC_IP[1], STA_STATIC_IP[2], 1), // первый доступный IP адрес сети (справедливо для 99,99% случаев; для сетей меньше чем на 255 адресов нужно вынести в константы)
|
||||
@@ -276,12 +305,8 @@ void setup()
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
LOG.println(F("Время ожидания ввода SSID и пароля от WiFi сети или подключения к WiFi сети превышено\nПерезагрузка модуля"));
|
||||
|
||||
#if defined(ESP8266)
|
||||
ESP.reset();
|
||||
#else
|
||||
showWarning(CRGB::Red, 250U, 250U); // мигание красным цветом 0,25 секунды (1 раз) - ожидание ввода SSID'а и пароля WiFi сети прекращено, перезагрузка
|
||||
ESP.restart();
|
||||
#endif
|
||||
}
|
||||
|
||||
LOG.print(F("IP адрес: "));
|
||||
@@ -292,13 +317,6 @@ void setup()
|
||||
Udp.begin(localPort);
|
||||
|
||||
|
||||
// EEPROM
|
||||
EepromManager::InitEepromSettings( // инициализация EEPROM; запись начального состояния настроек, если их там ещё нет; инициализация настроек лампы значениями из EEPROM
|
||||
modes, alarms, &ONflag, &dawnMode, ¤tMode,
|
||||
&(FavoritesManager::ReadFavoritesFromEeprom),
|
||||
&(FavoritesManager::SaveFavoritesToEeprom));
|
||||
|
||||
|
||||
// NTP
|
||||
#ifdef USE_NTP
|
||||
timeClient.begin();
|
||||
@@ -306,9 +324,12 @@ void setup()
|
||||
|
||||
|
||||
// MQTT
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
mqttClient = new AsyncMqttClient();
|
||||
MqttManager::setupMqtt(mqttClient, inputBuffer, &sendCurrent); // создание экземпляров объектов для работы с MQTT, их инициализация и подключение к MQTT брокеру
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
mqttClient = new AsyncMqttClient();
|
||||
MqttManager::setupMqtt(mqttClient, inputBuffer, &sendCurrent); // создание экземпляров объектов для работы с MQTT, их инициализация и подключение к MQTT брокеру
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -358,7 +379,7 @@ void loop()
|
||||
}
|
||||
|
||||
#if USE_MQTT
|
||||
if (ESP_MODE == 1 && mqttClient && WiFi.isConnected() && !mqttClient->connected())
|
||||
if (espMode == 1U && mqttClient && WiFi.isConnected() && !mqttClient->connected())
|
||||
{
|
||||
MqttManager::mqttConnect(); // библиотека не умеет восстанавливать соединение в случае потери подключения к MQTT брокеру, нужно управлять этим явно
|
||||
MqttManager::needToPublish = true;
|
||||
|
@@ -33,9 +33,14 @@ class OtaManager
|
||||
public:
|
||||
static OtaPhase OtaFlag;
|
||||
|
||||
OtaManager(ShowWarningDelegate showWarningDelegate)
|
||||
{
|
||||
this->showWarningDelegate = showWarningDelegate;
|
||||
}
|
||||
|
||||
bool RequestOtaUpdate() // пользователь однократно запросил обновление по воздуху; возвращает true, когда переходит в режим обновления - startOtaUpdate()
|
||||
{
|
||||
if (ESP_MODE != 1)
|
||||
if (espMode != 1U)
|
||||
{
|
||||
#ifdef GENERAL_DEBUG
|
||||
LOG.print(F("Запрос обновления по воздуху поддерживается только в режиме ESP_MODE = 1\n"));
|
||||
@@ -59,11 +64,13 @@ class OtaManager
|
||||
if (OtaFlag == OtaPhase::GotFirstConfirm)
|
||||
{
|
||||
OtaFlag = OtaPhase::GotSecondConfirm;
|
||||
momentOfOtaStart = millis();
|
||||
|
||||
#ifdef GENERAL_DEBUG
|
||||
LOG.print(F("Получено второе подтверждение обновления по воздуху\nСтарт режима обновления\n"));
|
||||
#endif
|
||||
|
||||
showWarningDelegate(CRGB::Yellow, 2000U, 500U); // мигание жёлтым цветом 2 секунды (2 раза) - готовность к прошивке
|
||||
startOtaUpdate();
|
||||
return true;
|
||||
}
|
||||
@@ -86,7 +93,7 @@ class OtaManager
|
||||
return;
|
||||
}
|
||||
|
||||
if (OtaFlag == OtaPhase::GotSecondConfirm &&
|
||||
if ((OtaFlag == OtaPhase::GotSecondConfirm || OtaFlag == OtaPhase::InProgress) &&
|
||||
millis() - momentOfOtaStart >= ESP_CONF_TIMEOUT * 1000)
|
||||
{
|
||||
OtaFlag = OtaPhase::None;
|
||||
@@ -97,12 +104,9 @@ class OtaManager
|
||||
delay(500);
|
||||
#endif
|
||||
|
||||
#if defined(ESP8266)
|
||||
ESP.reset();
|
||||
#else
|
||||
ESP.restart();
|
||||
#endif
|
||||
showWarningDelegate(CRGB::Red, 2000U, 500U); // мигание красным цветом 2 секунды (2 раза) - ожидание прошивки по воздуху прекращено, перезагрузка
|
||||
|
||||
ESP.restart();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,37 +119,41 @@ class OtaManager
|
||||
private:
|
||||
uint64_t momentOfFirstConfirmation = 0; // момент времени, когда получено первое подтверждение и с которого начинается отсчёт ожидания второго подтверждения
|
||||
uint64_t momentOfOtaStart = 0; // момент времени, когда развёрнута WiFi точка доступа для обновления по воздуху
|
||||
ShowWarningDelegate showWarningDelegate;
|
||||
|
||||
void startOtaUpdate()
|
||||
{
|
||||
char espHostName[65];
|
||||
sprintf(espHostName, "%s-%u", AP_NAME, ESP.getChipId());
|
||||
sprintf_P(espHostName, PSTR("%s-%u"), AP_NAME, ESP.getChipId());
|
||||
ArduinoOTA.setPort(ESP_OTA_PORT);
|
||||
ArduinoOTA.setHostname(espHostName);
|
||||
ArduinoOTA.setPassword(AP_PASS);
|
||||
|
||||
ArduinoOTA.onStart([this]()
|
||||
{
|
||||
String type;
|
||||
OtaFlag = OtaPhase::InProgress;
|
||||
char type[16];
|
||||
if (ArduinoOTA.getCommand() == U_FLASH)
|
||||
{
|
||||
type = "sketch";
|
||||
strcpy_P(type, PSTR("sketch"));
|
||||
}
|
||||
else // U_SPIFFS
|
||||
{
|
||||
type = "filesystem";
|
||||
strcpy_P(type, PSTR("filesystem"));
|
||||
}
|
||||
|
||||
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
||||
|
||||
#ifdef GENERAL_DEBUG
|
||||
LOG.printf_P(PSTR("Start updating %s\n"), type.c_str());
|
||||
LOG.printf_P(PSTR("Start updating %s\n"), type);
|
||||
#endif
|
||||
});
|
||||
|
||||
ArduinoOTA.onEnd([this]()
|
||||
{
|
||||
OtaFlag = OtaPhase::Done;
|
||||
momentOfFirstConfirmation = 0;
|
||||
momentOfOtaStart = 0;
|
||||
|
||||
#ifdef GENERAL_DEBUG
|
||||
LOG.print(F("Обновление по воздуху выполнено\nПерезапуск"));
|
||||
@@ -163,6 +171,8 @@ class OtaManager
|
||||
ArduinoOTA.onError([this](ota_error_t error)
|
||||
{
|
||||
OtaFlag = OtaPhase::None;
|
||||
momentOfFirstConfirmation = 0;
|
||||
momentOfOtaStart = 0;
|
||||
|
||||
#ifdef GENERAL_DEBUG
|
||||
LOG.printf_P(PSTR("Обновление по воздуху завершилось ошибкой [%u]: "), error);
|
||||
@@ -207,8 +217,6 @@ class OtaManager
|
||||
ArduinoOTA.setRebootOnSuccess(true);
|
||||
ArduinoOTA.begin();
|
||||
OtaFlag = OtaPhase::InProgress;
|
||||
momentOfFirstConfirmation = 0;
|
||||
momentOfOtaStart = 0;
|
||||
|
||||
#ifdef GENERAL_DEBUG
|
||||
LOG.printf_P(PSTR("Для обновления в Arduino IDE выберите пункт меню Инструменты - Порт - '%s at "), espHostName);
|
||||
|
@@ -4,14 +4,15 @@
|
||||
struct AlarmType
|
||||
{
|
||||
bool State = false;
|
||||
uint16_t Time = 0;
|
||||
uint16_t Time = 0U;
|
||||
};
|
||||
|
||||
struct ModeType
|
||||
{
|
||||
uint8_t Brightness = 50;
|
||||
uint8_t Speed = 30;
|
||||
uint8_t Scale = 40;
|
||||
uint8_t Brightness = 50U;
|
||||
uint8_t Speed = 30U;
|
||||
uint8_t Scale = 40U;
|
||||
};
|
||||
|
||||
typedef void (*SendCurrentDelegate)(char *outputBuffer);
|
||||
typedef void (*ShowWarningDelegate)(CRGB color, uint32_t duration, uint16_t blinkHalfPeriod);
|
||||
|
@@ -6,9 +6,9 @@ static bool startButtonHolding = false; // флаг: кно
|
||||
void buttonTick()
|
||||
{
|
||||
touch.tick();
|
||||
uint8_t clickCount = touch.hasClicks() ? touch.getClicks() : 0;
|
||||
uint8_t clickCount = touch.hasClicks() ? touch.getClicks() : 0U;
|
||||
|
||||
if (clickCount == 1)
|
||||
if (clickCount == 1U)
|
||||
{
|
||||
if (dawnFlag)
|
||||
{
|
||||
@@ -26,14 +26,17 @@ void buttonTick()
|
||||
eepromTimeout = millis();
|
||||
loadingFlag = true;
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ONflag && clickCount == 2)
|
||||
if (ONflag && clickCount == 2U)
|
||||
{
|
||||
if (++currentMode >= MODE_AMOUNT) currentMode = 0;
|
||||
if (++currentMode >= (int8_t)MODE_AMOUNT) currentMode = 0;
|
||||
FastLED.setBrightness(modes[currentMode].Brightness);
|
||||
loadingFlag = true;
|
||||
settChanged = true;
|
||||
@@ -41,12 +44,15 @@ void buttonTick()
|
||||
FastLED.clear();
|
||||
delay(1);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ONflag && clickCount == 3)
|
||||
if (ONflag && clickCount == 3U)
|
||||
{
|
||||
if (--currentMode < 0) currentMode = MODE_AMOUNT - 1;
|
||||
FastLED.setBrightness(modes[currentMode].Brightness);
|
||||
@@ -56,26 +62,31 @@ void buttonTick()
|
||||
FastLED.clear();
|
||||
delay(1);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (clickCount == 4)
|
||||
{
|
||||
#ifdef OTA
|
||||
if (otaManager.RequestOtaUpdate())
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
currentMode = EFF_MATRIX; // принудительное включение режима "Матрица" для индикации перехода в режим обновления по воздуху
|
||||
FastLED.clear();
|
||||
delay(1);
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ONflag && clickCount == 5) // вывод IP на лампу
|
||||
if (clickCount == 4U)
|
||||
{
|
||||
if (ESP_MODE == 1U)
|
||||
#ifdef OTA
|
||||
if (otaManager.RequestOtaUpdate())
|
||||
{
|
||||
ONflag = true;
|
||||
currentMode = EFF_MATRIX; // принудительное включение режима "Матрица" для индикации перехода в режим обновления по воздуху
|
||||
FastLED.clear();
|
||||
delay(1);
|
||||
changePower();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ONflag && clickCount == 5U) // вывод IP на лампу
|
||||
{
|
||||
if (espMode == 1U)
|
||||
{
|
||||
loadingFlag = true;
|
||||
while(!fillString(WiFi.localIP().toString().c_str())) delay(1);
|
||||
@@ -83,6 +94,22 @@ void buttonTick()
|
||||
}
|
||||
}
|
||||
|
||||
if (ONflag && clickCount == 7U) // смена рабочего режима лампы: с WiFi точки доступа на WiFi клиент или наоборот
|
||||
{
|
||||
espMode = (espMode == 0U) ? 1U : 0U;
|
||||
EepromManager::SaveEspMode(&espMode);
|
||||
|
||||
#ifdef GENERAL_DEBUG
|
||||
LOG.printf_P(PSTR("Рабочий режим лампы изменён и сохранён в энергонезависимую память\nНовый рабочий режим: ESP_MODE = %d, %s\nРестарт...\n"),
|
||||
espMode, espMode == 0U ? F("WiFi точка доступа") : F("WiFi клиент (подключение к роутеру)"));
|
||||
delay(1000);
|
||||
#endif
|
||||
|
||||
showWarning(CRGB::Red, 3000U, 500U); // мигание красным цветом 3 секунды - смена рабочего режима лампы, перезагрузка
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
|
||||
if (ONflag && touch.isHolded())
|
||||
{
|
||||
brightDirection = !brightDirection;
|
||||
@@ -91,9 +118,9 @@ void buttonTick()
|
||||
|
||||
if (ONflag && touch.isStep())
|
||||
{
|
||||
uint8_t delta = modes[currentMode].Brightness < 10 // определение шага изменения яркости: при яркости [1..10] шаг = 1, при [11..16] шаг = 3, при [17..255] шаг = 15
|
||||
? 1
|
||||
: 5;
|
||||
uint8_t delta = modes[currentMode].Brightness < 10U // определение шага изменения яркости: при яркости [1..10] шаг = 1, при [11..16] шаг = 3, при [17..255] шаг = 15
|
||||
? 1U
|
||||
: 5U;
|
||||
modes[currentMode].Brightness =
|
||||
constrain(brightDirection
|
||||
? modes[currentMode].Brightness + delta
|
||||
@@ -108,8 +135,8 @@ void buttonTick()
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
if (ONflag && !touch.isHold() && startButtonHolding) // кнопка отпущена после удерживания, нужно отправить MQTT сообщение об изменении яркости лампы
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U && ONflag && !touch.isHold() && startButtonHolding) // кнопка отпущена после удерживания, нужно отправить MQTT сообщение об изменении яркости лампы
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
startButtonHolding = false;
|
||||
|
@@ -46,7 +46,7 @@ void changePower()
|
||||
if (ONflag)
|
||||
{
|
||||
effectsTick();
|
||||
for (uint8_t i = 0; i < modes[currentMode].Brightness; i = constrain(i + 8, 0, modes[currentMode].Brightness))
|
||||
for (uint8_t i = 0U; i < modes[currentMode].Brightness; i = constrain(i + 8, 0, modes[currentMode].Brightness))
|
||||
{
|
||||
FastLED.setBrightness(i);
|
||||
delay(1);
|
||||
@@ -74,12 +74,15 @@ void changePower()
|
||||
TimerManager::TimerHasFired = false;
|
||||
TimerManager::TimeToFire = 0ULL;
|
||||
|
||||
if (FavoritesManager::UseSavedFavoritesRunning == 0) // если выбрана опция Сохранять состояние (вкл/выкл) "избранного", то ни выключение модуля, ни выключение матрицы не сбрасывают текущее состояние (вкл/выкл) "избранного"
|
||||
if (FavoritesManager::UseSavedFavoritesRunning == 0U) // если выбрана опция Сохранять состояние (вкл/выкл) "избранного", то ни выключение модуля, ни выключение матрицы не сбрасывают текущее состояние (вкл/выкл) "избранного"
|
||||
{
|
||||
FavoritesManager::TurnFavoritesOff();
|
||||
}
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@@ -6,11 +6,11 @@ void sparklesRoutine()
|
||||
{
|
||||
for (uint8_t i = 0; i < modes[EFF_SPARKLES].Scale; i++)
|
||||
{
|
||||
uint8_t x = random(0, WIDTH);
|
||||
uint8_t y = random(0, HEIGHT);
|
||||
if (getPixColorXY(x, y) == 0)
|
||||
uint8_t x = random(0U, WIDTH);
|
||||
uint8_t y = random(0U, HEIGHT);
|
||||
if (getPixColorXY(x, y) == 0U)
|
||||
{
|
||||
leds[getPixelNumber(x, y)] = CHSV(random(0, 255), 255, 255);
|
||||
leds[getPixelNumber(x, y)] = CHSV(random(0U, 255U), 255U, 255U);
|
||||
}
|
||||
}
|
||||
fader(FADE_OUT_SPEED);
|
||||
@@ -19,9 +19,9 @@ void sparklesRoutine()
|
||||
// функция плавного угасания цвета для всех пикселей
|
||||
void fader(uint8_t step)
|
||||
{
|
||||
for (uint8_t i = 0; i < WIDTH; i++)
|
||||
for (uint8_t i = 0U; i < WIDTH; i++)
|
||||
{
|
||||
for (uint8_t j = 0; j < HEIGHT; j++)
|
||||
for (uint8_t j = 0U; j < HEIGHT; j++)
|
||||
{
|
||||
fadePixel(i, j, step);
|
||||
}
|
||||
@@ -31,24 +31,24 @@ void fader(uint8_t step)
|
||||
void fadePixel(uint8_t i, uint8_t j, uint8_t step) // новый фейдер
|
||||
{
|
||||
int32_t pixelNum = getPixelNumber(i, j);
|
||||
if (getPixColor(pixelNum) == 0) return;
|
||||
if (getPixColor(pixelNum) == 0U) return;
|
||||
|
||||
if (leds[pixelNum].r >= 30 ||
|
||||
leds[pixelNum].g >= 30 ||
|
||||
leds[pixelNum].b >= 30)
|
||||
if (leds[pixelNum].r >= 30U ||
|
||||
leds[pixelNum].g >= 30U ||
|
||||
leds[pixelNum].b >= 30U)
|
||||
{
|
||||
leds[pixelNum].fadeToBlackBy(step);
|
||||
}
|
||||
else
|
||||
{
|
||||
leds[pixelNum] = 0;
|
||||
leds[pixelNum] = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------- огонь -----------------
|
||||
#define SPARKLES (1U) // вылетающие угольки вкл выкл
|
||||
uint8_t line[WIDTH];
|
||||
uint8_t pcnt = 0;
|
||||
uint8_t pcnt = 0U;
|
||||
|
||||
//these values are substracetd from the generated values to give a shape to the animation
|
||||
static const uint8_t valueMask[8][16] PROGMEM =
|
||||
@@ -99,7 +99,7 @@ void fireRoutine()
|
||||
// Randomly generate the next line (matrix row)
|
||||
void generateLine()
|
||||
{
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
line[x] = random(64, 255);
|
||||
}
|
||||
@@ -107,22 +107,22 @@ void generateLine()
|
||||
|
||||
void shiftUp()
|
||||
{
|
||||
for (uint8_t y = HEIGHT - 1; y > 0; y--)
|
||||
for (uint8_t y = HEIGHT - 1U; y > 0U; y--)
|
||||
{
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
uint8_t newX = x;
|
||||
if (x > 15) newX = x % 16;
|
||||
if (y > 7) continue;
|
||||
matrixValue[y][newX] = matrixValue[y - 1][newX];
|
||||
if (x > 15U) newX = x % 16U;
|
||||
if (y > 7U) continue;
|
||||
matrixValue[y][newX] = matrixValue[y - 1U][newX];
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
uint8_t newX = x;
|
||||
if (x > 15) newX = x % 16;
|
||||
matrixValue[0][newX] = line[newX];
|
||||
if (x > 15U) newX = x % 16U;
|
||||
matrixValue[0U][newX] = line[newX];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,13 +134,13 @@ void drawFrame(uint8_t pcnt)
|
||||
int32_t nextv;
|
||||
|
||||
//each row interpolates with the one before it
|
||||
for (uint8_t y = HEIGHT - 1; y > 0; y--)
|
||||
for (uint8_t y = HEIGHT - 1U; y > 0U; y--)
|
||||
{
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
uint8_t newX = x;
|
||||
if (x > 15) newX = x % 16;
|
||||
if (y < 8)
|
||||
if (x > 15U) newX = x % 16U;
|
||||
if (y < 8U)
|
||||
{
|
||||
nextv =
|
||||
(((100.0 - pcnt) * matrixValue[y][newX]
|
||||
@@ -149,32 +149,32 @@ void drawFrame(uint8_t pcnt)
|
||||
|
||||
CRGB color = CHSV(
|
||||
modes[EFF_FIRE].Scale * 2.5 + pgm_read_byte(&hueMask[y][newX]), // H
|
||||
255, // S
|
||||
255U, // S
|
||||
(uint8_t)max(0, nextv) // V
|
||||
);
|
||||
|
||||
leds[getPixelNumber(x, y)] = color;
|
||||
}
|
||||
else if (y == 8 && SPARKLES)
|
||||
else if (y == 8U && SPARKLES)
|
||||
{
|
||||
if (random(0, 20) == 0 && getPixColorXY(x, y - 1) != 0) drawPixelXY(x, y, getPixColorXY(x, y - 1));
|
||||
else drawPixelXY(x, y, 0);
|
||||
if (random(0, 20) == 0 && getPixColorXY(x, y - 1U) != 0U) drawPixelXY(x, y, getPixColorXY(x, y - 1U));
|
||||
else drawPixelXY(x, y, 0U);
|
||||
}
|
||||
else if (SPARKLES)
|
||||
{
|
||||
// старая версия для яркости
|
||||
if (getPixColorXY(x, y - 1) > 0)
|
||||
drawPixelXY(x, y, getPixColorXY(x, y - 1));
|
||||
else drawPixelXY(x, y, 0);
|
||||
if (getPixColorXY(x, y - 1U) > 0U)
|
||||
drawPixelXY(x, y, getPixColorXY(x, y - 1U));
|
||||
else drawPixelXY(x, y, 0U);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//first row interpolates with the "next" line
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
uint8_t newX = x;
|
||||
if (x > 15) newX = x % 16;
|
||||
if (x > 15U) newX = x % 16U;
|
||||
CRGB color = CHSV(
|
||||
modes[EFF_FIRE].Scale * 2.5 + pgm_read_byte(&(hueMask[0][newX])), // H
|
||||
255, // S
|
||||
@@ -193,7 +193,7 @@ void rainbowVerticalRoutine()
|
||||
for (uint8_t j = 0; j < HEIGHT; j++)
|
||||
{
|
||||
CHSV thisColor = CHSV((uint8_t)(hue + j * modes[EFF_RAINBOW_VER].Scale), 255, 255);
|
||||
for (uint8_t i = 0; i < WIDTH; i++)
|
||||
for (uint8_t i = 0U; i < WIDTH; i++)
|
||||
{
|
||||
drawPixelXY(i, j, thisColor);
|
||||
}
|
||||
@@ -204,10 +204,10 @@ void rainbowVerticalRoutine()
|
||||
void rainbowHorizontalRoutine()
|
||||
{
|
||||
hue += 4;
|
||||
for (uint8_t i = 0; i < WIDTH; i++)
|
||||
for (uint8_t i = 0U; i < WIDTH; i++)
|
||||
{
|
||||
CHSV thisColor = CHSV((uint8_t)(hue + i * modes[EFF_RAINBOW_HOR].Scale), 255, 255);
|
||||
for (uint8_t j = 0; j < HEIGHT; j++)
|
||||
for (uint8_t j = 0U; j < HEIGHT; j++)
|
||||
{
|
||||
drawPixelXY(i, j, thisColor);
|
||||
}
|
||||
@@ -224,12 +224,12 @@ void rainbowDiagonalRoutine()
|
||||
}
|
||||
|
||||
hue += 8;
|
||||
for (uint8_t i = 0; i < WIDTH; i++)
|
||||
for (uint8_t i = 0U; i < WIDTH; i++)
|
||||
{
|
||||
for (uint8_t j = 0; j < HEIGHT; j++)
|
||||
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(constrain(hue + (float)(WIDTH / HEIGHT * i + j * twirlFactor) * (float)(255 / maxDim), 0, 255), 255, 255);
|
||||
drawPixelXY(i, j, thisColor);
|
||||
}
|
||||
}
|
||||
@@ -242,9 +242,9 @@ void colorsRoutine()
|
||||
{
|
||||
hue += modes[EFF_COLORS].Scale;
|
||||
|
||||
for (int16_t i = 0; i < NUM_LEDS; i++)
|
||||
for (uint16_t i = 0U; i < NUM_LEDS; i++)
|
||||
{
|
||||
leds[i] = CHSV(hue, 255, 255);
|
||||
leds[i] = CHSV(hue, 255U, 255U);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,9 +257,9 @@ void colorRoutine()
|
||||
loadingFlag = false;
|
||||
FastLED.clear();
|
||||
|
||||
for (int16_t i = 0; i < NUM_LEDS; i++)
|
||||
for (int16_t i = 0U; i < NUM_LEDS; i++)
|
||||
{
|
||||
leds[i] = CHSV(modes[EFF_COLOR].Scale * 2.5, 255, 255);
|
||||
leds[i] = CHSV(modes[EFF_COLOR].Scale * 2.5, 255U, 255U);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -268,22 +268,22 @@ void colorRoutine()
|
||||
void snowRoutine()
|
||||
{
|
||||
// сдвигаем всё вниз
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
for (uint8_t y = 0; y < HEIGHT - 1; y++)
|
||||
for (uint8_t y = 0U; y < HEIGHT - 1; y++)
|
||||
{
|
||||
drawPixelXY(x, y, getPixColorXY(x, y + 1));
|
||||
drawPixelXY(x, y, getPixColorXY(x, y + 1U));
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
// заполняем случайно верхнюю строку
|
||||
// а также не даём двум блокам по вертикали вместе быть
|
||||
if (getPixColorXY(x, HEIGHT - 2) == 0 && (random(0, 100 - modes[EFF_SNOW].Scale) == 0))
|
||||
drawPixelXY(x, HEIGHT - 1, 0xE0FFFF - 0x101010 * random(0, 4));
|
||||
if (getPixColorXY(x, HEIGHT - 2U) == 0U && (random(0, 100 - modes[EFF_SNOW].Scale) == 0U))
|
||||
drawPixelXY(x, HEIGHT - 1U, 0xE0FFFF - 0x101010 * random(0, 4));
|
||||
else
|
||||
drawPixelXY(x, HEIGHT - 1, 0x000000);
|
||||
drawPixelXY(x, HEIGHT - 1U, 0x000000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -300,45 +300,45 @@ void snowStormRoutine()
|
||||
}
|
||||
|
||||
// заполняем головами комет левую и верхнюю линию
|
||||
for (uint8_t i = HEIGHT / 2; i < HEIGHT; i++)
|
||||
for (uint8_t i = HEIGHT / 2U; i < HEIGHT; i++)
|
||||
{
|
||||
if (getPixColorXY(0, i) == 0 &&
|
||||
if (getPixColorXY(0U, i) == 0U &&
|
||||
(random(0, SNOW_DENSE) == 0) &&
|
||||
getPixColorXY(0, i + 1) == 0 &&
|
||||
getPixColorXY(0, i - 1) == 0)
|
||||
getPixColorXY(0U, i + 1U) == 0U &&
|
||||
getPixColorXY(0U, i - 1U) == 0U)
|
||||
{
|
||||
leds[getPixelNumber(0, i)] = CHSV(random(0, 200), SNOW_SATURATION, 255);
|
||||
leds[getPixelNumber(0U, i)] = CHSV(random(0, 200), SNOW_SATURATION, 255U);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < WIDTH / 2; i++)
|
||||
for (uint8_t i = 0U; i < WIDTH / 2U; i++)
|
||||
{
|
||||
if (getPixColorXY(i, HEIGHT - 1) == 0 &&
|
||||
(random(0, map(modes[EFF_SNOWSTORM].Scale, 0, 255, 10, 120)) == 0) &&
|
||||
getPixColorXY(i + 1, HEIGHT - 1) == 0 &&
|
||||
getPixColorXY(i - 1, HEIGHT - 1) == 0)
|
||||
if (getPixColorXY(i, HEIGHT - 1U) == 0U &&
|
||||
(random(0, map(modes[EFF_SNOWSTORM].Scale, 0U, 255U, 10U, 120U)) == 0U) &&
|
||||
getPixColorXY(i + 1U, HEIGHT - 1U) == 0U &&
|
||||
getPixColorXY(i - 1U, HEIGHT - 1U) == 0U)
|
||||
{
|
||||
leds[getPixelNumber(i, HEIGHT - 1)] = CHSV(random(0, 200), SNOW_SATURATION, 255);
|
||||
leds[getPixelNumber(i, HEIGHT - 1U)] = CHSV(random(0, 200), SNOW_SATURATION, 255U);
|
||||
}
|
||||
}
|
||||
|
||||
// сдвигаем по диагонали
|
||||
for (uint8_t y = 0; y < HEIGHT - 1; y++)
|
||||
for (uint8_t y = 0U; y < HEIGHT - 1U; y++)
|
||||
{
|
||||
for (uint8_t x = WIDTH - 1; x > 0; x--)
|
||||
for (uint8_t x = WIDTH - 1U; x > 0U; x--)
|
||||
{
|
||||
drawPixelXY(x, y, getPixColorXY(x - 1, y + 1));
|
||||
drawPixelXY(x, y, getPixColorXY(x - 1U, y + 1U));
|
||||
}
|
||||
}
|
||||
|
||||
// уменьшаем яркость левой и верхней линии, формируем "хвосты"
|
||||
for (uint8_t i = HEIGHT / 2; i < HEIGHT; i++)
|
||||
for (uint8_t i = HEIGHT / 2U; i < HEIGHT; i++)
|
||||
{
|
||||
fadePixel(0, i, SNOW_TAIL_STEP);
|
||||
fadePixel(0U, i, SNOW_TAIL_STEP);
|
||||
}
|
||||
for (uint8_t i = 0; i < WIDTH / 2; i++)
|
||||
for (uint8_t i = 0U; i < WIDTH / 2U; i++)
|
||||
{
|
||||
fadePixel(i, HEIGHT - 1, SNOW_TAIL_STEP);
|
||||
fadePixel(i, HEIGHT - 1U, SNOW_TAIL_STEP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,77 +355,77 @@ void starfallRoutine()
|
||||
}
|
||||
|
||||
// заполняем головами комет левую и верхнюю линию
|
||||
for (uint8_t i = HEIGHT / 2; i < HEIGHT; i++)
|
||||
for (uint8_t i = HEIGHT / 2U; i < HEIGHT; i++)
|
||||
{
|
||||
if (getPixColorXY(0, i) == 0 &&
|
||||
if (getPixColorXY(0U, i) == 0U &&
|
||||
(random(0, STAR_DENSE) == 0) &&
|
||||
getPixColorXY(0, i + 1) == 0 &&
|
||||
getPixColorXY(0, i - 1) == 0)
|
||||
getPixColorXY(0U, i + 1U) == 0U &&
|
||||
getPixColorXY(0U, i - 1U) == 0U)
|
||||
{
|
||||
leds[getPixelNumber(0, i)] = CHSV(random(0, 200), STAR_SATURATION, 255);
|
||||
leds[getPixelNumber(0U, i)] = CHSV(random(0, 200), STAR_SATURATION, 255U);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < WIDTH / 2; i++)
|
||||
for (uint8_t i = 0U; i < WIDTH / 2U; i++)
|
||||
{
|
||||
if (getPixColorXY(i, HEIGHT - 1) == 0 &&
|
||||
(random(0, map(modes[EFF_STARFALL].Scale, 0, 255, 10, 120)) == 0) &&
|
||||
getPixColorXY(i + 1, HEIGHT - 1) == 0 &&
|
||||
getPixColorXY(i - 1, HEIGHT - 1) == 0)
|
||||
if (getPixColorXY(i, HEIGHT - 1U) == 0U &&
|
||||
(random(0, map(modes[EFF_STARFALL].Scale, 0U, 255U, 10U, 120U)) == 0U) &&
|
||||
getPixColorXY(i + 1U, HEIGHT - 1U) == 0U &&
|
||||
getPixColorXY(i - 1U, HEIGHT - 1U) == 0U)
|
||||
{
|
||||
leds[getPixelNumber(i, HEIGHT - 1)] = CHSV(random(0, 200), STAR_SATURATION, 255);
|
||||
leds[getPixelNumber(i, HEIGHT - 1U)] = CHSV(random(0, 200), STAR_SATURATION, 255U);
|
||||
}
|
||||
}
|
||||
|
||||
// сдвигаем по диагонали
|
||||
for (uint8_t y = 0; y < HEIGHT - 1; y++)
|
||||
for (uint8_t y = 0U; y < HEIGHT - 1U; y++)
|
||||
{
|
||||
for (uint8_t x = WIDTH - 1; x > 0; x--)
|
||||
for (uint8_t x = WIDTH - 1U; x > 0U; x--)
|
||||
{
|
||||
drawPixelXY(x, y, getPixColorXY(x - 1, y + 1));
|
||||
drawPixelXY(x, y, getPixColorXY(x - 1U, y + 1U));
|
||||
}
|
||||
}
|
||||
|
||||
// уменьшаем яркость левой и верхней линии, формируем "хвосты"
|
||||
for (uint8_t i = HEIGHT / 2; i < HEIGHT; i++)
|
||||
for (uint8_t i = HEIGHT / 2U; i < HEIGHT; i++)
|
||||
{
|
||||
fadePixel(0, i, STAR_TAIL_STEP);
|
||||
fadePixel(0U, i, STAR_TAIL_STEP);
|
||||
}
|
||||
for (uint8_t i = 0; i < WIDTH / 2; i++)
|
||||
for (uint8_t i = 0U; i < WIDTH / 2U; i++)
|
||||
{
|
||||
fadePixel(i, HEIGHT - 1, STAR_TAIL_STEP);
|
||||
fadePixel(i, HEIGHT - 1U, STAR_TAIL_STEP);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------- матрица ---------------
|
||||
void matrixRoutine()
|
||||
{
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
// заполняем случайно верхнюю строку
|
||||
uint32_t thisColor = getPixColorXY(x, HEIGHT - 1);
|
||||
if (thisColor == 0)
|
||||
drawPixelXY(x, HEIGHT - 1, 0x00FF00 * (random(0, 100 - modes[EFF_MATRIX].Scale) == 0));
|
||||
uint32_t thisColor = getPixColorXY(x, HEIGHT - 1U);
|
||||
if (thisColor == 0U)
|
||||
drawPixelXY(x, HEIGHT - 1U, 0x00FF00 * (random(0, 100 - modes[EFF_MATRIX].Scale) == 0U));
|
||||
else if (thisColor < 0x002000)
|
||||
drawPixelXY(x, HEIGHT - 1, 0);
|
||||
drawPixelXY(x, HEIGHT - 1U, 0U);
|
||||
else
|
||||
drawPixelXY(x, HEIGHT - 1, thisColor - 0x002000);
|
||||
drawPixelXY(x, HEIGHT - 1U, thisColor - 0x002000);
|
||||
}
|
||||
|
||||
// сдвигаем всё вниз
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
for (uint8_t y = 0; y < HEIGHT - 1; y++)
|
||||
for (uint8_t y = 0U; y < HEIGHT - 1U; y++)
|
||||
{
|
||||
drawPixelXY(x, y, getPixColorXY(x, y + 1));
|
||||
drawPixelXY(x, y, getPixColorXY(x, y + 1U));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------- светлячки --------------
|
||||
#define LIGHTERS_AM (100)
|
||||
int32_t lightersPos[2][LIGHTERS_AM];
|
||||
int8_t lightersSpeed[2][LIGHTERS_AM];
|
||||
#define LIGHTERS_AM (100U)
|
||||
int32_t lightersPos[2U][LIGHTERS_AM];
|
||||
int8_t lightersSpeed[2U][LIGHTERS_AM];
|
||||
CHSV lightersColor[LIGHTERS_AM];
|
||||
uint8_t loopCounter;
|
||||
int32_t angle[LIGHTERS_AM];
|
||||
@@ -437,44 +437,44 @@ void lightersRoutine()
|
||||
{
|
||||
loadingFlag = false;
|
||||
randomSeed(millis());
|
||||
for (uint8_t i = 0; i < LIGHTERS_AM; i++)
|
||||
for (uint8_t i = 0U; i < LIGHTERS_AM; i++)
|
||||
{
|
||||
lightersPos[0][i] = random(0, WIDTH * 10);
|
||||
lightersPos[1][i] = random(0, HEIGHT * 10);
|
||||
lightersSpeed[0][i] = random(-10, 10);
|
||||
lightersSpeed[1][i] = random(-10, 10);
|
||||
lightersColor[i] = CHSV(random(0, 255), 255, 255);
|
||||
lightersPos[0U][i] = random(0, WIDTH * 10);
|
||||
lightersPos[1U][i] = random(0, HEIGHT * 10);
|
||||
lightersSpeed[0U][i] = random(-10, 10);
|
||||
lightersSpeed[1U][i] = random(-10, 10);
|
||||
lightersColor[i] = CHSV(random(0U, 255U), 255U, 255U);
|
||||
}
|
||||
}
|
||||
FastLED.clear();
|
||||
if (++loopCounter > 20) loopCounter = 0;
|
||||
for (uint8_t i = 0; i < modes[EFF_LIGHTERS].Scale; i++)
|
||||
if (++loopCounter > 20U) loopCounter = 0U;
|
||||
for (uint8_t i = 0U; i < modes[EFF_LIGHTERS].Scale; i++)
|
||||
{
|
||||
if (loopCounter == 0) // меняем скорость каждые 255 отрисовок
|
||||
if (loopCounter == 0U) // меняем скорость каждые 255 отрисовок
|
||||
{
|
||||
lightersSpeed[0][i] += random(-3, 4);
|
||||
lightersSpeed[1][i] += random(-3, 4);
|
||||
lightersSpeed[0][i] = constrain(lightersSpeed[0][i], -20, 20);
|
||||
lightersSpeed[1][i] = constrain(lightersSpeed[1][i], -20, 20);
|
||||
lightersSpeed[0U][i] += random(-3, 4);
|
||||
lightersSpeed[1U][i] += random(-3, 4);
|
||||
lightersSpeed[0U][i] = constrain(lightersSpeed[0U][i], -20, 20);
|
||||
lightersSpeed[1U][i] = constrain(lightersSpeed[1U][i], -20, 20);
|
||||
}
|
||||
|
||||
lightersPos[0][i] += lightersSpeed[0][i];
|
||||
lightersPos[1][i] += lightersSpeed[1][i];
|
||||
lightersPos[0U][i] += lightersSpeed[0U][i];
|
||||
lightersPos[1U][i] += lightersSpeed[1U][i];
|
||||
|
||||
if (lightersPos[0][i] < 0) lightersPos[0][i] = (WIDTH - 1) * 10;
|
||||
if (lightersPos[0][i] >= WIDTH * 10) lightersPos[0][i] = 0;
|
||||
if (lightersPos[0U][i] < 0) lightersPos[0U][i] = (WIDTH - 1) * 10;
|
||||
if (lightersPos[0U][i] >= (int32_t)(WIDTH * 10)) lightersPos[0U][i] = 0;
|
||||
|
||||
if (lightersPos[1][i] < 0)
|
||||
if (lightersPos[1U][i] < 0)
|
||||
{
|
||||
lightersPos[1][i] = 0;
|
||||
lightersSpeed[1][i] = -lightersSpeed[1][i];
|
||||
lightersPos[1U][i] = 0;
|
||||
lightersSpeed[1U][i] = -lightersSpeed[1U][i];
|
||||
}
|
||||
if (lightersPos[1][i] >= (HEIGHT - 1) * 10)
|
||||
if (lightersPos[1U][i] >= (int32_t)(HEIGHT - 1) * 10)
|
||||
{
|
||||
lightersPos[1][i] = (HEIGHT - 1) * 10;
|
||||
lightersSpeed[1][i] = -lightersSpeed[1][i];
|
||||
lightersPos[1U][i] = (HEIGHT - 1U) * 10;
|
||||
lightersSpeed[1U][i] = -lightersSpeed[1U][i];
|
||||
}
|
||||
drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]);
|
||||
drawPixelXY(lightersPos[0U][i] / 10, lightersPos[1U][i] / 10, lightersColor[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,8 +483,8 @@ void lightersRoutine()
|
||||
#define CLEAR_PATH (1U) // очищать путь
|
||||
#define BALL_TRACK (1U) // (0 / 1) - вкл/выкл следы шариков
|
||||
#define TRACK_STEP (70U) // длина хвоста шарика (чем больше цифра, тем хвост короче)
|
||||
int16_t coord[BALLS_AMOUNT][2];
|
||||
int8_t vector[BALLS_AMOUNT][2];
|
||||
int16_t coord[BALLS_AMOUNT][2U];
|
||||
int8_t vector[BALLS_AMOUNT][2U];
|
||||
CRGB ballColors[BALLS_AMOUNT];
|
||||
void ballsRoutine()
|
||||
{
|
||||
@@ -492,17 +492,17 @@ void ballsRoutine()
|
||||
{
|
||||
loadingFlag = false;
|
||||
|
||||
for (uint8_t j = 0; j < BALLS_AMOUNT; j++)
|
||||
for (uint8_t j = 0U; j < BALLS_AMOUNT; j++)
|
||||
{
|
||||
int8_t sign;
|
||||
// забиваем случайными данными
|
||||
coord[j][0] = WIDTH / 2 * 10;
|
||||
coord[j][0U] = WIDTH / 2 * 10;
|
||||
random(0, 2) ? sign = 1 : sign = -1;
|
||||
vector[j][0] = random(4, 15) * sign;
|
||||
coord[j][1] = HEIGHT / 2 * 10;
|
||||
vector[j][0U] = random(4, 15) * sign;
|
||||
coord[j][1U] = HEIGHT / 2 * 10;
|
||||
random(0, 2) ? sign = 1 : sign = -1;
|
||||
vector[j][1] = random(4, 15) * sign;
|
||||
ballColors[j] = CHSV(random(0, 9) * 28, 255, 255);
|
||||
vector[j][1U] = random(4, 15) * sign;
|
||||
ballColors[j] = CHSV(random(0, 9) * 28, 255U, 255U);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,10 +516,10 @@ void ballsRoutine()
|
||||
}
|
||||
|
||||
// движение шариков
|
||||
for (uint8_t j = 0; j < BALLS_AMOUNT; j++)
|
||||
for (uint8_t j = 0U; j < BALLS_AMOUNT; j++)
|
||||
{
|
||||
// движение шариков
|
||||
for (uint8_t i = 0; i < 2; i++)
|
||||
for (uint8_t i = 0U; i < 2U; i++)
|
||||
{
|
||||
coord[j][i] += vector[j][i];
|
||||
if (coord[j][i] < 0)
|
||||
@@ -529,22 +529,22 @@ void ballsRoutine()
|
||||
}
|
||||
}
|
||||
|
||||
if (coord[j][0] > (WIDTH - 1) * 10)
|
||||
if (coord[j][0U] > (int16_t)((WIDTH - 1) * 10))
|
||||
{
|
||||
coord[j][0] = (WIDTH - 1) * 10;
|
||||
vector[j][0] = -vector[j][0];
|
||||
coord[j][0U] = (WIDTH - 1) * 10;
|
||||
vector[j][0U] = -vector[j][0U];
|
||||
}
|
||||
if (coord[j][1] > (HEIGHT - 1) * 10)
|
||||
if (coord[j][1U] > (int16_t)((HEIGHT - 1) * 10))
|
||||
{
|
||||
coord[j][1] = (HEIGHT - 1) * 10;
|
||||
vector[j][1] = -vector[j][1];
|
||||
coord[j][1U] = (HEIGHT - 1) * 10;
|
||||
vector[j][1U] = -vector[j][1U];
|
||||
}
|
||||
leds[getPixelNumber(coord[j][0] / 10, coord[j][1] / 10)] = ballColors[j];
|
||||
leds[getPixelNumber(coord[j][0U] / 10, coord[j][1U] / 10)] = ballColors[j];
|
||||
}
|
||||
}
|
||||
|
||||
// ------------- пейнтбол -------------
|
||||
const uint8_t BorderWidth = 2;
|
||||
const uint8_t BorderWidth = 2U;
|
||||
void lightBallsRoutine()
|
||||
{
|
||||
// Apply some blurring to whatever's already on the matrix
|
||||
@@ -562,10 +562,10 @@ void lightBallsRoutine()
|
||||
|
||||
// The color of each point shifts over time, each at a different speed.
|
||||
uint16_t ms = millis();
|
||||
leds[XY( i, j)] += CHSV( ms / 29, 200, 255);
|
||||
leds[XY( j, k)] += CHSV( ms / 41, 200, 255);
|
||||
leds[XY( k, m)] += CHSV( ms / 73, 200, 255);
|
||||
leds[XY( m, i)] += CHSV( ms / 97, 200, 255);
|
||||
leds[XY( i, j)] += CHSV( ms / 29, 200U, 255U);
|
||||
leds[XY( j, k)] += CHSV( ms / 41, 200U, 255U);
|
||||
leds[XY( k, m)] += CHSV( ms / 73, 200U, 255U);
|
||||
leds[XY( m, i)] += CHSV( ms / 97, 200U, 255U);
|
||||
|
||||
}
|
||||
// Trivial XY function for the SmartMatrix; use a different XY
|
||||
@@ -589,8 +589,8 @@ uint16_t XY(uint8_t x, uint8_t y)
|
||||
|
||||
// ------------- блуждающий кубик -------------
|
||||
#define RANDOM_COLOR (1U) // случайный цвет при отскоке
|
||||
int16_t coordB[2];
|
||||
int8_t vectorB[2];
|
||||
int16_t coordB[2U];
|
||||
int8_t vectorB[2U];
|
||||
CRGB ballColor;
|
||||
int8_t ballSize;
|
||||
void ballRoutine()
|
||||
@@ -600,49 +600,49 @@ void ballRoutine()
|
||||
loadingFlag = false;
|
||||
//FastLED.clear();
|
||||
|
||||
for (uint8_t i = 0; i < 2; i++)
|
||||
for (uint8_t i = 0U; i < 2U; i++)
|
||||
{
|
||||
coordB[i] = WIDTH / 2 * 10;
|
||||
vectorB[i] = random(8, 20);
|
||||
ballColor = CHSV(random(0, 9) * 28, 255, 255);
|
||||
ballColor = CHSV(random(0, 9) * 28, 255U, 255U);
|
||||
}
|
||||
}
|
||||
|
||||
ballSize = map(modes[EFF_CUBE].Scale, 0, 255, 2, max((int16_t)min(WIDTH,HEIGHT) / 3, 2));
|
||||
for (uint8_t i = 0; i < 2; i++)
|
||||
ballSize = map(modes[EFF_CUBE].Scale, 0U, 255U, 2U, max((uint8_t)min(WIDTH,HEIGHT) / 3, 2));
|
||||
for (uint8_t i = 0U; i < 2U; i++)
|
||||
{
|
||||
coordB[i] += vectorB[i];
|
||||
if (coordB[i] < 0)
|
||||
{
|
||||
coordB[i] = 0;
|
||||
vectorB[i] = -vectorB[i];
|
||||
if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255, 255);
|
||||
if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U);
|
||||
//vectorB[i] += random(0, 6) - 3;
|
||||
}
|
||||
}
|
||||
if (coordB[0] > (WIDTH - ballSize) * 10)
|
||||
if (coordB[0U] > (int16_t)((WIDTH - ballSize) * 10))
|
||||
{
|
||||
coordB[0] = (WIDTH - ballSize) * 10;
|
||||
vectorB[0] = -vectorB[0];
|
||||
if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255, 255);
|
||||
coordB[0U] = (WIDTH - ballSize) * 10;
|
||||
vectorB[0U] = -vectorB[0U];
|
||||
if (RANDOM_COLOR) ballColor = CHSV(random(0, 9) * 28, 255U, 255U);
|
||||
//vectorB[0] += random(0, 6) - 3;
|
||||
}
|
||||
if (coordB[1] > (HEIGHT - ballSize) * 10)
|
||||
if (coordB[1U] > (int16_t)((HEIGHT - ballSize) * 10))
|
||||
{
|
||||
coordB[1] = (HEIGHT - ballSize) * 10;
|
||||
vectorB[1] = -vectorB[1];
|
||||
coordB[1U] = (HEIGHT - ballSize) * 10;
|
||||
vectorB[1U] = -vectorB[1U];
|
||||
if (RANDOM_COLOR)
|
||||
{
|
||||
ballColor = CHSV(random(0, 9) * 28, 255, 255);
|
||||
ballColor = CHSV(random(0, 9) * 28, 255U, 255U);
|
||||
}
|
||||
//vectorB[1] += random(0, 6) - 3;
|
||||
}
|
||||
FastLED.clear();
|
||||
for (uint8_t i = 0; i < ballSize; i++)
|
||||
for (uint8_t i = 0U; i < ballSize; i++)
|
||||
{
|
||||
for (uint8_t j = 0; j < ballSize; j++)
|
||||
for (uint8_t j = 0U; j < ballSize; j++)
|
||||
{
|
||||
leds[getPixelNumber(coordB[0] / 10 + i, coordB[1] / 10 + j)] = ballColor;
|
||||
leds[getPixelNumber(coordB[0U] / 10 + i, coordB[1U] / 10 + j)] = ballColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -655,9 +655,9 @@ void whiteColorRoutine()
|
||||
loadingFlag = false;
|
||||
FastLED.clear();
|
||||
|
||||
for (int16_t i = 0; i < NUM_LEDS; i++)
|
||||
for (uint16_t i = 0U; i < NUM_LEDS; i++)
|
||||
{
|
||||
leds[i] = CHSV(0, 0, 255);
|
||||
leds[i] = CHSV(0U, 0U, 255U);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -676,82 +676,57 @@ void whiteColorStripeRoutine()
|
||||
for (int16_t y = centerY; y >= 0; y--)
|
||||
{
|
||||
CRGB color = CHSV(
|
||||
45, // определяем тон
|
||||
map(modes[EFF_WHITE_COLOR].Speed, 0, 255, 0, 170), // определяем насыщенность
|
||||
45U, // определяем тон
|
||||
map(modes[EFF_WHITE_COLOR].Speed, 0U, 255U, 0U, 170U), // определяем насыщенность
|
||||
y == centerY // определяем яркость
|
||||
? 255 // для центральной горизонтальной полосы (или двух) яркость всегда равна 255
|
||||
: (modes[EFF_WHITE_COLOR].Scale / 100.0F) > ((centerY + 1.0F) - (y + 1.0F)) / (centerY + 1.0F) ? 255 : 0); // для остальных горизонтальных полос яркость равна либо 255, либо 0 в зависимости от масштаба
|
||||
? 255U // для центральной горизонтальной полосы (или двух) яркость всегда равна 255
|
||||
: (modes[EFF_WHITE_COLOR].Scale / 100.0F) > ((centerY + 1.0F) - (y + 1.0F)) / (centerY + 1.0F) ? 255U : 0U); // для остальных горизонтальных полос яркость равна либо 255, либо 0 в зависимости от масштаба
|
||||
|
||||
for (uint8_t x = 0; x < WIDTH; x++)
|
||||
for (uint8_t x = 0U; x < WIDTH; x++)
|
||||
{
|
||||
drawPixelXY(x, y, color); // при чётной высоте матрицы максимально яркими отрисуются 2 центральных горизонтальных полосы
|
||||
drawPixelXY(x, max((uint8_t)(HEIGHT - 1) - (y + 1) + bottomOffset, 0), color); // при нечётной - одна, но дважды
|
||||
drawPixelXY(x, max((uint8_t)(HEIGHT - 1U) - (y + 1U) + bottomOffset, 0U), color); // при нечётной - одна, но дважды
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* устарело
|
||||
void lightersRoutine()
|
||||
// ------------- мигающий цвет (не эффект! используется для отображения краткосрочного предупреждения; блокирующий код!) -------------
|
||||
#define WARNING_BRIGHTNESS (10U) // яркость вспышки
|
||||
void showWarning(
|
||||
CRGB color, // цвет вспышки
|
||||
uint32_t duration, // продолжительность отображения предупреждения (общее время)
|
||||
uint16_t blinkHalfPeriod) // продолжительность одной вспышки в миллисекундах (полупериод)
|
||||
{
|
||||
if (loadingFlag)
|
||||
{
|
||||
loadingFlag = false;
|
||||
randomSeed(millis());
|
||||
for (uint8_t i = 0; i < LIGHTERS_AM; i++)
|
||||
{
|
||||
lightersPos[0][i] = random(0, WIDTH * 10);
|
||||
lightersPos[1][i] = random(0, HEIGHT * 10);
|
||||
|
||||
lightersColor[i] = CHSV(random(0, 255), 255, 255);
|
||||
|
||||
speedV[i] = random(5, 10);
|
||||
angle[i] = random(0, 360);
|
||||
angleSpeed[i] = random(-10, 10);
|
||||
}
|
||||
}
|
||||
uint32_t blinkTimer = millis();
|
||||
enum BlinkState { OFF = 0, ON = 1 } blinkState = BlinkState::OFF;
|
||||
FastLED.setBrightness(WARNING_BRIGHTNESS); // установка яркости для предупреждения
|
||||
FastLED.clear();
|
||||
if (++loopCounter > 20) loopCounter = 0;
|
||||
delay(2);
|
||||
FastLED.show();
|
||||
|
||||
for (uint8_t i = 0; i < modes[EFF_LIGHTER_TRACES].scale; i++)
|
||||
for (uint16_t i = 0U; i < NUM_LEDS; i++) // установка цвета всех диодов в WARNING_COLOR
|
||||
{
|
||||
if (loopCounter == 0) // меняем скорость каждые 255 отрисовок
|
||||
{
|
||||
angleSpeed[i] += random(-3, 4);
|
||||
angleSpeed[i] = constrain(angleSpeed[i], -15, 15);
|
||||
}
|
||||
|
||||
lightersPos[0][i] += speedV[i] * cos(radians(angle[i]));
|
||||
lightersPos[1][i] += speedV[i] * sin(radians(angle[i]));
|
||||
|
||||
if (lightersPos[0][i] < 0) lightersPos[0][i] = (WIDTH - 1) * 10;
|
||||
if (lightersPos[0][i] >= WIDTH * 10) lightersPos[0][i] = 0;
|
||||
|
||||
if (lightersPos[1][i] < 0)
|
||||
{
|
||||
lightersPos[1][i] = 0;
|
||||
angle[i] = 360 - angle[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
angle[i] += angleSpeed[i];
|
||||
}
|
||||
|
||||
if (lightersPos[1][i] >= (HEIGHT - 1) * 10)
|
||||
{
|
||||
lightersPos[1][i] = (HEIGHT - 1) * 10;
|
||||
angle[i] = 360 - angle[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
angle[i] += angleSpeed[i];
|
||||
}
|
||||
|
||||
if (angle[i] > 360) angle[i] = 360 - angle[i];
|
||||
if (angle[i] < 0) angle[i] = 360 + angle[i];
|
||||
|
||||
drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]);
|
||||
leds[i] = color;
|
||||
}
|
||||
|
||||
uint32_t startTime = millis();
|
||||
while (millis() - startTime <= (duration + 5)) // блокировка дальнейшего выполнения циклом на время отображения предупреждения
|
||||
{
|
||||
if (millis() - blinkTimer >= blinkHalfPeriod) // переключение вспышка/темнота
|
||||
{
|
||||
blinkTimer = millis();
|
||||
blinkState = (BlinkState)!blinkState;
|
||||
FastLED.setBrightness(blinkState == BlinkState::OFF ? 0 : WARNING_BRIGHTNESS);
|
||||
delay(1);
|
||||
FastLED.show();
|
||||
}
|
||||
delay(50);
|
||||
}
|
||||
|
||||
FastLED.clear();
|
||||
FastLED.setBrightness(ONflag ? modes[currentMode].Brightness : 0); // установка яркости, которая была выставлена до вызова предупреждения
|
||||
delay(1);
|
||||
FastLED.show();
|
||||
loadingFlag = true; // принудительное отображение текущего эффекта (того, что был активен перед предупреждением)
|
||||
}
|
||||
*/
|
||||
|
@@ -86,7 +86,7 @@ void zebraNoiseRoutine()
|
||||
{
|
||||
loadingFlag = false;
|
||||
// 'black out' all 16 palette entries...
|
||||
fill_solid( currentPalette, 16, CRGB::Black);
|
||||
fill_solid(currentPalette, 16, CRGB::Black);
|
||||
// and set every fourth one to white.
|
||||
currentPalette[0] = CRGB::White;
|
||||
currentPalette[4] = CRGB::White;
|
||||
|
@@ -21,8 +21,11 @@ void parseUDP()
|
||||
char reply[MAX_UDP_BUFFER_SIZE];
|
||||
processInputBuffer(inputBuffer, reply, true);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1) // отправка ответа выполнения команд по MQTT, если разрешено
|
||||
strcpy(MqttManager::mqttBuffer, reply); // разрешение определяется при выполнении каждой команды отдельно, команды GET, DEB, DISCOVER и OTA, пришедшие по UDP, игнорируются (приходят раз в 2 секунды от приложения)
|
||||
#if (USE_MQTT) // отправка ответа выполнения команд по MQTT, если разрешено
|
||||
if (espMode == 1U)
|
||||
{
|
||||
strcpy(MqttManager::mqttBuffer, reply); // разрешение определяется при выполнении каждой команды отдельно, команды GET, DEB, DISCOVER и OTA, пришедшие по UDP, игнорируются (приходят раз в 2 секунды от приложения)
|
||||
}
|
||||
#endif
|
||||
|
||||
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
|
||||
@@ -62,13 +65,18 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
memcpy(buff, &inputBuffer[3], strlen(inputBuffer)); // взять подстроку, состоящую последних символов строки inputBuffer, начиная с символа 4
|
||||
currentMode = (uint8_t)atoi(buff);
|
||||
loadingFlag = true;
|
||||
settChanged = true;
|
||||
eepromTimeout = millis();
|
||||
FastLED.clear();
|
||||
delay(1);
|
||||
sendCurrent(inputBuffer);
|
||||
FastLED.setBrightness(modes[currentMode].Brightness);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -82,8 +90,11 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
eepromTimeout = millis();
|
||||
sendCurrent(inputBuffer);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -96,8 +107,11 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
eepromTimeout = millis();
|
||||
sendCurrent(inputBuffer);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -110,8 +124,11 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
eepromTimeout = millis();
|
||||
sendCurrent(inputBuffer);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -124,8 +141,11 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
changePower();
|
||||
sendCurrent(inputBuffer);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -137,8 +157,11 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
changePower();
|
||||
sendCurrent(inputBuffer);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -160,15 +183,16 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
{
|
||||
memcpy(buff, &inputBuffer[8], strlen(inputBuffer)); // взять подстроку, состоящую последних символов строки inputBuffer, начиная с символа 9
|
||||
alarms[alarmNum].Time = atoi(buff);
|
||||
uint8_t hour = floor(alarms[alarmNum].Time / 60);
|
||||
uint8_t minute = alarms[alarmNum].Time - hour * 60;
|
||||
sendAlarms(inputBuffer);
|
||||
}
|
||||
EepromManager::SaveAlarmsSettings(&alarmNum, alarms);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
strcpy(MqttManager::mqttBuffer, inputBuffer);
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
strcpy(MqttManager::mqttBuffer, inputBuffer);
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -184,14 +208,17 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
EepromManager::SaveDawnMode(&dawnMode);
|
||||
sendAlarms(inputBuffer);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
else if (!strncmp_P(inputBuffer, PSTR("DISCOVER"), 8)) // обнаружение приложением модуля esp в локальной сети
|
||||
{
|
||||
if (ESP_MODE == 1) // работает только в режиме WiFi клиента
|
||||
if (espMode == 1U) // работает только в режиме WiFi клиента
|
||||
{
|
||||
sprintf_P(inputBuffer, PSTR("IP %u.%u.%u.%u:%u"),
|
||||
WiFi.localIP()[0],
|
||||
@@ -221,8 +248,11 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
TimerManager::TimerHasFired = false;
|
||||
sendTimer(inputBuffer);
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -238,8 +268,11 @@ void processInputBuffer(char *inputBuffer, char *outputBuffer, bool generateOutp
|
||||
settChanged = true;
|
||||
eepromTimeout = millis();
|
||||
|
||||
#if (USE_MQTT && ESP_MODE == 1)
|
||||
MqttManager::needToPublish = true;
|
||||
#if (USE_MQTT)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
MqttManager::needToPublish = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -282,7 +315,7 @@ void sendCurrent(char *outputBuffer)
|
||||
modes[currentMode].Speed,
|
||||
modes[currentMode].Scale,
|
||||
ONflag,
|
||||
ESP_MODE);
|
||||
espMode);
|
||||
|
||||
#ifdef USE_NTP
|
||||
strcat_P(outputBuffer, PSTR(" 1"));
|
||||
|
@@ -42,7 +42,7 @@ bool fillString(const char* text)
|
||||
}
|
||||
else
|
||||
{
|
||||
drawLetter(j, text[i], offset + j * (LET_WIDTH + SPACE));
|
||||
drawLetter(text[i], offset + j * (LET_WIDTH + SPACE));
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ bool fillString(const char* text)
|
||||
return false;
|
||||
}
|
||||
|
||||
void drawLetter(uint8_t index, uint8_t letter, int8_t offset)
|
||||
void drawLetter(uint8_t letter, int8_t offset)
|
||||
{
|
||||
uint8_t start_pos = 0, finish_pos = LET_WIDTH;
|
||||
|
||||
|
@@ -15,11 +15,18 @@ 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 шаг
|
||||
static CHSV dawnColorMinus2 = CHSV(0, 0, 0);
|
||||
static CHSV dawnColorMinus3 = CHSV(0, 0, 0);
|
||||
static CHSV dawnColorMinus4 = CHSV(0, 0, 0);
|
||||
static CHSV dawnColorMinus5 = CHSV(0, 0, 0);
|
||||
static uint8_t dawnCounter = 0; // счётчик первых 10 шагов будильника
|
||||
|
||||
|
||||
void timeTick()
|
||||
{
|
||||
if (ESP_MODE == 1)
|
||||
if (espMode == 1U)
|
||||
{
|
||||
if (timeTimer.isReady())
|
||||
{
|
||||
@@ -48,26 +55,41 @@ void timeTick()
|
||||
return;
|
||||
}
|
||||
|
||||
byte thisDay = timeClient.getDay();
|
||||
uint8_t thisDay = timeClient.getDay();
|
||||
if (thisDay == 0) thisDay = 7; // воскресенье это 0
|
||||
thisDay--;
|
||||
thisTime = timeClient.getHours() * 60 + timeClient.getMinutes();
|
||||
uint32_t thisFullTime = timeClient.getHours() * 3600 + timeClient.getMinutes() * 60 + timeClient.getSeconds();
|
||||
|
||||
// проверка рассвета
|
||||
if (alarms[thisDay].State && // день будильника
|
||||
thisTime >= (alarms[thisDay].Time - pgm_read_byte(&dawnOffsets[dawnMode])) && // позже начала
|
||||
thisTime < (alarms[thisDay].Time + DAWN_TIMEOUT)) // раньше конца + минута
|
||||
if (alarms[thisDay].State && // день будильника
|
||||
thisTime >= (uint16_t)constrain(alarms[thisDay].Time - pgm_read_byte(&dawnOffsets[dawnMode]), 0, (24 * 60)) && // позже начала
|
||||
thisTime < (alarms[thisDay].Time + DAWN_TIMEOUT)) // раньше конца + минута
|
||||
{
|
||||
if (!manualOff) // будильник не был выключен вручную (из приложения или кнопкой)
|
||||
{
|
||||
LOG.println("Будильник включен");
|
||||
// величина рассвета 0-255
|
||||
int32_t dawnPosition = 255 * ((float)(thisTime - (alarms[thisDay].Time - pgm_read_byte(&dawnOffsets[dawnMode]))) / pgm_read_byte(&dawnOffsets[dawnMode]));
|
||||
int32_t dawnPosition = 255 * ((float)(thisFullTime - (alarms[thisDay].Time - pgm_read_byte(&dawnOffsets[dawnMode])) * 60) / (pgm_read_byte(&dawnOffsets[dawnMode]) * 60));
|
||||
dawnPosition = constrain(dawnPosition, 0, 255);
|
||||
CHSV dawnColor = CHSV(map(dawnPosition, 0, 255, 10, 35),
|
||||
map(dawnPosition, 0, 255, 255, 170),
|
||||
map(dawnPosition, 0, 255, 10, DAWN_BRIGHT));
|
||||
fill_solid(leds, NUM_LEDS, dawnColor);
|
||||
dawnColorMinus5 = dawnCounter > 4 ? dawnColorMinus4 : dawnColorMinus5;
|
||||
dawnColorMinus4 = dawnCounter > 3 ? dawnColorMinus3 : dawnColorMinus4;
|
||||
dawnColorMinus3 = dawnCounter > 2 ? dawnColorMinus2 : dawnColorMinus3;
|
||||
dawnColorMinus2 = dawnCounter > 1 ? dawnColorMinus1 : dawnColorMinus2;
|
||||
dawnColorMinus1 = dawnCounter > 0 ? dawnColor : dawnColorMinus1;
|
||||
dawnColor = CHSV(map(dawnPosition, 0, 255, 10, 35),
|
||||
map(dawnPosition, 0, 255, 255, 170),
|
||||
map(dawnPosition, 0, 255, 10, DAWN_BRIGHT));
|
||||
dawnCounter++;
|
||||
// fill_solid(leds, NUM_LEDS, dawnColor);
|
||||
for (uint16_t i = 0U; i < NUM_LEDS; i++)
|
||||
{
|
||||
if (i % 6 == 0) leds[i] = dawnColor; // 1я 1/10 диодов: цвет текущего шага
|
||||
if (i % 6 == 1) leds[i] = dawnColorMinus1; // 2я 1/10 диодов: -1 шаг
|
||||
if (i % 6 == 2) leds[i] = dawnColorMinus2; // 3я 1/10 диодов: -2 шага
|
||||
if (i % 6 == 3) leds[i] = dawnColorMinus3; // 3я 1/10 диодов: -3 шага
|
||||
if (i % 6 == 4) leds[i] = dawnColorMinus4; // 3я 1/10 диодов: -4 шага
|
||||
if (i % 6 == 5) leds[i] = dawnColorMinus5; // 3я 1/10 диодов: -5 шагов
|
||||
}
|
||||
FastLED.setBrightness(255);
|
||||
delay(1);
|
||||
FastLED.show();
|
||||
@@ -86,6 +108,12 @@ void timeTick()
|
||||
changePower(); // выключение матрицы или установка яркости текущего эффекта в засисимости от того, была ли включена лампа до срабатывания будильника
|
||||
}
|
||||
manualOff = false;
|
||||
dawnColorMinus1 = CHSV(0, 0, 0);
|
||||
dawnColorMinus2 = CHSV(0, 0, 0);
|
||||
dawnColorMinus3 = CHSV(0, 0, 0);
|
||||
dawnColorMinus4 = CHSV(0, 0, 0);
|
||||
dawnColorMinus5 = CHSV(0, 0, 0);
|
||||
dawnCounter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,10 +10,10 @@ void fillAll(CRGB color)
|
||||
}
|
||||
|
||||
// функция отрисовки точки по координатам X Y
|
||||
void drawPixelXY(uint8_t x, uint8_t y, CRGB color)
|
||||
void drawPixelXY(int16_t x, int16_t y, CRGB color)
|
||||
{
|
||||
if (x < 0 || x > WIDTH - 1 || y < 0 || y > HEIGHT - 1) return;
|
||||
uint32_t thisPixel = getPixelNumber(x, y) * SEGMENTS;
|
||||
if (x < 0 || x > (int16_t)(WIDTH - 1) || y < 0 || y > (int16_t)(HEIGHT - 1)) return;
|
||||
uint32_t thisPixel = getPixelNumber((uint8_t)x, (uint8_t)y) * SEGMENTS;
|
||||
for (uint8_t i = 0; i < SEGMENTS; i++)
|
||||
{
|
||||
leds[thisPixel + i] = color;
|
||||
@@ -24,7 +24,7 @@ void drawPixelXY(uint8_t x, uint8_t y, CRGB color)
|
||||
uint32_t getPixColor(uint32_t thisSegm)
|
||||
{
|
||||
uint32_t thisPixel = thisSegm * SEGMENTS;
|
||||
if (thisPixel < 0 || thisPixel > NUM_LEDS - 1) return 0;
|
||||
if (thisPixel > NUM_LEDS - 1) return 0;
|
||||
return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user