From 0c94aa8e6fc849a034ad670198a3f1248eb173af Mon Sep 17 00:00:00 2001 From: Andrea Manni Date: Thu, 9 Mar 2017 12:54:22 +0100 Subject: [PATCH] FSM reorder --- advanced_projects/state_machine/README | 20 + advanced_projects/state_machine/README.html | 605 ++++++++++++++++++ .../state_machine/blink/blink_1/blink_1.ino | 43 -- .../blink/blink_2_trans/blink_2_trans.ino | 106 --- .../blink_2_trans/blink_2_trans.ino | 7 +- .../state_machine/semaforo_1/semaforo_1.ino | 10 +- .../semaforo_2_1_stimolo.ino} | 9 +- .../semaforo_2_2_doppio.ino} | 9 +- .../semaforo_3_millis/semaforo_3_millis.ino | 51 +- .../semaforo_4_doppio_single_FSM.ino} | 4 +- .../semaforo_5_doppia_fsm.ino | 20 +- .../semaforo_rgb.ino} | 94 ++- 12 files changed, 733 insertions(+), 245 deletions(-) create mode 100644 advanced_projects/state_machine/README.html delete mode 100644 advanced_projects/state_machine/blink/blink_1/blink_1.ino delete mode 100644 advanced_projects/state_machine/blink/blink_2_trans/blink_2_trans.ino rename advanced_projects/state_machine/{semaforo_2_stimolo/semaforo_2_stimolo.ino => semaforo_2_1_stimolo/semaforo_2_1_stimolo.ino} (89%) rename advanced_projects/state_machine/{semaforo_2_1_doppio/semaforo_2_1_doppio.ino => semaforo_2_2_doppio/semaforo_2_2_doppio.ino} (87%) rename advanced_projects/state_machine/{semaforo_4_doppio/semaforo_4_doppio.ino => semaforo_4_doppio_single_FSM/semaforo_4_doppio_single_FSM.ino} (94%) rename advanced_projects/state_machine/{semaforo_rgb_stimolo_millis/semaforo_rgb_stimolo_millis.ino => semaforo_rgb/semaforo_rgb.ino} (51%) diff --git a/advanced_projects/state_machine/README b/advanced_projects/state_machine/README index 15f5175..d17dce6 100644 --- a/advanced_projects/state_machine/README +++ b/advanced_projects/state_machine/README @@ -4,14 +4,33 @@ FSM Risorse utili per le Macchine a stati. +In questi esercizi vengono presentati alcuni paradigmi di base per la creazione +di macchine a stato con Arduino. Vengono proposti esempi con FSM singole e FSM +doppie concorrenti, per altri esempi pratici con semplici cicli IF, gestione degli eventi esterni / interni si puo' guardare anche il codice del progetto "Luci per Aerei RC": +- http://aerei.piffa.net/repo/esempi/base_th_3stati/base_th_3stati.ino +- http://aerei.piffa.net/esempi/2017/02/15/throttle-fsm.html +- http://aerei.piffa.net/esempi/2017/02/20/alettoni-fsm.html +- http://aerei.piffa.net/repo/aerei/ + Tutorials =========== * https://www.sparkfun.com/news/1801 +* http://digitaldiy.io/articles/mcu-programming/general-programming/500-finite-state-+machines#.VT0r1s90yh3 +* http://www.gammon.com.au/forum/?id=12316 +* https://github.com/JChristensen/Button/blob/master/Examples/LongPress/LongPress.pde +* http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html + +Teoria +======== +* https://en.wikipedia.org/wiki/Finite-state_machine +* https://en.wikipedia.org/wiki/Nondeterministic_finite_automaton +* https://en.wikipedia.org/wiki/Deterministic_finite_automaton#Complete_and_incomplete +* http://43oh.com/2017/02/how-to-implement-finite-state-machines-using-energia/ @@ -21,3 +40,4 @@ Elementi * http://playground.arduino.cc/Code/Enum * https://www.arduino.cc/en/Reference/SwitchCase +* https://learn.adafruit.com/multi-tasking-the-arduino-part-1 diff --git a/advanced_projects/state_machine/README.html b/advanced_projects/state_machine/README.html new file mode 100644 index 0000000..fe1f325 --- /dev/null +++ b/advanced_projects/state_machine/README.html @@ -0,0 +1,605 @@ + + + + + +FSM + + + + +
+

