#include "types.h"
#include "Timer.h"
#define BRIGHTNESS 1023
#define NUM 9
// nastavenie vlastnosti schodiska
Setting *set = new Setting {20.0, 1.0, 2.0,
0.3, 0.9, // intenzita cez den
0.1, 0.7, // intenzita v noci
0.0, 1.0, // intenzita podla dennej doby - vypocet
1.0
};
// vstupy
Pin *pir_up = new Pin {34, false, false, false, false}; // PIR hore nad schodiskom
Pin *pir_down = new Pin {13, false, false, false, false}; // PIR dole nad schodiskom
Pin *btn_on = new Pin {25, false, false, false, false}; // tlacidlo pre okamzite zaznutie vsetkych svetiel
Pin *btn_off = new Pin {27, false, false, false, false}; // tlacidlo pre okamzite zhasnutie vsetkych svetiel
// vystup
LED *led = new LED [NUM];
// casovace
Timer *timerMax = new Timer((unsigned long)(set->maxTime * 1000L)); // casovac schodiska
Timer *timerStep = new Timer((unsigned long)(set->stepTime * 1000L)); // casovac trasovania schodov
// procesne premenne
Pin *goUp = new Pin {-1, false, false, false, false}; // process hore schodiskom
Pin *goDown = new Pin {-1, false, false, false, false}; // process dole schodiskom
int step = 0; //index schodu
// rampy
Ramp *ramp = new Ramp[NUM]; // struktura premennych pre vypocet ramp kazdeho schodu
bool ramp_running = false; // priznak, za niektora rampa bezi
bool ramp_finished = true; // priznak, za niektora rampa dokoncila proces
float ramp_min, ramp_max; // pomocne intervaly rampy
unsigned long ulRampTime; // prekonvertovanu cas kazdej rampy
// linearna interpolacia rampy
auto lerp = [](unsigned long x1, float y1, unsigned long x2, float y2, float x)
{
return y1 + (y2 - y1) / (x2 - x1) * (x - x1);
};
void setup()
{
Serial.begin(115200);
pinMode(pir_up->hw_pin, INPUT); // PIR hore nad schodiskom
pinMode(pir_down->hw_pin, INPUT); // PIR dole pod schodiskom
pinMode(btn_on->hw_pin, INPUT); // tlacidlo pre okamzite zaznutie vsetkych svetiel
pinMode(btn_off->hw_pin, INPUT); // tlacidlo pre okamzite zhasnutie vsetkych svetiel
memset(led, 0, NUM * sizeof(led[0]));
led[0].hw_pin = 15;
led[1].hw_pin = 2;
led[2].hw_pin = 4;
led[3].hw_pin = 5;
led[4].hw_pin = 18;
led[5].hw_pin = 19;
led[6].hw_pin = 21;
led[7].hw_pin = 22;
led[8].hw_pin = 23;
for (int i = 0; i < NUM; i++)
pinMode(led[i].hw_pin, OUTPUT);
}
void loop()
{
// precitanie fyzickych vstupov - stav PIR hore nad schodiskom
pir_up->prev_status = pir_up->status;
pir_up->status = digitalRead(pir_up->hw_pin);
pir_up->osr = !pir_up->prev_status && pir_up->status;
pir_up->osf = pir_up->prev_status && !pir_up->status;
/*Serial.print("PIR UP bol: ");
Serial.print(pir_up->prev_status);
Serial.print(" PIR UP je: ");
Serial.println(pir_up->status);*/
// precitanie fyzickych vstupov - stav PIR dole pod schodiskom
pir_down->prev_status = pir_down->status;
pir_down->status = digitalRead(pir_down->hw_pin);
pir_down->osr = !pir_down->prev_status && pir_down->status;
pir_down->osf = pir_down->prev_status && !pir_down->status;
// precitanie fyzickych vstupov - stav tlacidla pre zaznutie vsetkych svetiel
btn_on->prev_status = btn_on->status;
btn_on->status = digitalRead(btn_on->hw_pin);
btn_on->osr = !btn_on->prev_status && btn_on->status;
btn_on->osf = btn_on->prev_status && !btn_on->status;
// precitanie fyzickych vstupov - stav tlacidla pre zhasnutie vsetkych svetiel
btn_off->prev_status = btn_off->status;
btn_off->status = digitalRead(btn_off->hw_pin);
btn_off->osr = !btn_off->prev_status && btn_off->status;
btn_off->osf = btn_off->prev_status && !btn_off->status;
//procesne premenne - proces zazinania smerom hore
goUp->prev_status = goUp->status;
goUp->status = !goUp->status && pir_down->osr ||
goUp->status && (!timerMax->lock || led[0].status || led[NUM - 1].status) &&
(!set->usePIR || set->usePIR && !pir_up->osr);
goUp->osr = !goUp->prev_status && goUp->status;
goUp->osf = goUp->prev_status && !goUp->status;
/* Serial.print("goUp status: ");
Serial.print(goUp->status);
Serial.print(" 1. podmienka: ");
Serial.print(!goUp->status && pir_down->osr);
Serial.print(" 2. podmienka: ");
Serial.print(goUp->status && (!timerMax->lock || led[0].status || led[NUM - 1].status));
Serial.print(" 3. podmienka: ");
Serial.println((!set->usePIR || set->usePIR && !pir_up->osr)); */
//procesne premenne - proces zazinania smerom dole
goDown->prev_status = goDown->status;
goDown->status = !goDown->status && pir_up->osr ||
goDown->status && (!timerMax->lock || led[0].status || led[NUM - 1].status) &&
(!set->usePIR || set->usePIR && !pir_down->osr);
goDown->osr = !goDown->prev_status && goDown->status;
goDown->osf = goDown->prev_status && !goDown->status;
Serial.print("PIR UP bol: ");
Serial.print(pir_up->prev_status);
Serial.print(" PIR UP je: ");
Serial.println(pir_up->status);
// rozsietenie vsetkych LED
if (btn_on->osr)
{
ramp_running = false;
goUp->prev_status = goDown->prev_status = false;
goUp->status = goDown->status = false;
goUp->osr = goDown->osr = false;
goUp->osf = goDown->osf = false;
memset(ramp, 0, NUM * sizeof(ramp[0]));
for (int i = 0; i < NUM; i++)
{
led[i].previous = led[i].status = false;
led[i].pwm = 1.0;
}
}
// zhasnutie vsetkych LED
if (btn_off->osr || goUp->osr || goDown->osr || goUp->osf || goDown->osf)
{
ramp_running = false;
goUp->prev_status = goDown->prev_status = false;
goUp->status = goDown->status = false;
goUp->osr = goDown->osr = false;
goUp->osf = goDown->osf = false;
memset(ramp, 0, NUM * sizeof(ramp[0]));
for (int i = 0; i < NUM; i++)
{
led[i].previous = led[i].status = false;
led[i].pwm = 0.0;
}
}
// casovace schodiska
timerStep->run(!timerStep->tick && (goUp->status || goDown->status)); // casovac trasovania schodov
timerMax->run(goUp->status || goDown->status); // casovac schodiska
step = goUp->osr ? 0 : step;
step = goDown->osr ? NUM - 1 : step;
led[step].previous = led[step].status;
led[step].status = goUp->osr || goDown->osr || timerStep->tick ? !led[step].status : led[step].status;
led[step].osr = !led[step].previous && led[step].status;
led[step].osf = led[step].previous && !led[step].status;
// reset priznaku dokoncenia rampy pre konkretny schod
ramp[step].done = led[step].osr || led[step].osf ? false : ramp[step].done;
// spustit proces zazinania schodu
ramp[step].fadeIn = !ramp[step].fadeIn && !ramp[step].fadeOut && led[step].osr || ramp[step].fadeIn && !ramp[step].done;
//spustit proces zhasania schodu
ramp[step].fadeOut = !ramp[step].fadeIn && !ramp[step].fadeOut && led[step].osf || ramp[step].fadeIn && !ramp[step].done;
// jas zaciatku rampy
ramp[step].from = ramp[step].fadeIn ? set->darkness : ramp[step].from;
ramp[step].from = ramp[step].fadeOut ? set->brightness : ramp[step].from;
// jas konca rampy
ramp[step].to = ramp[step].fadeIn ? set->brightness : ramp[step].to;
ramp[step].to = ramp[step].fadeOut ? set->darkness : ramp[step].to;
// zatial nie je zname, ci bezi nejaka rampa nebezi
ramp_running = false;
// konverzia casu rampy zo [s] na [ms]
ulRampTime = (unsigned long)(1000L * set->rampTime);
// startovaci cas rampy
ramp[step].previous = led[step].osr || led[step].osf ? millis() : ramp[step].previous;
// spracovanie ramp vsetkych schodov
for (int i = 0; i < NUM; i++)
{
if (!ramp[i].fadeIn && !ramp[i].fadeOut) continue; // ak nebezi tato rampa, skus inu
ramp_running = true; // tato rampa bezi
ramp_min = min(ramp[i].from, ramp[i].to);
ramp_max = max(ramp[i].from, ramp[i].to);
ramp[i].now = millis(); // aktualny cas
ramp[i].difference = ramp[i].now < ramp[i].previous ? // uplynuly cas
ULONG_MAX - ramp[i].previous + ramp[i].now :
ramp[i].now - ramp[i].previous;
// interpolacia urovne jasu
led[i].pwm = constrain(lerp(0L, ramp[i].from, ulRampTime, ramp[i].to, ramp[i].difference),
ramp_min, ramp_max);
/*
tu pride gamma krivka
*/
// ak je rampa dokoncena
ramp_finished = (led[i].pwm <= ramp_min) || (led[i].pwm >= ramp_max);
// resetovat priznaky procesu rampya
ramp[i].fadeIn = ramp_finished ? false : ramp[i].fadeIn;
ramp[i].fadeOut = ramp_finished ? false : ramp[i].fadeOut;
ramp[i].done = ramp_finished ? true : ramp[i].done;
}
// index dalsieho schodu
step = goUp->osr || goUp->status && timerStep->tick ? ++step % NUM : step;
step = goDown->osr || goDown->status && timerStep->tick ? ((step > 0) ? step - 1 : NUM - 1) : step;
// zapis do PWM
if (btn_on->osr || btn_off->osr || ramp_running)
for (int i = 0; i < NUM; i++)
analogWrite(led[i].hw_pin, (int)(BRIGHTNESS * led[i].pwm));
}