This commit is contained in:
Alex
2021-02-25 02:29:25 +03:00
parent 4ea34e6cfd
commit a3b58c876e
13 changed files with 256 additions and 103 deletions

View File

@@ -0,0 +1,89 @@
#pragma once
#include <Arduino.h>
class Clap {
public:
void tick(int val) {
if (millis() - _tmr >= 10) {
_tmr = millis();
int der = val - _prevVal;
_prevVal = val;
int signal = 0;
int front = 0;
if (der > _trsh) signal = 1;
if (der < -_trsh) signal = -1;
if (_prevSignal == 0 && signal == 1) front = 1;
if (_prevSignal == 0 && signal == -1) front = -1;
_prevSignal = signal;
uint32_t deb = millis() - _tmr2;
if (front == 1 && _state == 0) {
_state = 1;
if (!_startClap) {
_claps = 0;
_ready = 0;
}
_startClap = 1;
_clap = 0;
_tmr2 = millis();
} else if (front == -1 && _state == 1 && deb <= 200) {
_state = 2;
_tmr2 = millis();
} else if (front == 0 && _state == 2 && deb <= 200) {
_state = 0;
_claps++;
_clap = 1;
_tmr2 = millis();
} else if (_startClap && deb > _tout) {
_state = 0;
_startClap = 0;
if (_claps != 0) _ready = 1;
}
}
}
void setTrsh(int trsh) {
_trsh = trsh;
}
void setTimeout(int tout) {
_tout = tout;
}
bool isClap() {
if (_clap) {
_clap = 0;
return 1;
}
return 0;
}
bool hasClaps(byte claps) {
if (_ready && _claps == claps) {
_ready = 0;
_claps = 0;
return 1;
}
return 0;
}
bool hasClaps() {
return _ready;
}
byte getClaps() {
if (_ready) {
_ready = 0;
byte buf = _claps;
_claps = 0;
return buf;
} return 0;
}
private:
uint32_t _tmr = 0, _tmr2 = 0;
int _prevVal = 0;
int _trsh = 150;
byte _state = 0;
int8_t _prevSignal = 0;
int _tout = 700;
byte _claps = 0;
bool _ready = 0;
bool _clap = 0;
bool _startClap = 0;
};

View File