FSM

+ +

Risorse utili per le Macchine a stati.

+

In questi esercizi vengono presentati alcuni paradigmi di base per la creazione +di macchine a stato con Arduino. Vengono proposti esempi con FSM singole e FSM +doppie concorrenti, per altri esempi pratici con semplici cicli IF, gestione degli eventi esterni / interni si puo' guardare anche il codice del progetto "Luci per Aerei RC": +- http://aerei.piffa.net/repo/esempi/base_th_3stati/base_th_3stati.ino +- http://aerei.piffa.net/esempi/2017/02/15/throttle-fsm.html +- http://aerei.piffa.net/esempi/2017/02/20/alettoni-fsm.html +- http://aerei.piffa.net/repo/aerei/

+ + + +
+ + diff --git a/advanced_projects/state_machine/blink/blink_1/blink_1.ino b/advanced_projects/state_machine/blink/blink_1/blink_1.ino deleted file mode 100644 index c119794..0000000 --- a/advanced_projects/state_machine/blink/blink_1/blink_1.ino +++ /dev/null @@ -1,43 +0,0 @@ -/* - Blink FSM - - Accensione e spegnimanto di un LED utilizzando - una FSM 2 stati statici. - -Costrutto switch basato su uno struct. - - */ - -// Dichiarazione variabili -int led = 13; -int pausa = 500; // Variabile richiambile nel corso dell'esecuzione - -void setup() { - // Inizializziamo il PIN 13 come OUTPUT - pinMode(led, OUTPUT); -} - -enum fsm_stati { // Stati della FMS - on, - off -}; - -fsm_stati stato; - -void loop() { - switch (stato){ - case on : - digitalWrite(led, HIGH); // Mette il PIN del LED in stato acceso - delay(pausa); // Aspetta un secondo (mille millisecondi) - - stato = off ; // Setta il prossimo state - break; - - case off: - digitalWrite(led, LOW); // Mette il PIN del LED in stato spento - delay(pausa); // Aspetta mezzo secondo - - stato = on ; - break; - } -} diff --git a/advanced_projects/state_machine/blink/blink_2_trans/blink_2_trans.ino b/advanced_projects/state_machine/blink/blink_2_trans/blink_2_trans.ino deleted file mode 100644 index 1841f87..0000000 --- a/advanced_projects/state_machine/blink/blink_2_trans/blink_2_trans.ino +++ /dev/null @@ -1,106 +0,0 @@ -/* - Blink FSM - - Accensione e spegnimanto di un LED utilizzando - una FSM con 4 stati, statici e di transizione. - -Costrutto switch basato su uno struct. - - */ - -// Dichiarazione variabili -int led = 11; // PWM -int pausa = 1000; // Variabile richiambile nel corso dell'esecuzione -byte lum = 0 ; - -void setup() { - // Inizializziamo il PIN 13 come OUTPUT - pinMode(led, OUTPUT); -} - -enum fsm_stati { // Stati della FMS - on, // Statico - to_off, // Transizione - off, - to_on -}; - -fsm_stati stato ; - -void loop() { - switch (stato) { - case on : - // Operativa: Machine - digitalWrite(led, HIGH); // Mette il PIN del LED in stato acceso - delay(pausa); - - // Stati - stato = to_off ; // Setta il prossimo state - lum = 255; - break; - - case to_off : - while (lum > 0) { - lum-- ; - analogWrite(led, lum); // Mette il PIN del LED in stato acceso - delay(1); - } - - stato = off ; // Setta il prossimo state - break; - - case off: - digitalWrite(led, LOW); // Mette il PIN del LED in stato spento - delay(pausa); - - stato = to_on ; - lum = 0; - break; - - case to_on : - while (lum < 255) { - lum++ ; - analogWrite(led, lum); // Mette il PIN del LED in stato acceso - delay(1); - } - - stato = on ; // Setta il prossimo state - break; - } -} - -/* Domande: - - 1.Cosa comporta l'uso della funzione delay? - 2.Come si puo' modificare lo sketch per poter eseguire piu' conpiti contemporaneamente? - -Esercizi successivi: -- Creare una FSM con un LED RGB avente due stati Red e Green, una transizione yellow tra i due -- Creare una FSM per la gestione di un semaforo - (esempio disponibile in sketchbook_andrea/advanced_projects/state_machine ) - - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - . - Soluzioni: - - 1.Delay rende il codice blocking, null'altro puo' essere eseguito durante i delay - 2.Si potrebbe utilizzare millis(), vedi esercizi multitasking -*/ diff --git a/advanced_projects/state_machine/blink_2_trans/blink_2_trans.ino b/advanced_projects/state_machine/blink_2_trans/blink_2_trans.ino index 4abe599..6545cde 100644 --- a/advanced_projects/state_machine/blink_2_trans/blink_2_trans.ino +++ b/advanced_projects/state_machine/blink_2_trans/blink_2_trans.ino @@ -4,7 +4,7 @@ Accensione e spegnimanto di un LED utilizzando una FSM con 4 stati, statici e di transizione. -Costrutto switch basato su uno struct. +Costrutto switch basato su un enum: */ @@ -18,14 +18,13 @@ void setup() { pinMode(led, OUTPUT); } -enum fsm_stati { // Stati della FMS +enum fsm_stati: byte { // Stati della FMS, explicit type cast on, // Statico to_off, // Transizione off, to_on -}; +} stato ; // denominazione di una variabile -fsm_stati stato ; void loop() { switch (stato) { diff --git a/advanced_projects/state_machine/semaforo_1/semaforo_1.ino b/advanced_projects/state_machine/semaforo_1/semaforo_1.ino index 1318a08..b32e637 100644 --- a/advanced_projects/state_machine/semaforo_1/semaforo_1.ino +++ b/advanced_projects/state_machine/semaforo_1/semaforo_1.ino @@ -4,6 +4,9 @@ Un singolo semaforo costruito col paradigma delle macchine a stato. Viene utilizzato un oggetto della libreria common per gestire il LED. + +- Schema per un led RGB: https://lab.piffa.net/schemi/rgb.jpg + */ #include int pausa = 3000; @@ -14,7 +17,7 @@ enum states_available { // Stati della FMS red }; -states_available state ; +states_available state = red; void setup() { @@ -39,13 +42,12 @@ switch (state) { case turn_red : led.Yellow(); - delay(pausa/3); - led.Red(); - delay(pausa); + delay(pausa / 3); state = red ; break; case red : + led.Red(); delay(pausa); state = turn_green ; break; diff --git a/advanced_projects/state_machine/semaforo_2_stimolo/semaforo_2_stimolo.ino b/advanced_projects/state_machine/semaforo_2_1_stimolo/semaforo_2_1_stimolo.ino similarity index 89% rename from advanced_projects/state_machine/semaforo_2_stimolo/semaforo_2_stimolo.ino rename to advanced_projects/state_machine/semaforo_2_1_stimolo/semaforo_2_1_stimolo.ino index 9b4b367..b151838 100644 --- a/advanced_projects/state_machine/semaforo_2_stimolo/semaforo_2_stimolo.ino +++ b/advanced_projects/state_machine/semaforo_2_1_stimolo/semaforo_2_1_stimolo.ino @@ -7,6 +7,8 @@ Uno stimolo esterno rappresentato dalla pressione di un bottone causa il passaggio di stato. +- Schema per un led RGB: https://lab.piffa.net/schemi/rgb.jpg +- Schema per un bottone: https://www.arduino.cc/en/uploads/Tutorial/inputPullupButton.png */ #include @@ -55,12 +57,11 @@ switch (state) { case turn_red : led.Yellow(); delay(pausa/3); - led.Red(); - delay(pausa); state = red ; break; case red : + led.Red(); delay(pausa); state = turn_green ; break; @@ -80,8 +81,7 @@ Serial.println(state); } /* Domande: - 1. Introdurre una memoria nello stato green che tenga traccia della pressione del bottone - per lo stato succiessivo. + 1. Introdurre una memoria nello stato green che tenga traccia della pressione del bottone per lo stato successivo. 2. Introdurre un secondo semaforo che cambia stato quando viene attivato lo stimolo. 3. L'uso di delay() puo' essere limitativo: come rimediare? @@ -96,6 +96,7 @@ Serial.println(state); . . Soluzioni +1. Vedi sketch: semaforo_rgb 3. Si potrebbe utilizzare un interrupt per gli stimoli oppure millis() per gestire le pause. */ diff --git a/advanced_projects/state_machine/semaforo_2_1_doppio/semaforo_2_1_doppio.ino b/advanced_projects/state_machine/semaforo_2_2_doppio/semaforo_2_2_doppio.ino similarity index 87% rename from advanced_projects/state_machine/semaforo_2_1_doppio/semaforo_2_1_doppio.ino rename to advanced_projects/state_machine/semaforo_2_2_doppio/semaforo_2_2_doppio.ino index 412e11f..e25b487 100644 --- a/advanced_projects/state_machine/semaforo_2_1_doppio/semaforo_2_1_doppio.ino +++ b/advanced_projects/state_machine/semaforo_2_2_doppio/semaforo_2_2_doppio.ino @@ -9,6 +9,10 @@ Uno stimolo esterno rappresentato dalla pressione di un bottone causa il passaggio di stato. + Questo sketch usa due FSM indipendenti che modificano i rispettivi stati. + +- Schema per un led RGB: https://lab.piffa.net/schemi/rgb.jpg +- Schema per un bottone: https://www.arduino.cc/en/uploads/Tutorial/inputPullupButton.png */ #include @@ -37,6 +41,7 @@ RGBLed led_secondary(8, 7, 6); void loop() { switch (FSM1) { + // Semaforo principale case turn_green : led_main.Green(); FSM1 = green ; // Setta il prossimo state @@ -68,7 +73,9 @@ switch (FSM1) { //main = turn_green ; break; } + switch (FSM2) { + // Semaforo Secondario case turn_green : led_secondary.Green(); FSM2 = green ; // Setta il prossimo state @@ -90,7 +97,7 @@ switch (FSM2) { led_secondary.Red(); break; } - +// Debug Serial.print(millis()); Serial.print(" \t Stato attuale Main: "); Serial.print(FSM1); 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 index 68825a6..fea0a67 100644 --- a/advanced_projects/state_machine/semaforo_3_millis/semaforo_3_millis.ino +++ b/advanced_projects/state_machine/semaforo_3_millis/semaforo_3_millis.ino @@ -10,6 +10,8 @@ Implementata con millis() invece che con delay(), sono stati aggiuntu due stati per meglio gestire lo stato yellow. +- Schema per un led RGB: https://lab.piffa.net/schemi/rgb.jpg +- Schema per un bottone: https://www.arduino.cc/en/uploads/Tutorial/inputPullupButton.png */ #include @@ -30,61 +32,61 @@ states_available state ; void setup() { - pinMode(input, INPUT_PULLUP); - Serial.begin(9600); - timer = millis(); + pinMode(input, INPUT_PULLUP); + Serial.begin(9600); + timer = millis(); } RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte - // della classe RGBLed +// della classe RGBLed void loop() { switch (state) { - case turn_green : +case turn_green : state = green ; // Setta il prossimo state break; - case green: +case green: led.Green(); if (millis() - timer >= pausa * 2/3) { - state = wait_button ; - timer += pausa * 2/3 ; + state = wait_button ; + timer += pausa * 2/3 ; } 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(); +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 : +case turn_yellow : state = yellow ; break; - case yellow : +case yellow : led.Yellow(); - if (millis() - timer >= pausa * 2/3) { - state = turn_red ; - timer += pausa * 2/3; + if (millis() - timer >= pausa / 3) { + state = turn_red ; + timer += pausa / 3; } break; - case turn_red : +case turn_red : state = red ; break; - case red : +case red : led.Red(); if (millis() - timer >= pausa) { - state = turn_green ; - timer += pausa ; + state = turn_green ; + timer += pausa ; } break; - default: // In caso di default si fa giallo lampeggiante +default: // In caso di default si fa giallo lampeggiante led.Yellow(); delay(pausa/3); led.Off(); @@ -92,7 +94,8 @@ switch (state) { break; } -Serial.print(millis()); +// Debug: +Serial.print(millis()); Serial.print(" \t Stato attuale "); Serial.println(state); diff --git a/advanced_projects/state_machine/semaforo_4_doppio/semaforo_4_doppio.ino b/advanced_projects/state_machine/semaforo_4_doppio_single_FSM/semaforo_4_doppio_single_FSM.ino similarity index 94% rename from advanced_projects/state_machine/semaforo_4_doppio/semaforo_4_doppio.ino rename to advanced_projects/state_machine/semaforo_4_doppio_single_FSM/semaforo_4_doppio_single_FSM.ino index ab22ae0..be9bb04 100644 --- a/advanced_projects/state_machine/semaforo_4_doppio/semaforo_4_doppio.ino +++ b/advanced_projects/state_machine/semaforo_4_doppio_single_FSM/semaforo_4_doppio_single_FSM.ino @@ -1,5 +1,5 @@ /* - Semaforo RGB + Semaforo RGB single FSM Doppio semaforo, una via prinicipale (led) e una secondaria (secondary): @@ -12,6 +12,8 @@ Lo sketch e' stato implementato con una sola FSM in cui si incrociano gli stati dei due semafori. +- Schema per un led RGB: https://lab.piffa.net/schemi/rgb.jpg +- Schema per un bottone: https://www.arduino.cc/en/uploads/Tutorial/inputPullupButton.png */ #include 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 index dfcc362..db72e6a 100644 --- 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 @@ -1,15 +1,21 @@ /* - Semaforo RGB + Semaforo con doppia FSM - Un singolo semaforo costruito col paradigma delle macchine a stato. - Viene utilizzato un oggetto della libreria common per gestire il LED. +Due FSM indipendenti per la gestione di ognuno dei 2 semafori +che costituiscono un incrocio. Le due FSM possono modificare +i rispettivi stati. - Uno stimolo esterno rappresentato dalla pressione di un bottone - causa il passaggio di stato. +Un singolo semaforo costruito col paradigma delle macchine a stato. +Viene utilizzato un oggetto della libreria common per gestire il LED. - Implementata con millis() invece che con delay(), - sono stati aggiuntu due stati per meglio gestire lo stato yellow. +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. + +- Schema per un led RGB: https://lab.piffa.net/schemi/rgb.jpg +- Schema per un bottone: https://www.arduino.cc/en/uploads/Tutorial/inputPullupButton.png */ #include diff --git a/advanced_projects/state_machine/semaforo_rgb_stimolo_millis/semaforo_rgb_stimolo_millis.ino b/advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.ino similarity index 51% rename from advanced_projects/state_machine/semaforo_rgb_stimolo_millis/semaforo_rgb_stimolo_millis.ino rename to advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.ino index a8a14c0..1fce582 100644 --- a/advanced_projects/state_machine/semaforo_rgb_stimolo_millis/semaforo_rgb_stimolo_millis.ino +++ b/advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.ino @@ -19,82 +19,74 @@ 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 ; +boolean wait = 0; void setup() { - pinMode(input, INPUT_PULLUP); - Serial.begin(9600); - timer = millis(); + pinMode(input, INPUT_PULLUP); + Serial.begin(9600); + timer = millis(); } RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte - // della classe RGBLed +// della classe RGBLed void loop() { -switch (state) { + switch (state) { case turn_green : - state = green ; // Setta il prossimo state - break; + state = green ; // Setta il prossimo state + break; case green: - led.Green(); - if (millis() - timer >= pausa * 2/3) { - state = wait_button ; - timer += pausa * 2/3; - } - break; + led.Green(); + if (wait && millis() - timer >= pausa * 2/3) { + state = yellow; + timer += pausa * 2/3; + } - 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; + if (digitalRead(input) == LOW) { + wait = 1; + } + break; - case turn_yellow : - state = yellow ; - break; case yellow : - led.Yellow(); - if (millis() - timer >= pausa * 2/3) { - state = turn_red ; - timer += pausa * 2/3; - } - break; - - case turn_red : - state = red ; - break; + led.Yellow(); + if (millis() - timer >= pausa /3) { + state = red ; + wait = 0 ; + timer += pausa /3; + } + break; case red : - led.Red(); - if (millis() - timer >= pausa) { - state = turn_green ; - timer += pausa ; - } - break; + led.Red(); + if (millis() - timer >= pausa) { + state = turn_green ; + timer += pausa ; + } + break; default: // In caso di default si fa giallo lampeggiante - led.Yellow(); - delay(pausa/3); - led.Off(); - delay(pausa/3); - break; + led.Yellow(); + delay(pausa/3); + led.Off(); + delay(pausa/3); + break; -} -Serial.print(millis()); -Serial.print(" \t Stato attuale "); -Serial.println(state); + } + + //Debug: + Serial.print(millis()); + Serial.print(" \t Stato attuale "); + Serial.print(state); + Serial.print(" \t Wait: "); + Serial.println(wait); } -- 2.39.2