This commit is contained in:
Alex
2021-02-23 16:46:13 +03:00
parent aa6c2618fa
commit 7b935d2f9c
7 changed files with 152 additions and 63 deletions

View File

@@ -1,4 +1,10 @@
/*
Версия 0.14b
Мелкие баги
Вернул искры огню
Добавлены палитры
Добавлен огонь 2020
Версия 0.13b
Улучшена стабильность
@@ -24,9 +30,6 @@
Базовый пак
Предложения Серёги крутского
Убрать аплод?
Огонь 2018/2020?
Взять огонь отсюда https://community.alexgyver.ru/threads/wifi-lampa-budilnik-obsuzhdenie-proshivki-ot-gunner47.2418/page-72#post-33652
Вернуть искры
Эффект погода https://it4it.club/topic/40-esp8266-i-parsing-pogodyi-s-openweathermap/
Эффект часы
*/
@@ -70,10 +73,10 @@ const char AP_NameChar[] = "GyverLamp2";
const char WiFiPassword[] = "12345678";
// ------------ Прочее -------------
#define GL_VERSION 013 // код версии прошивки
#define GL_VERSION 014 // код версии прошивки
#define EE_TOUT 30000 // таймаут сохранения епром после изменения, мс
//#define DEBUG_SERIAL // закомментируй чтобы выключить отладку (скорость 115200)
#define EE_KEY 51 // ключ сброса WiFi (измени для сброса всех настроек)
#define EE_KEY 52 // ключ сброса WiFi (измени для сброса всех настроек)
#define NTP_UPD_PRD 5 // период обновления времени с NTP сервера, минут
//#define SKIP_WIFI // пропустить подключение к вафле (для отладки)
@@ -127,6 +130,7 @@ FastFilter phot;
byte btnClicks = 0, brTicks = 0;
unsigned char matrixValue[11][16];
bool gotNTP = false, gotTime = false;
bool loading = true;
void blink8(CRGB color);
// ------------------- SETUP --------------------

View File