@@ -8,6 +8,10 @@
class FastFilter { class FastFilter {
public: public:
FastFilter(byte k = 20, int dt = 0) {
setK(k);
setDt(dt);
}
void setK(byte k) { void setK(byte k) {
_k1 = k; _k1 = k;
_k2 = 32 - k; _k2 = 32 - k;

View File

@@ -1,4 +1,13 @@
/* /*
Версия 0.17b
Автосмена отключается 30 сек во время настройки режимов
Убрана кнопка upload в режимах
Лампа чуть мигает при получении данных
Кастом палитра работает на огне 2020
Вкл выкл двумя хлопками
Плавное выключение
Починил рассвет
Версия 0.16b Версия 0.16b
Исправлен масштаб огня 2020 Исправлен масштаб огня 2020
Фикс невыключения рассвета Фикс невыключения рассвета
@@ -33,7 +42,6 @@
Mqtt? Mqtt?
Базовый пак Базовый пак
Предложения Серёги крутского Предложения Серёги крутского
Убрать аплод?
Эффект погода https://it4it.club/topic/40-esp8266-i-parsing-pogodyi-s-openweathermap/ Эффект погода https://it4it.club/topic/40-esp8266-i-parsing-pogodyi-s-openweathermap/
Эффект часы Эффект часы
*/ */
@@ -55,6 +63,7 @@
// ------------- АЦП -------------- // ------------- АЦП --------------
#define USE_ADC 1 // можно выпилить АЦП #define USE_ADC 1 // можно выпилить АЦП
#define USE_CLAP 1 // два хлопка в ладоши вкл выкл лампу
#define MIC_VCC 12 // питание микрофона GPIO12 (D6 на wemos/node) #define MIC_VCC 12 // питание микрофона GPIO12 (D6 на wemos/node)
#define PHOT_VCC 14 // питание фоторезистора GPIO14 (D5 на wemos/node) #define PHOT_VCC 14 // питание фоторезистора GPIO14 (D5 на wemos/node)
@@ -77,10 +86,10 @@ const char AP_NameChar[] = "GyverLamp2";
const char WiFiPassword[] = "12345678"; const char WiFiPassword[] = "12345678";
// ------------ Прочее ------------- // ------------ Прочее -------------
#define GL_VERSION 016 // код версии прошивки #define GL_VERSION 017 // код версии прошивки
#define EE_TOUT 30000 // таймаут сохранения епром после изменения, мс #define EE_TOUT 30000 // таймаут сохранения епром после изменения, мс
//#define DEBUG_SERIAL // закомментируй чтобы выключить отладку (скорость 115200) //#define DEBUG_SERIAL // закомментируй чтобы выключить отладку (скорость 115200)
#define EE_KEY 52 // ключ сброса WiFi (измени для сброса всех настроек) #define EE_KEY 55 // ключ сброса WiFi (измени для сброса всех настроек)
#define NTP_UPD_PRD 5 // период обновления времени с NTP сервера, минут #define NTP_UPD_PRD 5 // период обновления времени с NTP сервера, минут
//#define SKIP_WIFI // пропустить подключение к вафле (для отладки) //#define SKIP_WIFI // пропустить подключение к вафле (для отладки)
@@ -113,6 +122,7 @@ const char WiFiPassword[] = "12345678";
#include <EEPROM.h> // епром #include <EEPROM.h> // епром
#include "ESP8266httpUpdate.h" // OTA #include "ESP8266httpUpdate.h" // OTA
#include "mString.h" // стринг билдер #include "mString.h" // стринг билдер
#include "Clap.h" // обработка хлопков
// ------------------- ДАТА -------------------- // ------------------- ДАТА --------------------
Config cfg; Config cfg;
@@ -126,10 +136,11 @@ 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(120000), dawnTmr; timerMillis EEtmr(EE_TOUT), turnoffTmr, connTmr(120000ul), dawnTmr, holdPresTmr(30000ul), blinkTmr(300);
TimeRandom trnd; TimeRandom trnd;
VolAnalyzer vol(A0), low, high; VolAnalyzer vol(A0), low, high;
FastFilter phot; FastFilter phot;
Clap clap;
byte btnClicks = 0, brTicks = 0; byte btnClicks = 0, brTicks = 0;
unsigned char matrixValue[11][16]; unsigned char matrixValue[11][16];
@@ -145,7 +156,7 @@ void setup() {
Serial.begin(115200); Serial.begin(115200);
DEBUGLN(); DEBUGLN();
#endif #endif
EEPROM.begin(512); // старт епром EEPROM.begin(1000); // старт епром
startStrip(); // старт ленты startStrip(); // старт ленты
btn.setLevel(digitalRead(BTN_PIN)); // смотрим что за кнопка btn.setLevel(digitalRead(BTN_PIN)); // смотрим что за кнопка
EE_startup(); // читаем епром EE_startup(); // читаем епром

View File

@@ -49,8 +49,8 @@ class VolAnalyzer {
} }
bool tick(int thisRead = -1) { bool tick(int thisRead = -1) {
volF.compute(); volF.compute();
if (millis() - tmr4 >= _ampliDt) { // период сглаживания амплитуды if (millis() - tmr3 >= _ampliDt) { // период сглаживания амплитуды
tmr4 = millis(); tmr3 = millis();
maxF.setRaw(maxs); maxF.setRaw(maxs);
minF.setRaw(mins); minF.setRaw(mins);
maxF.compute(); maxF.compute();
@@ -68,11 +68,13 @@ class VolAnalyzer {
maxF.setFil(thisRead); maxF.setFil(thisRead);
minF.setFil(thisRead); minF.setFil(thisRead);
} }
if (++count >= _window) { // выборка завершена if (++count >= _window) { // выборка завершена
tmr1 = millis(); tmr1 = millis();
raw = max; raw = max;
if (max > maxs) maxs = max; // максимумы среди максимумов if (max > maxs) maxs = max; // максимумы среди максимумов
if (max < mins) mins = max; // минимумы реди максимумов if (max < mins) mins = max; // минимумы реди максимумов
rawMax = maxs;
maxF.checkPass(max); // проверка выше максимума maxF.checkPass(max); // проверка выше максимума
if (getMax() - getMin() < _trsh) max = 0; // если окно громкости меньше порого то 0 if (getMax() - getMin() < _trsh) max = 0; // если окно громкости меньше порого то 0
else max = constrain(map(max, getMin(), getMax(), _volMin, _volMax), _volMin, _volMax); // перевод в громкость else max = constrain(map(max, getMin(), getMax(), _volMin, _volMax), _volMin, _volMax); // перевод в громкость
@@ -89,6 +91,9 @@ class VolAnalyzer {
int getRaw() { int getRaw() {
return raw; return raw;
} }
int getRawMax() {
return rawMax;
}
int getVol() { int getVol() {
return volF.getFil(); return volF.getFil();
} }
@@ -108,12 +113,13 @@ class VolAnalyzer {
private: private:
int _pin; int _pin;
int _dt = 600; // 600 мкс между сэмплами достаточно для музыки int _dt = 500; // 500 мкс между сэмплами достаточно для музыки
int _period = 5; // 5 мс между выборами достаточно int _period = 4; // 4 мс между выборами достаточно
int _ampliDt = 150; int _ampliDt = 150;
int _window = 20; // при таком размере окна получаем длительность оцифровки 12 мс, вполне хватает int _window = 20; // при таком размере окна получаем длительность оцифровки вполне хватает
uint32_t tmr1 = 0, tmr2 = 0, tmr3 = 0, tmr4 = 0; uint32_t tmr1 = 0, tmr2 = 0, tmr3 = 0;
int raw = 0; int raw = 0;
int rawMax = 0;
int max = 0, count = 0; int max = 0, count = 0;
int maxs = 0, mins = 1023; int maxs = 0, mins = 1023;
int _volMin = 0, _volMax = 100, _trsh = 30; int _volMin = 0, _volMax = 100, _trsh = 30;

View File

@@ -1,5 +1,6 @@
#if (USE_ADC == 1) #if (USE_ADC == 1)
void setupADC() { void setupADC() {
clap.setTimeout(500);
low.setDt(0); low.setDt(0);
low.setPeriod(0); low.setPeriod(0);
low.setWindow(0); low.setWindow(0);
@@ -32,32 +33,36 @@ void setupADC() {
void checkAnalog() { void checkAnalog() {
if (cfg.state) { //if (cfg.state) {
switch (cfg.adcMode) { switch (cfg.adcMode) {
case GL_ADC_NONE: break; case GL_ADC_NONE: break;
case GL_ADC_BRI: checkPhot(); break; case GL_ADC_BRI: checkPhot(); break;
case GL_ADC_MIC: checkMusic(); break; case GL_ADC_MIC: checkMusic(); break;
case GL_ADC_BOTH: case GL_ADC_BOTH:
{ {
static timerMillis tmr(1000, 1); static timerMillis tmr(1000, 1);
if (tmr.isReady()) { if (tmr.isReady()) {
switchToPhot(); switchToPhot();
phot.setRaw(analogRead(A0)); phot.setRaw(analogRead(A0));
switchToMic(); switchToMic();
} else { } else {
checkMusic(); checkMusic();
}
phot.compute();
} }
break; phot.compute();
} }
break;
} }
//}
} }
void checkMusic() { void checkMusic() {
if (CUR_PRES.advMode == GL_ADV_VOL) { // громкость vol.tick();
vol.tick(); #if (USE_CLAP == 1)
} else if (CUR_PRES.advMode == GL_ADV_LOW || CUR_PRES.advMode == GL_ADV_HIGH) { // частоты clap.tick(vol.getRawMax());
if (clap.hasClaps(2)) controlHandler(!cfg.state);
#endif
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);
FFT(raw, spectr); FFT(raw, spectr);

View File

@@ -16,7 +16,7 @@
#define GL_REACT_LEN 3 #define GL_REACT_LEN 3
#define GL_SLAVE 0 #define GL_SLAVE 0
#define GL_MASTER 1 #define GL_MASTER 1
#define MAX_PRESETS 25 // макс количество режимов #define MAX_PRESETS 40 // макс количество режимов
// ------------------- МАКРО -------------------- // ------------------- МАКРО --------------------
#ifdef DEBUG_SERIAL #ifdef DEBUG_SERIAL
@@ -61,9 +61,8 @@ struct Palette {
byte strip[16 * 3]; byte strip[16 * 3];
}; };
#define CFG_SIZE 13 #define CFG_SIZE 12
struct Config { struct Config {
byte GMT = 3; // часовой пояс +13
byte bright = 100; // яркость byte bright = 100; // яркость
byte adcMode = 1; // режим ацп (1 выкл, 2 ярк, 3 муз) byte adcMode = 1; // режим ацп (1 выкл, 2 ярк, 3 муз)
byte minBright = 0; // мин яркость byte minBright = 0; // мин яркость
@@ -79,7 +78,15 @@ struct Config {
int16_t length = 16; // длина ленты int16_t length = 16; // длина ленты
int16_t width = 16; // ширина матрицы int16_t width = 16; // ширина матрицы
byte GMT = 3; // часовой пояс +13
uint32_t cityID = 1; // city ID uint32_t cityID = 1; // city ID
bool mqtt = 0; // mqtt
char mqttID[32]; //
char mqttHost[32]; //
int mqttPort = 0; //
char mqttLogin[16]; //
char mqttPass[16]; //
byte state = 1; // состояние 0 выкл, 1 вкл byte state = 1; // состояние 0 выкл, 1 вкл
byte group = 1; // группа девайса (1-10) byte group = 1; // группа девайса (1-10)

View File

@@ -5,23 +5,23 @@ bool EEpalFlag = false;
void EE_startup() { void EE_startup() {
// старт епром // старт епром
if (EEPROM.read(511) != EE_KEY) { if (EEPROM.read(0) != EE_KEY) {
EEPROM.write(511, EE_KEY); EEPROM.write(0, EE_KEY);
EEPROM.put(0, cfg); EEPROM.put(1, cfg);
EEPROM.put(sizeof(cfg), dawn); EEPROM.put(sizeof(cfg) + 1, dawn);
EEPROM.put(sizeof(cfg) + sizeof(dawn), pal); EEPROM.put(sizeof(cfg) + sizeof(dawn) + 1, pal);
EEPROM.put(sizeof(cfg) + sizeof(dawn) + sizeof(pal), preset); EEPROM.put(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + 1, preset);
EEPROM.commit(); EEPROM.commit();
blink8(CRGB::Magenta); blink8(CRGB::Magenta);
DEBUGLN("First start"); DEBUGLN("First start");
} }
EEPROM.get(0, cfg); EEPROM.get(1, cfg);
EEPROM.get(sizeof(cfg), dawn); EEPROM.get(sizeof(cfg) + 1, dawn);
EEPROM.get(sizeof(cfg) + sizeof(dawn), pal); EEPROM.get(sizeof(cfg) + sizeof(dawn) + 1, pal);
EEPROM.get(sizeof(cfg) + sizeof(dawn) + sizeof(pal), preset); EEPROM.get(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + 1, preset);
DEBUG("EEPR size: "); DEBUG("EEPR size: ");
DEBUGLN(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + sizeof(preset)); DEBUGLN(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + sizeof(preset) + 1);
// запускаем всё // запускаем всё
FastLED.setMaxPowerInVoltsAndMilliamps(STRIP_VOLT, cfg.maxCur * 100); FastLED.setMaxPowerInVoltsAndMilliamps(STRIP_VOLT, cfg.maxCur * 100);
@@ -49,22 +49,22 @@ void checkEEupdate() {
if (EEcfgFlag || EEdawnFlag || EEpresetFlag) { if (EEcfgFlag || EEdawnFlag || EEpresetFlag) {
if (EEcfgFlag) { if (EEcfgFlag) {
EEcfgFlag = false; EEcfgFlag = false;
EEPROM.put(0, cfg); EEPROM.put(1, cfg);
DEBUGLN("save cfg"); DEBUGLN("save cfg");
} }
if (EEdawnFlag) { if (EEdawnFlag) {
EEdawnFlag = false; EEdawnFlag = false;
EEPROM.put(sizeof(cfg), dawn); EEPROM.put(sizeof(cfg) + 1, dawn);
DEBUGLN("save dawn"); DEBUGLN("save dawn");
} }
if (EEpalFlag) { if (EEpalFlag) {
EEpalFlag = false; EEpalFlag = false;
EEPROM.put(sizeof(cfg) + sizeof(dawn), pal); EEPROM.put(sizeof(cfg) + sizeof(dawn) + 1, pal);
DEBUGLN("save pal"); DEBUGLN("save pal");
} }
if (EEpresetFlag) { if (EEpresetFlag) {
EEpresetFlag = false; EEpresetFlag = false;
EEPROM.put(sizeof(cfg) + sizeof(dawn) + sizeof(pal), preset); EEPROM.put(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + 1, preset);
DEBUGLN("save preset"); DEBUGLN("save preset");
} }
EEPROM.commit(); EEPROM.commit();
@@ -79,6 +79,6 @@ void EE_updCfgRst() {
ESP.restart(); ESP.restart();
} }
void EE_updCfg() { void EE_updCfg() {
EEPROM.put(0, cfg); EEPROM.put(1, cfg);
EEPROM.commit(); EEPROM.commit();
} }

View File

@@ -22,6 +22,7 @@ void effectsRoutine() {
byte thisBright = getBright(); byte thisBright = getBright();
if (turnoffTmr.running()) thisBright = scaleFF(thisBright, 255 - turnoffTmr.getLength8()); if (turnoffTmr.running()) thisBright = scaleFF(thisBright, 255 - turnoffTmr.getLength8());
else if (blinkTmr.runningStop()) thisBright = scaleFF(thisBright, blinkTmr.getLength8());
if (turnoffTmr.isReady()) { if (turnoffTmr.isReady()) {
turnoffTmr.stop(); turnoffTmr.stop();
setPower(0); setPower(0);
@@ -40,12 +41,12 @@ void effectsRoutine() {
if (cfg.deviceType > 1) { if (cfg.deviceType > 1) {
FOR_j(0, cfg.length) { FOR_j(0, cfg.length) {
FOR_i(0, cfg.width) { FOR_i(0, cfg.width) {
leds[getPix(i, j)] = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], setPix(i, j, ColorFromPalette(paletteArr[CUR_PRES.palette - 1],
scalePal(inoise8( scalePal(inoise8(
i * (thisScale / 5) - cfg.width * (thisScale / 5) / 2, i * (thisScale / 5) - cfg.width * (thisScale / 5) / 2,
j * (thisScale / 5) - cfg.length * (thisScale / 5) / 2, j * (thisScale / 5) - cfg.length * (thisScale / 5) / 2,
(now.weekMs >> 1) * CUR_PRES.speed / 255)), (now.weekMs >> 1) * CUR_PRES.speed / 255)),
255, LINEARBLEND); 255, LINEARBLEND));
} }
} }

View File

@@ -31,7 +31,7 @@ void fire2020(byte scale, int len) {
} }
for (uint8_t i = 0; i < cfg.width; i++) { for (uint8_t i = 0; i < cfg.width; i++) {
for (uint8_t j = 0; j < len; j++) { for (uint8_t j = 0; j < len; j++) {
leds[getPix(i, len - 1U - j)] = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], qsub8(inoise8(i * deltaValue, (j + ff_y + random8(2)) * deltaHue, ff_z), shiftHue[j]), 255U); leds[getPix(i, len - 1U - j)] = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(qsub8(inoise8(i * deltaValue, (j + ff_y + random8(2)) * deltaHue, ff_z), shiftHue[j])), 255U);
} }
} }

View File

@@ -9,17 +9,15 @@ void parsing() {
buf[n] = NULL; buf[n] = NULL;
DEBUGLN(buf); // пакет вида <ключ>,<канал>,<тип>,<дата1>,<дата2>... DEBUGLN(buf); // пакет вида <ключ>,<канал>,<тип>,<дата1>,<дата2>...
mString pars(buf, sizeof(buf)); byte keyLen = strchr(buf, ',') - buf; // indexof
if (!pars.startsWith(GL_KEY)) return; // не наш ключ if (strncmp(buf, GL_KEY, keyLen)) return; // не наш ключ
byte keyLen = strlen(GL_KEY);
byte data[MAX_PRESETS * PRES_SIZE + 5]; byte data[MAX_PRESETS * PRES_SIZE + 5];
memset(data, 0, MAX_PRESETS * PRES_SIZE + keyLen); memset(data, 0, MAX_PRESETS * PRES_SIZE + 5);
int count = 0; int count = 0;
char *str, *p = buf + keyLen; // сдвиг до даты char *str, *p = buf + keyLen; // сдвиг до даты
char *ssid, *pass; char *ssid, *pass;
uint32_t city = 0;
uint16_t stripL, stripW;
while ((str = strtok_r(p, ",", &p)) != NULL) { while ((str = strtok_r(p, ",", &p)) != NULL) {
uint32_t thisInt = atoi(str); uint32_t thisInt = atoi(str);
data[count++] = (byte)thisInt; data[count++] = (byte)thisInt;
@@ -28,9 +26,16 @@ void parsing() {
if (count == 5) pass = str; if (count == 5) pass = str;
} }
if (data[1] == 1) { if (data[1] == 1) {
if (count == 16) stripL = thisInt; if (count == 15) cfg.length = thisInt;
if (count == 17) stripW = thisInt; if (count == 16) cfg.width = thisInt;
if (count == 18) city = thisInt; if (count == 17) cfg.GMT = byte(thisInt);
if (count == 18) cfg.cityID = thisInt;
if (count == 19) cfg.mqtt = byte(thisInt);
if (count == 20) strcpy(cfg.mqttID, str);
if (count == 21) strcpy(cfg.mqttHost, str);
if (count == 22) cfg.mqttPort = thisInt;
if (count == 23) strcpy(cfg.mqttLogin, str);
if (count == 24) strcpy(cfg.mqttPass, str);
} }
} }
@@ -46,7 +51,7 @@ void parsing() {
if (data[0] != cfg.group) return; // не наш адрес, выходим if (data[0] != cfg.group) return; // не наш адрес, выходим
switch (data[1]) { // тип 0 - control, 1 - config, 2 - effects, 3 - dawn, 4 - from master, 5 - palette switch (data[1]) { // тип 0 - control, 1 - config, 2 - effects, 3 - dawn, 4 - from master, 5 - palette
case 0: DEBUGLN("Control"); case 0: DEBUGLN("Control"); blinkTmr.restart();
switch (data[2]) { switch (data[2]) {
case 0: controlHandler(0); break; // выкл case 0: controlHandler(0); break; // выкл
case 1: controlHandler(1); break; // вкл case 1: controlHandler(1); break; // вкл
@@ -81,24 +86,21 @@ void parsing() {
case 13: // выключить через case 13: // выключить через
if (data[3] == 0) turnoffTmr.stop(); if (data[3] == 0) turnoffTmr.stop();
else { else {
turnoffTmr.setInterval((uint32_t)data[3] * 60000ul); fadeDown((uint32_t)data[3] * 60000ul);
turnoffTmr.restart();
} }
break; break;
} }
EE_updCfg(); EE_updCfg();
break; break;
case 1: DEBUGLN("Config"); case 1: DEBUGLN("Config"); blinkTmr.restart();
FOR_i(0, CFG_SIZE) { FOR_i(0, CFG_SIZE) {
*((byte*)&cfg + i) = data[i + 2]; // загоняем в структуру *((byte*)&cfg + i) = data[i + 2]; // загоняем в структуру
} }
cfg.length = stripL; if (cfg.deviceType == GL_TYPE_STRIP) {
cfg.width = stripW; if (cfg.length > MAX_LEDS) cfg.length = MAX_LEDS;
cfg.cityID = city; cfg.width = 1;
}
if (cfg.length > MAX_LEDS) cfg.length = MAX_LEDS;
if (cfg.deviceType == GL_TYPE_STRIP) cfg.width = 1;
if (cfg.length * cfg.width > MAX_LEDS) cfg.width = MAX_LEDS / cfg.length; if (cfg.length * cfg.width > MAX_LEDS) cfg.width = MAX_LEDS / cfg.length;
ntp.setTimeOffset((cfg.GMT - 13) * 3600); ntp.setTimeOffset((cfg.GMT - 13) * 3600);
FastLED.setMaxPowerInVoltsAndMilliamps(STRIP_VOLT, cfg.maxCur * 100); FastLED.setMaxPowerInVoltsAndMilliamps(STRIP_VOLT, cfg.maxCur * 100);
@@ -115,13 +117,15 @@ void parsing() {
*((byte*)&preset + j * PRES_SIZE + i) = data[j * PRES_SIZE + i + 3]; // загоняем в структуру *((byte*)&preset + j * PRES_SIZE + i) = data[j * PRES_SIZE + i + 3]; // загоняем в структуру
} }
} }
if (!cfg.rotation) setPreset(data[cfg.presetAmount * PRES_SIZE + 3] - 1); //if (!cfg.rotation) setPreset(data[cfg.presetAmount * PRES_SIZE + 3] - 1);
setPreset(data[cfg.presetAmount * PRES_SIZE + 3] - 1);
EE_updatePreset(); EE_updatePreset();
presetRotation(true); // форсировать смену режима //presetRotation(true); // форсировать смену режима
holdPresTmr.restart();
loading = true; loading = true;
break; break;
case 3: DEBUGLN("Dawn"); case 3: DEBUGLN("Dawn"); blinkTmr.restart();
FOR_i(0, (2 + 3 * 7)) { FOR_i(0, (2 + 3 * 7)) {
*((byte*)&dawn + i) = data[i + 2]; // загоняем в структуру *((byte*)&dawn + i) = data[i + 2]; // загоняем в структуру
} }
@@ -131,7 +135,7 @@ void parsing() {
case 4: DEBUGLN("From master"); case 4: DEBUGLN("From master");
if (cfg.role == GL_SLAVE) { if (cfg.role == GL_SLAVE) {
switch (data[2]) { switch (data[2]) {
case 0: setPower(data[3]); break; // вкл выкл case 0: fade(data[3]); break; // вкл выкл
case 1: setPreset(data[3]); break; // пресет case 1: setPreset(data[3]); break; // пресет
case 2: cfg.bright = data[3]; break; // яркость case 2: cfg.bright = data[3]; break; // яркость
} }
@@ -139,7 +143,7 @@ void parsing() {
} }
break; break;
case 5: DEBUGLN("Palette"); case 5: DEBUGLN("Palette"); blinkTmr.restart();
FOR_i(0, 1 + 16 * 3) { FOR_i(0, 1 + 16 * 3) {
*((byte*)&pal + i) = data[i + 2]; // загоняем в структуру *((byte*)&pal + i) = data[i + 2]; // загоняем в структуру
} }
@@ -147,7 +151,7 @@ void parsing() {
EE_updatePal(); EE_updatePal();
break; break;
case 6: DEBUGLN("Time"); case 6: DEBUGLN("Time"); blinkTmr.restart();
if (!cfg.WiFimode) { // если мы AP if (!cfg.WiFimode) { // если мы AP
now.day = data[2]; now.day = data[2];
now.hour = data[3]; now.hour = data[3];

View File

@@ -1,4 +1,5 @@
void presetRotation(bool force) { void presetRotation(bool force) {
if (holdPresTmr.runningStop()) return;
if (cfg.rotation && (now.newMin() || force)) { // если автосмена и новая минута if (cfg.rotation && (now.newMin() || force)) { // если автосмена и новая минута
if (cfg.rotRnd) { // случайная if (cfg.rotRnd) { // случайная
cfg.curPreset = trnd.fromMin(cfg.rotPeriod, cfg.presetAmount); cfg.curPreset = trnd.fromMin(cfg.rotPeriod, cfg.presetAmount);
@@ -17,35 +18,46 @@ void changePreset(int dir) {
cfg.curPreset += dir; cfg.curPreset += dir;
if (cfg.curPreset >= cfg.presetAmount) cfg.curPreset = 0; if (cfg.curPreset >= cfg.presetAmount) cfg.curPreset = 0;
if (cfg.curPreset < 0) cfg.curPreset = cfg.presetAmount - 1; if (cfg.curPreset < 0) cfg.curPreset = cfg.presetAmount - 1;
holdPresTmr.restart();
DEBUG("Preset changed to "); DEBUG("Preset changed to ");
DEBUGLN(cfg.curPreset); DEBUGLN(cfg.curPreset);
} }
} }
void setPreset(byte pres) { void setPreset(byte pres) {
if (!cfg.rotation) { // ручная смена //if (!cfg.rotation) { // ручная смена
cfg.curPreset = constrain(pres, 0, cfg.presetAmount - 1); cfg.curPreset = constrain(pres, 0, cfg.presetAmount - 1);
DEBUG("Preset set to "); holdPresTmr.restart();
DEBUGLN(cfg.curPreset); DEBUG("Preset set to ");
} DEBUGLN(cfg.curPreset);
//}
} }
void controlHandler(bool state) { void controlHandler(bool state) {
if (turnoffTmr.running()) { if (turnoffTmr.running()) {
turnoffTmr.stop(); turnoffTmr.stop();
delay(50);
FastLED.clear(); FastLED.clear();
FastLED.show();
DEBUGLN("stop off timer"); DEBUGLN("stop off timer");
return; return;
} }
if (dawnTmr.running()) { if (dawnTmr.running()) {
dawnTmr.stop(); dawnTmr.stop();
delay(50);
FastLED.clear(); FastLED.clear();
FastLED.show();
DEBUGLN("stop dawn timer"); DEBUGLN("stop dawn timer");
return; return;
} }
if (state) cfg.manualOff = 0; if (state) cfg.manualOff = 0;
if (cfg.state && !state) cfg.manualOff = 1; if (cfg.state && !state) cfg.manualOff = 1;
setPower(state); fade(state);
}
void fade(bool state) {
if (cfg.state && !state) fadeDown(600);
else setPower(state);
} }
void setPower(bool state) { void setPower(bool state) {
@@ -58,3 +70,8 @@ void setPower(bool state) {
sendToSlaves(0, cfg.state); sendToSlaves(0, cfg.state);
DEBUGLN(state ? "Power on" : "Power off"); DEBUGLN(state ? "Power on" : "Power off");
} }
void fadeDown(uint32_t time) {
turnoffTmr.setInterval(time);
turnoffTmr.restart();
}

View File

@@ -5,7 +5,10 @@ void setupTime() {
if (cfg.WiFimode) { if (cfg.WiFimode) {
// если подключены - запрашиваем время с сервера // если подключены - запрашиваем время с сервера
ntp.begin(); ntp.begin();
if (ntp.update() && !gotNTP) gotNTP = true; if (ntp.update() && !gotNTP) {
gotNTP = true;
DEBUGLN("Got ntp");
}
} }
} }
@@ -32,10 +35,10 @@ void updateTime() {
// берём время с интернета каждую NTP_UPD_PRD минуту, ставим флаг что данные с NTP получены, значит мы онлайн // берём время с интернета каждую NTP_UPD_PRD минуту, ставим флаг что данные с NTP получены, значит мы онлайн
if (ntp.update() && !gotNTP) gotNTP = true; if (ntp.update() && !gotNTP) gotNTP = true;
} }
checkDawn();
} else { // если нет } else { // если нет
now.tick(); // тикаем своим счётчиком now.tick(); // тикаем своим счётчиком
} }
if (gotNTP || gotTime) checkDawn();
} }
void sendTimeToSlaves() { void sendTimeToSlaves() {
@@ -53,9 +56,11 @@ void checkDawn() {
int dawnMinute = dawn.hour[now.day] * 60 + dawn.minute[now.day] - dawn.time; int dawnMinute = dawn.hour[now.day] * 60 + dawn.minute[now.day] - dawn.time;
if (dawnMinute < 0) dawnMinute += 1440; if (dawnMinute < 0) dawnMinute += 1440;
if (dawnMinute == now.hour * 60 + now.min) { if (dawnMinute == now.hour * 60 + now.min) {
DEBUGLN("dawn start"); DEBUG("dawn start ");
DEBUGLN(dawn.time * 60000ul);
dawnTmr.setInterval(dawn.time * 60000ul); dawnTmr.setInterval(dawn.time * 60000ul);
dawnTmr.restart(); dawnTmr.restart();
FastLED.setBrightness(255);
} }
} }
} }
@@ -65,8 +70,8 @@ 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;
if (curState && !cfg.state && !cfg.manualOff) setPower(1); // нужно включить, а лампа выключена и не выключалась вручную if (curState && !cfg.state && !cfg.manualOff) fade(1); // нужно включить, а лампа выключена и не выключалась вручную
if (!curState && cfg.state) setPower(0); // нужно выключить, а лампа включена if (!curState && cfg.state) fade(0); // нужно выключить, а лампа включена
} }
} }

View File

@@ -17,6 +17,10 @@ class timerMillis {
} }
return false; return false;
} }
boolean runningStop() {
if (_active && millis() - _tmr >= _interval) stop();
return _active;
}
void reset() { void reset() {
_tmr = millis(); _tmr = millis();
} }
@@ -31,7 +35,7 @@ class timerMillis {
return _active; return _active;
} }
byte getLength8() { byte getLength8() {
return (millis() - _tmr) * 255ul / _interval; return (_active) ? ((millis() - _tmr) * 255ul / _interval) : 0;
} }
private: private: