#include <FastLED.h>
#define SENSOR_START 2 // пин датчика движения
#define SENSOR_END 3 // пин датчика движения
#define LED_PIN 4 // пин ленты
#define COUNT_STEPS 10 // количество ступенек
#define LED_STEP 20 // лампочек на ступеньке
#define LED_TYPE WS2812B //тип ленты
#define COLOR_ORDER GRB //порядок цветов
#define CUSTOM_BRIGHT 100 // ручная яркость
#define TIMEOUT 5 // секунд, таймаут выключения ступенек после срабатывания одного из датчиков движения
#define NUMLEDS COUNT_STEPS*LED_STEP // кол-во светодиодов
#define SPEED 500 // скорость переключения
struct Step {
byte led_amount; //количество чипов в ступеньке
byte status_step; //статус ступеньки(0-выключена,1включяется,2-включена,3-выключается)
byte num_animation; //номер кадра анимации
uint16_t night_mode_bitmask;// маска
uint16_t start_chip;// номер начального чипа в ступеньке вычесляется програмно
};
// описание всех ступенек с возможностью подсветки ЛЮБЫХ ступенек в ночном режиме
Step steps[COUNT_STEPS] = {
{ 20, 0, 0, 0b0100100100, 0}, // первая ступенька(20 чипов,0-выключена,0-кадр анимацыи, 0b0100100100100100 - маска,начальный чип заполним потом
{ 20, 0, 0, 0b0100100100 },
{ 20, 0, 0, 0b0100100100 },
{ 20, 0, 0, 0b0100100100 },
{ 20, 0, 0, 0b0100100100 },
{ 20, 0, 0, 0b0100100100 },
{ 20, 0, 0, 0b0100100100 },
{ 20, 0, 0, 0b0100100100 },
{ 20, 0, 0, 0b0100100100 },
{ 20, 0, 0, 0b0100100100 }
};
CRGB leds[NUMLEDS]; // буфер ленты
CRGB ON = CRGB::Red; // цвет включения
CRGB OF = CRGB::Black; // цвет выключения
// ==== удобные макросы ====================================================
#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() {
Serial.begin(9600);
FastLED.addLeds< LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUMLEDS);
avtonum_startled();// автоматически находим и проставляем стартовый чип на каждой ступеньке
FastLED.clear();
FastLED.show();
}
void loop() {
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;;startPirSensor.cvet = ON;
startPirSensor.lastState=false;startPirSensor.zag_tuh = 2;
// Serial.println("начало start") ;
}
// Serial.println(step) ;
FOR_i(0, step + 1) {
FOR_j(steps[i].start_chip, steps[i].start_chip + steps[i].led_amount) {
leds[j] = startPirSensor.cvet;
// Serial.print(j);
}
// Serial.println() ;
}
if (step == COUNT_STEPS - 1){
if( startPirSensor.zag_tuh==2) {
step = 0;
startPirSensor.lastState = false;
startPirSensor.zag_tuh = 1;
startPirSensor.cvet = OF;
TIMEstat = true;
timeoutCounter = millis();
// Serial.println("конец start") ;
}
if( startPirSensor.zag_tuh==1) {
startPirSensor.lastState = false;
startPirSensor.zag_tuh = 0;
}
} else {
step += 1;
}
}
void anim_end() {
static int step = COUNT_STEPS - 1;
if(endPirSensor.lastState){
step = COUNT_STEPS - 1;endPirSensor.cvet = ON;
endPirSensor.lastState=false;endPirSensor.zag_tuh = 2;
// Serial.println("начало end") ;
}
// Serial.println(step) ;
FOR_k(COUNT_STEPS - 1, step - 1) {
FOR_j(steps[k].start_chip, steps[k].start_chip + steps[k].led_amount) {
leds[j] = endPirSensor.cvet;
// Serial.print(j);
}
// Serial.println() ;
}
if (step == 0){
if( endPirSensor.zag_tuh==2) {
step = COUNT_STEPS - 1;
endPirSensor.lastState = false;
endPirSensor.zag_tuh = 1;
endPirSensor.cvet = OF;
TIMEstat = true;
timeoutCounter = millis();
// Serial.println("конец end") ;
}
if( endPirSensor.zag_tuh==1) {
endPirSensor.lastState = false;
endPirSensor.zag_tuh = 0;
}
}else {
step -= 1;
}
}
void anim() {
// Serial.println(startPirSensor.lastState) ;
// if (startPirSensor.lastState ) {
// Serial.print("крутим анимацыю") ;
// Serial.println(2) ;
if(startPirSensor.zag_tuh>0)anim_start();
// }
// if (endPirSensor.lastState ) {
// Serial.print("крутим анимацыю") ;
// Serial.println(3) ;
if(endPirSensor.zag_tuh>0)anim_end();
// }
FastLED.show();
}
// void nightLight() {
// Serial.print(0);
// FastLED.clear();
// FastLED.show();
// Serial.println("выключаем");
// return;
// }
void handleTimeout() {// таймер
if (millis() - timeoutCounter >= (TIMEOUT * 1000)) {
TIMEstat = false;
if (poslednyi == 2) {
startPirSensor.lastState = false;// выключаем
startPirSensor.zag_tuh = 1;
}
if (poslednyi == 3) {
endPirSensor.lastState = false;// выключаем
endPirSensor.zag_tuh = 1;
}
}
}
void handlePirSensor(PirSensor * sensor) { //прослушивание сенсора
// Serial.println("опрашиваем датчик");
int newState = digitalRead(sensor->pin);
if (newState) {
// Serial.print(newState);
// Serial.print("сработал");
// Serial.println(sensor->pin);
if (sensor->zag_tuh<2 && millis()-sensor->time>1100){sensor->lastState = newState; sensor->cvet = ON;
sensor->zag_tuh=2; sensor->time= millis();
// Serial.print("загарается-");Serial.println(sensor->pin);
}
poslednyi = sensor->pin;
TIMEstat = false;
// Serial.println(newState);
}
}
void avtonum_startled() {
FOR_i(1, COUNT_STEPS) {
steps[i].start_chip = steps[i - 1].start_chip + steps[i - 1].led_amount;
// Serial.print(steps[i].start_chip) ;
}
// Serial.println();
}