#include <FastLED.h>
#include "tables.h"
#define SENSOR_START 4 // пин датчика движения 4
#define SENSOR_END 5 // пин датчика движения 1
#define LED_PIN 13 // пин ленты 2
#define COUNT_STEPS 16 // количество ступенек
#define LED_STEP 20 // лампочек на ступеньке
#define LED_TYPE WS2812 //тип ленты
#define COLOR_ORDER GRB //порядок цветов
#define CUSTOM_BRIGHT 100 // ручная яркость
#define TIMEOUT 2 // секунд, таймаут выключения ступенек после срабатывания одного из датчиков движения
#define NUMLEDS 762 // кол-во светодиодов
#define SPEED 300 // скорость переключения
#define SPEEDani 80 // скорость анимацыи
#define ON CRGB::Red // цвет включения
#define OF CRGB::Black
struct Step {
byte led_amount; //количество чипов в ступеньке
byte status_step; //статус ступеньки(0-выключена,1включяется,2-включена,3-выключается)
byte num_animation; //номер кадра анимации
uint16_t night_mode_bitmask;// маска
int start_chip;// номер начального чипа в ступеньке вычесляется програмно
};
// описание всех ступенек с возможностью подсветки ЛЮБЫХ ступенек в ночном режиме
Step steps[COUNT_STEPS] = {
{ 47, 0,0,0,0 }, // первая ступенька 16 чипов, 0b0100100100100100 - каждый третий чип активен в ночном режиме
{ 48, 0,0,0,0 }, // вторая ступенька 16 чипов, 0b0000000000000000 - не активен в ночном режиме
{ 48, 0,0,0,0 },
{ 48, 0,0,0,0 }, // первая ступенька 16 чипов, 0b0100100100100100 - каждый третий чип активен в ночном режиме
{ 48, 0,0,0,0 }, // вторая ступенька 16 чипов, 0b0000000000000000 - не активен в ночном режиме
{ 46, 0,0,0,0 },
{ 47, 0,0,0,0 }, // первая ступенька 16 чипов, 0b0100100100100100 - каждый третий чип активен в ночном режиме
{ 47, 0,0,0,0 }, // вторая ступенька 16 чипов, 0b0000000000000000 - не активен в ночном режиме
{ 47, 0,0,0,0 },
{ 48, 0,0,0,0 }, // первая ступенька 16 чипов, 0b0100100100100100 - каждый третий чип активен в ночном режиме
{ 48, 0,0,0,0 }, // вторая ступенька 16 чипов, 0b0000000000000000 - не активен в ночном режиме
{ 48, 0,0,0,0 },
{ 48, 0,0,0,0 }, // первая ступенька 16 чипов, 0b0100100100100100 - каждый третий чип активен в ночном режиме
{ 48, 0,0,0,0 }, // вторая ступенька 16 чипов, 0b0000000000000000 - не активен в ночном режиме
{ 48, 0,0,0,0 },
{ 48, 0,0,0,0 } // 3
};
CRGB leds[NUMLEDS]; // буфер ленты
// ==== удобные макросы ====================================================
#define FOR_i(from, to) for (int i = (from); i < (to); i++)
#define FOR_j(from, to) for (int j = (from); j < (to); j++)
#define FOR_k(from, to) for (int k = (from); k > (to); k--)
#define ANIMATE_TM(x) \
static uint32_t Tmr=0;\
bool flag = millis() - Tmr >= (x);\
if (flag)Tmr += (x);\
if (flag)
//===========================
bool M_stat = 0;// ----------глобальнве переменные
int effSpeed;
int8_t effectDirection;
byte curBright = CUSTOM_BRIGHT;
byte effectCounter;
uint32_t timeoutCounter;
bool TIMEstat = false;
byte poslednyi;
// bool systemOffState;
struct PirSensor { //--------------датчик
int8_t effectDirection;
int8_t pin;
bool lastState;
CRGB cvet;
byte zag_tuh;
uint32_t time; //загорается или тухнет или 0 ничего не делает
};
PirSensor startPirSensor = { 1, SENSOR_START, false, OF, false, millis()};
PirSensor endPirSensor = { -1, SENSOR_END, false, OF, false, millis()};
//--------------------------------------------------
// CRGBPalette16 firePalette;
void setup() {
Serial2.begin(9600);
FastLED.addLeds< LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUMLEDS);
avtonum_startled();// автоматически находим и проставляем стартовый чип на каждой ступеньке
FastLED.setBrightness(250) ;
FastLED.clear();
FastLED.show();
FastLED.showColor(CRGB::Red);
FastLED.show();
FastLED.clear();
FastLED.show();
}
void loop() {
{
ANIMATE_TM(SPEEDani) animSTEP();//крутим анимацыю ступеньки
}
if (!startPirSensor.lastState)handlePirSensor(&startPirSensor); //опрашивается датчик если не сработал только что
if (!endPirSensor.lastState)handlePirSensor(&endPirSensor); //опрашивается датчик если не сработал только что
ANIMATE_TM(SPEED) anim(); // крутим переключение со скоростью переключения ступенек
if (TIMEstat) handleTimeout();// если таймер на выключение то проверяем
}
void anim_start() {
static int step = 0;
if (startPirSensor.lastState) { // когда сработал датчик надо загаратся
step = 0;
if(endPirSensor.zag_tuh==2)endPirSensor.zag_tuh =0;// если с другой стороны тухнет то прекрати
startPirSensor.lastState = false; // услышали что надо загоратся и сбросили флаг
startPirSensor.zag_tuh = 1;
}
if (startPirSensor.zag_tuh == 2 && steps[step].status_step != 0)steps[step].status_step = 3;
if (startPirSensor.zag_tuh == 1 && steps[step].status_step != 2 )steps[step].status_step = 1;
if (step == COUNT_STEPS - 1) { // дошел до конца
// Serial2.println("ok") ;
step = 0;
if ( startPirSensor.zag_tuh == 1) {//если загорелась
TIMEstat = true; // запустить таймер через сколько потухнет
timeoutCounter = millis();
}
startPirSensor.zag_tuh = 0;
} else {
step += 1;
}
}
void anim_end() {
static int step = COUNT_STEPS - 1;
if (endPirSensor.lastState) { //когда сработал датчик надо загаратся
step = COUNT_STEPS - 1; endPirSensor.lastState = false; // услышали что надо загоратся и сбросили флаг
if(startPirSensor.zag_tuh==2)startPirSensor.zag_tuh=0;// если с другой стороны тухнет то прекрати
endPirSensor.zag_tuh = 1;
}
if (endPirSensor.zag_tuh == 2 && steps[step].status_step != 0)steps[step].status_step = 3;
if (endPirSensor.zag_tuh == 1 && steps[step].status_step != 2 )steps[step].status_step = 1;
// Serial2.println() ;
if (step == 0) {// дошол до конца
step = COUNT_STEPS - 1;
if ( endPirSensor.zag_tuh == 1) {//если загорелась
TIMEstat = true; // запустить таймер через сколько потухнет
timeoutCounter = millis();
}
endPirSensor.zag_tuh = 0;
} else {
step -= 1;
}
}
void anim() {
if (endPirSensor.zag_tuh > 0)anim_end();
if (startPirSensor.zag_tuh > 0)anim_start();
}
void handleTimeout() {// таймер
if (millis() - timeoutCounter >= (TIMEOUT * 1000)) {
TIMEstat = false;
if (poslednyi == 2) {
startPirSensor.zag_tuh = 2;
Serial2.print("тай-");
}
if (poslednyi == 3) {
Serial2.print("тай-");
endPirSensor.zag_tuh = 2;
}
}
}
void handlePirSensor(PirSensor * sensor) { //прослушивание сенсора
if ( millis() - sensor->time > 1500) {// не раньше 1,5 секунды
if (digitalRead(sensor->pin)) {
sensor->lastState =true ; sensor->time = millis(); sensor->zag_tuh = 1;
poslednyi = sensor->pin;
TIMEstat = false; Serial2.println("тут");
}
}
}
void avtonum_startled() {
FOR_i(1, COUNT_STEPS) {
steps[i].start_chip = steps[i - 1].start_chip + steps[i - 1].led_amount;
// Serial2.println(steps[i].start_chip) ;
}
// Serial2.println();
}
// заливка лесинки массивом
void animSTEP() {
FOR_i(0, COUNT_STEPS) {
if (steps[i].status_step == 0 || steps[i].status_step == 2)continue;
int vel = (steps[i].status_step == 1) ? 1 : -1;
steps[i].num_animation += vel;
fill_Array(steps[i].start_chip, steps[i]. led_amount, steps[i].num_animation);
if (steps[i].num_animation == 0 )steps[i].status_step = 0;
if (steps[i].num_animation == 9)steps[i].status_step = 2;
}
FastLED.show();
}
void fill_Array(int start, byte num, byte numan ) {
for (int i = 0; i < num ; i++) {
leds[i + start] = pgm_read_word(&Mask1[numan*50+i]);
}
}