diff --git a/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino b/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino index 49ceb82..cd60951 100644 --- a/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino +++ b/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino @@ -16,58 +16,64 @@ // Ссылка для менеджера плат: // http://arduino.esp8266.com/stable/package_esp8266com_index.json + // ============= НАСТРОЙКИ ============= -// -------- ВРЕМЯ ------- -#define GMT 3 // смещение (москва 3) -#define NTP_ADDRESS "europe.pool.ntp.org" // сервер времени +// --- ВРЕМЯ --------------------------- +#define USE_NTP // закомментировать или удалить эту строку, если не нужно, чтобы устройство не лезло в интернет +#define GMT (3) // часовой пояс (москва 3) +#define NTP_ADDRESS "europe.pool.ntp.org" // сервер времени -// -------- РАССВЕТ ------- -#define DAWN_BRIGHT 200 // макс. яркость рассвета -#define DAWN_TIMEOUT 1 // сколько рассвет светит после времени будильника, минут +// --- РАССВЕТ ------------------------- +#define DAWN_BRIGHT (200U) // максимальная яркость рассвета (0-255) +#define DAWN_TIMEOUT (1U) // сколько рассвет светит после времени будильника, минут -// ---------- МАТРИЦА --------- -#define BRIGHTNESS 40 // стандартная маскимальная яркость (0-255) -#define CURRENT_LIMIT 2000 // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит +// --- МАТРИЦА ------------------------- +#define BRIGHTNESS (40U) // стандартная маскимальная яркость (0-255) +#define CURRENT_LIMIT (2000U) // лимит по току в миллиамперах, автоматически управляет яркостью (пожалей свой блок питания!) 0 - выключить лимит -#define WIDTH 16 // ширина матрицы -#define HEIGHT 16 // высота матрицы +#define WIDTH (16U) // ширина матрицы +#define HEIGHT (16U) // высота матрицы -#define COLOR_ORDER GRB // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB +#define COLOR_ORDER (GRB) // порядок цветов на ленте. Если цвет отображается некорректно - меняйте. Начать можно с RGB -#define MATRIX_TYPE 0 // тип матрицы: 0 - зигзаг, 1 - параллельная -#define CONNECTION_ANGLE 0 // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний -#define STRIP_DIRECTION 0 // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз -// при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" -// шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ +#define MATRIX_TYPE (0U) // тип матрицы: 0 - зигзаг, 1 - параллельная +#define CONNECTION_ANGLE (0U) // угол подключения: 0 - левый нижний, 1 - левый верхний, 2 - правый верхний, 3 - правый нижний +#define STRIP_DIRECTION (0U) // направление ленты из угла: 0 - вправо, 1 - вверх, 2 - влево, 3 - вниз + // при неправильной настройке матрицы вы получите предупреждение "Wrong matrix parameters! Set to default" + // шпаргалка по настройке матрицы здесь! https://alexgyver.ru/matrix_guide/ -// --------- ESP -------- -#define ESP_MODE 1 -// 0 - точка доступа -// 1 - локальный -byte IP_AP[] = {192, 168, 4, 66}; // статический IP точки доступа (менять только последнюю цифру) -byte IP_STA[] = {192, 168, 1, 66}; // статический IP локальный (менять только последнюю цифру) +// --- ESP ----------------------------- +#define ESP_MODE (1U) // 0U - WiFi точка доступа, 1U - клиент WiFi (подключение к роутеру) +#define ESP_USE_BUTTON // если строка не закомментирована, должна быть подключена кнопка (иначе ESP может регистрировать "фантомные" нажатия и некорректно устанавливать яркость) +#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_CONF_TIMEOUT (300U) // время в секундах, которое ESP будет ждать ввода SSID и пароля WiFi сети роутера в конфигурационном режиме, после его истечения ESP перезагружается +#define GENERAL_DEBUG // если строка не закомментирована, будут выводиться отладочные сообщения +#define WIFIMAN_DEBUG (true) // вывод отладочных сообщений при подключении к WiFi сети: true - выводятся, false - не выводятся; настройка не зависит от GENERAL_DEBUG -// ----- AP (точка доступа) ------- -#define AP_SSID "GyverLamp" -#define AP_PASS "12345678" -#define AP_PORT 8888 +// --- ESP (WiFi клиент) --------------- +uint8_t STA_STATIC_IP[] ={}; // статический IP адрес: {} - IP адрес определяется роутером; {192, 168, 1, 66} - IP адрес задан явно (если DHCP на роутере не решит иначе); должен быть из того же диапазона адресов, что разадёт роутер + // SSID WiFi сети и пароль будут запрошены WiFi Manager'ом в режиме WiFi точки доступа, нет способа захардкодить их в прошивке -// -------- Менеджер WiFi --------- -#define AC_SSID "AutoConnectAP" -#define AC_PASS "12345678" +// --- AP (WiFi точка доступа) --- +#define AP_NAME ("GyverLamp") // имя WiFi точки доступа, используется как при запросе SSID и пароля WiFi сети роутера, так и при работе в режиме ESP_MODE = 0 +#define AP_PASS ("12345678") // пароль WiFi точки доступа +uint8_t AP_STATIC_IP[] = {192, 168, 4, 1}; // статический IP точки доступа (лучше не менять) -// ============= ДЛЯ РАЗРАБОТЧИКОВ ============= -#define LED_PIN 2 // пин ленты -#define BTN_PIN 4 -#define MODE_AMOUNT 18 +// ============= ДЛЯ РАЗРАБОТЧИКОВ ===== +#define LED_PIN (2U) // пин ленты +#define BTN_PIN (4U) // пин кнопки +#define MODE_AMOUNT (18U) -#define NUM_LEDS WIDTH * HEIGHT -#define SEGMENTS 1 // диодов в одном "пикселе" (для создания матрицы из кусков ленты) -// ---------------- БИБЛИОТЕКИ ----------------- -#define FASTLED_INTERRUPT_RETRY_COUNT 0 -#define FASTLED_ALLOW_INTERRUPTS 0 +#define NUM_LEDS (WIDTH * HEIGHT) +#define SEGMENTS (1U) // диодов в одном "пикселе" (для создания матрицы из кусков ленты) + +// --- БИБЛИОТЕКИ ---------------------- +#define FASTLED_INTERRUPT_RETRY_COUNT (0U) +#define FASTLED_ALLOW_INTERRUPTS (0U) #define FASTLED_ESP8266_RAW_PIN_ORDER -#define NTP_INTERVAL 60 * 1000 // обновление (1 минута) +#define NTP_INTERVAL (30UL * 60UL * 1000UL)// интервал синхронизации времени (30 минут) #include "timerMinim.h" #include @@ -77,40 +83,48 @@ byte IP_STA[] = {192, 168, 1, 66}; // статический IP локальн #include #include #include -#include +#ifdef ESP_USE_BUTTON #include +#endif +#ifdef USE_NTP +#include +#endif -// ------------------- ТИПЫ -------------------- +// --- ИНИЦИАЛИЗАЦИЯ ОБЪЕКТОВ ---------- CRGB leds[NUM_LEDS]; -WiFiServer server(80); +WiFiManager wifiManager; +WiFiServer wifiServer(ESP_HTTP_PORT); WiFiUDP Udp; WiFiUDP ntpUDP; +#ifdef USE_NTP NTPClient timeClient(ntpUDP, NTP_ADDRESS, GMT * 3600, NTP_INTERVAL); +#endif timerMinim timeTimer(3000); +#ifdef ESP_USE_BUTTON GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN); +#endif -// ----------------- ПЕРЕМЕННЫЕ ------------------ -const char* autoConnectSSID = AC_SSID; -const char* autoConnectPass = AC_PASS; -const char AP_NameChar[] = AP_SSID; -const char WiFiPassword[] = AP_PASS; -unsigned int localPort = AP_PORT; -char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; //buffer to hold incoming packet +// --- ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ ------- +uint16_t localPort = ESP_UDP_PORT; +char packetBuffer[UDP_TX_PACKET_MAX_SIZE + 1]; // buffer to hold incoming packet String inputBuffer; -static const byte maxDim = max(WIDTH, HEIGHT); -struct { - byte brightness = 50; - byte speed = 30; - byte scale = 40; +static const uint8_t maxDim = max(WIDTH, HEIGHT); + +struct +{ + uint8_t brightness = 50; + uint8_t speed = 30; + uint8_t scale = 40; } modes[MODE_AMOUNT]; -struct { +struct +{ boolean state = false; - int time = 0; + int16_t time = 0; } alarm[7]; -byte dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60}; -byte dawnMode; +uint8_t dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60}; +uint8_t dawnMode; boolean dawnFlag = false; long thisTime; boolean manualOff = false; @@ -126,7 +140,9 @@ boolean settChanged = false; unsigned char matrixValue[8][16]; -void setup() { + +void setup() +{ ESP.wdtDisable(); //ESP.wdtEnable(WDTO_8S); @@ -137,97 +153,152 @@ void setup() { FastLED.clear(); FastLED.show(); + #ifdef ESP_USE_BUTTON touch.setStepTimeout(100); touch.setClickTimeout(500); + #endif Serial.begin(115200); Serial.println(); // WI-FI - if (ESP_MODE == 0) { // режим точки доступа - WiFi.softAPConfig(IPAddress(IP_AP[0], IP_AP[1], IP_AP[2], IP_AP[3]), - IPAddress(192, 168, 4, 1), - IPAddress(255, 255, 255, 0)); + wifiManager.setDebugOutput(WIFIMAN_DEBUG); // вывод отладочных сообщений + if (ESP_MODE == 0) // режим WiFi точки доступа + { + 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)); // маска подсети - WiFi.softAP(AP_NameChar, WiFiPassword); - IPAddress myIP = WiFi.softAPIP(); - Serial.print("Access point Mode"); - Serial.print("AP IP address: "); - Serial.println(myIP); + WiFi.softAP(AP_NAME, AP_PASS); - server.begin(); - } else { // подключаемся к роутеру - Serial.print("WiFi manager"); - WiFiManager wifiManager; - wifiManager.setDebugOutput(false); + Serial.println("Режим WiFi точки доступа"); + Serial.print("IP адрес: "); + Serial.println(WiFi.softAPIP()); + + wifiServer.begin(); + } + else + { // режим WiFi клиента (подключаемся к роутеру, если есть сохранённые SSID и пароль, иначе создаём WiFi точку доступа и запрашиваем их) + Serial.println("Режим WiFi клиента"); + if (WiFi.SSID()) + { + Serial.print("Подключение WiFi сети: "); + Serial.println(WiFi.SSID()); + } + else + { + Serial.println("WiFi сеть не определена, запуск WiFi точки доступа для настройки параметров подключения к WiFi сети..."); + } + //wifiManager.resetSettings(); - wifiManager.autoConnect(autoConnectSSID, autoConnectPass); - WiFi.config(IPAddress(IP_STA[0], IP_STA[1], IP_STA[2], IP_STA[3]), - IPAddress(192, 168, 1, 1), - IPAddress(255, 255, 255, 0)); - Serial.print("Connected! IP address: "); + if (STA_STATIC_IP) + { + 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 адресов нужно вынести в константы) + IPAddress(255, 255, 255, 0)); // маска подсети (справедливо для 99,99% случаев; для сетей меньше чем на 255 адресов нужно вынести в константы) + } + + wifiManager.setConnectTimeout(ESP_CONN_TIMEOUT); // установка времени ожидания подключения к WiFi сети, затем старт WiFi точки доступа + wifiManager.setConfigPortalTimeout(ESP_CONF_TIMEOUT); // установка времени работы WiFi точки доступа, затем перезагрузка; отключить watchdog? + wifiManager.autoConnect(AP_NAME, AP_PASS); // пытаемся подключиться к сохранённой ранее WiFi сети; в случае ошибки, будет развёрнута WiFi точка доступа с указанными AP_NAME и паролем на время ESP_CONN_TIMEOUT секунд; http://AP_STATIC_IP:ESP_HTTP_PORT (обычно http://192.168.0.1:80) - страница для ввода SSID и пароля от WiFi сети роутера + + if (WiFi.status() != WL_CONNECTED) + { + Serial.printf("Время ожидания ввода SSID и пароля от WiFi сети или подключения к WiFi сети превышено\nПерезагрузка модуля"); + + #if defined(ESP8266) + ESP.reset(); + #else + ESP.restart(); + #endif + } + + Serial.print("IP адрес: "); Serial.println(WiFi.localIP()); } - Serial.printf("UDP server on port %d\n", localPort); + + Serial.printf("Порт UDP сервера: %u\n", localPort); Udp.begin(localPort); // EEPROM EEPROM.begin(202); delay(50); - if (EEPROM.read(198) != 20) { // первый запуск + if (EEPROM.read(198) != 20) // первый запуск + { EEPROM.write(198, 20); EEPROM.commit(); - for (byte i = 0; i < MODE_AMOUNT; i++) { + for (uint8_t i = 0; i < MODE_AMOUNT; i++) + { EEPROM.put(3 * i + 40, modes[i]); EEPROM.commit(); } - for (byte i = 0; i < 7; i++) { - EEPROM.write(5 * i, alarm[i].state); // рассвет + + for (uint8_t i = 0; i < 7; i++) + { + EEPROM.write(5 * i, alarm[i].state); // рассвет eeWriteInt(5 * i + 1, alarm[i].time); EEPROM.commit(); } - EEPROM.write(199, 0); // рассвет - EEPROM.write(200, 0); // режим + + EEPROM.write(199, 0); // рассвет + EEPROM.write(200, 0); // режим EEPROM.commit(); } - for (byte i = 0; i < MODE_AMOUNT; i++) { + + for (uint8_t i = 0; i < MODE_AMOUNT; i++) + { EEPROM.get(3 * i + 40, modes[i]); } - for (byte i = 0; i < 7; i++) { + + for (uint8_t i = 0; i < 7; i++) + { alarm[i].state = EEPROM.read(5 * i); alarm[i].time = eeGetInt(5 * i + 1); } + dawnMode = EEPROM.read(199); currentMode = (int8_t)EEPROM.read(200); - // отправляем настройки - sendCurrent(); + sendCurrent(); // отправляем настройки char reply[inputBuffer.length() + 1]; inputBuffer.toCharArray(reply, inputBuffer.length() + 1); Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(reply); Udp.endPacket(); + #ifdef USE_NTP timeClient.begin(); + #endif + memset(matrixValue, 0, sizeof(matrixValue)); randomSeed(micros()); } -void loop() { + +void loop() +{ parseUDP(); effectsTick(); eepromTick(); + #ifdef USE_NTP timeTick(); + #endif + #ifdef ESP_USE_BUTTON buttonTick(); - ESP.wdtFeed(); // пнуть собаку - yield(); + #endif + ESP.wdtFeed(); // пнуть собаку + yield(); // обработать все "служебные" задачи: WiFi подключение и т.д. } -void eeWriteInt(int pos, int val) { - byte* p = (byte*) &val; + +void eeWriteInt(int16_t pos, int16_t val) +{ + uint8_t* p = (uint8_t*) &val; EEPROM.write(pos, *p); EEPROM.write(pos + 1, *(p + 1)); EEPROM.write(pos + 2, *(p + 2)); @@ -235,9 +306,11 @@ void eeWriteInt(int pos, int val) { EEPROM.commit(); } -int eeGetInt(int pos) { - int val; - byte* p = (byte*) &val; + +int16_t eeGetInt(int16_t pos) +{ + int16_t val; + uint8_t* p = (uint8_t*) &val; *p = EEPROM.read(pos); *(p + 1) = EEPROM.read(pos + 1); *(p + 2) = EEPROM.read(pos + 2); diff --git a/firmware/GyverLamp_v1.4/button.ino b/firmware/GyverLamp_v1.4/button.ino index 8b30f59..ba5d4ca 100644 --- a/firmware/GyverLamp_v1.4/button.ino +++ b/firmware/GyverLamp_v1.4/button.ino @@ -1,26 +1,36 @@ +#ifdef ESP_USE_BUTTON boolean brightDirection; -void buttonTick() { +void buttonTick() +{ touch.tick(); - if (touch.isSingle()) { - if (dawnFlag) { + if (touch.isSingle()) + { + if (dawnFlag) + { manualOff = true; dawnFlag = false; loadingFlag = true; FastLED.setBrightness(modes[currentMode].brightness); changePower(); - } else { - if (ONflag) { + } + else + { + if (ONflag) + { ONflag = false; changePower(); - } else { + } + else + { ONflag = true; changePower(); } } } - if (ONflag && touch.isDouble()) { + if (ONflag && touch.isDouble()) + { if (++currentMode >= MODE_AMOUNT) currentMode = 0; FastLED.setBrightness(modes[currentMode].brightness); loadingFlag = true; @@ -29,7 +39,9 @@ void buttonTick() { FastLED.clear(); delay(1); } - if (ONflag && touch.isTriple()) { + + if (ONflag && touch.isTriple()) + { if (--currentMode < 0) currentMode = 0; FastLED.setBrightness(modes[currentMode].brightness); loadingFlag = true; @@ -39,21 +51,32 @@ void buttonTick() { delay(1); } - if (ONflag && touch.isHolded()) { + if (ONflag && touch.isHolded()) + { brightDirection = !brightDirection; } - if (ONflag && touch.isStep()) { - if (brightDirection) { + + if (ONflag && touch.isStep()) + { + if (brightDirection) + { if (modes[currentMode].brightness < 10) modes[currentMode].brightness += 1; else if (modes[currentMode].brightness < 250) modes[currentMode].brightness += 5; else modes[currentMode].brightness = 255; - } else { + } + else + { if (modes[currentMode].brightness > 15) modes[currentMode].brightness -= 5; else if (modes[currentMode].brightness > 1) modes[currentMode].brightness -= 1; - else modes[currentMode].brightness = 1; + else modes[currentMode].brightness = 0; } FastLED.setBrightness(modes[currentMode].brightness); settChanged = true; eepromTimer = millis(); + + #ifdef GENERAL_DEBUG + Serial.printf("New brightness value: %d\n", modes[currentMode].brightness); + #endif } } +#endif diff --git a/firmware/GyverLamp_v1.4/eeprom.ino b/firmware/GyverLamp_v1.4/eeprom.ino index 3c25dc1..6dfdc71 100644 --- a/firmware/GyverLamp_v1.4/eeprom.ino +++ b/firmware/GyverLamp_v1.4/eeprom.ino @@ -1,10 +1,13 @@ -void saveEEPROM() { +void saveEEPROM() +{ EEPROM.put(3 * currentMode + 40, modes[currentMode]); EEPROM.commit(); } -void eepromTick() { - if (settChanged && millis() - eepromTimer > 30000) { +void eepromTick() +{ + if (settChanged && millis() - eepromTimer > 30000) + { settChanged = false; eepromTimer = millis(); saveEEPROM(); @@ -13,13 +16,15 @@ void eepromTick() { } } -void saveAlarm(byte almNumber) { - EEPROM.write(5 * almNumber, alarm[almNumber].state); // рассвет +void saveAlarm(byte almNumber) +{ + EEPROM.write(5 * almNumber, alarm[almNumber].state); // рассвет eeWriteInt(5 * almNumber + 1, alarm[almNumber].time); EEPROM.commit(); } -void saveDawnMmode() { - EEPROM.write(199, dawnMode); // рассвет +void saveDawnMmode() +{ + EEPROM.write(199, dawnMode); // рассвет EEPROM.commit(); } diff --git a/firmware/GyverLamp_v1.4/effectTicker.ino b/firmware/GyverLamp_v1.4/effectTicker.ino index 583616b..da60dbd 100644 --- a/firmware/GyverLamp_v1.4/effectTicker.ino +++ b/firmware/GyverLamp_v1.4/effectTicker.ino @@ -1,10 +1,14 @@ uint32_t effTimer; -void effectsTick() { - if (!dawnFlag) { - if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) { +void effectsTick() +{ + if (!dawnFlag) + { + if (ONflag && millis() - effTimer >= ((currentMode < 5 || currentMode > 13) ? modes[currentMode].speed : 50) ) + { effTimer = millis(); - switch (currentMode) { + switch (currentMode) + { case 0: sparklesRoutine(); break; case 1: fireRoutine(); @@ -47,10 +51,17 @@ void effectsTick() { } } -void changePower() { - if (ONflag) { +void changePower() +{ + #ifdef GENERAL_DEBUG + Serial.printf("changePower(); brightness: %d\n", modes[currentMode].brightness); + #endif + + if (ONflag) + { effectsTick(); - for (int i = 0; i < modes[currentMode].brightness; i += 8) { + for (uint8_t i = 0; i < modes[currentMode].brightness; i = constrain(i + 8, 0, modes[currentMode].brightness)) + { FastLED.setBrightness(i); delay(1); FastLED.show(); @@ -58,9 +69,12 @@ void changePower() { FastLED.setBrightness(modes[currentMode].brightness); delay(2); FastLED.show(); - } else { + } + else + { effectsTick(); - for (int i = modes[currentMode].brightness; i > 8; i -= 8) { + for (uint8_t i = modes[currentMode].brightness; i > 0; i = constrain(i - 8, 0, modes[currentMode].brightness)) + { FastLED.setBrightness(i); delay(1); FastLED.show(); diff --git a/firmware/GyverLamp_v1.4/effects.ino b/firmware/GyverLamp_v1.4/effects.ino index a536e6f..0975fbf 100644 --- a/firmware/GyverLamp_v1.4/effects.ino +++ b/firmware/GyverLamp_v1.4/effects.ino @@ -1,8 +1,10 @@ -// ================================= ЭФФЕКТЫ ==================================== +// ============= ЭФФЕКТЫ =============== -// --------------------------------- конфетти ------------------------------------ -void sparklesRoutine() { - for (byte i = 0; i < modes[0].scale; i++) { +// ------------- конфетти -------------- +void sparklesRoutine() +{ + for (byte i = 0; i < modes[0].scale; i++) + { byte x = random(0, WIDTH); byte y = random(0, HEIGHT); if (getPixColorXY(x, y) == 0) @@ -12,34 +14,42 @@ void sparklesRoutine() { } // функция плавного угасания цвета для всех пикселей -void fader(byte step) { - for (byte i = 0; i < WIDTH; i++) { - for (byte j = 0; j < HEIGHT; j++) { +void fader(byte step) +{ + for (byte i = 0; i < WIDTH; i++) + { + for (byte j = 0; j < HEIGHT; j++) + { fadePixel(i, j, step); } } } -void fadePixel(byte i, byte j, byte step) { // новый фейдер - int pixelNum = getPixelNumber(i, j); + +void fadePixel(byte i, byte j, byte step) // новый фейдер +{ + int32_t pixelNum = getPixelNumber(i, j); if (getPixColor(pixelNum) == 0) return; if (leds[pixelNum].r >= 30 || leds[pixelNum].g >= 30 || - leds[pixelNum].b >= 30) { + leds[pixelNum].b >= 30) + { leds[pixelNum].fadeToBlackBy(step); - } else { + } + else + { leds[pixelNum] = 0; } } -// -------------------------------------- огонь --------------------------------------------- -// эффект "огонь" -#define SPARKLES 1 // вылетающие угольки вкл выкл +// ------------- огонь ----------------- +#define SPARKLES 1 // вылетающие угольки вкл выкл unsigned char line[WIDTH]; -int pcnt = 0; +int32_t pcnt = 0; //these values are substracetd from the generated values to give a shape to the animation -const unsigned char valueMask[8][16] PROGMEM = { +const unsigned char valueMask[8][16] PROGMEM = +{ {32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 }, {64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 }, {96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 }, @@ -52,7 +62,8 @@ const unsigned char valueMask[8][16] PROGMEM = { //these are the hues for the fire, //should be between 0 (red) to about 25 (yellow) -const unsigned char hueMask[8][16] PROGMEM = { +const unsigned char hueMask[8][16] PROGMEM = +{ {1 , 11, 19, 25, 25, 22, 11, 1 , 1 , 11, 19, 25, 25, 22, 11, 1 }, {1 , 8 , 13, 19, 25, 19, 8 , 1 , 1 , 8 , 13, 19, 25, 19, 8 , 1 }, {1 , 8 , 13, 16, 19, 16, 8 , 1 , 1 , 8 , 13, 16, 19, 16, 8 , 1 }, @@ -63,13 +74,16 @@ const unsigned char hueMask[8][16] PROGMEM = { {0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 } }; -void fireRoutine() { - if (loadingFlag) { +void fireRoutine() +{ + if (loadingFlag) + { loadingFlag = false; //FastLED.clear(); generateLine(); } - if (pcnt >= 100) { + if (pcnt >= 100) + { shiftUp(); generateLine(); pcnt = 0; @@ -79,16 +93,20 @@ void fireRoutine() { } // Randomly generate the next line (matrix row) - -void generateLine() { - for (uint8_t x = 0; x < WIDTH; x++) { +void generateLine() +{ + for (uint8_t x = 0; x < WIDTH; x++) + { line[x] = random(64, 255); } } -void shiftUp() { - for (uint8_t y = HEIGHT - 1; y > 0; y--) { - for (uint8_t x = 0; x < WIDTH; x++) { +void shiftUp() +{ + for (uint8_t y = HEIGHT - 1; y > 0; y--) + { + for (uint8_t x = 0; x < WIDTH; x++) + { uint8_t newX = x; if (x > 15) newX = x - 15; if (y > 7) continue; @@ -96,7 +114,8 @@ void shiftUp() { } } - for (uint8_t x = 0; x < WIDTH; x++) { + for (uint8_t x = 0; x < WIDTH; x++) + { uint8_t newX = x; if (x > 15) newX = x - 15; matrixValue[0][newX] = line[newX]; @@ -106,98 +125,118 @@ void shiftUp() { // draw a frame, interpolating between 2 "key frames" // @param pcnt percentage of interpolation -void drawFrame(int pcnt) { - int nextv; +void drawFrame(int32_t pcnt) +{ + int32_t nextv; //each row interpolates with the one before it - for (unsigned char y = HEIGHT - 1; y > 0; y--) { - for (unsigned char x = 0; x < WIDTH; x++) { + for (unsigned char y = HEIGHT - 1; y > 0; y--) + { + for (unsigned char x = 0; x < WIDTH; x++) + { uint8_t newX = x; if (x > 15) newX = x - 15; - if (y < 8) { + if (y < 8) + { nextv = (((100.0 - pcnt) * matrixValue[y][newX] + pcnt * matrixValue[y - 1][newX]) / 100.0) - pgm_read_byte(&(valueMask[y][newX])); CRGB color = CHSV( - modes[1].scale * 2.5 + pgm_read_byte(&(hueMask[y][newX])), // H - 255, // S - (uint8_t)max(0, nextv) // V - ); + modes[1].scale * 2.5 + pgm_read_byte(&(hueMask[y][newX])), // H + 255, // S + (uint8_t)max(0, nextv) // V + ); leds[getPixelNumber(x, y)] = color; - } else if (y == 8 && SPARKLES) { + } + else if (y == 8 && SPARKLES) + { if (random(0, 20) == 0 && getPixColorXY(x, y - 1) != 0) drawPixelXY(x, y, getPixColorXY(x, y - 1)); else drawPixelXY(x, y, 0); - } else if (SPARKLES) { - + } + else if (SPARKLES) + { // старая версия для яркости if (getPixColorXY(x, y - 1) > 0) drawPixelXY(x, y, getPixColorXY(x, y - 1)); else drawPixelXY(x, y, 0); - } } } //first row interpolates with the "next" line - for (unsigned char x = 0; x < WIDTH; x++) { + for (unsigned char x = 0; x < WIDTH; x++) + { uint8_t newX = x; if (x > 15) newX = x - 15; CRGB color = CHSV( - modes[1].scale * 2.5 + pgm_read_byte(&(hueMask[0][newX])), // H - 255, // S - (uint8_t)(((100.0 - pcnt) * matrixValue[0][newX] + pcnt * line[newX]) / 100.0) // V - ); + modes[1].scale * 2.5 + pgm_read_byte(&(hueMask[0][newX])), // H + 255, // S + (uint8_t)(((100.0 - pcnt) * matrixValue[0][newX] + pcnt * line[newX]) / 100.0) // V + ); leds[getPixelNumber(newX, 0)] = color; } } byte hue; -// ---------------------------------------- радуга ------------------------------------------ -void rainbowVertical() { +// ------------- радуга ---------------- +void rainbowVertical() +{ hue += 2; - for (byte j = 0; j < HEIGHT; j++) { + for (byte j = 0; j < HEIGHT; j++) + { CHSV thisColor = CHSV((byte)(hue + j * modes[2].scale), 255, 255); for (byte i = 0; i < WIDTH; i++) drawPixelXY(i, j, thisColor); } } -void rainbowHorizontal() { + +void rainbowHorizontal() +{ hue += 2; - for (byte i = 0; i < WIDTH; i++) { + for (byte i = 0; i < WIDTH; i++) + { CHSV thisColor = CHSV((byte)(hue + i * modes[3].scale), 255, 255); for (byte j = 0; j < HEIGHT; j++) - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = thisColor; } } -// ---------------------------------------- ЦВЕТА ------------------------------------------ -void colorsRoutine() { +// ------------- цвета ----------------- +void colorsRoutine() +{ hue += modes[4].scale; - for (int i = 0; i < NUM_LEDS; i++) { + for (int32_t i = 0; i < NUM_LEDS; i++) + { leds[i] = CHSV(hue, 255, 255); } } -// --------------------------------- ЦВЕТ ------------------------------------ -void colorRoutine() { - for (int i = 0; i < NUM_LEDS; i++) { +// ------------- цвет ------------------ +void colorRoutine() +{ + for (int32_t i = 0; i < NUM_LEDS; i++) + { leds[i] = CHSV(modes[14].scale * 2.5, 255, 255); } } -// ------------------------------ снегопад 2.0 -------------------------------- -void snowRoutine() { +// ------------- снегопад 2.0 ---------- +void snowRoutine() +{ // сдвигаем всё вниз - for (byte x = 0; x < WIDTH; x++) { - for (byte y = 0; y < HEIGHT - 1; y++) { + for (byte x = 0; x < WIDTH; x++) + { + for (byte y = 0; y < HEIGHT - 1; y++) + { drawPixelXY(x, y, getPixColorXY(x, y + 1)); } } - for (byte x = 0; x < WIDTH; x++) { + for (byte x = 0; x < WIDTH; x++) + { // заполняем случайно верхнюю строку // а также не даём двум блокам по вертикали вместе быть if (getPixColorXY(x, HEIGHT - 2) == 0 && (random(0, modes[15].scale) == 0)) @@ -207,9 +246,11 @@ void snowRoutine() { } } -// ------------------------------ МАТРИЦА ------------------------------ -void matrixRoutine() { - for (byte x = 0; x < WIDTH; x++) { +// ------------- матрица --------------- +void matrixRoutine() +{ + for (byte x = 0; x < WIDTH; x++) + { // заполняем случайно верхнюю строку uint32_t thisColor = getPixColorXY(x, HEIGHT - 1); if (thisColor == 0) @@ -221,29 +262,34 @@ void matrixRoutine() { } // сдвигаем всё вниз - for (byte x = 0; x < WIDTH; x++) { - for (byte y = 0; y < HEIGHT - 1; y++) { + for (byte x = 0; x < WIDTH; x++) + { + for (byte y = 0; y < HEIGHT - 1; y++) + { drawPixelXY(x, y, getPixColorXY(x, y + 1)); } } } -// ----------------------------- СВЕТЛЯКИ ------------------------------ +// ------------- светляки -------------- #define LIGHTERS_AM 100 -int lightersPos[2][LIGHTERS_AM]; +int32_t lightersPos[2][LIGHTERS_AM]; int8_t lightersSpeed[2][LIGHTERS_AM]; CHSV lightersColor[LIGHTERS_AM]; byte loopCounter; -int angle[LIGHTERS_AM]; -int speedV[LIGHTERS_AM]; +int32_t angle[LIGHTERS_AM]; +int32_t speedV[LIGHTERS_AM]; int8_t angleSpeed[LIGHTERS_AM]; -void lightersRoutine() { - if (loadingFlag) { +void lightersRoutine() +{ + if (loadingFlag) + { loadingFlag = false; randomSeed(millis()); - for (byte i = 0; i < LIGHTERS_AM; i++) { + for (byte i = 0; i < LIGHTERS_AM; i++) + { lightersPos[0][i] = random(0, WIDTH * 10); lightersPos[1][i] = random(0, HEIGHT * 10); lightersSpeed[0][i] = random(-10, 10); @@ -253,8 +299,10 @@ void lightersRoutine() { } FastLED.clear(); if (++loopCounter > 20) loopCounter = 0; - for (byte i = 0; i < modes[17].scale; i++) { - if (loopCounter == 0) { // меняем скорость каждые 255 отрисовок + for (byte i = 0; i < modes[17].scale; i++) + { + if (loopCounter == 0) // меняем скорость каждые 255 отрисовок + { lightersSpeed[0][i] += random(-3, 4); lightersSpeed[1][i] += random(-3, 4); lightersSpeed[0][i] = constrain(lightersSpeed[0][i], -20, 20); @@ -267,11 +315,13 @@ void lightersRoutine() { 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) { + if (lightersPos[1][i] < 0) + { lightersPos[1][i] = 0; lightersSpeed[1][i] = -lightersSpeed[1][i]; } - if (lightersPos[1][i] >= (HEIGHT - 1) * 10) { + if (lightersPos[1][i] >= (HEIGHT - 1) * 10) + { lightersPos[1][i] = (HEIGHT - 1) * 10; lightersSpeed[1][i] = -lightersSpeed[1][i]; } @@ -280,11 +330,14 @@ void lightersRoutine() { } /* - void lightersRoutine() { - if (loadingFlag) { +void lightersRoutine() +{ + if (loadingFlag) + { loadingFlag = false; randomSeed(millis()); - for (byte i = 0; i < LIGHTERS_AM; i++) { + for (byte i = 0; i < LIGHTERS_AM; i++) + { lightersPos[0][i] = random(0, WIDTH * 10); lightersPos[1][i] = random(0, HEIGHT * 10); @@ -298,8 +351,10 @@ void lightersRoutine() { FastLED.clear(); if (++loopCounter > 20) loopCounter = 0; - for (byte i = 0; i < modes[17].scale; i++) { - if (loopCounter == 0) { // меняем скорость каждые 255 отрисовок + for (byte i = 0; i < modes[17].scale; i++) + { + if (loopCounter == 0) // меняем скорость каждые 255 отрисовок + { angleSpeed[i] += random(-3, 4); angleSpeed[i] = constrain(angleSpeed[i], -15, 15); } @@ -310,17 +365,23 @@ void lightersRoutine() { 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) { + if (lightersPos[1][i] < 0) + { lightersPos[1][i] = 0; angle[i] = 360 - angle[i]; - } else { + } + else + { angle[i] += angleSpeed[i]; } - if (lightersPos[1][i] >= (HEIGHT - 1) * 10) { + if (lightersPos[1][i] >= (HEIGHT - 1) * 10) + { lightersPos[1][i] = (HEIGHT - 1) * 10; angle[i] = 360 - angle[i]; - } else { + } + else + { angle[i] += angleSpeed[i]; } @@ -329,5 +390,5 @@ void lightersRoutine() { drawPixelXY(lightersPos[0][i] / 10, lightersPos[1][i] / 10, lightersColor[i]); } - } +} */ diff --git a/firmware/GyverLamp_v1.4/noiseEffects.ino b/firmware/GyverLamp_v1.4/noiseEffects.ino index 06c14cb..46303b6 100644 --- a/firmware/GyverLamp_v1.4/noiseEffects.ino +++ b/firmware/GyverLamp_v1.4/noiseEffects.ino @@ -1,4 +1,4 @@ -// ******************* НАСТРОЙКИ ***************** +// ************* НАСТРОЙКИ ************* // "масштаб" эффектов. Чем меньше, тем крупнее! #define MADNESS_SCALE 100 #define CLOUD_SCALE 30 @@ -10,15 +10,15 @@ #define FOREST_SCALE 120 #define OCEAN_SCALE 90 -// ***************** ДЛЯ РАЗРАБОТЧИКОВ ****************** +// ************* ДЛЯ РАЗРАБОТЧИКОВ ***** // The 16 bit version of our coordinates static uint16_t x; static uint16_t y; static uint16_t z; -uint16_t speed = 20; // speed is set dynamically once we've started up -uint16_t scale = 30; // scale is set dynamically once we've started up +uint16_t speed = 20; // speed is set dynamically once we've started up +uint16_t scale = 30; // scale is set dynamically once we've started up // This is the array that we keep our computed noise values in #define MAX_DIMENSION (max(WIDTH, HEIGHT)) @@ -32,23 +32,30 @@ CRGBPalette16 currentPalette( PartyColors_p ); uint8_t colorLoop = 1; uint8_t ihue = 0; -void madnessNoise() { - if (loadingFlag) { +void madnessNoise() +{ + if (loadingFlag) + { loadingFlag = false; scale = modes[5].scale; speed = modes[5].speed; } fillnoise8(); - for (int i = 0; i < WIDTH; i++) { - for (int j = 0; j < HEIGHT; j++) { + for (uint8_t i = 0; i < WIDTH; i++) + { + for (uint8_t j = 0; j < HEIGHT; j++) + { CRGB thisColor = CHSV(noise[j][i], 255, noise[i][j]); - drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); + drawPixelXY(i, j, thisColor); //leds[getPixelNumber(i, j)] = CHSV(noise[j][i], 255, noise[i][j]); } } ihue += 1; } -void rainbowNoise() { - if (loadingFlag) { + +void rainbowNoise() +{ + if (loadingFlag) + { loadingFlag = false; currentPalette = RainbowColors_p; scale = modes[9].scale; @@ -57,8 +64,11 @@ void rainbowNoise() { } fillNoiseLED(); } -void rainbowStripeNoise() { - if (loadingFlag) { + +void rainbowStripeNoise() +{ + if (loadingFlag) + { loadingFlag = false; currentPalette = RainbowStripeColors_p; scale = modes[10].scale; @@ -67,8 +77,11 @@ void rainbowStripeNoise() { } fillNoiseLED(); } -void zebraNoise() { - if (loadingFlag) { + +void zebraNoise() +{ + if (loadingFlag) + { loadingFlag = false; // 'black out' all 16 palette entries... fill_solid( currentPalette, 16, CRGB::Black); @@ -83,8 +96,11 @@ void zebraNoise() { } fillNoiseLED(); } -void forestNoise() { - if (loadingFlag) { + +void forestNoise() +{ + if (loadingFlag) + { loadingFlag = false; currentPalette = ForestColors_p; scale = modes[12].scale; @@ -93,8 +109,11 @@ void forestNoise() { } fillNoiseLED(); } -void oceanNoise() { - if (loadingFlag) { + +void oceanNoise() +{ + if (loadingFlag) + { loadingFlag = false; currentPalette = OceanColors_p; scale = modes[13].scale; @@ -104,8 +123,11 @@ void oceanNoise() { fillNoiseLED(); } -void plasmaNoise() { - if (loadingFlag) { + +void plasmaNoise() +{ + if (loadingFlag) + { loadingFlag = false; currentPalette = PartyColors_p; scale = modes[8].scale; @@ -114,8 +136,11 @@ void plasmaNoise() { } fillNoiseLED(); } -void cloudNoise() { - if (loadingFlag) { + +void cloudNoise() +{ + if (loadingFlag) + { loadingFlag = false; currentPalette = CloudColors_p; scale = modes[6].scale; @@ -124,8 +149,11 @@ void cloudNoise() { } fillNoiseLED(); } -void lavaNoise() { - if (loadingFlag) { + +void lavaNoise() +{ + if (loadingFlag) + { loadingFlag = false; currentPalette = LavaColors_p; scale = modes[7].scale; @@ -135,23 +163,28 @@ void lavaNoise() { fillNoiseLED(); } -// ******************* СЛУЖЕБНЫЕ ******************* -void fillNoiseLED() { +// ************* СЛУЖЕБНЫЕ ************* +void fillNoiseLED() +{ uint8_t dataSmoothing = 0; - if ( speed < 50) { + if ( speed < 50) + { dataSmoothing = 200 - (speed * 4); } - for (int i = 0; i < MAX_DIMENSION; i++) { - int ioffset = scale * i; - for (int j = 0; j < MAX_DIMENSION; j++) { - int joffset = scale * j; + for (uint8_t i = 0; i < MAX_DIMENSION; i++) + { + int32_t ioffset = scale * i; + for (uint8_t j = 0; j < MAX_DIMENSION; j++) + { + int32_t joffset = scale * j; uint8_t data = inoise8(x + ioffset, y + joffset, z); data = qsub8(data, 16); data = qadd8(data, scale8(data, 39)); - if ( dataSmoothing ) { + if ( dataSmoothing ) + { uint8_t olddata = noise[i][j]; uint8_t newdata = scale8( olddata, dataSmoothing) + scale8( data, 256 - dataSmoothing); data = newdata; @@ -166,33 +199,42 @@ void fillNoiseLED() { x += speed / 8; y -= speed / 16; - for (int i = 0; i < WIDTH; i++) { - for (int j = 0; j < HEIGHT; j++) { + for (uint8_t i = 0; i < WIDTH; i++) + { + for (uint8_t j = 0; j < HEIGHT; j++) + { uint8_t index = noise[j][i]; uint8_t bri = noise[i][j]; // if this palette is a 'loop', add a slowly-changing base value - if ( colorLoop) { + if ( colorLoop) + { index += ihue; } // brighten up, as the color palette itself often contains the // light/dark dynamic range desired - if ( bri > 127 ) { + if ( bri > 127 ) + { bri = 255; - } else { + } + else + { bri = dim8_raw( bri * 2); } CRGB color = ColorFromPalette( currentPalette, index, bri); - drawPixelXY(i, j, color); //leds[getPixelNumber(i, j)] = color; + drawPixelXY(i, j, color); //leds[getPixelNumber(i, j)] = color; } } ihue += 1; } -void fillnoise8() { - for (int i = 0; i < MAX_DIMENSION; i++) { - int ioffset = scale * i; - for (int j = 0; j < MAX_DIMENSION; j++) { - int joffset = scale * j; +void fillnoise8() +{ + for (uint8_t i = 0; i < MAX_DIMENSION; i++) + { + int32_t ioffset = scale * i; + for (uint8_t j = 0; j < MAX_DIMENSION; j++) + { + int32_t joffset = scale * j; noise[i][j] = inoise8(x + ioffset, y + joffset, z); } } diff --git a/firmware/GyverLamp_v1.4/parsing.ino b/firmware/GyverLamp_v1.4/parsing.ino index dc955bb..49325ad 100644 --- a/firmware/GyverLamp_v1.4/parsing.ino +++ b/firmware/GyverLamp_v1.4/parsing.ino @@ -1,15 +1,35 @@ -void parseUDP() { - int packetSize = Udp.parsePacket(); - if (packetSize) { - int n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); +void parseUDP() +{ + int32_t packetSize = Udp.parsePacket(); + + if (packetSize) + { + int32_t n = Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); packetBuffer[n] = 0; inputBuffer = packetBuffer; - if (inputBuffer.startsWith("DEB")) { - inputBuffer = "OK " + timeClient.getFormattedTime(); - } else if (inputBuffer.startsWith("GET")) { + #ifdef GENERAL_DEBUG + Serial.print("Inbound UDP packet: "); + Serial.println(inputBuffer); + #endif + + if (inputBuffer.startsWith("DEB")) + { + inputBuffer = + #ifdef USE_NTP + "OK " + timeClient.getFormattedTime(); + #else + "OK --:--"; + #endif + } + + else if (inputBuffer.startsWith("GET")) + { sendCurrent(); - } else if (inputBuffer.startsWith("EFF")) { + } + + else if (inputBuffer.startsWith("EFF")) + { saveEEPROM(); currentMode = (byte)inputBuffer.substring(3).toInt(); loadingFlag = true; @@ -17,40 +37,71 @@ void parseUDP() { delay(1); sendCurrent(); FastLED.setBrightness(modes[currentMode].brightness); - } else if (inputBuffer.startsWith("BRI")) { - modes[currentMode].brightness = inputBuffer.substring(3).toInt(); + } + + else if (inputBuffer.startsWith("BRI")) + { + #ifdef GENERAL_DEBUG + Serial.printf("New brightness value: %d\n", inputBuffer.substring(3).toInt()); + #endif + + modes[currentMode].brightness = constrain(inputBuffer.substring(3).toInt(), 0, 255); FastLED.setBrightness(modes[currentMode].brightness); settChanged = true; eepromTimer = millis(); - } else if (inputBuffer.startsWith("SPD")) { + + #ifdef GENERAL_DEBUG + Serial.printf("modes[currentMode].brightness: %d\n", modes[currentMode].brightness); + #endif + } + + else if (inputBuffer.startsWith("SPD")) + { modes[currentMode].speed = inputBuffer.substring(3).toInt(); loadingFlag = true; settChanged = true; eepromTimer = millis(); - } else if (inputBuffer.startsWith("SCA")) { + } + + else if (inputBuffer.startsWith("SCA")) + { modes[currentMode].scale = inputBuffer.substring(3).toInt(); loadingFlag = true; settChanged = true; eepromTimer = millis(); - } else if (inputBuffer.startsWith("P_ON")) { + } + + else if (inputBuffer.startsWith("P_ON")) + { ONflag = true; changePower(); sendCurrent(); - } else if (inputBuffer.startsWith("P_OFF")) { + } + + else if (inputBuffer.startsWith("P_OFF")) + { ONflag = false; changePower(); sendCurrent(); - } else if (inputBuffer.startsWith("ALM_SET")) { + } + + else if (inputBuffer.startsWith("ALM_SET")) + { byte alarmNum = (char)inputBuffer[7] - '0'; alarmNum -= 1; - if (inputBuffer.indexOf("ON") != -1) { + if (inputBuffer.indexOf("ON") != -1) + { alarm[alarmNum].state = true; inputBuffer = "alm #" + String(alarmNum + 1) + " ON"; - } else if (inputBuffer.indexOf("OFF") != -1) { + } + else if (inputBuffer.indexOf("OFF") != -1) + { alarm[alarmNum].state = false; inputBuffer = "alm #" + String(alarmNum + 1) + " OFF"; - } else { - int almTime = inputBuffer.substring(8).toInt(); + } + else + { + int32_t almTime = inputBuffer.substring(8).toInt(); alarm[alarmNum].time = almTime; byte hour = floor(almTime / 60); byte minute = almTime - hour * 60; @@ -59,9 +110,15 @@ void parseUDP() { ":" + String(minute); } saveAlarm(alarmNum); - } else if (inputBuffer.startsWith("ALM_GET")) { + } + + else if (inputBuffer.startsWith("ALM_GET")) + { sendAlarms(); - } else if (inputBuffer.startsWith("DAWN")) { + } + + else if (inputBuffer.startsWith("DAWN")) + { dawnMode = inputBuffer.substring(4).toInt() - 1; saveDawnMmode(); } @@ -71,10 +128,17 @@ void parseUDP() { Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); Udp.write(reply); Udp.endPacket(); + + #ifdef GENERAL_DEBUG + Serial.print("Outbound UDP packet: "); + Serial.println(reply); + Serial.println(); + #endif } } -void sendCurrent() { +void sendCurrent() +{ inputBuffer = "CURR"; inputBuffer += " "; inputBuffer += String(currentMode); @@ -88,7 +152,8 @@ void sendCurrent() { inputBuffer += String(ONflag); } -void sendAlarms() { +void sendAlarms() +{ inputBuffer = "ALMS "; for (byte i = 0; i < 7; i++) { inputBuffer += String(alarm[i].state); diff --git a/firmware/GyverLamp_v1.4/time.ino b/firmware/GyverLamp_v1.4/time.ino index a746d55..30ffac8 100644 --- a/firmware/GyverLamp_v1.4/time.ino +++ b/firmware/GyverLamp_v1.4/time.ino @@ -1,19 +1,25 @@ -void timeTick() { - if (ESP_MODE == 1) { - if (timeTimer.isReady()) { +#ifdef USE_NTP +void timeTick() +{ + if (ESP_MODE == 1) + { + if (timeTimer.isReady()) + { timeClient.update(); byte thisDay = timeClient.getDay(); - if (thisDay == 0) thisDay = 7; // воскресенье это 0 + if (thisDay == 0) thisDay = 7; // воскресенье это 0 thisDay--; thisTime = timeClient.getHours() * 60 + timeClient.getMinutes(); // проверка рассвета - if (alarm[thisDay].state && // день будильника - thisTime >= (alarm[thisDay].time - dawnOffsets[dawnMode]) && // позже начала - thisTime < (alarm[thisDay].time + DAWN_TIMEOUT) ) { // раньше конца + минута - if (!manualOff) { + if (alarm[thisDay].state && // день будильника + thisTime >= (alarm[thisDay].time - dawnOffsets[dawnMode]) && // позже начала + thisTime < (alarm[thisDay].time + DAWN_TIMEOUT)) // раньше конца + минута + { + if (!manualOff) + { // величина рассвета 0-255 - int dawnPosition = 255 * ((float)(thisTime - (alarm[thisDay].time - dawnOffsets[dawnMode])) / dawnOffsets[dawnMode]); + int32_t dawnPosition = 255 * ((float)(thisTime - (alarm[thisDay].time - dawnOffsets[dawnMode])) / dawnOffsets[dawnMode]); dawnPosition = constrain(dawnPosition, 0, 255); CHSV dawnColor = CHSV(map(dawnPosition, 0, 255, 10, 35), map(dawnPosition, 0, 255, 255, 170), @@ -23,14 +29,17 @@ void timeTick() { FastLED.show(); dawnFlag = true; } - } else { - if (dawnFlag) { + } + else + { + if (dawnFlag) + { dawnFlag = false; manualOff = false; FastLED.setBrightness(modes[currentMode].brightness); } } - } } } +#endif USE_NTP diff --git a/firmware/GyverLamp_v1.4/timerMinim.h b/firmware/GyverLamp_v1.4/timerMinim.h index 643a7f6..8e43a7c 100644 --- a/firmware/GyverLamp_v1.4/timerMinim.h +++ b/firmware/GyverLamp_v1.4/timerMinim.h @@ -3,34 +3,41 @@ class timerMinim { public: - timerMinim(uint32_t interval); // объявление таймера с указанием интервала - void setInterval(uint32_t interval); // установка интервала работы таймера - boolean isReady(); // возвращает true, когда пришло время. Сбрасывается в false сам (AUTO) или вручную (MANUAL) - void reset(); // ручной сброс таймера на установленный интервал + timerMinim(uint32_t interval); // объявление таймера с указанием интервала + void setInterval(uint32_t interval); // установка интервала работы таймера + boolean isReady(); // возвращает true, когда пришло время. Сбрасывается в false сам (AUTO) или вручную (MANUAL) + void reset(); // ручной сброс таймера на установленный интервал private: uint32_t _timer = 0; uint32_t _interval = 0; }; -timerMinim::timerMinim(uint32_t interval) { +timerMinim::timerMinim(uint32_t interval) +{ _interval = interval; _timer = millis(); } -void timerMinim::setInterval(uint32_t interval) { +void timerMinim::setInterval(uint32_t interval) +{ _interval = interval; } -boolean timerMinim::isReady() { - if ((long)millis() - _timer >= _interval) { +boolean timerMinim::isReady() +{ + if ((long)millis() - _timer >= _interval) + { _timer = millis(); return true; - } else { + } + else + { return false; } } -void timerMinim::reset() { +void timerMinim::reset() +{ _timer = millis(); } diff --git a/firmware/GyverLamp_v1.4/utility.ino b/firmware/GyverLamp_v1.4/utility.ino index 6110de5..7bf0b73 100644 --- a/firmware/GyverLamp_v1.4/utility.ino +++ b/firmware/GyverLamp_v1.4/utility.ino @@ -1,34 +1,39 @@ // служебные функции // залить все -void fillAll(CRGB color) { - for (int i = 0; i < NUM_LEDS; i++) { +void fillAll(CRGB color) +{ + for (int32_t i = 0; i < NUM_LEDS; i++) { leds[i] = color; } } // функция отрисовки точки по координатам X Y -void drawPixelXY(int8_t x, int8_t y, CRGB color) { +void drawPixelXY(int8_t x, int8_t y, CRGB color) +{ if (x < 0 || x > WIDTH - 1 || y < 0 || y > HEIGHT - 1) return; - int thisPixel = getPixelNumber(x, y) * SEGMENTS; - for (byte i = 0; i < SEGMENTS; i++) { + int32_t thisPixel = getPixelNumber(x, y) * SEGMENTS; + for (uint8_t i = 0; i < SEGMENTS; i++) + { leds[thisPixel + i] = color; } } // функция получения цвета пикселя по его номеру -uint32_t getPixColor(int thisSegm) { - int thisPixel = thisSegm * SEGMENTS; +uint32_t getPixColor(uint32_t thisSegm) +{ + uint32_t thisPixel = thisSegm * SEGMENTS; if (thisPixel < 0 || thisPixel > NUM_LEDS - 1) return 0; - return (((uint32_t)leds[thisPixel].r << 16) | ((long)leds[thisPixel].g << 8 ) | (long)leds[thisPixel].b); + return (((uint32_t)leds[thisPixel].r << 16) | ((uint32_t)leds[thisPixel].g << 8 ) | (uint32_t)leds[thisPixel].b); } // функция получения цвета пикселя в матрице по его координатам -uint32_t getPixColorXY(int8_t x, int8_t y) { +uint32_t getPixColorXY(int8_t x, int8_t y) +{ return getPixColor(getPixelNumber(x, y)); } -// **************** НАСТРОЙКА МАТРИЦЫ **************** +// ************* НАСТРОЙКА МАТРИЦЫ ***** #if (CONNECTION_ANGLE == 0 && STRIP_DIRECTION == 0) #define _WIDTH WIDTH #define THIS_X x @@ -78,10 +83,14 @@ uint32_t getPixColorXY(int8_t x, int8_t y) { #endif // получить номер пикселя в ленте по координатам -uint16_t getPixelNumber(int8_t x, int8_t y) { - if ((THIS_Y % 2 == 0) || MATRIX_TYPE) { // если чётная строка +uint16_t getPixelNumber(int8_t x, int8_t y) +{ + if ((THIS_Y % 2 == 0) || MATRIX_TYPE) // если чётная строка + { return (THIS_Y * _WIDTH + THIS_X); - } else { // если нечётная строка + } + else // если нечётная строка + { return (THIS_Y * _WIDTH + _WIDTH - THIS_X - 1); } }