#define LEDS 6
//primul grup de leduri
int ledsA[LEDS] = {13,12,11,10,9,8};
//al 2-lea grup de leduri
int ledsB[LEDS] = {7,6,5,4,3,2};
//tip de data pointer la functie, ca sa scutim timp cu iterarea task-urilor
typedef void (*TASK)(int,int);
//array pentru timpii ledurilor care sunt comandate de la serial
int timp[LEDS] = {0};
//array pentru tipul ledurilor care sunt comandate de la serial (0-blink, 1-fade-in, 2- fade-out, 3-fade-in-out)
int tip[LEDS] = {-1,-1,-1,-1,-1,-1};
void setup()
{
Serial.begin(9600);
for (int i=0;i<LEDS;i++)
{
pinMode(ledsA[i], OUTPUT);
pinMode(ledsB[i], OUTPUT);
digitalWrite(ledsA[i], 0);
digitalWrite(ledsB[i], 0);
}
}
//aceasta functie trebuie sa execute pe rand cele 2 animatii de pe primul grup de 6 leduri
//fiecare led are ca timp 500ms
//nu se foloseste delay() si nici bucle, functia nu trebuie sa fie blocanta
//fiecare animatie se executa de 2 ori consecutiv iar apoi procesul se reia
//aceasta functie ar trebuie sa aiba cel mult 5 linii de cod, 1 instructiune pe linie
//fara a apela alte functii decat millis() si digitalWrite()
void TaskA(int timp_led)
{
int i = 0;
long long int startA = millis();
if(millis() - startA < 500){
digitalWrite(13, 1);
}else if((millis() - startA) < 1000 && (millis() - startA > 500) && i < 2){
digitalWrite(13, 0);
analogWrite(12, 1);
}else if((millis() - startA) < 1500 && (millis() - startA > 1000) && i < 2){
digitalWrite(12, 0);
analogWrite(11, 255);
}else if((millis() - startA) < 2000 && (millis() - startA > 1500) && i < 2){
analogWrite(11, 0);
analogWrite(10, 255);
}else if((millis() - startA) < 2500 && (millis() - startA > 2000) && i < 2){
analogWrite(10, 0);
analogWrite(9, 255);
}else if((millis() - startA) < 3000 && (millis() - startA > 2500) && i < 2){
analogWrite(9, 0);
digitalWrite(8, 1);
}else if((millis() - startA) < 3500 && (millis() - startA > 3000) && i < 2){
digitalWrite(8, 0);
digitalWrite(13, 1);
i = 1;
}
}
//aceasta functie trebuie sa transfere caracterele de la Serial, in buffer
//returneaza true daca s-a gasit '#', sau false daca mai sunt caractere de primit, sau nu avem nimic de receptionat
//nu se foloseste delay sau bucle
bool FillBuffer(char* buffer)
{
if(Serial.available()){
char c = Serial.read();
if(c == '#'){
buffer[strlen(buffer)] = '\0';
}return true;
buffer[strlen(buffer)] = c;
}
return false;
}
//aceasta functie interpreteaza ceea ce se afla in buffer
//format buffer exemplu: 3,1000,0 (3 este indexul ledului verde pornind de la stanga, care se refera de fapt la ledul de la pinul 4), 1000 este timpul in ms pentru toate operatiile implicate, 0 se refera la blink
//comenzile suportate variaza intre 0 si 3 (0-blink, 1-fade-in, 2-fade-out, 3-fadein-out)
//indexul ledului variaza intre 0 si 5 si pinii echivalenti indexilor sunt 0-7, 1-6, 2-5, 3-4, 4-3, 5-2
//in urma apelului vom seta in array-ul timp, pe pozitia data de index (prima valoare), timpul in ms, iar in array-ul tip pe acelasi index vom avea ultima valoare - tipul taskului
void HandleCommand(char *buffer, int* timp, int* tip)
{
char * p = NULL;
int i = 0, led_index = -1;
p = strtok(buffer, ',');
while(p){
if(i == 0){
if(strlen(p) > 1){
Serial.println("Wrong format for command");
return;
}else{
led_index = p[0] - '0';
i++;
}
}else if(i == 1){
timp[led_index] = atoi(p);
i++;
}else if(i == 2){
if(strlen(p) > 1){
Serial.println("Wrong format for command");
return;
}else{
tip[led_index] = p[0] - '0';
i++;
}else{
Serial.println("Wrong format for command");
return;
}
}
p = strtok(NULL, ',');
}
}
//functia pentru blink
//fara delay, fara bucle
//led - pinul la care este conectat ledul 2-7
//timp - timpul total de blink (timp/2 ON, timp/2 OFF)
//aceasta functie ar trebuie sa aiba cel mult 5 linii de cod, fara a apela alte functii decat millis() si digitalWrite()
void blink(int led, int timp)
{
long long int start = millis();
if(start-millis() > timp/2){
if(digitalRead(led) == LOW){
digitalWrite(led, HIGH);
}else{
digitalWrite(led, LOW);
}
}
}
//functia pentru fade-in (de la stins maxim spre aprins)
//fara delay, fara bucle
//trebuie sa mearga atat cu pinii 6,5,3 - analog cat si cu pinii 7,4,2 - digitali
//led - pinul la care este conectat ledul 2-7
//timp - timpul total de fade
//aceasta functie ar trebuie sa aiba cel mult 10 linii de cod, 1 instructiune pe linie
//fara a apela alte functii decat millis() si digitalWrite()
void fade_in(int led, int timp)
{
long long int start = millis();
int brightness = 0;
int step = 0.5;
while(millis() - start < timp){
if(millis() - start < timp*brightness/5){
digitalWrite(led, HIGH);
brightness+=step;
}else{
digitalWrite(led, LOW);
}
}
if(brightness > 5)return;
}
//la fel ca la fade-in dar fade-out (de la aprins maxim spre stins)
//aceasta functie ar trebuie sa aiba cel mult 10 linii de cod, 1 instructiune pe linie
//fara a apela alte functii decat millis() si digitalWrite()
void fade_out(int led, int timp)
{
long long int start = millis();
int brightness = 5;
int step = 0.5;
while(millis() - start < timp){
if(millis() - start < timp*brightness/5){
digitalWrite(led, HIGH);
brightness-=step;
}else{
digitalWrite(led, LOW);
}
}
if(brightness <0)return;
}
//aceasta functie ar trebui sa apeleze functiile de mai sus ca sa facem si fade-in si fade-out
//fara bucle sau delay
//aceasta functie ar trebuie sa aiba cel mult 5 linii de cod, 1 instructiune pe linie
//apeland fade_in si fade_out
void fade_in_out(int led, int timp)
{
long long int start = millis();
int brightness = 0;
int step = 0.5;
while(millis() - start < timp){
if(millis() - start < timp*brightness/5){
digitalWrite(led, HIGH);
brightness-=step;
}else{
digitalWrite(led, LOW);
}
}
if(brightness > 5 || brightness < 0){
step = -step;
}
}
//acest task se ocupa de ledurile spre care trimitem comenzi de la Serial (al 2-lea grup de 6 leduri)
//trebuie apelate functiile FillBuffer() si HandleCommand() ca sa preluam comanda de la Serial si sa completam corect array-urile tip si timp
void TaskB()
{
//ne folosim de functiile de mai sus, ca sa scutim timp si definim un array de pointeri la functii
TASK tasksB[4] = {blink, fade_in, fade_out, fade_in_out};
char*buffer[1000];
FillBuffer(buffer);
HandleCommand(buffer, timp, tip);
//pentru fiecare led din cele 6, daca tipul programului este valid, atunci il executam
for (int i=0;i<LEDS;i++)
//initial tipul este invalid, si are sens sa executam ceva numai daca este valid
if (tip[i] != -1)
//apelam functia cu indexul tip[i] din tasksB, cu parametrii ledsB[i] si timp[i]
tasksB[tip[i]](ledsB[i], timp[i]);
}
//in loop, intr-un timp cat mai scurt executam o fractiune din taskA si taskB pe fiecare iteratie
void loop()
{
TaskA(500);
// TaskB();
}