This commit is contained in:
Alex
2021-03-04 17:26:02 +03:00
parent 2705a04948
commit 8ee8145077
7 changed files with 126 additions and 48 deletions

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);
} }
@@ -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,4 +1,10 @@
/* /*
Версия 0.21b
Выбор палитры для частиц и конфетти
Счётчик количества ламп онлайн в приложении
Синхронизация текущего эффекта с приложением
Добавлен эффект смерч
Версия 0.20b Версия 0.20b
Оптимизация Оптимизация
Исправление критических ошибок Исправление критических ошибок
@@ -75,6 +81,7 @@
// При прошивке с других прошивок лампы поставить: Инструменты/Erase Flash/All Flash Contents // При прошивке с других прошивок лампы поставить: Инструменты/Erase Flash/All Flash Contents
// ESP core 2.7.4+ http://arduino.esp8266.com/stable/package_esp8266com_index.json // ESP core 2.7.4+ http://arduino.esp8266.com/stable/package_esp8266com_index.json
// FastLED 3.4.0+ https://github.com/FastLED/FastLED/releases // FastLED 3.4.0+ https://github.com/FastLED/FastLED/releases
#define GL_BUILD 0 // 0: com 300, 1: com 900, 2: esp1 300, 3: esp1 900, 4: module 300, 5: module 900
// ---------- Настройки ----------- // ---------- Настройки -----------
#define GL_KEY "GL" // ключ сети #define GL_KEY "GL" // ключ сети
@@ -108,7 +115,7 @@ const char AP_NameChar[] = "GyverLamp2";
const char WiFiPassword[] = "12345678"; const char WiFiPassword[] = "12345678";
// ------------ Прочее ------------- // ------------ Прочее -------------
#define GL_VERSION 20 // код версии прошивки #define GL_VERSION 21 // код версии прошивки
#define EE_TOUT 30000 // таймаут сохранения епром после изменения, мс #define EE_TOUT 30000 // таймаут сохранения епром после изменения, мс
//#define DEBUG_SERIAL // закомментируй чтобы выключить отладку (скорость 115200) //#define DEBUG_SERIAL // закомментируй чтобы выключить отладку (скорость 115200)
#define EE_KEY 55 // ключ сброса WiFi (измени для сброса всех настроек) #define EE_KEY 55 // ключ сброса WiFi (измени для сброса всех настроек)
@@ -116,22 +123,33 @@ const char WiFiPassword[] = "12345678";
//#define SKIP_WIFI // пропустить подключение к вафле (для отладки) //#define SKIP_WIFI // пропустить подключение к вафле (для отладки)
// ------------ БИЛДЕР ------------- // ------------ БИЛДЕР -------------
//#define MAX_LEDS 900 #if (GL_BUILD == 0)
#elif (GL_BUILD == 1)
// esp01 #define MAX_LEDS 900
//#define BTN_PIN 0 #elif (GL_BUILD == 2)
//#define STRIP_PIN 2 #define MAX_LEDS 300
//#define USE_ADC 0 #define BTN_PIN 0
#define STRIP_PIN 2
// GL2 module #define USE_ADC 0
//#define STRIP_PIN 5 // GPIO5 на gl module (D1 на wemos/node) #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" // сервер времени (модиф)
@@ -154,13 +172,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);
TimeRandom trnd; TimeRandom trnd;
VolAnalyzer vol(A0), low, high; VolAnalyzer vol(A0), low, high;
FastFilter phot; FastFilter phot;
@@ -214,4 +232,5 @@ void loop() {
button(); // проверяем кнопку button(); // проверяем кнопку
checkAnalog(); // чтение звука и датчика checkAnalog(); // чтение звука и датчика
yield(); yield();
iAmOnline();
} }

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) {
@@ -118,7 +119,7 @@ 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 23
@@ -134,4 +135,5 @@ struct Dawn {
- Каждые 5 минут лампа AP отправляет время (день час минута) на Local лампы всех ролей в сети с ней (GL,6,день,час,мин) - Каждые 5 минут лампа AP отправляет время (день час минута) на Local лампы всех ролей в сети с ней (GL,6,день,час,мин)
- Если включен АЦП, Мастер отправляет своей группе данные с него на каждой итерации отрисовки эффектов (GL,1,длина,масштаб,яркость) - Если включен АЦП, Мастер отправляет своей группе данные с него на каждой итерации отрисовки эффектов (GL,1,длина,масштаб,яркость)
- Установка времени с мобилы - получают все роли АР и Local (не получившие ntp) - Установка времени с мобилы - получают все роли АР и Local (не получившие ntp)
- Каждую секунду устройства шлют посылку GL_ONL
*/ */

