Merge branch 'main' into platformio

This commit is contained in:
Alex
2021-07-14 00:21:22 +03:00
committed by GitHub
14 changed files with 197 additions and 146 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -1,22 +1,30 @@
void sendUDP(char *data) { void sendUDP(char *data) {
Udp.beginPacket(deviceIP, portNum + cfg.group); Udp.beginPacket(broadIP, portNum + cfg.group);
Udp.write(data); Udp.write(data);
Udp.endPacket(); Udp.endPacket();
} }
void sendUDP(byte cmd, int data1 = 0, int data2 = 0, int data3 = 0) { void sendUDP(byte cmd, int data1 = 0, int data2 = 0, int data3 = 0) {
char reply[20] = ""; char reply[20] = "";
mString packet(reply, sizeof(reply)); mString packet(reply);
packet = packet + "GL," + cmd + ',' + data1 + ',' + data2 + ',' + data3; packet = packet + "GL," + cmd + ',' + data1 + ',' + data2 + ',' + data3;
sendUDP(reply); sendUDP(reply);
//DEBUG("Sending: "); //DEBUG("Sending: ");
//DEBUGLN(cmd); //DEBUGLN(cmd);
} }
void iAmOnline() {
if (onlineTmr.isReady()) {
char reply[10] = "GL_ONL";
mString packet(reply);
packet += cfg.curPreset;
sendUDP(reply);
}
}
void restartUDP() { void restartUDP() {
Udp.stop(); Udp.stop();
Udp.begin(portNum + cfg.group); Udp.begin(portNum + cfg.group);
deviceIP = WiFi.localIP(); broadIP = WiFi.localIP();
deviceIP[3] = 255; broadIP[3] = 255;
DEBUG("UDP port: "); DEBUG("UDP port: ");
DEBUGLN(portNum + cfg.group); DEBUGLN(portNum + cfg.group);
} }
@@ -60,7 +68,7 @@ void drawDots(int X, int Y, CRGB color) {
} }
void drawClock(byte Y, byte speed, CRGB color) { void drawClock(byte Y, byte speed, CRGB color) {
if (cfg.deviceType == 1 || cfg.width < 16) return; // лента или мелкая матрица - на выход if (cfg.deviceType == 1) return; // лента - на выход
byte h1, h2, m1, m2; byte h1, h2, m1, m2;
if (gotNTP || gotTime) { if (gotNTP || gotTime) {
h1 = now.hour / 10; h1 = now.hour / 10;
@@ -71,7 +79,9 @@ void drawClock(byte Y, byte speed, CRGB color) {
} else { } else {
h1 = h2 = m1 = m2 = 10; h1 = h2 = m1 = m2 = 10;
} }
int pos = cfg.width - (now.weekMs / (speed * 2)) % (cfg.width + 26); int pos;
if (speed == 0) pos = cfg.width / 2 - 13;
else pos = cfg.width - (now.weekMs / (speed * 2)) % (cfg.width + 26);
drawDigit(h1, pos, Y, color); drawDigit(h1, pos, Y, color);
drawDigit(h2, pos + 6, Y, color); drawDigit(h2, pos + 6, Y, color);
if (now.getMs() < 500) drawDots(pos + 12, Y, color); if (now.getMs() < 500) drawDots(pos + 12, Y, color);

View File

@@ -1,73 +1,27 @@
/* /*
Версия 0.19b ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ!
Минимальная версия приложения 1.17!!! ДЛЯ КОМПИЛЯЦИИ ПРОШИВКИ ПОД NODEMCU/WEMOS/ESP01/ESP12 ВЫБИРАТЬ
Почищен мусор, оптимизация, повышена стабильность и производительность Инструменты / Плата Generic ESP8266
Мигает теперь 16 светиков Инструменты / Flash Size 4MB (FS:2MB OTA)
Снова переделана сетевая политика, упрощён и сильно ускорен парсинг CPU Frequency / 160 MHz (рекомендуется для стабильности светомузыки!!!)
Изменены пределы по светодиодам, что сильно увеличило производительность При прошивке с других прошивок лампы поставить: Инструменты/Erase Flash/All Flash Contents
Выключенная (программно) лампа не принимает сервисные команды кроме команды включиться ESP core 2.7.4+ http://arduino.esp8266.com/stable/package_esp8266com_index.json
Добавлены часы, в том числе в рассвет FastLED 3.4.0+ https://github.com/FastLED/FastLED/releases
Slave работает со светомузыкой сам, если не получает данные с мастера
Версия 0.18b
Уменьшена чувствительность хлопков
Увеличена плавность светомузыки
Переделана сетевая политика
Микрофон и датчик света опрашивает только мастер и отсылает данные слейвам своей группы
4 клика - включить первый режим
Отправка точного времени на лампу в режиме АР для работы рассвета и синхронизации эффектов
Версия 0.17b
Автосмена отключается 30 сек во время настройки режимов
Убрана кнопка upload в режимах
Лампа чуть мигает при получении данных
Кастом палитра работает на огне 2020
Вкл выкл двумя хлопками
Плавное выключение
Починил рассвет
Версия 0.16b
Исправлен масштаб огня 2020
Фикс невыключения рассвета
Версия 0.14b
Мелкие баги
Вернул искры огню
Добавлены палитры
Добавлен огонь 2020
Версия 0.13b
Улучшена стабильность
Версия 0.12b
Мелкие исправления
Версия 0.11b
Добавлен редактор палитр
Исправлены мелкие баги в эффектах
Переподключение к роутеру после сброса сети
Настройка ориентации матрицы из приложения
Переработан эффект "Частицы"
Добавлена скорость огня
Переключение на новый/выбранный режим при редактировании
Отправка времени из сервиса (для АР)
Выключение по таймеру теперь плавное
Добавлен рассвет
TODO:
плавная смена режимов
Mqtt?
Базовый пак
Эффект погода https://it4it.club/topic/40-esp8266-i-parsing-pogodyi-s-openweathermap/
*/ */
// ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! /*
// ДЛЯ КОМПИЛЯЦИИ ПРОШИВКИ ПОД NODEMCU/WEMOS/ESP01/ESP12 ВЫБИРАТЬ Версия 0.23b
// Инструменты/Плата Generic ESP8266 Поправлена яркость рассвета
// Инструменты/Flash Size 4MB (FS:2MB OTA)
// При прошивке с других прошивок лампы поставить: Инструменты/Erase Flash/All Flash Contents TODO:
// ESP core 2.7.4+ http://arduino.esp8266.com/stable/package_esp8266com_index.json Upload -> Применить
// FastLED 3.4.0+ https://github.com/FastLED/FastLED/releases Длина огня в светомуз?
Плавная смена режимов
Mqtt
Базовый пак
Поддержка куба
Погода https://it4it.club/topic/40-esp8266-i-parsing-pogodyi-s-openweathermap/
*/
// ---------- Настройки ----------- // ---------- Настройки -----------
#define GL_KEY "GL" // ключ сети #define GL_KEY "GL" // ключ сети
@@ -83,7 +37,7 @@
#define PHOT_VCC 14 // питание фоторезистора GPIO14 (D5 на wemos/node) #define PHOT_VCC 14 // питание фоторезистора GPIO14 (D5 на wemos/node)
// ------------ Лента ------------- // ------------ Лента -------------
#define STRIP_PIN 2 // пин ленты GPIO2 (D4 на wemos/node) #define STRIP_PIN 2 // пин ленты GPIO2 (D4 на wemos/node), GPIO5 (D1) для module
#define MAX_LEDS 300 // макс. светодиодов #define MAX_LEDS 300 // макс. светодиодов
#define STRIP_CHIP WS2812 // чип ленты #define STRIP_CHIP WS2812 // чип ленты
#define STRIP_COLOR GRB // порядок цветов в ленте #define STRIP_COLOR GRB // порядок цветов в ленте
@@ -101,30 +55,43 @@ const char AP_NameChar[] = "GyverLamp2";
const char WiFiPassword[] = "12345678"; const char WiFiPassword[] = "12345678";
// ------------ Прочее ------------- // ------------ Прочее -------------
#define GL_VERSION 19 // код версии прошивки #define GL_VERSION 23 // код версии прошивки
#define EE_TOUT 30000 // таймаут сохранения епром после изменения, мс #define EE_TOUT 30000 // таймаут сохранения епром после изменения, мс
#define DEBUG_SERIAL_LAMP // закомментируй чтобы выключить отладку (скорость 115200) #define DEBUG_SERIAL_LAMP // закомментируй чтобы выключить отладку (скорость 115200)
#define EE_KEY 55 // ключ сброса WiFi (измени для сброса всех настроек) #define EE_KEY 56 // ключ сброса eeprom
#define NTP_UPD_PRD 5 // период обновления времени с NTP сервера, минут #define NTP_UPD_PRD 5 // период обновления времени с NTP сервера, минут
//#define SKIP_WIFI // пропустить подключение к вафле (для отладки) //#define SKIP_WIFI // пропустить подключение к вафле (для отладки)
// ------------ БИЛДЕР ------------- // ------------ БИЛДЕР -------------
//#define MAX_LEDS 900 #define GL_BUILD 0 // 0: com 300, 1: com 900, 2: esp1 300, 3: esp1 900, 4: module 300, 5: module 900
// esp01 #if (GL_BUILD == 0)
//#define BTN_PIN 0 #elif (GL_BUILD == 1)
//#define STRIP_PIN 2 #define MAX_LEDS 900
//#define USE_ADC 0 #elif (GL_BUILD == 2)
#define MAX_LEDS 300
// GL2 module #define BTN_PIN 0
//#define STRIP_PIN 5 // GPIO5 на gl module (D1 на wemos/node) #define STRIP_PIN 2
#define USE_ADC 0
#elif (GL_BUILD == 3)
#define MAX_LEDS 900
#define BTN_PIN 0
#define STRIP_PIN 2
#define USE_ADC 0
#elif (GL_BUILD == 4)
#define MAX_LEDS 300
#define STRIP_PIN 5
#elif (GL_BUILD == 5)
#define MAX_LEDS 900
#define STRIP_PIN 5
#endif
// ---------- БИБЛИОТЕКИ ----------- // ---------- БИБЛИОТЕКИ -----------
#define FASTLED_ALLOW_INTERRUPTS 0 //#define FASTLED_ALLOW_INTERRUPTS 0
#include "data.h" // данные #include "data.h" // данные
#include "Time.h" // часы #include "Time.h" // часы
#include "TimeRandom.h" // случайные числа по времени #include "TimeRandom.h" // случайные числа по времени
#include "FastRandom.h" // быстрый рандом //#include "FastRandom.h" // быстрый рандом
#include "Button.h" // библа кнопки #include "Button.h" // библа кнопки
#include "palettes.h" // палитры #include "palettes.h" // палитры
#include "NTPClient-Gyver.h" // сервер времени (модиф) #include "NTPClient-Gyver.h" // сервер времени (модиф)
@@ -147,13 +114,13 @@ Palette pal;
WiFiServer server(80); WiFiServer server(80);
WiFiUDP Udp; WiFiUDP Udp;
WiFiUDP ntpUDP; WiFiUDP ntpUDP;
IPAddress deviceIP; IPAddress broadIP;
NTPClient ntp(ntpUDP); NTPClient ntp(ntpUDP);
CRGB leds[MAX_LEDS]; CRGB leds[MAX_LEDS];
Time now; Time now;
Button btn(BTN_PIN); Button btn(BTN_PIN);
timerMillis EEtmr(EE_TOUT), turnoffTmr, connTmr(120000ul), dawnTmr, holdPresTmr(30000ul), blinkTmr(300); timerMillis EEtmr(EE_TOUT), turnoffTmr, connTmr(120000ul), dawnTmr, holdPresTmr(30000ul), blinkTmr(300);
timerMillis effTmr(30, true); timerMillis effTmr(30, true), onlineTmr(500, true), postDawn(10 * 60000ul);
TimeRandom trnd; TimeRandom trnd;
VolAnalyzer vol(A0), low, high; VolAnalyzer vol(A0), low, high;
FastFilter phot; FastFilter phot;
@@ -207,4 +174,5 @@ void loop() {
button(); // проверяем кнопку button(); // проверяем кнопку
checkAnalog(); // чтение звука и датчика checkAnalog(); // чтение звука и датчика
yield(); yield();
iAmOnline();
} }

View File

@@ -5,7 +5,7 @@ void setupADC() {
vol.setDt(700); vol.setDt(700);
vol.setPeriod(5); vol.setPeriod(5);
vol.setWindow(map(MAX_LEDS, 300, 1200, 20, 1)); vol.setWindow(map(MAX_LEDS, 300, 900, 20, 1));
low.setDt(0); low.setDt(0);
low.setPeriod(0); low.setPeriod(0);
@@ -63,11 +63,11 @@ void checkAnalog() {
void checkMusic() { void checkMusic() {
vol.tick(); vol.tick();
yield();
#if (USE_CLAP == 1) #if (USE_CLAP == 1)
clap.tick(vol.getRawMax()); clap.tick(vol.getRawMax());
if (clap.hasClaps(2)) controlHandler(!cfg.state); if (clap.hasClaps(2)) controlHandler(!cfg.state);
#endif #endif
yield();
if (CUR_PRES.advMode == GL_ADV_LOW || CUR_PRES.advMode == GL_ADV_HIGH) { // частоты if (CUR_PRES.advMode == GL_ADV_LOW || CUR_PRES.advMode == GL_ADV_HIGH) { // частоты
int raw[FFT_SIZE], spectr[FFT_SIZE]; int raw[FFT_SIZE], spectr[FFT_SIZE];
for (int i = 0; i < FFT_SIZE; i++) raw[i] = analogRead(A0); for (int i = 0; i < FFT_SIZE; i++) raw[i] = analogRead(A0);

View File

@@ -29,6 +29,7 @@
#define FOR_i(x,y) for (int i = (x); i < (y); i++) #define FOR_i(x,y) for (int i = (x); i < (y); i++)
#define FOR_j(x,y) for (int j = (x); j < (y); j++) #define FOR_j(x,y) for (int j = (x); j < (y); j++)
#define FOR_k(x,y) for (int k = (x); k < (y); k++)
#define CUR_PRES preset[cfg.curPreset] #define CUR_PRES preset[cfg.curPreset]
byte scaleFF(byte x, byte b) { byte scaleFF(byte x, byte b) {
@@ -80,7 +81,7 @@ struct Config {
int16_t length = 16; // длина ленты int16_t length = 16; // длина ленты
int16_t width = 16; // ширина матрицы int16_t width = 16; // ширина матрицы
byte GMT = 3; // часовой пояс +13 byte GMT = 16; // часовой пояс +13
uint32_t cityID = 1; // city ID uint32_t cityID = 1; // city ID
bool mqtt = 0; // mqtt bool mqtt = 0; // mqtt
char mqttID[32]; // char mqttID[32]; //
@@ -118,20 +119,22 @@ struct Preset {
byte scale = 100; // масштаб (0.. 255) byte scale = 100; // масштаб (0.. 255)
byte fromCenter = 0; // эффект из центра (0/1) byte fromCenter = 0; // эффект из центра (0/1)
byte color = 0; // цвет (0.. 255) byte color = 0; // цвет (0.. 255)
byte rnd = 0; // случайный (0/1) byte fromPal = 0; // из палитры (0/1)
}; };
#define DAWN_SIZE 23 #define DAWN_SIZE 24
struct Dawn { struct Dawn {
byte state[7] = {0, 0, 0, 0, 0, 0, 0}; // (1/0) byte state[7] = {0, 0, 0, 0, 0, 0, 0}; // (1/0)
byte hour[7] = {0, 0, 0, 0, 0, 0, 0}; // (0.. 59) byte hour[7] = {0, 0, 0, 0, 0, 0, 0}; // (0.. 59)
byte minute[7] = {0, 0, 0, 0, 0, 0, 0}; // (0.. 59) byte minute[7] = {0, 0, 0, 0, 0, 0, 0}; // (0.. 59)
byte bright = 100; // (0.. 255) byte bright = 100; // (0.. 255)
byte time = 1; // (5,10,15,20..) byte time = 1; // (5,10,15,20..)
byte post = 1; // (5,10,15,20..)
}; };
/* /*
- Каждые 5 минут лампа AP отправляет время (день час минута) на Local лампы всех ролей в сети с ней (GL,6,день,час,мин) - Каждые 5 минут лампа AP отправляет время (день час минута) на Local лампы всех ролей в сети с ней (GL,6,день,час,мин)
- Если включен АЦП, Мастер отправляет своей группе данные с него на каждой итерации отрисовки эффектов (GL,1,длина,масштаб,яркость) - Если включен АЦП, Мастер отправляет своей группе данные с него на каждой итерации отрисовки эффектов (GL,1,длина,масштаб,яркость)
- Установка времени с мобилы - получают все роли АР и Local (не получившие ntp) - Установка времени с мобилы - получают все роли АР и Local (не получившие ntp)
- Каждую секунду устройства шлют посылку GL_ONL
*/ */

View File

@@ -26,6 +26,11 @@ void EE_startup() {
DEBUGLN(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + sizeof(preset) + 1); DEBUGLN(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + sizeof(preset) + 1);
// запускаем всё // запускаем всё
if (cfg.deviceType == GL_TYPE_STRIP) {
if (cfg.length > MAX_LEDS) cfg.length = MAX_LEDS;
cfg.width = 1;
}
if (cfg.length * cfg.width > MAX_LEDS) cfg.width = MAX_LEDS / cfg.length;
FastLED.setMaxPowerInVoltsAndMilliamps(STRIP_VOLT, cfg.maxCur * 100); FastLED.setMaxPowerInVoltsAndMilliamps(STRIP_VOLT, cfg.maxCur * 100);
updPal(); updPal();
} }

View File

@@ -2,12 +2,20 @@ void effectsRoutine() {
static byte prevEff = 255; static byte prevEff = 255;
if (!effTmr.isReady()) return; if (!effTmr.isReady()) return;
if (dawnTmr.running()) { if (dawnTmr.running() || postDawn.running()) {
fill_solid(leds, MAX_LEDS, ColorFromPalette(HeatColors_p, dawnTmr.getLength8(), scaleFF(dawnTmr.getLength8(), dawn.bright), LINEARBLEND)); FastLED.setBrightness(255);
drawClock(cfg.length / 2 - 4, 150, 0); byte thisColor = dawnTmr.getLength8();
if (postDawn.running()) thisColor = 255;
fill_solid(leds, MAX_LEDS, ColorFromPalette(HeatColors_p, thisColor, scaleFF(thisColor, dawn.bright), LINEARBLEND));
drawClock(cfg.length / 2 - 4, 100, 0);
FastLED.show(); FastLED.show();
if (dawnTmr.isReady()) { if (dawnTmr.isReady()) {
dawnTmr.stop(); dawnTmr.stop();
postDawn.setInterval(dawn.post * 60000ul);
postDawn.restart();
}
if (postDawn.isReady()) {
postDawn.stop();
FastLED.clear(); FastLED.clear();
FastLED.show(); FastLED.show();
} }
@@ -19,12 +27,15 @@ void effectsRoutine() {
byte thisScale = getScale(); byte thisScale = getScale();
byte thisBright = getBright(); byte thisBright = getBright();
if (cfg.adcMode > 1) { // музыка или яркость if (musicMode() || briMode()) { // музыка или яркость
if (cfg.role) { // мастер отправляет if (cfg.role) { // мастер отправляет
static timerMillis adcSend(120, true); static uint32_t tmr = 0;
if (adcSend.isReady() && millis() - udpTmr >= 1000) sendUDP(7, thisLength, thisScale, thisBright); if ((millis() - tmr >= musicMode() ? 60 : 1000) && millis() - udpTmr >= 1000) {
sendUDP(7, thisLength, thisScale, thisBright);
tmr = millis();
}
} else { // слейв получает } else { // слейв получает
if (millis() - gotADCtmr < 2000) { // есть сигнал с мастера if (millis() - gotADCtmr < 4000) { // есть сигнал с мастера
thisLength = udpLength; thisLength = udpLength;
thisScale = udpScale; thisScale = udpScale;
thisBright = udpBright; thisBright = udpBright;
@@ -46,6 +57,7 @@ void effectsRoutine() {
prevEff = CUR_PRES.effect; prevEff = CUR_PRES.effect;
loading = true; loading = true;
} }
yield();
// =================================================== ЭФФЕКТЫ =================================================== // =================================================== ЭФФЕКТЫ ===================================================
switch (CUR_PRES.effect) { switch (CUR_PRES.effect) {
@@ -132,7 +144,8 @@ void effectsRoutine() {
FOR_i(0, cfg.length * cfg.width) leds[i].fadeToBlackBy(70); FOR_i(0, cfg.length * cfg.width) leds[i].fadeToBlackBy(70);
{ {
uint16_t rndVal = 0; uint16_t rndVal = 0;
FOR_i(0, thisScale / 8 + 1) { byte amount = (thisScale >> 3) + 1;
FOR_i(0, amount) {
rndVal = rndVal * 2053 + 13849; // random2053 алгоритм rndVal = rndVal * 2053 + 13849; // random2053 алгоритм
int homeX = inoise16(i * 100000000ul + (now.weekMs << 3) * CUR_PRES.speed / 255); int homeX = inoise16(i * 100000000ul + (now.weekMs << 3) * CUR_PRES.speed / 255);
homeX = map(homeX, 15000, 50000, 0, cfg.length); homeX = map(homeX, 15000, 50000, 0, cfg.length);
@@ -146,9 +159,15 @@ void effectsRoutine() {
int offsY = inoise8(i * 2500 + 30000 + (now.weekMs >> 1) * CUR_PRES.speed / 255) - 128; int offsY = inoise8(i * 2500 + 30000 + (now.weekMs >> 1) * CUR_PRES.speed / 255) - 128;
offsY = cfg.length / 2 * offsY / 128; offsY = cfg.length / 2 * offsY / 128;
int thisY = homeY + offsY; int thisY = homeY + offsY;
setPix(thisX, thisY, CHSV(CUR_PRES.rnd ? rndVal : CUR_PRES.color, 255, 255)); setPix(thisX, thisY, CUR_PRES.fromPal ?
ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(i * 255 / amount), 255, LINEARBLEND) :
CHSV(CUR_PRES.color, 255, 255)
);
} else { } else {
setLED(thisX, CHSV(CUR_PRES.rnd ? rndVal : CUR_PRES.color, 255, 255)); setLED(thisX, CUR_PRES.fromPal ?
ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(i * 255 / amount), 255, LINEARBLEND) :
CHSV(CUR_PRES.color, 255, 255)
);
} }
} }
} }
@@ -204,27 +223,53 @@ void effectsRoutine() {
break; break;
case 8: // ================================== КОНФЕТТИ ================================== case 8: // ================================== КОНФЕТТИ ==================================
FOR_i(0, (thisScale >> 3) + 1) { {
byte amount = (thisScale >> 3) + 1;
FOR_i(0, amount) {
int x = random(0, cfg.length * cfg.width); int x = random(0, cfg.length * cfg.width);
if (leds[x] == CRGB(0, 0, 0)) leds[x] = CHSV(CUR_PRES.rnd ? random(0, 255) : CUR_PRES.color, 255, 255); if (leds[x] == CRGB(0, 0, 0)) leds[x] = CUR_PRES.fromPal ?
ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(i * 255 / amount), 255, LINEARBLEND) :
CHSV(CUR_PRES.color, 255, 255);
} }
FOR_i(0, cfg.length * cfg.width) { FOR_i(0, cfg.length * cfg.width) {
if (leds[i].r >= 10 || leds[i].g >= 10 || leds[i].b >= 10) leds[i].fadeToBlackBy(CUR_PRES.speed / 2 + 1); if (leds[i].r >= 10 || leds[i].g >= 10 || leds[i].b >= 10) leds[i].fadeToBlackBy(CUR_PRES.speed / 2 + 1);
else leds[i] = 0; else leds[i] = 0;
} }
}
break; break;
case 9: // =================================== СМЕРЧ ===================================
case 9: // =================================== ЧАСЫ ===================================
FastLED.clear(); FastLED.clear();
drawClock(mapFF(CUR_PRES.scale, 0, cfg.length - 7), (255 - CUR_PRES.speed), CHSV(CUR_PRES.color, 255, 255)); FOR_k(0, (thisScale >> 5) + 1) {
FOR_i(0, cfg.length) {
//byte thisPos = inoise8(i * 10 - (now.weekMs >> 1) * CUR_PRES.speed / 255, k * 10000);
byte thisPos = inoise8(i * 10 + (now.weekMs >> 3) * CUR_PRES.speed / 255 + k * 10000, (now.weekMs >> 1) * CUR_PRES.speed / 255);
thisPos = map(thisPos, 50, 200, 0, cfg.width);
byte scale = 4;
FOR_j(0, scale) {
CRGB color = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(j * 255 / scale), (255 - j * 255 / (scale - 1)), LINEARBLEND);
if (j == 0) {
setPixOverlap(thisPos, i, color);
} else {
setPixOverlap(thisPos - j, i, color);
setPixOverlap(thisPos + j, i, color);
}
}
}
}
break; break;
case 10: // ================================= ПОГОДА ================================== case 10: // =================================== ЧАСЫ ===================================
FastLED.clear();
drawClock(mapFF(CUR_PRES.scale, 0, cfg.length - 7), (CUR_PRES.speed < 10) ? 0 : (255 - CUR_PRES.speed), CHSV(CUR_PRES.color, 255, 255));
break;
case 11: // ================================= ПОГОДА ==================================
break; break;
} }
if (CUR_PRES.advMode == GL_ADV_CLOCK && CUR_PRES.effect != 9) drawClock(mapFF(CUR_PRES.scale, 0, cfg.length - 7), 150, 0); if (CUR_PRES.advMode == GL_ADV_CLOCK && CUR_PRES.effect != 9) drawClock(mapFF(CUR_PRES.scale, 0, cfg.length - 7), 100, 0);
// выводим нажатия кнопки // выводим нажатия кнопки
if (btnClicks > 0) fill_solid(leds, btnClicks, CRGB::White); if (btnClicks > 0) fill_solid(leds, btnClicks, CRGB::White);
if (brTicks > 0) fill_solid(leds, brTicks, CRGB::Cyan); if (brTicks > 0) fill_solid(leds, brTicks, CRGB::Cyan);
@@ -236,13 +281,16 @@ void effectsRoutine() {
bool musicMode() { bool musicMode() {
return ((cfg.adcMode == GL_ADC_MIC || cfg.adcMode == GL_ADC_BOTH) && (CUR_PRES.advMode > 1 && CUR_PRES.advMode <= 4)); return ((cfg.adcMode == GL_ADC_MIC || cfg.adcMode == GL_ADC_BOTH) && (CUR_PRES.advMode > 1 && CUR_PRES.advMode <= 4));
} }
bool briMode() {
return (cfg.adcMode == GL_ADC_BRI || cfg.adcMode == GL_ADC_BOTH);
}
byte getBright() { byte getBright() {
int maxBr = cfg.bright; // макс яркость из конфига int maxBr = cfg.bright; // макс яркость из конфига
byte fadeBr = 255; byte fadeBr = 255;
if (CUR_PRES.fadeBright) fadeBr = CUR_PRES.bright; // ограничен вручную if (CUR_PRES.fadeBright) fadeBr = CUR_PRES.bright; // ограничен вручную
if (cfg.adcMode == GL_ADC_BRI || cfg.adcMode == GL_ADC_BOTH) { // ----> датчик света или оба if (briMode()) { // ----> датчик света или оба
maxBr = constrain(phot.getFil(), cfg.minLight, cfg.maxLight); maxBr = constrain(phot.getFil(), cfg.minLight, cfg.maxLight);
if (cfg.minLight != cfg.maxLight) if (cfg.minLight != cfg.maxLight)
maxBr = map(maxBr, cfg.minLight, cfg.maxLight, cfg.minBright, cfg.maxBright); maxBr = map(maxBr, cfg.minLight, cfg.maxLight, cfg.minBright, cfg.maxBright);
@@ -298,6 +346,13 @@ byte scalePal(byte val) {
void setPix(int x, int y, CRGB color) { void setPix(int x, int y, CRGB color) {
if (y >= 0 && y < cfg.length && x >= 0 && x < cfg.width) leds[getPix(x, y)] = color; if (y >= 0 && y < cfg.length && x >= 0 && x < cfg.width) leds[getPix(x, y)] = color;
} }
void setPixOverlap(int x, int y, CRGB color) {
if (y < 0) y += cfg.length;
if (x < 0) x += cfg.width;
if (y >= cfg.length) y -= cfg.length;
if (x >= cfg.width) x -= cfg.width;
setPix(x, y, color);
}
void setLED(int x, CRGB color) { void setLED(int x, CRGB color) {
if (x >= 0 && x < cfg.length) leds[x] = color; if (x >= 0 && x < cfg.length) leds[x] = color;
} }

View File

@@ -1,5 +1,7 @@
// TODO #ifndef mString_h
// защита от переполнения #define mString_h
#include <Arduino.h>
char* mUtoa(uint32_t value, char *buffer, bool clear = 1); char* mUtoa(uint32_t value, char *buffer, bool clear = 1);
char* mLtoa(int32_t value, char *buffer, bool clear = 1); char* mLtoa(int32_t value, char *buffer, bool clear = 1);
@@ -53,7 +55,7 @@ class mString {
} }
// constructor // constructor
mString(char* buffer, int newSize) { mString(char* buffer, int newSize = -1) {
buf = buffer; buf = buffer;
size = newSize; size = newSize;
} }
@@ -101,7 +103,7 @@ class mString {
// add // add
mString& add(const char c) { mString& add(const char c) {
byte len = length(); byte len = length();
if (len + 1 >= size) return *this; if (size != -1 && len + 1 >= size) return *this;
buf[len++] = c; buf[len++] = c;
buf[len++] = NULL; buf[len++] = NULL;
return *this; return *this;
@@ -111,13 +113,13 @@ class mString {
do { do {
buf[len] = *(data++); buf[len] = *(data++);
} while (buf[len++] != 0);*/ } while (buf[len++] != 0);*/
if (length() + strlen(data) >= size) return *this; if (size != -1 && length() + strlen(data) >= size) return *this;
strcpy(buf + length(), data); strcpy(buf + length(), data);
return *this; return *this;
} }
mString& add(const __FlashStringHelper *data) { mString& add(const __FlashStringHelper *data) {
PGM_P p = reinterpret_cast<PGM_P>(data); PGM_P p = reinterpret_cast<PGM_P>(data);
if (length() + strlen_P(p) >= size) return *this; if (size != -1 && length() + strlen_P(p) >= size) return *this;
strcpy_P(buf + length(), p); strcpy_P(buf + length(), p);
return *this; return *this;
/*do { /*do {
@@ -297,7 +299,7 @@ class mString {
// convert & parse // convert & parse
char operator [] (uint16_t index) const { char operator [] (uint16_t index) const {
return (index < size ? buf[index] : 0); return buf[index];//(index < size ? buf[index] : 0);
} }
char& operator [] (uint16_t index) { char& operator [] (uint16_t index) {
return buf[index]; return buf[index];
@@ -356,5 +358,5 @@ class mString {
} }
} }
private: private:
}; };
#endif

View File

@@ -1,6 +1,6 @@
char buf[UDP_TX_PACKET_MAX_SIZE + 1];
void parsing() { void parsing() {
if (Udp.parsePacket()) { if (Udp.parsePacket()) {
static char buf[UDP_TX_PACKET_MAX_SIZE + 1];
int n = Udp.read(buf, UDP_TX_PACKET_MAX_SIZE); int n = Udp.read(buf, UDP_TX_PACKET_MAX_SIZE);
buf[n] = NULL; buf[n] = NULL;
@@ -9,7 +9,7 @@ void parsing() {
if (buf[3] == '7') { // АЦП GL,7, if (buf[3] == '7') { // АЦП GL,7,
if (!cfg.role) { // принимаем данные ацп если слейв if (!cfg.role) { // принимаем данные ацп если слейв
int data[3]; int data[3];
mString ints(buf + 5, 20); mString ints(buf + 5);
ints.parseInts(data, 3); ints.parseInts(data, 3);
udpLength = data[0]; udpLength = data[0];
udpScale = data[1]; udpScale = data[1];
@@ -27,7 +27,7 @@ void parsing() {
// ПАРСИНГ // ПАРСИНГ
byte data[MAX_PRESETS * PRES_SIZE + 10]; byte data[MAX_PRESETS * PRES_SIZE + 10];
memset(data, 0, sizeof(data)); memset(data, 0, MAX_PRESETS * PRES_SIZE + 10);
int count = 0; int count = 0;
char *str, *p = buf; char *str, *p = buf;
char *ssid, *pass; char *ssid, *pass;
@@ -53,7 +53,6 @@ void parsing() {
if (count == 24) strcpy(cfg.mqttPass, str); if (count == 24) strcpy(cfg.mqttPass, str);
} }
} }
yield();
// тип 0 - control, 1 - config, 2 - effects, 3 - dawn, 4 - from master, 5 - palette, 6 - time // тип 0 - control, 1 - config, 2 - effects, 3 - dawn, 4 - from master, 5 - palette, 6 - time
switch (data[1]) { switch (data[1]) {
@@ -81,7 +80,7 @@ void parsing() {
FastLED.clear(); FastLED.clear();
FastLED.show(); FastLED.show();
char OTA[60]; char OTA[60];
mString ota(OTA, 60); mString ota(OTA);
ota.clear(); ota.clear();
ota += OTAhost; ota += OTAhost;
ota += OTAfile[data[3]]; ota += OTAfile[data[3]];
@@ -93,6 +92,7 @@ void parsing() {
case 13: // выключить через case 13: // выключить через
if (data[3] == 0) turnoffTmr.stop(); if (data[3] == 0) turnoffTmr.stop();
else { else {
DEBUGLN("Fade");
fadeDown((uint32_t)data[3] * 60000ul); fadeDown((uint32_t)data[3] * 60000ul);
} }
break; break;
@@ -185,16 +185,16 @@ void parsing() {
void sendToSlaves(byte data1, byte data2) { void sendToSlaves(byte data1, byte data2) {
if (cfg.role == GL_MASTER) { if (cfg.role == GL_MASTER) {
char reply[15]; char reply[15];
mString packet(reply, sizeof(reply)); mString packet(reply);
packet.clear(); packet.clear();
packet = packet + "GL,4," + data1 + ',' + data2; packet = packet + "GL,4," + data1 + ',' + data2;
DEBUG("Sending to Slaves: "); DEBUG("Sending to Slaves: ");
DEBUGLN(reply); DEBUGLN(reply);
FOR_i(0, 3) { FOR_i(0, 4) {
sendUDP(reply); sendUDP(reply);
delay(10); delay(8);
} }
} }
} }

View File

@@ -42,8 +42,9 @@ void controlHandler(bool state) {
DEBUGLN("stop off timer"); DEBUGLN("stop off timer");
return; return;
} }
if (dawnTmr.running()) { if (dawnTmr.running() || postDawn.running()) {
dawnTmr.stop(); dawnTmr.stop();
postDawn.stop();
delay(50); delay(50);
FastLED.clear(); FastLED.clear();
FastLED.show(); FastLED.show();
@@ -68,7 +69,7 @@ void setPower(bool state) {
FastLED.clear(); FastLED.clear();
FastLED.show(); FastLED.show();
} }
if (millis() - udpTmr >= 1000) sendToSlaves(0, cfg.state); // пиздец костыль if (millis() - udpTmr >= 1000) sendToSlaves(0, cfg.state); // пиздец костыль (не отправлять слейвам если команда получена по воздуху)
DEBUGLN(state ? "Power on" : "Power off"); DEBUGLN(state ? "Power on" : "Power off");
} }

View File

@@ -156,7 +156,7 @@ void setupLocal() {
} }
void checkUpdate() { void checkUpdate() {
if (cfg.update) { if (cfg.update) { // было ОТА обновление
if (cfg.version != GL_VERSION) { if (cfg.version != GL_VERSION) {
cfg.version = GL_VERSION; cfg.version = GL_VERSION;
blink16(CRGB::Cyan); blink16(CRGB::Cyan);
@@ -164,10 +164,17 @@ void checkUpdate() {
DEBUGLN(GL_VERSION); DEBUGLN(GL_VERSION);
} else { } else {
blink16(CRGB::Blue); blink16(CRGB::Blue);
DEBUG("Update to current"); DEBUGLN("Update to current");
} }
cfg.update = 0; cfg.update = 0;
EE_updCfg(); EE_updCfg();
} else {
if (cfg.version != GL_VERSION) {
cfg.version = GL_VERSION;
blink16(CRGB::Cyan);
DEBUG("Update to");
DEBUGLN(GL_VERSION);
}
} }
} }

View File

@@ -1,6 +1,6 @@
void setupTime() { void setupTime() {
ntp.setUpdateInterval(NTP_UPD_PRD * 60000ul); ntp.setUpdateInterval(NTP_UPD_PRD * 60000ul / 2); // ставим меньше, так как апдейт вручную
ntp.setTimeOffset((cfg.GMT - 13) * 3600); ntp.setTimeOffset((cfg.GMT - 13) * 3600l);
ntp.setPoolServerName(NTPserver); ntp.setPoolServerName(NTPserver);
if (cfg.WiFimode && !connTmr.running()) { // если успешно подключились к WiFi if (cfg.WiFimode && !connTmr.running()) { // если успешно подключились к WiFi
ntp.begin(); ntp.begin();
@@ -12,14 +12,14 @@ void setupTime() {
void timeTicker() { void timeTicker() {
static timerMillis tmr(30, true); static timerMillis tmr(30, true);
if (tmr.isReady()) { if (tmr.isReady()) {
if (cfg.WiFimode && WiFi.status() == WL_CONNECTED) { // если вайфай подключен if (cfg.WiFimode && WiFi.status() == WL_CONNECTED && !connTmr.running()) { // если вайфай подключен и это не попытка переподключиться
now.sec = ntp.getSeconds(); now.sec = ntp.getSeconds();
now.min = ntp.getMinutes(); now.min = ntp.getMinutes();
now.hour = ntp.getHours(); now.hour = ntp.getHours();
now.day = ntp.getDay(); // вс 0, сб 6 now.day = ntp.getDay(); // вс 0, сб 6
now.weekMs = now.getWeekS() * 1000ul + ntp.getMillis(); now.weekMs = now.getWeekS() * 1000ul + ntp.getMillis();
now.setMs(ntp.getMillis()); now.setMs(ntp.getMillis());
if (ntp.update()) gotNTP = true; if (now.sec == 0 && now.min % NTP_UPD_PRD == 0 && ntp.update()) gotNTP = true;
} else { // если вайфай не подключен } else { // если вайфай не подключен
now.tick(); // тикаем своим счётчиком now.tick(); // тикаем своим счётчиком
} }
@@ -65,7 +65,6 @@ void checkDawn() {
DEBUGLN(dawn.time * 60000ul); DEBUGLN(dawn.time * 60000ul);
dawnTmr.setInterval(dawn.time * 60000ul); dawnTmr.setInterval(dawn.time * 60000ul);
dawnTmr.restart(); dawnTmr.restart();
FastLED.setBrightness(255);
} }
} }
} }
@@ -75,6 +74,7 @@ void checkWorkTime() {
byte curState = isWorkTime(now.hour, cfg.workFrom, cfg.workTo); byte curState = isWorkTime(now.hour, cfg.workFrom, cfg.workTo);
if (prevState != curState) { // переключение расписания if (prevState != curState) { // переключение расписания
prevState = curState; prevState = curState;
// todo: проверить пересечение с рассветом
if (curState && !cfg.state && !cfg.manualOff) fade(1); // нужно включить, а лампа выключена и не выключалась вручную if (curState && !cfg.state && !cfg.manualOff) fade(1); // нужно включить, а лампа выключена и не выключалась вручную
if (!curState && cfg.state) fade(0); // нужно выключить, а лампа включена if (!curState && cfg.state) fade(0); // нужно выключить, а лампа включена
} }

View File

@@ -38,7 +38,7 @@ class timerMillis {
return _active; return _active;
} }
byte getLength8() { byte getLength8() {
return (_active) ? ((millis() - _tmr) * 255ul / _interval) : 0; return (_active) ? ((min(uint32_t(millis() - _tmr), _interval)) * 255ul / _interval) : 0;
} }
private: private: