From: eaman Date: Thu, 20 Oct 2016 23:38:18 +0000 (+0200) Subject: State machines X-Git-Url: http://git.piffa.net/web?p=sketchbook_andrea;a=commitdiff_plain;h=b15c46840c12896bd1b29dc360db4f30f8b5dfa4 State machines --- diff --git a/advanced_projects/state_machine/blink/blink.ino b/advanced_projects/state_machine/blink/blink.ino deleted file mode 100644 index 485c2f2..0000000 --- a/advanced_projects/state_machine/blink/blink.ino +++ /dev/null @@ -1,56 +0,0 @@ -/* - Blink con state machine - - Introduzione alle state machine - - */ -int led = 13; -int pausa = 1000; -enum states_available { // Stati della FMS - turn_on, // Dinamico, transizione - on, // Statico - turn_off, - off -}; - -states_available state ; - -void setup() { - pinMode(led, OUTPUT); - Serial.begin(9600); - Serial.flush(); -} - -void loop() { -switch (state) { - case turn_on : - digitalWrite(led, HIGH); - state = on ; // Setta il prossimo state - break; - - case on: - delay(pausa); - state = turn_off ; - break; - - case turn_off : - digitalWrite(led, LOW); - state = off ; - break; - - case off : - delay(pausa); - state = turn_on ; - break; - - default: // In caso di default si fa turn_off - digitalWrite(led, LOW); - state = off ; - break; - -} -Serial.print(millis()); -Serial.print(" \t Stato attuale "); -Serial.println(state); - -} diff --git a/advanced_projects/state_machine/semaforo_1/semaforo_1.ino b/advanced_projects/state_machine/semaforo_1/semaforo_1.ino new file mode 100644 index 0000000..1318a08 --- /dev/null +++ b/advanced_projects/state_machine/semaforo_1/semaforo_1.ino @@ -0,0 +1,70 @@ +/* + Semaforo RGB + + Un singolo semaforo costruito col paradigma delle macchine a stato. + Viene utilizzato un oggetto della libreria common per gestire il LED. + + */ +#include +int pausa = 3000; +enum states_available { // Stati della FMS + turn_green, // Dinamico, transizione + green, // Statico + turn_red, + red +}; + +states_available state ; + + +void setup() { + Serial.begin(9600); + Serial.flush(); +} + +RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte + // della classe RGBLed + +void loop() { +switch (state) { + case turn_green : + led.Green(); + state = green ; // Setta il prossimo state + break; + + case green: + delay(pausa * 2/3); + state = turn_red ; + break; + + case turn_red : + led.Yellow(); + delay(pausa/3); + led.Red(); + delay(pausa); + state = red ; + break; + + case red : + delay(pausa); + state = turn_green ; + break; + + default: // In caso di default si fa giallo + led.Yellow(); + delay(pausa/3); + led.Off(); + delay(pausa/3); + break; + +} +Serial.print(millis()); +Serial.print(" \t Stato attuale "); +Serial.println(state); + +} + +/* Domande: + 1. Come legare il passaggio di stato ad un evento esterno, + ad es. la pressione di un bottone? + */ diff --git a/advanced_projects/state_machine/semaforo_2_1_doppio/semaforo_2_1_doppio.ino b/advanced_projects/state_machine/semaforo_2_1_doppio/semaforo_2_1_doppio.ino new file mode 100644 index 0000000..412e11f --- /dev/null +++ b/advanced_projects/state_machine/semaforo_2_1_doppio/semaforo_2_1_doppio.ino @@ -0,0 +1,100 @@ +/* + Incrocio RGB + + Un incrocio costituito da due strade, una principale e una secondaria. + La via viene concessa al secondario alla pressione di un bottone, + il secondario cambia automaticamente dopo una pausa. + Viene utilizzato un oggetto della libreria common per gestire i LED. + + Uno stimolo esterno rappresentato dalla pressione di un bottone + causa il passaggio di stato. + + */ + +#include +const byte input = 2; // PIN del bottone +int pausa = 3000; +enum states_available { // Stati della FMS + turn_green, // Dinamico, transizione + green, // Statico + wait_button, + turn_red, + red +}; + +states_available FSM1 ; +states_available FSM2 ; + + +void setup() { + pinMode(input, INPUT_PULLUP); + Serial.begin(9600); + Serial.flush(); +} + +RGBLed led_main(11, 10, 9); +RGBLed led_secondary(8, 7, 6); + +void loop() { +switch (FSM1) { + case turn_green : + led_main.Green(); + FSM1 = green ; // Setta il prossimo state + FSM2 = red ; // Setta il prossimo state + break; + + case green: + delay(pausa * 2/3); + FSM1 = wait_button ; + break; + + case wait_button: + if (digitalRead(input) == LOW) { + FSM1 = turn_red ; // Il passaggio di stato avviene alla pressione di un bottone + }; + delay(20); + break; + + case turn_red : + led_main.Yellow(); + delay(pausa/3); + led_main.Red(); + FSM1 = red ; + FSM2 = turn_green; // Stimolo al semafor secondario + break; + + case red : + //delay(pausa); + //main = turn_green ; + break; +} +switch (FSM2) { + case turn_green : + led_secondary.Green(); + FSM2 = green ; // Setta il prossimo state + break; + + case green: + delay(pausa * 2/3); + FSM2 = turn_red ; // Niente stimoli + break; + + case turn_red : + led_secondary.Yellow(); + delay(pausa/3); + FSM1 = turn_green ; + FSM2 = red ; + break; + + case red : + led_secondary.Red(); + break; +} + +Serial.print(millis()); +Serial.print(" \t Stato attuale Main: "); +Serial.print(FSM1); +Serial.print(", secondary: "); +Serial.println(FSM2); + +} diff --git a/advanced_projects/state_machine/semaforo_2_stimolo/semaforo_2_stimolo.ino b/advanced_projects/state_machine/semaforo_2_stimolo/semaforo_2_stimolo.ino new file mode 100644 index 0000000..e31949f --- /dev/null +++ b/advanced_projects/state_machine/semaforo_2_stimolo/semaforo_2_stimolo.ino @@ -0,0 +1,99 @@ +/* + Semaforo RGB + + Un singolo semaforo costruito col paradigma delle macchine a stato. + Viene utilizzato un oggetto della libreria common per gestire il LED. + + Uno stimolo esterno rappresentato dalla pressione di un bottone + causa il passaggio di stato. + + */ + +#include +const byte input = 2; // PIN del bottone +int pausa = 3000; +enum states_available { // Stati della FMS + turn_green, // Dinamico, transizione + green, // Statico + wait_button, // Evento - Stimolo + turn_red, // Dinamico, transizione + red // Statico +}; + +states_available state ; + + +void setup() { + pinMode(input, INPUT_PULLUP); + Serial.begin(9600); + Serial.flush(); +} + +RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte + // della classe RGBLed + +void loop() { +switch (state) { + case turn_green : + led.Green(); + state = green ; // Setta il prossimo state + break; + + case green: + delay(pausa * 2/3); + state = wait_button ; + break; + + case wait_button: + if (digitalRead(input) == LOW) { + state = turn_red ; // Il passaggio di stato avviene alla pressione di un bottone + delay(20); + }; + + break; + + case turn_red : + led.Yellow(); + delay(pausa/3); + led.Red(); + delay(pausa); + state = red ; + break; + + case red : + delay(pausa); + state = turn_green ; + break; + + default: // In caso di default si fa giallo lampeggiante + led.Yellow(); + delay(pausa/3); + led.Off(); + delay(pausa/3); + break; + +} +Serial.print(millis()); +Serial.print(" \t Stato attuale "); +Serial.println(state); + +} + +/* Domande: + 1. Introdurre un secondo semaforo che cambia stato quando viene attivato + lo stimolo. + 2. L'uso di delay() puo' essere limitativo: come rimediare? +. +. +. +. +. +. +. +. +. +. + Soluzioni +2. Si potrebbe utilizzare un interrupt per gli stimoli oppure millis() + per gestire le pause. + */ diff --git a/advanced_projects/state_machine/semaforo_3_millis/semaforo_3_millis.ino b/advanced_projects/state_machine/semaforo_3_millis/semaforo_3_millis.ino new file mode 100644 index 0000000..af151a7 --- /dev/null +++ b/advanced_projects/state_machine/semaforo_3_millis/semaforo_3_millis.ino @@ -0,0 +1,118 @@ +/* + Semaforo RGB + + Un singolo semaforo costruito col paradigma delle macchine a stato. + Viene utilizzato un oggetto della libreria common per gestire il LED. + + Uno stimolo esterno rappresentato dalla pressione di un bottone + causa il passaggio di stato. + + Implementata con millis() invece che con delay(), + sono stati aggiuntu due stati per meglio gestire lo stato yellow. + + */ + +#include +const byte input = 2; // PIN del bottone +int pausa = 3000; +long timer ; +enum states_available { // Stati della FMS + turn_green, // Dinamico, transizione + green, // Statico + wait_button, // Evento - Stimolo + turn_yellow, // Dinamico, transizione + yellow, // Statico + turn_red, // Dinamico, transizione + red // Statico +}; + +states_available state ; + + +void setup() { + pinMode(input, INPUT_PULLUP); + Serial.begin(9600); + timer = millis(); +} + +RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte + // della classe RGBLed + +void loop() { +switch (state) { + case turn_green : + state = green ; // Setta il prossimo state + break; + + case green: + led.Green(); + if (millis() > timer + pausa * 2/3) { + state = wait_button ; + timer = millis(); + } + break; + + case wait_button: + if (digitalRead(input) == LOW) { + state = turn_yellow ; // Il passaggio di stato avviene alla pressione di un bottone + timer = millis(); + delay(20); // Debouncing, si potrebbe fare con millis() + }; + break; + + case turn_yellow : + state = yellow ; + break; + + case yellow : + led.Yellow(); + if (millis() > timer + pausa * 2/3) { + state = turn_red ; + timer = millis(); + } + break; + + case turn_red : + state = red ; + break; + + case red : + led.Red(); + if (millis() > timer + pausa) { + state = turn_green ; + timer = millis(); + } + break; + + default: // In caso di default si fa giallo lampeggiante + led.Yellow(); + delay(pausa/3); + led.Off(); + delay(pausa/3); + break; + +} +Serial.print(millis()); +Serial.print(" \t Stato attuale "); +Serial.println(state); + +} + +/* Domande: + 1. Introdurre un secondo semaforo che cambia stato quando viene attivato + lo stimolo. + 2. L'uso di delay() puo' essere limitativo: come rimediare? +. +. +. +. +. +. +. +. +. +. + Soluzioni +2. Si potrebbe utilizzare un interrupt per gli stimoli oppure millis() + per gestire le pause. + */ diff --git a/advanced_projects/state_machine/semaforo_4_doppio/semaforo_4_doppio.ino b/advanced_projects/state_machine/semaforo_4_doppio/semaforo_4_doppio.ino new file mode 100644 index 0000000..3866ad2 --- /dev/null +++ b/advanced_projects/state_machine/semaforo_4_doppio/semaforo_4_doppio.ino @@ -0,0 +1,140 @@ +/* + Semaforo RGB + + + Doppio semaforo, una via prinicipale (led) e una secondaria (secondary): + la via secondaria ottiene la precedenza alla pressione di un bottone. + + Implementata con millis() invece che con delay(), + sono stati aggiuntu due stati per gestire lo stato yellow + del semafor secondario. + + Lo sketch e' stato implementato con una sola FSM in cui si incrociano + gli stati dei due semafori. + + */ + +#include +const byte input = 2; // PIN del bottone +int pausa = 3000; +long timer ; +enum states_available { // Stati della FMS + turn_green, // Dinamico, transizione + green, // Statico + wait_button, // Evento - Stimolo + turn_yellow, // Dinamico, transizione + yellow, // Statico + turn_red, // Dinamico, transizione + turn_sec_yellow, // Yellow per semaforo secondario + sec_yellow, + red // Statico +}; + +states_available state ; + + +void setup() { + pinMode(input, INPUT_PULLUP); + Serial.begin(9600); + timer = millis(); +} + +RGBLed led(11, 10, 9); // Semaforo principale +RGBLed secondary(8,7,6); // Semaforo secondario + + +void loop() { +switch (state) { + case turn_green : + led.Green(); + secondary.Red() ; + state = green ; // Setta il prossimo state + break; + + case green: + if (millis() > timer + pausa * 2/3) { + state = wait_button ; + timer = millis(); + } + break; + + case wait_button: + if (digitalRead(input) == LOW) { + state = turn_yellow ; // Il passaggio di stato avviene alla pressione di un bottone + delay(20); // Debouncing, si potrebbe fare con millis() + timer = millis(); + }; + + break; + + case turn_yellow : + led.Yellow(); + state = yellow ; + break; + + case yellow : + if (millis() > timer + pausa / 3) { + state = turn_red ; + timer = millis(); + } + break; + + case turn_red : + led.Red(); + secondary.Green(); + state = red ; + break; + + case red : + if (millis() > timer + pausa /3) { + state = turn_sec_yellow ; + timer = millis(); + } + break; + + case turn_sec_yellow : + secondary.Yellow(); + state = sec_yellow ; + break; + + case sec_yellow : + if (millis() > timer + pausa / 3) { + state = turn_green ; + timer = millis(); + } + break; + + default: // In caso di default si fa giallo lampeggiante + led.Yellow(); + secondary.Yellow(); + delay(pausa/3); + led.Off(); + secondary.Off(); + delay(pausa/3); + break; + +} +Serial.print(millis()); +Serial.print(" \t Stato attuale "); +Serial.println(state); + +} + +/* Domande: + 1. E' agevole inserire degli altri semafori? + 2. Provare a inserire un altro semafori implementando una FSM + separata. +. +. +. +. +. +. +. +. +. +. + Soluzioni +1. Be' bisogna ragionare sul loro comportamente in rapporto alla FSM principale, diciamo che non e' un approccio plug and play. +2. Vedi esercizio successivo. + */ diff --git a/advanced_projects/state_machine/semaforo_5_doppia_fsm/semaforo_5_doppia_fsm.ino b/advanced_projects/state_machine/semaforo_5_doppia_fsm/semaforo_5_doppia_fsm.ino new file mode 100644 index 0000000..619b85e --- /dev/null +++ b/advanced_projects/state_machine/semaforo_5_doppia_fsm/semaforo_5_doppia_fsm.ino @@ -0,0 +1,166 @@ +/* + Semaforo RGB + + Un singolo semaforo costruito col paradigma delle macchine a stato. + Viene utilizzato un oggetto della libreria common per gestire il LED. + + Uno stimolo esterno rappresentato dalla pressione di un bottone + causa il passaggio di stato. + + Implementata con millis() invece che con delay(), + sono stati aggiuntu due stati per meglio gestire lo stato yellow. + + */ + +#include +const byte input = 2; // PIN del bottone +int pausa = 3000; +long timer ; +enum states_available { // Stati della FMS + turn_green, // Transizione + green, // Statico + wait_button, // Evento - Stimolo + turn_yellow, // transizione + yellow, // Statico + turn_red, // transizione + red // Statico +}; + +states_available FSM1 ; +states_available FSM2 ; + + +void setup() { + pinMode(input, INPUT_PULLUP); + Serial.begin(9600); + timer = millis(); +} + +RGBLed led1(11, 10, 9); //Istanziamo un oggetto led facente parte +RGBLed led2(8,7,6); //Istanziamo un oggetto led facente parte + // della classe RGBLed + +void loop() { +switch (FSM1) { + case turn_green : + led1.Green(); + FSM1 = green ; // Setta il prossimo state + FSM2 = red ; // Setta il prossimo state + break; + + case green: + if (millis() > timer + pausa * 2/3) { + FSM1 = wait_button ; + timer = millis(); + } + break; + + case wait_button: + if (digitalRead(input) == LOW) { + FSM1 = turn_yellow ; + timer = millis(); + delay(20); // Debouncing, si potrebbe fare con millis() + }; + + break; + + case turn_yellow : + led1.Yellow(); + FSM1 = yellow ; + break; + + case yellow : + if (millis() > timer + pausa * 2/3) { + FSM1 = turn_red ; + timer = millis(); + } + break; + + case turn_red : + led1.Red(); + FSM1 = red ; + FSM2 = turn_green ; + break; + + case red : + break; + + default: // In caso di default si fa giallo lampeggiante + led1.Yellow(); + delay(pausa/3); + led1.Off(); + delay(pausa/3); + break; + +} +switch (FSM2) { + case turn_green : + led2.Green(); + FSM2 = green ; // Setta il prossimo state + break; + + case green: + if (millis() > timer + pausa * 2/3) { + FSM2 = turn_yellow; + timer = millis(); + } + break; + + case turn_yellow : + led2.Yellow(); + FSM2 = yellow ; + break; + + case yellow : + if (millis() > timer + pausa / 3) { + FSM2 = turn_red ; + timer = millis(); + } + break; + + case turn_red : + FSM2 = red ; + FSM1 = turn_green; + break; + + case red : + led2.Red(); // Aggiorniamo il LED in questo stato invece che nel precedente + // per entrare nel primo ciclo di esecuzione con il LED rosso + break; + + default: // In caso di default si fa giallo lampeggiante + led2.Yellow(); + delay(pausa/3); + led2.Off(); + delay(pausa/3); + break; +} + +Serial.print(millis()); +Serial.print(" \t Stato attuale FSM1: "); +Serial.print(FSM1); +Serial.print(" - FSM2: "); +Serial.println(FSM2); +} + +/* Domande: + 1. E' piu' semplice ora inserire degli altri oggetti nello sketch? + 2. Gli eventi sono condivisi? Le varie FSM hanno modo di scambiarsi + informazioni sui relativi stati? + 3. Creare un dispatcher degli eventi al quale le varie FSM possono + riferirsi. +. +. +. +. +. +. +. +. +. +. + Soluzioni +1. Si, per quanto le 2 FSM non siano indipendenti l'una dall'altra. +2. No, c'e' un solo flusso degli eventi, il blocco di una delle FSM + puo' causare lo stop di tutto il sistema. + */ diff --git a/advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.ino b/advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.ino deleted file mode 100644 index 1318a08..0000000 --- a/advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.ino +++ /dev/null @@ -1,70 +0,0 @@ -/* - Semaforo RGB - - Un singolo semaforo costruito col paradigma delle macchine a stato. - Viene utilizzato un oggetto della libreria common per gestire il LED. - - */ -#include -int pausa = 3000; -enum states_available { // Stati della FMS - turn_green, // Dinamico, transizione - green, // Statico - turn_red, - red -}; - -states_available state ; - - -void setup() { - Serial.begin(9600); - Serial.flush(); -} - -RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte - // della classe RGBLed - -void loop() { -switch (state) { - case turn_green : - led.Green(); - state = green ; // Setta il prossimo state - break; - - case green: - delay(pausa * 2/3); - state = turn_red ; - break; - - case turn_red : - led.Yellow(); - delay(pausa/3); - led.Red(); - delay(pausa); - state = red ; - break; - - case red : - delay(pausa); - state = turn_green ; - break; - - default: // In caso di default si fa giallo - led.Yellow(); - delay(pausa/3); - led.Off(); - delay(pausa/3); - break; - -} -Serial.print(millis()); -Serial.print(" \t Stato attuale "); -Serial.println(state); - -} - -/* Domande: - 1. Come legare il passaggio di stato ad un evento esterno, - ad es. la pressione di un bottone? - */ diff --git a/advanced_projects/state_machine/semaforo_rgb_stimolo/semaforo_rgb_stimolo.ino b/advanced_projects/state_machine/semaforo_rgb_stimolo/semaforo_rgb_stimolo.ino deleted file mode 100644 index de2373b..0000000 --- a/advanced_projects/state_machine/semaforo_rgb_stimolo/semaforo_rgb_stimolo.ino +++ /dev/null @@ -1,98 +0,0 @@ -/* - Semaforo RGB - - Un singolo semaforo costruito col paradigma delle macchine a stato. - Viene utilizzato un oggetto della libreria common per gestire il LED. - - Uno stimolo esterno rappresentato dalla pressione di un bottone - causa il passaggio di stato. - - */ -#include -const byte input = 2; // PIN del bottone -int pausa = 3000; -enum states_available { // Stati della FMS - turn_green, // Dinamico, transizione - green, // Statico - wait_button, - turn_red, - red -}; - -states_available state ; - - -void setup() { - pinMode(input, INPUT_PULLUP); - Serial.begin(9600); - Serial.flush(); -} - -RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte - // della classe RGBLed - -void loop() { -switch (state) { - case turn_green : - led.Green(); - state = green ; // Setta il prossimo state - break; - - case green: - delay(pausa * 2/3); - state = wait_button ; - break; - - case wait_button: - if (digitalRead(input) == LOW) { - state = turn_red ; // Il passaggio di stato avviene alla pressione di un bottone - delay(20); - }; - - break; - - case turn_red : - led.Yellow(); - delay(pausa/3); - led.Red(); - delay(pausa); - state = red ; - break; - - case red : - delay(pausa); - state = turn_green ; - break; - - default: // In caso di default si fa giallo lampeggiante - led.Yellow(); - delay(pausa/3); - led.Off(); - delay(pausa/3); - break; - -} -Serial.print(millis()); -Serial.print(" \t Stato attuale "); -Serial.println(state); - -} - -/* Domande: - 1. Introdurre un secondo semaforo che cambia stato quando viene attivato - lo stimolo. - 2. L'uso di delay() puo' essere limitativo: come rimediare? -. -. -. -. -. -. -. -. -. -. - Soluzioni -2. Si potrebbe utilizzare un interrupt per gli stimoli oppure millis() - per gestire le pause. - */ diff --git a/advanced_projects/state_machine/semaforo_rgb_stimolo_millis/semaforo_rgb_stimolo_millis.ino b/advanced_projects/state_machine/semaforo_rgb_stimolo_millis/semaforo_rgb_stimolo_millis.ino new file mode 100644 index 0000000..af151a7 --- /dev/null +++ b/advanced_projects/state_machine/semaforo_rgb_stimolo_millis/semaforo_rgb_stimolo_millis.ino @@ -0,0 +1,118 @@ +/* + Semaforo RGB + + Un singolo semaforo costruito col paradigma delle macchine a stato. + Viene utilizzato un oggetto della libreria common per gestire il LED. + + Uno stimolo esterno rappresentato dalla pressione di un bottone + causa il passaggio di stato. + + Implementata con millis() invece che con delay(), + sono stati aggiuntu due stati per meglio gestire lo stato yellow. + + */ + +#include +const byte input = 2; // PIN del bottone +int pausa = 3000; +long timer ; +enum states_available { // Stati della FMS + turn_green, // Dinamico, transizione + green, // Statico + wait_button, // Evento - Stimolo + turn_yellow, // Dinamico, transizione + yellow, // Statico + turn_red, // Dinamico, transizione + red // Statico +}; + +states_available state ; + + +void setup() { + pinMode(input, INPUT_PULLUP); + Serial.begin(9600); + timer = millis(); +} + +RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte + // della classe RGBLed + +void loop() { +switch (state) { + case turn_green : + state = green ; // Setta il prossimo state + break; + + case green: + led.Green(); + if (millis() > timer + pausa * 2/3) { + state = wait_button ; + timer = millis(); + } + break; + + case wait_button: + if (digitalRead(input) == LOW) { + state = turn_yellow ; // Il passaggio di stato avviene alla pressione di un bottone + timer = millis(); + delay(20); // Debouncing, si potrebbe fare con millis() + }; + break; + + case turn_yellow : + state = yellow ; + break; + + case yellow : + led.Yellow(); + if (millis() > timer + pausa * 2/3) { + state = turn_red ; + timer = millis(); + } + break; + + case turn_red : + state = red ; + break; + + case red : + led.Red(); + if (millis() > timer + pausa) { + state = turn_green ; + timer = millis(); + } + break; + + default: // In caso di default si fa giallo lampeggiante + led.Yellow(); + delay(pausa/3); + led.Off(); + delay(pausa/3); + break; + +} +Serial.print(millis()); +Serial.print(" \t Stato attuale "); +Serial.println(state); + +} + +/* Domande: + 1. Introdurre un secondo semaforo che cambia stato quando viene attivato + lo stimolo. + 2. L'uso di delay() puo' essere limitativo: come rimediare? +. +. +. +. +. +. +. +. +. +. + Soluzioni +2. Si potrebbe utilizzare un interrupt per gli stimoli oppure millis() + per gestire le pause. + */ diff --git a/advanced_projects/state_machine/semaphore/semaphore.ino b/advanced_projects/state_machine/semaphore/semaphore.ino deleted file mode 100644 index f309a6a..0000000 --- a/advanced_projects/state_machine/semaphore/semaphore.ino +++ /dev/null @@ -1,194 +0,0 @@ -/* -A traffic light for an intersection of a -highway and a country road. Normally, the light -should be green for the highway and red for the -country road, but when traffic approaches on -the country road, the highway gets a red light -and the country road gets a green light. - -When a light turns red it transitions from green to -red it goes through yellow, but a red light changing -to green transitions directly to green. - -A pushbutton represents a car approaching on -the country road. - -Implement the solution with a Finite State -Machine or FSM. - -Following the excellent description at -http://hacking.majenko.co.uk/finite-state-machine -first break down the problem into states. - -Identify which states are Transitional (T) and -which are Static (S). A Static state is one in -which the FSM is waiting for stimulus, and is -taking no actions. A Transitional State is a -state which causes actions, but doesn't look -for stimulus. - -A Transitional State runs once and immediately -moves on to a Static State. - -State 0: highway = green, country = red; (T) -State 1: wait for car on country road (S) -State 2: highway = yellow, make note of current time (T) -State 3: wait for yellow time to pass (S) -State 4: highway = red, country = green, make note of current time (T) -State 5: wait for highway red time to pass (S) -State 6: country = yellow, make note of current time (T) -state 7: wait for yellow time to pass (S) then go to 0 -*/ - -// Use names for states so it's easier to -// understand what the code is doing -const int S_HIGHWAYGREEN = 0; -const int S_WAITCARCOUNTRY = 1; -const int S_HIGHWAYYELLOW = 2; -const int S_WAITHIGHWAYYELLOW = 3; -const int S_HIGHWAYRED = 4; -const int S_WAITHIGHWAYRED = 5; -const int S_COUNTRYYELLOW = 6; -const int S_WAITCOUNTRYYELLOW = 7; - -// Pin numbers -const int countrySensorPin = 2; - -const int highwayGreenLEDPin = 3; -const int highwayYellowLEDPin = 4; -const int highwayRedLEDPin = 5; - -const int countryGreenLEDPin = 6; -const int countryYellowLEDPin = 7; -const int countryRedLEDPin = 8; - -void setup() -{ - pinMode(highwayGreenLEDPin, OUTPUT); - pinMode(highwayYellowLEDPin, OUTPUT); - pinMode(highwayRedLEDPin, OUTPUT); - pinMode(countryGreenLEDPin, OUTPUT); - pinMode(countryYellowLEDPin, OUTPUT); - pinMode(countryRedLEDPin, OUTPUT); -} - -void loop() -{ - - // start off with the highway getting green - // The keyword "static" makes sure the variable - // isn't destroyed after each loop - static int state = S_HIGHWAYGREEN ; - - // To store the current time for delays - static unsigned long ts; - - switch (state) - { - case S_HIGHWAYGREEN: - // Highway gets green, country road red - digitalWrite( highwayGreenLEDPin, HIGH); - digitalWrite( highwayYellowLEDPin, LOW); - digitalWrite( highwayRedLEDPin, LOW); - - digitalWrite( countryGreenLEDPin, LOW); - digitalWrite( countryYellowLEDPin, LOW); - digitalWrite( countryRedLEDPin, HIGH); - - state = S_WAITCARCOUNTRY; - - break; - - case S_WAITCARCOUNTRY: - - if ( digitalRead (countrySensorPin) == HIGH) { - state = S_HIGHWAYYELLOW; - } - - break; - - case S_HIGHWAYYELLOW: - digitalWrite( highwayGreenLEDPin, LOW); - digitalWrite( highwayYellowLEDPin, HIGH); - digitalWrite( highwayRedLEDPin, LOW); - - digitalWrite( countryGreenLEDPin, LOW); - digitalWrite( countryYellowLEDPin, LOW); - digitalWrite( countryRedLEDPin, HIGH); - - ts = millis(); // Remember the current time - - state = S_WAITHIGHWAYYELLOW; // Move to the next state - - break; - - case S_WAITHIGHWAYYELLOW: - // If two seconds have passed, then move on to the next state. - if (millis() > ts + 2000) - { - state = S_HIGHWAYRED; - } - - break; - - case S_HIGHWAYRED: - // Highway red, country road green - digitalWrite( highwayGreenLEDPin, LOW); - digitalWrite( highwayYellowLEDPin, LOW); - digitalWrite( highwayRedLEDPin, HIGH); - - digitalWrite( countryGreenLEDPin, HIGH); - digitalWrite( countryYellowLEDPin, LOW); - digitalWrite( countryRedLEDPin, LOW); - - ts = millis(); // Remember the current time - - state = S_WAITHIGHWAYRED; - - break; - - case S_WAITHIGHWAYRED: - - // If five seconds have passed, then start - // transition to a red light for the country - // road - if (millis() > ts + 5000) - { - state = S_COUNTRYYELLOW; - } - - break; - - case S_COUNTRYYELLOW: - digitalWrite( highwayGreenLEDPin, LOW); - digitalWrite( highwayYellowLEDPin, LOW); - digitalWrite( highwayRedLEDPin, HIGH); - - digitalWrite( countryGreenLEDPin, LOW); - digitalWrite( countryYellowLEDPin, HIGH); - digitalWrite( countryRedLEDPin, LOW); - - ts = millis(); // Remember the current time - - state = S_WAITCOUNTRYYELLOW; - - break; - - case S_WAITCOUNTRYYELLOW: - - // If two seconds have passed, then go - // back to the beginning with the highway - // getting the green light - if (millis() > ts + 2000) - { - state = S_HIGHWAYGREEN; - } - - break; - - } // end of switch - - // other things could go on here, and they would not affect the timing - // of the traffic light - -} // end of loop diff --git a/libraries/common/common.cpp b/libraries/common/common.cpp index 94657ae..1eed6a2 100644 --- a/libraries/common/common.cpp +++ b/libraries/common/common.cpp @@ -1,6 +1,11 @@ /* Common - * - * Oggetti di uso comune + Collezione di funzioni e oggetti comuni incontrati durante + i vari esercizi. + + Source file + Contiene il codice C++ delle funzioni e degli oggetti, + nel file common.h ci sono gli headers: prototipi. + */ #include "Arduino.h" @@ -92,7 +97,7 @@ void RGBLed::SetColor (byte r, byte g, byte b) { void brilla(byte pin) { // Accende e spegne il LED senza un argomento - // per impostare la velocita'. + // per impostare la velocita' con delay(). const int velocita = 500; pinMode(pin, OUTPUT); diff --git a/libraries/common/common.h b/libraries/common/common.h index 71cb19a..e1b0cf0 100644 --- a/libraries/common/common.h +++ b/libraries/common/common.h @@ -1,15 +1,21 @@ /* Common Class - Oggetti comuni + Collezione di funzioni e oggetti comuni incontrati durante + i vari esercizi. + + Header file + Contiene i prototipi delle funzioni e degli oggetti, + il codice e' nel fine *.cpp */ #include "Arduino.h" -#ifndef common_h -#define common_h +#ifndef common_h // Questi cicli IF, gestiti come macro da preprocessor +#define common_h // fanno si che questo file non venga incluso piu' volte +///////////////////////////////////////////// class RGBLed { // Classe rappresentativa di un LED RGB @@ -33,6 +39,7 @@ class RGBLed { void SetColor (byte r, byte g, byte b) ; }; +///////////////////////////////////////////// void brilla(byte pin, int velocita = 500) ; #endif