From 3b78d813afb2e27ed29faa261570d2eeb8d5068d Mon Sep 17 00:00:00 2001 From: eaman Date: Wed, 19 Oct 2016 03:32:24 +0200 Subject: [PATCH] State machine e blinks con millis() --- .../state_machine/blink/blink.ino | 56 +++++ .../semaforo_rgb/semaforo_rgb.ino | 70 +++++++ .../semaforo_rgb_stimolo.ino | 98 +++++++++ .../state_machine/semaphore/semaphore.ino | 194 ++++++++++++++++++ .../BlinkWithoutDelay_1.ino | 2 +- .../BlinkWithoutDelay_2_led.ino | 4 +- .../BlinkWithoutDelay_3_funzione.ino | 4 +- .../BlinkWithoutDelay_4_argomento.ino | 4 +- .../BlinkWithoutDelay_5_cleanup.ino | 4 +- .../BlinkWithoutDelay_6_1_interrupt.ino | 2 +- .../BlinkWithoutDelay_6_class.ino | 2 +- .../BlinkWithoutDelay_7_struct.ino | 2 +- .../BlinkWithoutDelay_8_struct_pointer.ino | 2 +- 13 files changed, 431 insertions(+), 13 deletions(-) create mode 100644 advanced_projects/state_machine/blink/blink.ino create mode 100644 advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.ino create mode 100644 advanced_projects/state_machine/semaforo_rgb_stimolo/semaforo_rgb_stimolo.ino create mode 100644 advanced_projects/state_machine/semaphore/semaphore.ino diff --git a/advanced_projects/state_machine/blink/blink.ino b/advanced_projects/state_machine/blink/blink.ino new file mode 100644 index 0000000..485c2f2 --- /dev/null +++ b/advanced_projects/state_machine/blink/blink.ino @@ -0,0 +1,56 @@ +/* + 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_rgb/semaforo_rgb.ino b/advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.ino new file mode 100644 index 0000000..1318a08 --- /dev/null +++ b/advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.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_rgb_stimolo/semaforo_rgb_stimolo.ino b/advanced_projects/state_machine/semaforo_rgb_stimolo/semaforo_rgb_stimolo.ino new file mode 100644 index 0000000..de2373b --- /dev/null +++ b/advanced_projects/state_machine/semaforo_rgb_stimolo/semaforo_rgb_stimolo.ino @@ -0,0 +1,98 @@ +/* + 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/semaphore/semaphore.ino b/advanced_projects/state_machine/semaphore/semaphore.ino new file mode 100644 index 0000000..f309a6a --- /dev/null +++ b/advanced_projects/state_machine/semaphore/semaphore.ino @@ -0,0 +1,194 @@ +/* +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/multitasking/BlinkWithoutDelay_1/BlinkWithoutDelay_1.ino b/multitasking/BlinkWithoutDelay_1/BlinkWithoutDelay_1.ino index f7fee43..72a9694 100644 --- a/multitasking/BlinkWithoutDelay_1/BlinkWithoutDelay_1.ino +++ b/multitasking/BlinkWithoutDelay_1/BlinkWithoutDelay_1.ino @@ -48,7 +48,7 @@ void loop() // the LED is bigger than the interval at which you want to // blink the LED. - if(millis() - previousMillis > interval) { + if (millis() > previousMillis + interval) { // Aggiorniamo il contatore previousMillis previousMillis = millis(); diff --git a/multitasking/BlinkWithoutDelay_2_led/BlinkWithoutDelay_2_led.ino b/multitasking/BlinkWithoutDelay_2_led/BlinkWithoutDelay_2_led.ino index 0283339..2100ead 100644 --- a/multitasking/BlinkWithoutDelay_2_led/BlinkWithoutDelay_2_led.ino +++ b/multitasking/BlinkWithoutDelay_2_led/BlinkWithoutDelay_2_led.ino @@ -48,7 +48,7 @@ void setup() { void loop() { // Primo LED - if(millis() - previousMillisA > intervalA) { + if (millis() > previousMillisA + intervalA) { // save the last time you blinked the LED previousMillisA = millis(); @@ -62,7 +62,7 @@ void loop() } // Secondo LED - if(millis() - previousMillisB > intervalB) { + if (millis() > previousMillisB + intervalB) { // save the last time you blinked the LED previousMillisB = millis(); diff --git a/multitasking/BlinkWithoutDelay_3_funzione/BlinkWithoutDelay_3_funzione.ino b/multitasking/BlinkWithoutDelay_3_funzione/BlinkWithoutDelay_3_funzione.ino index 93387bd..e27cf55 100644 --- a/multitasking/BlinkWithoutDelay_3_funzione/BlinkWithoutDelay_3_funzione.ino +++ b/multitasking/BlinkWithoutDelay_3_funzione/BlinkWithoutDelay_3_funzione.ino @@ -47,7 +47,7 @@ void loop() // Funzioni: void lightLedA () { - if(millis() - previousMillisA > intervalA) { + if (millis() > previousMillisA + intervalA) { // save the last time you blinked the LED previousMillisA = millis(); @@ -65,7 +65,7 @@ void lightLedA () { void lightLedB () { long intervalB = 500; static int ledStateB ; // https://www.arduino.cc/en/Reference/Static - if(millis() - previousMillisB > intervalB) { + if (millis() > previousMillisB + intervalB) { // save the last time you blinked the LED previousMillisB = millis(); diff --git a/multitasking/BlinkWithoutDelay_4_argomento/BlinkWithoutDelay_4_argomento.ino b/multitasking/BlinkWithoutDelay_4_argomento/BlinkWithoutDelay_4_argomento.ino index ae2205a..e2b28a9 100644 --- a/multitasking/BlinkWithoutDelay_4_argomento/BlinkWithoutDelay_4_argomento.ino +++ b/multitasking/BlinkWithoutDelay_4_argomento/BlinkWithoutDelay_4_argomento.ino @@ -34,7 +34,7 @@ void loop() void lightLedA (int interval) { // Illumina il ledA secondo un intervallo passato come argomento - if(millis() - previousMillisA > interval) { + if (millis() > previousMillisA + interval) { // save the last time you blinked the LED previousMillisA = millis(); @@ -52,7 +52,7 @@ void lightLedA (int interval) { void lightLedB (int interval) { // Illumina il ledB secondo un intervallo passato come argomento - if(millis() - previousMillisB > interval) { + if (millis() > previousMillisB + interval) { // save the last time you blinked the LED previousMillisB = millis(); diff --git a/multitasking/BlinkWithoutDelay_5_cleanup/BlinkWithoutDelay_5_cleanup.ino b/multitasking/BlinkWithoutDelay_5_cleanup/BlinkWithoutDelay_5_cleanup.ino index 2a74c5c..824c53f 100644 --- a/multitasking/BlinkWithoutDelay_5_cleanup/BlinkWithoutDelay_5_cleanup.ino +++ b/multitasking/BlinkWithoutDelay_5_cleanup/BlinkWithoutDelay_5_cleanup.ino @@ -38,7 +38,7 @@ void loop() void lightLedA (int interval) { // Illumina il ledA secondo un intervallo passato come argomento - if(millis() - previousMillisA > interval) { + if (millis() > previousMillisA + interval) { // save the last time you blinked the LED previousMillisA = millis(); @@ -51,7 +51,7 @@ void lightLedA (int interval) { void lightLedB (int interval) { // Illumina il ledB secondo un intervallo passato come argomento - if(millis() - previousMillisB > interval) { + if (millis() > previousMillisB + interval) { previousMillisB = millis(); digitalWrite(ledB, !digitalRead(ledB)); // Leggiamo direttamente il registro di ledB e scriviamo il suo opposto, diff --git a/multitasking/BlinkWithoutDelay_6_1_interrupt/BlinkWithoutDelay_6_1_interrupt.ino b/multitasking/BlinkWithoutDelay_6_1_interrupt/BlinkWithoutDelay_6_1_interrupt.ino index 6018195..175f705 100644 --- a/multitasking/BlinkWithoutDelay_6_1_interrupt/BlinkWithoutDelay_6_1_interrupt.ino +++ b/multitasking/BlinkWithoutDelay_6_1_interrupt/BlinkWithoutDelay_6_1_interrupt.ino @@ -28,7 +28,7 @@ public: void Update () { // Illumina il ledB secondo un intervallo passato come argomento - if(millis() - previousMillis > interval) { + if (millis() > previousMillis + interval) { // save the last time you blinked the LED previousMillis = millis(); diff --git a/multitasking/BlinkWithoutDelay_6_class/BlinkWithoutDelay_6_class.ino b/multitasking/BlinkWithoutDelay_6_class/BlinkWithoutDelay_6_class.ino index 7a1f27e..9ce5e9b 100644 --- a/multitasking/BlinkWithoutDelay_6_class/BlinkWithoutDelay_6_class.ino +++ b/multitasking/BlinkWithoutDelay_6_class/BlinkWithoutDelay_6_class.ino @@ -28,7 +28,7 @@ public: void Update () { // Illumina il ledB secondo un intervallo passato come argomento - if(millis() - previousMillis > interval) { + if (millis() > previousMillis + interval) { // save the last time you blinked the LED previousMillis = millis(); diff --git a/multitasking/BlinkWithoutDelay_7_struct/BlinkWithoutDelay_7_struct.ino b/multitasking/BlinkWithoutDelay_7_struct/BlinkWithoutDelay_7_struct.ino index 61a53b5..e726662 100644 --- a/multitasking/BlinkWithoutDelay_7_struct/BlinkWithoutDelay_7_struct.ino +++ b/multitasking/BlinkWithoutDelay_7_struct/BlinkWithoutDelay_7_struct.ino @@ -37,7 +37,7 @@ void loop() struct blinkLed lightLed(struct blinkLed temp) { // dataType tipo_di_struct nome_funzione(argomenti) // Illumina il ledA secondo un intervallo passato come argomento - if(millis() - temp.previousMillis > temp.interval) { // gli elementi dello struct sono accessibili tramite l'operatore [punto] + if (millis() > temp.previousMillis + temp.interval) { // gli elementi dello struct sono accessibili tramite l'operatore [punto] // save the last time you blinked the LED temp.previousMillis = millis(); diff --git a/multitasking/BlinkWithoutDelay_8_struct_pointer/BlinkWithoutDelay_8_struct_pointer.ino b/multitasking/BlinkWithoutDelay_8_struct_pointer/BlinkWithoutDelay_8_struct_pointer.ino index 635642d..f038199 100644 --- a/multitasking/BlinkWithoutDelay_8_struct_pointer/BlinkWithoutDelay_8_struct_pointer.ino +++ b/multitasking/BlinkWithoutDelay_8_struct_pointer/BlinkWithoutDelay_8_struct_pointer.ino @@ -20,7 +20,7 @@ struct blinkLed { long interval ; // milliseconds di intervallo nel lampeggiare long previousMillis ; //precedente cambio di stato }; -// Instanziamo i due led dalla struttur +// Instanziamo i due led dalla struttura blinkLed ledA = { 13 , LOW , 1000, 0 }; blinkLed ledB = { -- 2.39.2