View File

@@ -4,7 +4,7 @@ void effectsRoutine() {
if (dawnTmr.running()) { if (dawnTmr.running()) {
fill_solid(leds, MAX_LEDS, ColorFromPalette(HeatColors_p, dawnTmr.getLength8(), scaleFF(dawnTmr.getLength8(), dawn.bright), LINEARBLEND)); fill_solid(leds, MAX_LEDS, ColorFromPalette(HeatColors_p, dawnTmr.getLength8(), scaleFF(dawnTmr.getLength8(), dawn.bright), LINEARBLEND));
drawClock(cfg.length / 2 - 4, 150, 0); drawClock(cfg.length / 2 - 4, 100, 0);
FastLED.show(); FastLED.show();
if (dawnTmr.isReady()) { if (dawnTmr.isReady()) {
dawnTmr.stop(); dawnTmr.stop();
@@ -22,7 +22,7 @@ void effectsRoutine() {
if (musicMode() || briMode()) { // музыка или яркость if (musicMode() || briMode()) { // музыка или яркость
if (cfg.role) { // мастер отправляет if (cfg.role) { // мастер отправляет
static uint32_t tmr = 0; static uint32_t tmr = 0;
if ((millis() - tmr >= musicMode() ? 120 : 1000) && millis() - udpTmr >= 1000) { if ((millis() - tmr >= musicMode() ? 60 : 1000) && millis() - udpTmr >= 1000) {
sendUDP(7, thisLength, thisScale, thisBright); sendUDP(7, thisLength, thisScale, thisBright);
tmr = millis(); tmr = millis();
} }
@@ -136,7 +136,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);
@@ -150,9 +151,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)
);
} }
} }
} }
@@ -208,27 +215,53 @@ void effectsRoutine() {
break; break;
case 8: // ================================== КОНФЕТТИ ================================== case 8: // ================================== КОНФЕТТИ ==================================
FOR_i(0, (thisScale >> 3) + 1) { {
int x = random(0, cfg.length * cfg.width); byte amount = (thisScale >> 3) + 1;
if (leds[x] == CRGB(0, 0, 0)) leds[x] = CHSV(CUR_PRES.rnd ? random(0, 255) : CUR_PRES.color, 255, 255); FOR_i(0, amount) {
} int x = random(0, cfg.length * cfg.width);
FOR_i(0, cfg.length * cfg.width) { if (leds[x] == CRGB(0, 0, 0)) leds[x] = CUR_PRES.fromPal ?
if (leds[i].r >= 10 || leds[i].g >= 10 || leds[i].b >= 10) leds[i].fadeToBlackBy(CUR_PRES.speed / 2 + 1); ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(i * 255 / amount), 255, LINEARBLEND) :
else leds[i] = 0; CHSV(CUR_PRES.color, 255, 255);
}
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);
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);
thisPos = map(thisPos, 50, 200, 0, cfg.width);
byte scale = 3;
FOR_j(0, scale) {
CRGB color = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(j * 255 / scale), 255, LINEARBLEND);
color.fadeToBlackBy(j * 180 / scale);
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);
@@ -305,6 +338,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

@@ -53,7 +53,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 +101,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 +111,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 +297,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];

View File

@@ -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];
@@ -80,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]];
@@ -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

@@ -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);
@@ -168,6 +168,13 @@ void checkUpdate() {
} }
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);
}
} }
} }