]> git.piffa.net Git - sketchbook_andrea/blob - advanced_projects/state_machine/semaforo_3_millis/semaforo_3_millis.ino
FSM reorder
[sketchbook_andrea] / advanced_projects / state_machine / semaforo_3_millis / semaforo_3_millis.ino
1 /*
2    Semaforo RGB
3
4    Un singolo semaforo costruito col paradigma delle macchine a stato.
5    Viene utilizzato un oggetto della libreria common per gestire il LED.
6
7    Uno stimolo esterno rappresentato dalla pressione di un bottone
8    causa il passaggio di stato.
9
10    Implementata con millis() invece che con delay(),
11    sono stati aggiuntu due stati per meglio gestire lo stato yellow.
12
13 - Schema per un led RGB: https://lab.piffa.net/schemi/rgb.jpg
14 - Schema per un bottone: https://www.arduino.cc/en/uploads/Tutorial/inputPullupButton.png
15    */
16
17 #include <common.h>
18 const byte input = 2; // PIN del bottone
19 int pausa = 3000;
20 long timer ;
21 enum states_available { // Stati della FMS
22     turn_green,    // Dinamico, transizione
23     green,         // Statico
24     wait_button,   // Evento - Stimolo
25     turn_yellow,      // Dinamico, transizione
26     yellow,            // Statico
27     turn_red,      // Dinamico, transizione
28     red            // Statico
29 };
30
31 states_available state  ;
32
33
34 void setup() {
35     pinMode(input, INPUT_PULLUP);
36     Serial.begin(9600);
37     timer = millis();
38 }
39
40 RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte
41 // della classe RGBLed
42
43 void loop() {
44 switch (state) {
45 case turn_green :
46     state = green ; // Setta il prossimo state
47     break;
48
49 case green:
50     led.Green();
51     if (millis() - timer >= pausa * 2/3) {
52         state = wait_button ;
53         timer += pausa * 2/3 ;
54     }
55     break;
56
57 case wait_button:
58     if (digitalRead(input) == LOW) {
59         state = turn_yellow ; // Il passaggio di stato avviene alla pressione di un bottone
60         delay(20); // Debouncing, si potrebbe fare con millis()
61         timer = millis();
62     };
63     break;
64
65 case turn_yellow :
66     state = yellow ;
67     break;
68
69 case yellow :
70     led.Yellow();
71     if (millis() - timer >= pausa / 3) {
72         state = turn_red ;
73         timer += pausa  / 3;
74     }
75     break;
76
77 case turn_red :
78     state = red ;
79     break;
80
81 case red :
82     led.Red();
83     if (millis() - timer >= pausa) {
84         state = turn_green ;
85         timer += pausa ;
86     }
87     break;
88
89 default:    // In caso di default si fa giallo lampeggiante
90     led.Yellow();
91     delay(pausa/3);
92     led.Off();
93     delay(pausa/3);
94     break;
95
96 }
97 // Debug:
98 Serial.print(millis());
99 Serial.print(" \t Stato attuale ");
100 Serial.println(state);
101
102 }
103
104 /* Domande:
105  1. Introdurre un secondo semaforo che cambia stato quando viene attivato
106     lo stimolo.
107  2. L'uso di delay() puo' essere limitativo: come rimediare?
108 .
109 .
110 .
111 .
112 .
113 .
114 .
115 .
116 .
117 .
118   Soluzioni
119 2. Si potrebbe utilizzare un interrupt per gli stimoli oppure millis()
120    per gestire le pause.
121  */