+++ /dev/null
-/*
- 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);
-
-}
--- /dev/null
+/*
+ Semaforo RGB
+
+ Un singolo semaforo costruito col paradigma delle macchine a stato.
+ Viene utilizzato un oggetto della libreria common per gestire il LED.
+
+ */
+#include <common.h>
+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?
+ */
--- /dev/null
+/*
+ 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 <common.h>
+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);
+
+}
--- /dev/null
+/*
+ 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 <common.h>
+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.
+ */
--- /dev/null
+/*
+ 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 <common.h>
+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.
+ */
--- /dev/null
+/*
+ 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 <common.h>
+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.
+ */
--- /dev/null
+/*
+ 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 <common.h>
+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.
+ */
+++ /dev/null
-/*
- Semaforo RGB
-
- Un singolo semaforo costruito col paradigma delle macchine a stato.
- Viene utilizzato un oggetto della libreria common per gestire il LED.
-
- */
-#include <common.h>
-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?
- */
+++ /dev/null
-/*
- 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 <common.h>
-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.
- */
--- /dev/null
+/*
+ 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 <common.h>
+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.
+ */
+++ /dev/null
-/*
-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
pinMode(greenPin, OUTPUT);
};
+void RGBLed::SetColor (byte r, byte g, byte b) {
+// Imposta il colore di un LED RGB
+ analogWrite(redPin, r);
+ analogWrite(greenPin, g);
+ analogWrite(bluePin, b);
+ };
+
void RGBLed::Red () {
// Accende il LED di rosso
- analogWrite(redPin, 0);
- analogWrite(greenPin, 255);
- analogWrite(bluePin, 255);
+ SetColor(0,255,255);
};
void RGBLed::Green () {
// Accende il LED di verde
- analogWrite(redPin, 255);
- analogWrite(greenPin, 0);
- analogWrite(bluePin, 255);
+ SetColor(255,0,255);
};
void RGBLed::Blue () {
// Accende il LED di blu
- analogWrite(redPin, 255);
- analogWrite(greenPin, 255);
- analogWrite(bluePin, 0);
+ SetColor(255,255,0);
};
void RGBLed::Magenta () {
// Accende il LED di magenta
- analogWrite(redPin, 0);
- analogWrite(greenPin, 255);
- analogWrite(bluePin, 0);
+ SetColor(0,255,0);
};
void RGBLed::Cyano () {
// Accende il LED di Cyano
- analogWrite(redPin, 255);
- analogWrite(greenPin, 0);
- analogWrite(bluePin, 0);
+ SetColor(255,0,0);
};
void RGBLed::Yellow () {
// Accende il LED di giallo
- analogWrite(redPin, 0);
- analogWrite(greenPin, 0);
- analogWrite(bluePin, 255);
+ SetColor(0,0,255);
};
void RGBLed::White () {
// Accende il LED
- analogWrite(redPin, 0);
- analogWrite(greenPin, 0);
- analogWrite(bluePin, 0);
+ SetColor(0,0,0);
};
void RGBLed::Off () {
// Spegne il LED
- analogWrite(redPin, 255);
- analogWrite(greenPin, 255);
- analogWrite(bluePin, 255);
+ SetColor(255,255,255);
};
-void RGBLed::SetColor (byte r, byte g, byte b) {
- // Imposta il colore di un LED RGB
- analogWrite(redPin, r);
- analogWrite(greenPin, g);
- analogWrite(bluePin, b);
+
+/////////////////////////////////////
+// Lampeggiatore
+// Constructor
+Lampeggiatore::Lampeggiatore(int pin)
+{
+ ledPin = pin;
+ pinMode(ledPin, OUTPUT);
+ ledState = LOW;
+ previousMillis = 0;
+ interval = 500;
+};
+
+
+
+
+// Una funzione facente parte di una classe prende il nome di "metodo" della stessa:
+void Lampeggiatore::Blink() {
+ // Illumina il led a 500ms
+
+ if(millis() - previousMillis > interval) {
+ // save the last time you blinked the LED
+ previousMillis = millis();
+
+ // if the LED is off turn it on and vice-versa:
+ ledState = !ledState ; // Inverti il LED
+ }
+ // set the LED with the ledState of the variable:
+ digitalWrite(ledPin, ledState);
+};
+
+void Lampeggiatore::Blink(long time) {
+ // Illumina il led secondo un intervallo passato come argomento
+
+ if(millis() - previousMillis > time) {
+ // save the last time you blinked the LED
+ previousMillis = millis();
+
+ // if the LED is off turn it on and vice-versa:
+ ledState = !ledState ; // Inverti il LED
+ }
+ // set the LED with the ledState of the variable:
+ digitalWrite(ledPin, ledState);
+};
+
+void Lampeggiatore::Blink(long up, long down) {
+ // Illumina il ledB precisando ontime e downtime
+
+ if((ledState == HIGH)&& (millis() - previousMillis > up)) {
+ // save the last time you blinked the LED
+ previousMillis = millis();
+ ledState = LOW ;
+ }
+ else if((ledState == LOW)&& (millis() - previousMillis > down)) {
+ previousMillis = millis();
+ ledState = HIGH ;
+ }
+
+ // set the LED with the ledState of the variable:
+ digitalWrite(ledPin, ledState);
+};
+
+/////////////////////////////////////
+// Pwm
+// Constructor
+Pwm::Pwm(int pin)
+{
+ ledPin = pin;
+ pinMode(ledPin, OUTPUT);
+ previousMillis = 0;
+ byte brightness = 0 ;
+ increment = 1;
+};
+
+void Pwm::Up(long speed) {
+ // Aumenta progressivamente la luminosita' usanndo millis()
+ // quindi senza bloccare il processore
+
+ analogWrite(ledPin, brightness); // La funziona analogWrite utilizza il PWM
+ // a 8 bit integrato nel MCU: simula un serie di valori intermedi
+ // nell'intervallo discreto con minimo 0 (spento) e massimo 255 (acceso).
+
+ if ((millis() - previousMillis) > speed / 256) {
+ brightness++; // Incrementiamo la luminosita'
+ previousMillis = millis();
+ };
+}
+
+void Pwm::Down(long speed ) {
+ // Riduce progressivamente la luminosita' usanndo millis()
+ // quindi senza bloccare il processore
+
+ analogWrite(ledPin, brightness); // La funziona analogWrite utilizza il PWM
+ // a 8 bit integrato nel MCU: simula un serie di valori intermedi
+ // nell'intervallo discreto con minimo 0 (spento) e massimo 255 (acceso).
+
+ if ((millis() - previousMillis) > speed / 256) {
+ brightness--; // Incrementiamo la luminosita'
+ previousMillis = millis();
+ };
+}
+
+void Pwm::UD(long speed ) {
+ // Aumenta e riduce in sequenza la luminosita' usanndo millis()
+ if ((millis() - previousMillis) > speed / 512) {
+ brightness = brightness + increment; // Incrementiamo la luminosita'
+ previousMillis = millis();
+ if (brightness == 0 || brightness == 255) { // Reverse direction
+ increment = -increment ;
+ };
};
+ analogWrite(ledPin, brightness);
+}
+
//////////////////
// Funzioni
-void brilla(byte pin) {
- // Accende e spegne il LED senza un argomento
- // per impostare la velocita'.
- const int velocita = 500;
-pinMode(pin, OUTPUT);
- // sequenze di istruzione: accendere e spegnere il LED
- digitalWrite(pin, HIGH); // turn the LED on (HIGH is the voltage level)
- delay(velocita); // wait for a second
- digitalWrite(pin, LOW); // turn the LED off by making the voltage LOW
- delay(velocita); // wait for a second
-};
-
-void brilla(byte pin, int velocita) {
+void brilla(byte pin, int velocita ) { // Defalt value di velocita' solo nell'Header
// Accende e spegne il LED accetando un argomento
// per impostare la velocita'.
digitalWrite(pin, LOW); // turn the LED off by making the voltage LOW
delay(velocita); // wait for a second
};
+
class RGBLed {
// Classe rappresentativa di un LED RGB
-
+ protected: // Vedi esempio Ereditarieta'
byte redPin ;
byte greenPin ;
byte bluePin ;
public:
RGBLed (byte pinR, byte pinG, byte pinB) ;
+ void SetColor (byte r, byte g, byte b) ;
void Red ();
void Green ();
void Blue ();
void White ();
void Yellow ();
void Off ();
- void SetColor (byte r, byte g, byte b) ;
};
-void brilla(byte pin, int velocita = 500) ;
+
+class Lampeggiatore {
+ // Lampeggia un LED utilizzando millis()
+ // Variabili
+ int ledPin ; // il numero del LED pin
+ int ledState ; // stato attuale del LED
+ long interval ; // milliseconds di intervallo nel lampeggiare
+ long previousMillis ; // precedente cambio di stato
+
+
+ // Constructor: come viene instanziato un oggetto facente parte della classe
+public:
+ Lampeggiatore(int pin);
+ void Blink(); // Lampeggia ogni 500ms
+ void Blink(long interval); // Lampeggia inpostando l'intervallo
+ void Blink(long on, long down); // Imposta il tempo acceso e il tempo spento
+};
+
+
+
+////////////////////////////
+class Pwm {
+ /*
+ PWM per un LED: aumentare progressivamente la luminosita'.
+ Utilizza la funzione millis() invece che un delay()
+ in modo da non blocare il processore.
+ */
+ // Variabili
+ int ledPin ; // il numero del LED pin
+ int speed ; // velocita' del ciclo in ms
+ byte brightness ; // luminostia' iniziale
+ long previousMillis ; //precedente cambio di stato
+ byte increment ; // aumenta brighteness nel loop UD
+
+ // Constructor: come viene instanziato un oggetto facente parte della classe
+public:
+ Pwm(int pin); // numero di pin, velocita' di ciclo
+ void Up(long speed);
+ void Down(long speed);
+ void UD(long speed);
+};
+
+//////////////////////
+// Funzioni
+
+void brilla(byte pin, int velocita = 200) ;
#endif
--- /dev/null
+/* Ereditarieta'
+
+ La classe SuperLED definita in questo sketch
+ eredita le caratteristiche di RGBLed e introduce un nuovo metodo.
+
+*/
+
+#include <common.h> // L'orine e' importante: prima l'include,
+ // poi la dichiarazione della nuova classe (non a fondo pagina)
+ // poi potremo usare la nuova classe
+
+class SuperLED : public RGBLed { // Ereditamo dalla classe RGBLed
+ // Nuovi colori per RGBLed
+
+ using RGBLed::RGBLed ; // Richiamiamo il constructor del genitore
+ public:
+ void Violet () { // Nuovo metodo
+ // Accende il LED di viola
+ analogWrite(redPin, 255 - 238);
+ analogWrite(greenPin, 255 - 130);
+ analogWrite(bluePin, 255 - 238);
+ };
+};
+
+void setup() {
+ // I PINs vengono impostati dalla dichiarazione dell'ogetto.
+}
+
+// Instanziamo un LED
+SuperLED led(11, 10, 9); //Istanziamo un oggetto led facente parte
+ // della inuova classe SuperLed che eredita da RGBLed
+
+void loop() {
+ led.Violet(); // Nuovo metodo
+ delay(1000);
+ led.Off();
+ delay(1000); // Vecchio metodo
+}
+