--- /dev/null
+/*
+ Semaforo RGB single FSM
+
+
+ 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.
+
+- 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 <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 += pausa * 2/3 ;
+ }
+ break;
+
+ case wait_button:
+ if (digitalRead(input) == LOW) {
+ delay(20); // Debouncing, si potrebbe fare con millis()
+ state = turn_yellow ; // Il passaggio di stato avviene alla pressione di un bottone
+ timer = millis();
+ };
+
+ break;
+
+ case turn_yellow :
+ led.Yellow();
+ state = yellow ;
+ break;
+
+ case yellow :
+ if (millis() - timer >= pausa / 3) {
+ state = turn_red ;
+ timer += pausa / 3;
+ }
+ break;
+
+ case turn_red :
+ led.Red();
+ secondary.Green();
+ state = red ;
+ break;
+
+ case red :
+ if (millis() - timer >= pausa /3) {
+ state = turn_sec_yellow ;
+ timer += pausa /3 ;
+ }
+ break;
+
+ case turn_sec_yellow :
+ secondary.Yellow();
+ state = sec_yellow ;
+ break;
+
+ case sec_yellow :
+ if (millis() - timer >= pausa / 3) {
+ state = turn_green ;
+ timer += pausa /3;
+ }
+ 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.
+ */