@@ -7,7 +7,10 @@ void effectsRoutine() {
fill_solid(leds, MAX_LEDS, ColorFromPalette(HeatColors_p, dawnTmr.getLength8(), scaleFF(dawnTmr.getLength8(), dawn.bright), LINEARBLEND));
FastLED.show();
}
if (dawnTmr.isReady()) dawnTmr.stop();
if (dawnTmr.isReady()) {
dawnTmr.stop();
FastLED.clear();
}
return;
}
@@ -28,8 +31,9 @@ void effectsRoutine() {
if (prevEff != CUR_PRES.effect) {
FastLED.clear();
prevEff = CUR_PRES.effect;
loading = true;
}
// =================================================== ЭФФЕКТЫ ===================================================
switch (CUR_PRES.effect) {
case 1: // =================================== ПЕРЛИН ===================================
if (cfg.deviceType > 1) {
@@ -56,8 +60,8 @@ void effectsRoutine() {
case 2: // ==================================== ЦВЕТ ====================================
{
fill_solid(leds, cfg.length * thisWidth, CHSV(CUR_PRES.color, thisScale, CUR_PRES.min));
CRGB thisColor = CHSV(CUR_PRES.color, thisScale, CUR_PRES.max);
fill_solid(leds, cfg.length * thisWidth, CHSV(CUR_PRES.color, thisScale, 30));
CRGB thisColor = CHSV(CUR_PRES.color, thisScale, thisBright);
if (CUR_PRES.fromCenter) {
fillStrip(cfg.length / 2, cfg.length / 2 + thisLength / 2, thisColor);
fillStrip(cfg.length / 2 - thisLength / 2, cfg.length / 2, thisColor);
@@ -69,9 +73,9 @@ void effectsRoutine() {
case 3: // ================================= СМЕНА ЦВЕТА =================================
{
CRGB thisColor = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal((now.weekMs >> 5) * CUR_PRES.speed / 255), CUR_PRES.min, LINEARBLEND);
CRGB thisColor = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal((now.weekMs >> 5) * CUR_PRES.speed / 255), 10, LINEARBLEND);
fill_solid(leds, cfg.length * thisWidth, thisColor);
thisColor = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal((now.weekMs >> 5) * CUR_PRES.speed / 255), CUR_PRES.max, LINEARBLEND);
thisColor = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal((now.weekMs >> 5) * CUR_PRES.speed / 255), thisBright, LINEARBLEND);
if (CUR_PRES.fromCenter) {
fillStrip(cfg.length / 2, cfg.length / 2 + thisLength / 2, thisColor);
fillStrip(cfg.length / 2 - thisLength / 2, cfg.length / 2, thisColor);
@@ -85,7 +89,7 @@ void effectsRoutine() {
if (CUR_PRES.fromCenter) {
FOR_i(cfg.length / 2, cfg.length) {
byte bright = 255;
if (CUR_PRES.soundReact == GL_REACT_LEN) bright = (i < cfg.length / 2 + thisLength / 2) ? (CUR_PRES.max) : (CUR_PRES.min);
if (CUR_PRES.soundReact == GL_REACT_LEN) bright = (i < cfg.length / 2 + thisLength / 2) ? (thisBright) : (10);
CRGB thisColor = ColorFromPalette(
paletteArr[CUR_PRES.palette - 1], // (x*1.9 + 25) / 255 - быстрый мап 0..255 в 0.1..2
scalePal((i * (thisScale * 1.9 + 25) / cfg.length) + ((now.weekMs >> 3) * (CUR_PRES.speed - 128) / 128)),
@@ -99,7 +103,7 @@ void effectsRoutine() {
} else {
FOR_i(0, cfg.length) {
byte bright = 255;
if (CUR_PRES.soundReact == GL_REACT_LEN) bright = (i < thisLength) ? (CUR_PRES.max) : (CUR_PRES.min);
if (CUR_PRES.soundReact == GL_REACT_LEN) bright = (i < thisLength) ? (thisBright) : (10);
CRGB thisColor = ColorFromPalette(
paletteArr[CUR_PRES.palette - 1], // (x*1.9 + 25) / 255 - быстрый мап 0..255 в 0.1..2
scalePal((i * (thisScale * 1.9 + 25) / cfg.length) + ((now.weekMs >> 3) * (CUR_PRES.speed - 128) / 128)),
@@ -117,14 +121,14 @@ void effectsRoutine() {
FOR_i(0, thisScale / 8 + 1) {
rndVal = rndVal * 2053 + 13849; // random2053 алгоритм
int homeX = inoise16(i * 100000000ul + (now.weekMs << 3) * CUR_PRES.speed / 255);
homeX = map(homeX, 10000, 55000, 0, cfg.length);
homeX = map(homeX, 15000, 50000, 0, cfg.length);
int offsX = inoise8(i * 2500 + (now.weekMs >> 1) * CUR_PRES.speed / 255) - 128;
offsX = cfg.length / 2 * offsX / 128;
int thisX = homeX + offsX;
if (cfg.deviceType > 1) {
int homeY = inoise16(i * 100000000ul + 2000000000ul + (now.weekMs << 3) * CUR_PRES.speed / 255);
homeY = map(homeY, 10000, 55000, 0, cfg.width);
homeY = map(homeY, 15000, 50000, 0, cfg.width);
int offsY = inoise8(i * 2500 + 30000 + (now.weekMs >> 1) * CUR_PRES.speed / 255) - 128;
offsY = cfg.length / 2 * offsY / 128;
int thisY = homeY + offsY;
@@ -134,59 +138,58 @@ void effectsRoutine() {
}
}
}
/*
FOR_i(0, cfg.length * cfg.width) leds[i].fadeToBlackBy(70);
if (cfg.deviceType > 1) {
uint16_t rndVal = 0;
FOR_i(0, thisScale / 8) {
int thisY = inoise16(i * 100000000ul + (now.weekMs << 6) * CUR_PRES.speed / 255);
thisY = map(thisY, 10000, 55000, 0, cfg.length);
int thisX = inoise16(i * 100000000ul + 2000000000ul + (now.weekMs << 6) * CUR_PRES.speed / 255);
thisX = map(thisX, 10000, 55000, 0, cfg.width);
rndVal = rndVal * 2053 + 13849; // random2053 алгоритм
if (thisY >= 0 && thisY < cfg.length && thisX >= 0 && thisX < cfg.width)
leds[getPix(thisX, thisY)] = CHSV(CUR_PRES.rnd ? rndVal : CUR_PRES.color, 255, 255);
}
} else {
uint16_t rndVal = 0;
FOR_i(0, thisScale / 8) {
int thisPos = inoise16(i * 100000000ul + (now.weekMs << 6) * CUR_PRES.speed / 255);
thisPos = map(thisPos, 10000, 55000, 0, cfg.length);
rndVal = rndVal * 2053 + 13849; // random2053 алгоритм
if (thisPos >= 0 && thisPos < cfg.length) leds[thisPos] = CHSV(CUR_PRES.rnd ? rndVal : CUR_PRES.color, 255, 255);
}
}*/
break;
case 6: // ==================================== ОГОНЬ ====================================
{
if (cfg.deviceType > 1) { // 2D огонь
fireRoutine(CUR_PRES.speed / 2);
} else { // 1D огонь
static byte heat[MAX_LEDS];
CRGBPalette16 gPal;
if (CUR_PRES.color < 5) gPal = HeatColors_p;
else gPal = CRGBPalette16(CRGB::Black, CHSV(CUR_PRES.color, 255, 255), CRGB::White);
if (CUR_PRES.fromCenter) thisLength /= 2;
if (cfg.deviceType > 1) { // 2D огонь
fireRoutine(CUR_PRES.speed / 2);
} else { // 1D огонь
FastLED.clear();
static byte heat[MAX_LEDS];
CRGBPalette16 gPal;
if (CUR_PRES.color < 5) gPal = HeatColors_p;
else gPal = CRGBPalette16(CRGB::Black, CHSV(CUR_PRES.color, 255, 255), CRGB::White);
if (CUR_PRES.fromCenter) thisLength /= 2;
for (int i = 0; i < thisLength; i++) heat[i] = qsub8(heat[i], random8(0, ((((255 - thisScale) / 2 + 20) * 10) / thisLength) + 2));
for (int k = thisLength - 1; k >= 2; k--) heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
if (random8() < 120 ) {
int y = random8(7);
heat[y] = qadd8(heat[y], random8(160, 255));
}
if (CUR_PRES.fromCenter) {
for (int j = 0; j < thisLength; j++) leds[cfg.length / 2 + j] = ColorFromPalette(gPal, scale8(heat[j], 240));
FOR_i(0, cfg.length / 2) leds[i] = leds[cfg.length - i - 1];
} else {
for (int j = 0; j < thisLength; j++) leds[j] = ColorFromPalette(gPal, scale8(heat[j], 240));
}
for (int i = 0; i < thisLength; i++) heat[i] = qsub8(heat[i], random8(0, ((((255 - thisScale) / 2 + 20) * 10) / thisLength) + 2));
for (int k = thisLength - 1; k >= 2; k--) heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
if (random8() < 120 ) {
int y = random8(7);
heat[y] = qadd8(heat[y], random8(160, 255));
}
if (CUR_PRES.fromCenter) {
for (int j = 0; j < thisLength; j++) leds[cfg.length / 2 + j] = ColorFromPalette(gPal, scale8(heat[j], 240));
FOR_i(0, cfg.length / 2) leds[i] = leds[cfg.length - i - 1];
} else {
for (int j = 0; j < thisLength; j++) leds[j] = ColorFromPalette(gPal, scale8(heat[j], 240));
}
}
break;
case 7: // ================================== КОНФЕТТИ ==================================
case 7: // ==================================== ОГОНЬ 2020 ====================================
FastLED.clear();
if (cfg.deviceType > 1) { // 2D огонь
fire2020(CUR_PRES.scale, thisLength);
} else { // 1D огонь
static byte heat[MAX_LEDS];
if (CUR_PRES.fromCenter) thisLength /= 2;
for (int i = 0; i < thisLength; i++) heat[i] = qsub8(heat[i], random8(0, ((((255 - thisScale) / 2 + 20) * 10) / thisLength) + 2));
for (int k = thisLength - 1; k >= 2; k--) heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
if (random8() < 120 ) {
int y = random8(7);
heat[y] = qadd8(heat[y], random8(160, 255));
}
if (CUR_PRES.fromCenter) {
for (int j = 0; j < thisLength; j++) leds[cfg.length / 2 + j] = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scale8(heat[j], 240));
FOR_i(0, cfg.length / 2) leds[i] = leds[cfg.length - i - 1];
} else {
for (int j = 0; j < thisLength; j++) leds[j] = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scale8(heat[j], 240));
}
}
break;
case 8: // ================================== КОНФЕТТИ ==================================
FOR_i(0, (thisScale >> 3) + 1) {
int x = random(0, cfg.length * cfg.width);
if (leds[x] == CRGB(0, 0, 0)) leds[x] = CHSV(CUR_PRES.rnd ? random(0, 255) : CUR_PRES.color, 255, 255);
@@ -197,7 +200,7 @@ void effectsRoutine() {
}
break;
case 8: // ================================== ПОГОДА ==================================
case 9: // ================================== ПОГОДА ==================================
break;
}
@@ -209,6 +212,8 @@ void effectsRoutine() {
}
}
// ====================================================================================================================
bool musicMode() {
return ((cfg.adcMode == GL_ADC_MIC || cfg.adcMode == GL_ADC_BOTH) && (CUR_PRES.advMode > 1 && CUR_PRES.advMode <= 4));
}
@@ -233,7 +238,8 @@ byte getBright() {
int getLength() {
if (musicMode() // светомузыка вкл
&& CUR_PRES.soundReact == GL_REACT_LEN // режим длины
) return mapFF(getSoundVol(), 0, cfg.length);
) //return mapFF(getSoundVol(), 0, cfg.length);
return mapFF(getSoundVol(), scaleFF(cfg.length, CUR_PRES.min), scaleFF(cfg.length, CUR_PRES.max));
else return cfg.length;
}
@@ -287,6 +293,11 @@ void setPix(int x, int y, CRGB color) {
void setLED(int x, CRGB color) {
if (x >= 0 && x < cfg.length) leds[x] = color;
}
uint32_t getPixColor(int x, int y) {
int thisPix = getPix(x, y);
if (thisPix < 0 || thisPix >= MAX_LEDS) return 0;
return (((uint32_t)leds[thisPix].r << 16) | ((long)leds[thisPix].g << 8 ) | (long)leds[thisPix].b);
}
// получить номер пикселя в ленте по координатам
uint16_t getPix(int x, int y) {

View File

@@ -0,0 +1,52 @@
// ============= Огонь 2020 ===============
// (c) SottNick
//сильно по мотивам https://pastebin.com/RG0QGzfK
//Perlin noise fire procedure by Yaroslaw Turbin
//https://www.reddit.com/r/FastLED/comments/hgu16i/my_fire_effect_implementation_based_on_perlin/
void fire2020(byte scale, int len) {
static uint8_t deltaValue;
static uint8_t deltaHue;
static uint8_t step;
static uint8_t shiftHue[50];
static float trackingObjectPosX[100];
static float trackingObjectPosY[100];
static uint16_t ff_x, ff_y, ff_z;
if (loading) {
loading = false;
deltaValue = (((scale - 1U) % 11U + 1U) << 4U) - 8U; // ширина языков пламени (масштаб шума Перлина)
deltaHue = map(deltaValue, 8U, 168U, 8U, 84U); // высота языков пламени должна уменьшаться не так быстро, как ширина
step = map(255U - deltaValue, 87U, 247U, 4U, 32U); // вероятность смещения искорки по оси ИКС
for (uint8_t j = 0; j < cfg.length; j++) {
shiftHue[j] = (cfg.length - 1 - j) * 255 / (cfg.length - 1); // init colorfade table
}
for (uint8_t i = 0; i < cfg.width / 8; i++) {
trackingObjectPosY[i] = random8(cfg.length);
trackingObjectPosX[i] = random8(cfg.width);
}
}
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);
}
}
//вставляем искорки из отдельного массива
for (uint8_t i = 0; i < cfg.width / 8; i++) {
if (trackingObjectPosY[i] > 3U) {
leds[getPix(trackingObjectPosX[i], trackingObjectPosY[i])] = leds[getPix(trackingObjectPosX[i], 3U)];
leds[getPix(trackingObjectPosX[i], trackingObjectPosY[i])].fadeToBlackBy( trackingObjectPosY[i] * 2U );
}
trackingObjectPosY[i]++;
if (trackingObjectPosY[i] >= len) {
trackingObjectPosY[i] = random8(4U);
trackingObjectPosX[i] = random8(cfg.width);
}
if (!random8(step))
trackingObjectPosX[i] = (cfg.width + (uint8_t)trackingObjectPosX[i] + 1U - random8(3U)) % cfg.width;
}
ff_y++;
if (ff_y & 0x01) ff_z++;
}

View File

@@ -72,6 +72,14 @@ void drawFrame(int pcnt) {
255, // S
(uint8_t)max(0, nextv) // V
);
} else if (y == 11) {
if (random8(0, 20) == 0 && getPixColor(x, y - 1) != 0) setPix(x, y, getPixColor(x, y - 1));
else setPix(x, y, 0);
} else {
// старая версия для яркости
if (getPixColor(x, y - 1) > 0)
setPix(x, y, getPixColor(x, y - 1));
else setPix(x, y, 0);
}
}
}

View File

@@ -222,10 +222,23 @@ DEFINE_GRADIENT_PALETTE ( aurora_gp ) {
255, 171, 101, 221 //Purple
};
const TProgmemRGBPalette16 WoodFireColors_p PROGMEM = {CRGB::Black, 0x330e00, 0x661c00, 0x992900, 0xcc3700, CRGB::OrangeRed, 0xff5800, 0xff6b00, 0xff7f00, 0xff9200, CRGB::Orange, 0xffaf00, 0xffb900, 0xffc300, 0xffcd00, CRGB::Gold}; //* рыжий
const TProgmemRGBPalette16 NormalFire_p PROGMEM = {CRGB::Black, 0x330000, 0x660000, 0x990000, 0xcc0000, CRGB::Red, 0xff0c00, 0xff1800, 0xff2400, 0xff3000, 0xff3c00, 0xff4800, 0xff5400, 0xff6000, 0xff6c00, 0xff7800}; // красный
const TProgmemRGBPalette16 LithiumFireColors_p PROGMEM = {CRGB::Black, 0x240707, 0x470e0e, 0x6b1414, 0x8e1b1b, CRGB::FireBrick, 0xc14244, 0xd16166, 0xe08187, 0xf0a0a9, CRGB::Pink, 0xff9ec0, 0xff7bb5, 0xff59a9, 0xff369e, CRGB::DeepPink}; //* пастель
const TProgmemRGBPalette16 SodiumFireColors_p PROGMEM = {CRGB::Black, 0x332100, 0x664200, 0x996300, 0xcc8400, CRGB::Orange, 0xffaf00, 0xffb900, 0xffc300, 0xffcd00, CRGB::Gold, 0xf8cd06, 0xf0c30d, 0xe9b913, 0xe1af1a, CRGB::Goldenrod}; //* Yellow
const TProgmemRGBPalette16 CopperFireColors_p PROGMEM = {CRGB::Black, 0x001a00, 0x003300, 0x004d00, 0x006600, CRGB::Green, 0x239909, 0x45b313, 0x68cc1c, 0x8ae626, CRGB::GreenYellow, 0x94f530, 0x7ceb30, 0x63e131, 0x4bd731, CRGB::LimeGreen}; //* Green
const TProgmemRGBPalette16 AlcoholFireColors_p PROGMEM = {CRGB::Black, 0x000033, 0x000066, 0x000099, 0x0000cc, CRGB::Blue, 0x0026ff, 0x004cff, 0x0073ff, 0x0099ff, CRGB::DeepSkyBlue, 0x1bc2fe, 0x36c5fd, 0x51c8fc, 0x6ccbfb, CRGB::LightSkyBlue}; //* Blue
CRGBPalette16 paletteArr[] = {
customPal,
HeatColors_p,
Fire_gp,
WoodFireColors_p,
NormalFire_p,
LithiumFireColors_p,
SodiumFireColors_p,
CopperFireColors_p,
AlcoholFireColors_p,
LavaColors_p,
PartyColors_p,
RainbowColors_p,

View File

@@ -118,6 +118,7 @@ void parsing() {
if (!cfg.rotation) setPreset(data[cfg.presetAmount * PRES_SIZE + 3] - 1);
EE_updatePreset();
presetRotation(true); // форсировать смену режима
loading = true;
break;
case 3: DEBUGLN("Dawn");

View File

@@ -1,5 +1,5 @@
void presetRotation(bool force) {
if (cfg.rotation && (now.newMin() || force)) { // если автосмена и новая минута
if (cfg.rotation && (now.newMin() || force)) { // если автосмена и новая минута
if (cfg.rotRnd) { // случайная
cfg.curPreset = trnd.fromMin(cfg.rotPeriod, cfg.presetAmount);
DEBUG("Rnd changed to ");