mirror of
https://github.com/AlexGyver/GyverLamp2.git
synced 2025-08-08 17:11:05 +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 {
|
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;
|
||||||
|
@@ -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(); // читаем епром
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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)
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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];
|
||||||
|
@@ -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();
|
||||||
|
}
|
||||||
|
@@ -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); // нужно выключить, а лампа включена
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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:
|
||||||
|
Reference in New Issue
Block a user