mirror of
https://github.com/AlexGyver/GyverLamp2.git
synced 2025-08-07 08:40:35 +03:00
v0.17b
This commit is contained in:
89
firmware/GyverLamp2/Clap.h
Normal file
89
firmware/GyverLamp2/Clap.h
Normal 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;
|
||||
};
|
@@ -8,6 +8,10 @@
|
||||
|
||||
class FastFilter {
|
||||
public:
|
||||
FastFilter(byte k = 20, int dt = 0) {
|
||||
setK(k);
|
||||
setDt(dt);
|
||||
}
|
||||
void setK(byte k) {
|
||||
_k1 = k;
|
||||
_k2 = 32 - k;
|
||||
|
@@ -1,4 +1,13 @@
|
||||
/*
|
||||
Версия 0.17b
|
||||
Автосмена отключается 30 сек во время настройки режимов
|
||||
Убрана кнопка upload в режимах
|
||||
Лампа чуть мигает при получении данных
|
||||
Кастом палитра работает на огне 2020
|
||||
Вкл выкл двумя хлопками
|
||||
Плавное выключение
|
||||
Починил рассвет
|
||||
|
||||
Версия 0.16b
|
||||
Исправлен масштаб огня 2020
|
||||
Фикс невыключения рассвета
|
||||
@@ -27,13 +36,12 @@
|
||||
Выключение по таймеру теперь плавное
|
||||
Добавлен рассвет
|
||||
|
||||
TODO:
|
||||
TODO:
|
||||
плавная смена режимов
|
||||
4 клика вкл выкл смену?
|
||||
Mqtt?
|
||||
Базовый пак
|
||||
Предложения Серёги крутского
|
||||
Убрать аплод?
|
||||
Эффект погода https://it4it.club/topic/40-esp8266-i-parsing-pogodyi-s-openweathermap/
|
||||
Эффект часы
|
||||
*/
|
||||
@@ -55,6 +63,7 @@
|
||||
|
||||
// ------------- АЦП --------------
|
||||
#define USE_ADC 1 // можно выпилить АЦП
|
||||
#define USE_CLAP 1 // два хлопка в ладоши вкл выкл лампу
|
||||
#define MIC_VCC 12 // питание микрофона GPIO12 (D6 на wemos/node)
|
||||
#define PHOT_VCC 14 // питание фоторезистора GPIO14 (D5 на wemos/node)
|
||||
|
||||
@@ -77,10 +86,10 @@ const char AP_NameChar[] = "GyverLamp2";
|
||||
const char WiFiPassword[] = "12345678";
|
||||
|
||||
// ------------ Прочее -------------
|
||||
#define GL_VERSION 016 // код версии прошивки
|
||||
#define GL_VERSION 017 // код версии прошивки
|
||||
#define EE_TOUT 30000 // таймаут сохранения епром после изменения, мс
|
||||
//#define DEBUG_SERIAL // закомментируй чтобы выключить отладку (скорость 115200)
|
||||
#define EE_KEY 52 // ключ сброса WiFi (измени для сброса всех настроек)
|
||||
#define EE_KEY 55 // ключ сброса WiFi (измени для сброса всех настроек)
|
||||
#define NTP_UPD_PRD 5 // период обновления времени с NTP сервера, минут
|
||||
//#define SKIP_WIFI // пропустить подключение к вафле (для отладки)
|
||||
|
||||
@@ -113,6 +122,7 @@ const char WiFiPassword[] = "12345678";
|
||||
#include <EEPROM.h> // епром
|
||||
#include "ESP8266httpUpdate.h" // OTA
|
||||
#include "mString.h" // стринг билдер
|
||||
#include "Clap.h" // обработка хлопков
|
||||
|
||||
// ------------------- ДАТА --------------------
|
||||
Config cfg;
|
||||
@@ -126,10 +136,11 @@ NTPClient ntp(ntpUDP);
|
||||
CRGB leds[MAX_LEDS];
|
||||
Time now;
|
||||
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;
|
||||
VolAnalyzer vol(A0), low, high;
|
||||
FastFilter phot;
|
||||
Clap clap;
|
||||
|
||||
byte btnClicks = 0, brTicks = 0;
|
||||
unsigned char matrixValue[11][16];
|
||||
@@ -145,7 +156,7 @@ void setup() {
|
||||
Serial.begin(115200);
|
||||
DEBUGLN();
|
||||
#endif
|
||||
EEPROM.begin(512); // старт епром
|
||||
EEPROM.begin(1000); // старт епром
|
||||
startStrip(); // старт ленты
|
||||
btn.setLevel(digitalRead(BTN_PIN)); // смотрим что за кнопка
|
||||
EE_startup(); // читаем епром
|
||||
|
@@ -49,8 +49,8 @@ class VolAnalyzer {
|
||||
}
|
||||
bool tick(int thisRead = -1) {
|
||||
volF.compute();
|
||||
if (millis() - tmr4 >= _ampliDt) { // период сглаживания амплитуды
|
||||
tmr4 = millis();
|
||||
if (millis() - tmr3 >= _ampliDt) { // период сглаживания амплитуды
|
||||
tmr3 = millis();
|
||||
maxF.setRaw(maxs);
|
||||
minF.setRaw(mins);
|
||||
maxF.compute();
|
||||
@@ -68,11 +68,13 @@ class VolAnalyzer {
|
||||
maxF.setFil(thisRead);
|
||||
minF.setFil(thisRead);
|
||||
}
|
||||
|
||||
if (++count >= _window) { // выборка завершена
|
||||
tmr1 = millis();
|
||||
raw = max;
|
||||
if (max > maxs) maxs = max; // максимумы среди максимумов
|
||||
if (max < mins) mins = max; // минимумы реди максимумов
|
||||
rawMax = maxs;
|
||||
maxF.checkPass(max); // проверка выше максимума
|
||||
if (getMax() - getMin() < _trsh) max = 0; // если окно громкости меньше порого то 0
|
||||
else max = constrain(map(max, getMin(), getMax(), _volMin, _volMax), _volMin, _volMax); // перевод в громкость
|
||||
@@ -89,6 +91,9 @@ class VolAnalyzer {
|
||||
int getRaw() {
|
||||
return raw;
|
||||
}
|
||||
int getRawMax() {
|
||||
return rawMax;
|
||||
}
|
||||
int getVol() {
|
||||
return volF.getFil();
|
||||
}
|
||||
@@ -108,15 +113,16 @@ class VolAnalyzer {
|
||||
|
||||
private:
|
||||
int _pin;
|
||||
int _dt = 600; // 600 мкс между сэмплами достаточно для музыки
|
||||
int _period = 5; // 5 мс между выборами достаточно
|
||||
int _dt = 500; // 500 мкс между сэмплами достаточно для музыки
|
||||
int _period = 4; // 4 мс между выборами достаточно
|
||||
int _ampliDt = 150;
|
||||
int _window = 20; // при таком размере окна получаем длительность оцифровки 12 мс, вполне хватает
|
||||
uint32_t tmr1 = 0, tmr2 = 0, tmr3 = 0, tmr4 = 0;
|
||||
int _window = 20; // при таком размере окна получаем длительность оцифровки вполне хватает
|
||||
uint32_t tmr1 = 0, tmr2 = 0, tmr3 = 0;
|
||||
int raw = 0;
|
||||
int rawMax = 0;
|
||||
int max = 0, count = 0;
|
||||
int maxs = 0, mins = 1023;
|
||||
int _volMin = 0, _volMax = 100, _trsh = 30;
|
||||
bool _pulse = 0, _first = 0;
|
||||
bool _pulse = 0, _first = 0;
|
||||
FastFilter minF, maxF, volF;
|
||||
};
|
||||
|
@@ -1,5 +1,6 @@
|
||||
#if (USE_ADC == 1)
|
||||
void setupADC() {
|
||||
clap.setTimeout(500);
|
||||
low.setDt(0);
|
||||
low.setPeriod(0);
|
||||
low.setWindow(0);
|
||||
@@ -32,32 +33,36 @@ void setupADC() {
|
||||
|
||||
|
||||
void checkAnalog() {
|
||||
if (cfg.state) {
|
||||
switch (cfg.adcMode) {
|
||||
case GL_ADC_NONE: break;
|
||||
case GL_ADC_BRI: checkPhot(); break;
|
||||
case GL_ADC_MIC: checkMusic(); break;
|
||||
case GL_ADC_BOTH:
|
||||
{
|
||||
static timerMillis tmr(1000, 1);
|
||||
if (tmr.isReady()) {
|
||||
switchToPhot();
|
||||
phot.setRaw(analogRead(A0));
|
||||
switchToMic();
|
||||
} else {
|
||||
checkMusic();
|
||||
}
|
||||
phot.compute();
|
||||
//if (cfg.state) {
|
||||
switch (cfg.adcMode) {
|
||||
case GL_ADC_NONE: break;
|
||||
case GL_ADC_BRI: checkPhot(); break;
|
||||
case GL_ADC_MIC: checkMusic(); break;
|
||||
case GL_ADC_BOTH:
|
||||
{
|
||||
static timerMillis tmr(1000, 1);
|
||||
if (tmr.isReady()) {
|
||||
switchToPhot();
|
||||
phot.setRaw(analogRead(A0));
|
||||
switchToMic();
|
||||
} else {
|
||||
checkMusic();
|
||||
}
|
||||
break;
|
||||
}
|
||||
phot.compute();
|
||||
}
|
||||
break;
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
void checkMusic() {
|
||||
if (CUR_PRES.advMode == GL_ADV_VOL) { // громкость
|
||||
vol.tick();
|
||||
} else if (CUR_PRES.advMode == GL_ADV_LOW || CUR_PRES.advMode == GL_ADV_HIGH) { // частоты
|
||||
vol.tick();
|
||||
#if (USE_CLAP == 1)
|
||||
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];
|
||||
for (int i = 0; i < FFT_SIZE; i++) raw[i] = analogRead(A0);
|
||||
FFT(raw, spectr);
|
||||
|
@@ -16,7 +16,7 @@
|
||||
#define GL_REACT_LEN 3
|
||||
#define GL_SLAVE 0
|
||||
#define GL_MASTER 1
|
||||
#define MAX_PRESETS 25 // макс количество режимов
|
||||
#define MAX_PRESETS 40 // макс количество режимов
|
||||
|
||||
// ------------------- МАКРО --------------------
|
||||
#ifdef DEBUG_SERIAL
|
||||
@@ -61,9 +61,8 @@ struct Palette {
|
||||
byte strip[16 * 3];
|
||||
};
|
||||
|
||||
#define CFG_SIZE 13
|
||||
#define CFG_SIZE 12
|
||||
struct Config {
|
||||
byte GMT = 3; // часовой пояс +13
|
||||
byte bright = 100; // яркость
|
||||
byte adcMode = 1; // режим ацп (1 выкл, 2 ярк, 3 муз)
|
||||
byte minBright = 0; // мин яркость
|
||||
@@ -79,7 +78,15 @@ struct Config {
|
||||
|
||||
int16_t length = 16; // длина ленты
|
||||
int16_t width = 16; // ширина матрицы
|
||||
|
||||
byte GMT = 3; // часовой пояс +13
|
||||
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 group = 1; // группа девайса (1-10)
|
||||
|
@@ -5,23 +5,23 @@ bool EEpalFlag = false;
|
||||
|
||||
void EE_startup() {
|
||||
// старт епром
|
||||
if (EEPROM.read(511) != EE_KEY) {
|
||||
EEPROM.write(511, EE_KEY);
|
||||
EEPROM.put(0, cfg);
|
||||
EEPROM.put(sizeof(cfg), dawn);
|
||||
EEPROM.put(sizeof(cfg) + sizeof(dawn), pal);
|
||||
EEPROM.put(sizeof(cfg) + sizeof(dawn) + sizeof(pal), preset);
|
||||
if (EEPROM.read(0) != EE_KEY) {
|
||||
EEPROM.write(0, EE_KEY);
|
||||
EEPROM.put(1, cfg);
|
||||
EEPROM.put(sizeof(cfg) + 1, dawn);
|
||||
EEPROM.put(sizeof(cfg) + sizeof(dawn) + 1, pal);
|
||||
EEPROM.put(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + 1, preset);
|
||||
EEPROM.commit();
|
||||
blink8(CRGB::Magenta);
|
||||
DEBUGLN("First start");
|
||||
}
|
||||
EEPROM.get(0, cfg);
|
||||
EEPROM.get(sizeof(cfg), dawn);
|
||||
EEPROM.get(sizeof(cfg) + sizeof(dawn), pal);
|
||||
EEPROM.get(sizeof(cfg) + sizeof(dawn) + sizeof(pal), preset);
|
||||
|
||||
EEPROM.get(1, cfg);
|
||||
EEPROM.get(sizeof(cfg) + 1, dawn);
|
||||
EEPROM.get(sizeof(cfg) + sizeof(dawn) + 1, pal);
|
||||
EEPROM.get(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + 1, preset);
|
||||
|
||||
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);
|
||||
@@ -49,24 +49,24 @@ void checkEEupdate() {
|
||||
if (EEcfgFlag || EEdawnFlag || EEpresetFlag) {
|
||||
if (EEcfgFlag) {
|
||||
EEcfgFlag = false;
|
||||
EEPROM.put(0, cfg);
|
||||
EEPROM.put(1, cfg);
|
||||
DEBUGLN("save cfg");
|
||||
}
|
||||
if (EEdawnFlag) {
|
||||
EEdawnFlag = false;
|
||||
EEPROM.put(sizeof(cfg), dawn);
|
||||
EEPROM.put(sizeof(cfg) + 1, dawn);
|
||||
DEBUGLN("save dawn");
|
||||
}
|
||||
if (EEpalFlag) {
|
||||
EEpalFlag = false;
|
||||
EEPROM.put(sizeof(cfg) + sizeof(dawn), pal);
|
||||
EEPROM.put(sizeof(cfg) + sizeof(dawn) + 1, pal);
|
||||
DEBUGLN("save pal");
|
||||
}
|
||||
if (EEpresetFlag) {
|
||||
EEpresetFlag = false;
|
||||
EEPROM.put(sizeof(cfg) + sizeof(dawn) + sizeof(pal), preset);
|
||||
EEPROM.put(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + 1, preset);
|
||||
DEBUGLN("save preset");
|
||||
}
|
||||
}
|
||||
EEPROM.commit();
|
||||
}
|
||||
EEtmr.stop();
|
||||
@@ -79,6 +79,6 @@ void EE_updCfgRst() {
|
||||
ESP.restart();
|
||||
}
|
||||
void EE_updCfg() {
|
||||
EEPROM.put(0, cfg);
|
||||
EEPROM.put(1, cfg);
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ void effectsRoutine() {
|
||||
byte thisBright = getBright();
|
||||
|
||||
if (turnoffTmr.running()) thisBright = scaleFF(thisBright, 255 - turnoffTmr.getLength8());
|
||||
else if (blinkTmr.runningStop()) thisBright = scaleFF(thisBright, blinkTmr.getLength8());
|
||||
if (turnoffTmr.isReady()) {
|
||||
turnoffTmr.stop();
|
||||
setPower(0);
|
||||
@@ -40,12 +41,12 @@ void effectsRoutine() {
|
||||
if (cfg.deviceType > 1) {
|
||||
FOR_j(0, cfg.length) {
|
||||
FOR_i(0, cfg.width) {
|
||||
leds[getPix(i, j)] = ColorFromPalette(paletteArr[CUR_PRES.palette - 1],
|
||||
scalePal(inoise8(
|
||||
i * (thisScale / 5) - cfg.width * (thisScale / 5) / 2,
|
||||
j * (thisScale / 5) - cfg.length * (thisScale / 5) / 2,
|
||||
(now.weekMs >> 1) * CUR_PRES.speed / 255)),
|
||||
255, LINEARBLEND);
|
||||
setPix(i, j, ColorFromPalette(paletteArr[CUR_PRES.palette - 1],
|
||||
scalePal(inoise8(
|
||||
i * (thisScale / 5) - cfg.width * (thisScale / 5) / 2,
|
||||
j * (thisScale / 5) - cfg.length * (thisScale / 5) / 2,
|
||||
(now.weekMs >> 1) * CUR_PRES.speed / 255)),
|
||||
255, LINEARBLEND));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,7 +170,7 @@ void effectsRoutine() {
|
||||
|
||||
case 7: // ==================================== ОГОНЬ 2020 ====================================
|
||||
FastLED.clear();
|
||||
if (cfg.deviceType > 1) { // 2D огонь
|
||||
if (cfg.deviceType > 1) { // 2D огонь
|
||||
fire2020(CUR_PRES.scale, thisLength);
|
||||
} else { // 1D огонь
|
||||
static byte heat[MAX_LEDS];
|
||||
|
@@ -31,7 +31,7 @@ void fire2020(byte scale, int len) {
|
||||
}
|
||||
for (uint8_t i = 0; i < cfg.width; i++) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -9,17 +9,15 @@ void parsing() {
|
||||
|
||||
buf[n] = NULL;
|
||||
DEBUGLN(buf); // пакет вида <ключ>,<канал>,<тип>,<дата1>,<дата2>...
|
||||
mString pars(buf, sizeof(buf));
|
||||
if (!pars.startsWith(GL_KEY)) return; // не наш ключ
|
||||
byte keyLen = strlen(GL_KEY);
|
||||
byte keyLen = strchr(buf, ',') - buf; // indexof
|
||||
if (strncmp(buf, GL_KEY, keyLen)) return; // не наш ключ
|
||||
|
||||
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;
|
||||
char *str, *p = buf + keyLen; // сдвиг до даты
|
||||
char *ssid, *pass;
|
||||
uint32_t city = 0;
|
||||
uint16_t stripL, stripW;
|
||||
|
||||
while ((str = strtok_r(p, ",", &p)) != NULL) {
|
||||
uint32_t thisInt = atoi(str);
|
||||
data[count++] = (byte)thisInt;
|
||||
@@ -28,9 +26,16 @@ void parsing() {
|
||||
if (count == 5) pass = str;
|
||||
}
|
||||
if (data[1] == 1) {
|
||||
if (count == 16) stripL = thisInt;
|
||||
if (count == 17) stripW = thisInt;
|
||||
if (count == 18) city = thisInt;
|
||||
if (count == 15) cfg.length = thisInt;
|
||||
if (count == 16) cfg.width = 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; // не наш адрес, выходим
|
||||
|
||||
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]) {
|
||||
case 0: controlHandler(0); break; // выкл
|
||||
case 1: controlHandler(1); break; // вкл
|
||||
@@ -81,24 +86,21 @@ void parsing() {
|
||||
case 13: // выключить через
|
||||
if (data[3] == 0) turnoffTmr.stop();
|
||||
else {
|
||||
turnoffTmr.setInterval((uint32_t)data[3] * 60000ul);
|
||||
turnoffTmr.restart();
|
||||
fadeDown((uint32_t)data[3] * 60000ul);
|
||||
}
|
||||
break;
|
||||
}
|
||||
EE_updCfg();
|
||||
break;
|
||||
|
||||
case 1: DEBUGLN("Config");
|
||||
case 1: DEBUGLN("Config"); blinkTmr.restart();
|
||||
FOR_i(0, CFG_SIZE) {
|
||||
*((byte*)&cfg + i) = data[i + 2]; // загоняем в структуру
|
||||
}
|
||||
cfg.length = stripL;
|
||||
cfg.width = stripW;
|
||||
cfg.cityID = city;
|
||||
|
||||
if (cfg.length > MAX_LEDS) cfg.length = MAX_LEDS;
|
||||
if (cfg.deviceType == GL_TYPE_STRIP) cfg.width = 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;
|
||||
ntp.setTimeOffset((cfg.GMT - 13) * 3600);
|
||||
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]; // загоняем в структуру
|
||||
}
|
||||
}
|
||||
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();
|
||||
presetRotation(true); // форсировать смену режима
|
||||
//presetRotation(true); // форсировать смену режима
|
||||
holdPresTmr.restart();
|
||||
loading = true;
|
||||
break;
|
||||
|
||||
case 3: DEBUGLN("Dawn");
|
||||
case 3: DEBUGLN("Dawn"); blinkTmr.restart();
|
||||
FOR_i(0, (2 + 3 * 7)) {
|
||||
*((byte*)&dawn + i) = data[i + 2]; // загоняем в структуру
|
||||
}
|
||||
@@ -131,7 +135,7 @@ void parsing() {
|
||||
case 4: DEBUGLN("From master");
|
||||
if (cfg.role == GL_SLAVE) {
|
||||
switch (data[2]) {
|
||||
case 0: setPower(data[3]); break; // вкл выкл
|
||||
case 0: fade(data[3]); break; // вкл выкл
|
||||
case 1: setPreset(data[3]); break; // пресет
|
||||
case 2: cfg.bright = data[3]; break; // яркость
|
||||
}
|
||||
@@ -139,7 +143,7 @@ void parsing() {
|
||||
}
|
||||
break;
|
||||
|
||||
case 5: DEBUGLN("Palette");
|
||||
case 5: DEBUGLN("Palette"); blinkTmr.restart();
|
||||
FOR_i(0, 1 + 16 * 3) {
|
||||
*((byte*)&pal + i) = data[i + 2]; // загоняем в структуру
|
||||
}
|
||||
@@ -147,7 +151,7 @@ void parsing() {
|
||||
EE_updatePal();
|
||||
break;
|
||||
|
||||
case 6: DEBUGLN("Time");
|
||||
case 6: DEBUGLN("Time"); blinkTmr.restart();
|
||||
if (!cfg.WiFimode) { // если мы AP
|
||||
now.day = data[2];
|
||||
now.hour = data[3];
|
||||
|
@@ -1,5 +1,6 @@
|
||||
void presetRotation(bool force) {
|
||||
if (cfg.rotation && (now.newMin() || force)) { // если автосмена и новая минута
|
||||
if (holdPresTmr.runningStop()) return;
|
||||
if (cfg.rotation && (now.newMin() || force)) { // если автосмена и новая минута
|
||||
if (cfg.rotRnd) { // случайная
|
||||
cfg.curPreset = trnd.fromMin(cfg.rotPeriod, cfg.presetAmount);
|
||||
DEBUG("Rnd changed to ");
|
||||
@@ -17,35 +18,46 @@ void changePreset(int dir) {
|
||||
cfg.curPreset += dir;
|
||||
if (cfg.curPreset >= cfg.presetAmount) cfg.curPreset = 0;
|
||||
if (cfg.curPreset < 0) cfg.curPreset = cfg.presetAmount - 1;
|
||||
holdPresTmr.restart();
|
||||
DEBUG("Preset changed to ");
|
||||
DEBUGLN(cfg.curPreset);
|
||||
}
|
||||
}
|
||||
|
||||
void setPreset(byte pres) {
|
||||
if (!cfg.rotation) { // ручная смена
|
||||
cfg.curPreset = constrain(pres, 0, cfg.presetAmount - 1);
|
||||
DEBUG("Preset set to ");
|
||||
DEBUGLN(cfg.curPreset);
|
||||
}
|
||||
//if (!cfg.rotation) { // ручная смена
|
||||
cfg.curPreset = constrain(pres, 0, cfg.presetAmount - 1);
|
||||
holdPresTmr.restart();
|
||||
DEBUG("Preset set to ");
|
||||
DEBUGLN(cfg.curPreset);
|
||||
//}
|
||||
}
|
||||
|
||||
void controlHandler(bool state) {
|
||||
if (turnoffTmr.running()) {
|
||||
turnoffTmr.stop();
|
||||
delay(50);
|
||||
FastLED.clear();
|
||||
FastLED.show();
|
||||
DEBUGLN("stop off timer");
|
||||
return;
|
||||
}
|
||||
if (dawnTmr.running()) {
|
||||
dawnTmr.stop();
|
||||
delay(50);
|
||||
FastLED.clear();
|
||||
FastLED.show();
|
||||
DEBUGLN("stop dawn timer");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (state) cfg.manualOff = 0;
|
||||
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) {
|
||||
@@ -58,3 +70,8 @@ void setPower(bool state) {
|
||||
sendToSlaves(0, cfg.state);
|
||||
DEBUGLN(state ? "Power on" : "Power off");
|
||||
}
|
||||
|
||||
void fadeDown(uint32_t time) {
|
||||
turnoffTmr.setInterval(time);
|
||||
turnoffTmr.restart();
|
||||
}
|
||||
|
@@ -5,7 +5,10 @@ void setupTime() {
|
||||
if (cfg.WiFimode) {
|
||||
// если подключены - запрашиваем время с сервера
|
||||
ntp.begin();
|
||||
if (ntp.update() && !gotNTP) gotNTP = true;
|
||||
if (ntp.update() && !gotNTP) {
|
||||
gotNTP = true;
|
||||
DEBUGLN("Got ntp");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,11 +34,11 @@ void updateTime() {
|
||||
if (now.min % NTP_UPD_PRD == 0 && now.sec == 0) {
|
||||
// берём время с интернета каждую NTP_UPD_PRD минуту, ставим флаг что данные с NTP получены, значит мы онлайн
|
||||
if (ntp.update() && !gotNTP) gotNTP = true;
|
||||
}
|
||||
checkDawn();
|
||||
}
|
||||
} else { // если нет
|
||||
now.tick(); // тикаем своим счётчиком
|
||||
}
|
||||
if (gotNTP || gotTime) checkDawn();
|
||||
}
|
||||
|
||||
void sendTimeToSlaves() {
|
||||
@@ -53,9 +56,11 @@ void checkDawn() {
|
||||
int dawnMinute = dawn.hour[now.day] * 60 + dawn.minute[now.day] - dawn.time;
|
||||
if (dawnMinute < 0) dawnMinute += 1440;
|
||||
if (dawnMinute == now.hour * 60 + now.min) {
|
||||
DEBUGLN("dawn start");
|
||||
DEBUG("dawn start ");
|
||||
DEBUGLN(dawn.time * 60000ul);
|
||||
dawnTmr.setInterval(dawn.time * 60000ul);
|
||||
dawnTmr.restart();
|
||||
FastLED.setBrightness(255);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,8 +70,8 @@ void checkWorkTime() {
|
||||
byte curState = isWorkTime(now.hour, cfg.workFrom, cfg.workTo);
|
||||
if (prevState != curState) { // переключение расписания
|
||||
prevState = curState;
|
||||
if (curState && !cfg.state && !cfg.manualOff) setPower(1); // нужно включить, а лампа выключена и не выключалась вручную
|
||||
if (!curState && cfg.state) setPower(0); // нужно выключить, а лампа включена
|
||||
if (curState && !cfg.state && !cfg.manualOff) fade(1); // нужно включить, а лампа выключена и не выключалась вручную
|
||||
if (!curState && cfg.state) fade(0); // нужно выключить, а лампа включена
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,10 @@ class timerMillis {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
boolean runningStop() {
|
||||
if (_active && millis() - _tmr >= _interval) stop();
|
||||
return _active;
|
||||
}
|
||||
void reset() {
|
||||
_tmr = millis();
|
||||
}
|
||||
@@ -31,7 +35,7 @@ class timerMillis {
|
||||
return _active;
|
||||
}
|
||||
byte getLength8() {
|
||||
return (millis() - _tmr) * 255ul / _interval;
|
||||
return (_active) ? ((millis() - _tmr) * 255ul / _interval) : 0;
|
||||
}
|
||||
|
||||
private:
|
||||
|
Reference in New Issue
Block a user