Добавлена возможность смены ESP_MODE без перепрошивки; доработан будильник; добавлена визуальная сигнализация красными и жёлтыми вспышками для некоторых действий/состояний; оптимизирован код, исправлены ошибки

This commit is contained in:
gunner47
2019-10-12 19:52:04 +03:00
parent baa82236ee
commit 33c811ab59
13 changed files with 469 additions and 363 deletions

View File

@@ -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) // диодов в одном "пикселе" (для создания матрицы из кусков ленты)

View File

@@ -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);

View File

@@ -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, &currentMode,
&(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, &currentMode,
&(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;

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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; // принудительное отображение текущего эффекта (того, что был активен перед предупреждением)
}
*/

View File

@@ -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;

View File

@@ -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"));

View File

@@ -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;

View File

@@ -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;
}
}
}

View File

@@ -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);
}