]> git.piffa.net Git - sketchbook_andrea/blob - advanced_projects/state_machine/semaforo_5_doppia_fsm/semaforo_5_doppia_fsm.ino
db72e6a95ee642a0f27089f5cef78deb28461d48
[sketchbook_andrea] / advanced_projects / state_machine / semaforo_5_doppia_fsm / semaforo_5_doppia_fsm.ino
1 /*
2    Semaforo con doppia FSM
3
4 Due FSM indipendenti per la gestione di ognuno dei 2 semafori
5 che costituiscono un incrocio. Le due FSM possono modificare
6 i rispettivi stati.
7
8 Un singolo semaforo costruito col paradigma delle macchine a stato.
9 Viene utilizzato un oggetto della libreria common per gestire il LED.
10
11 Uno stimolo esterno rappresentato dalla pressione di un bottone
12 causa il passaggio di stato.
13
14 Implementata con millis() invece che con delay(),
15 sono stati aggiuntu due stati per meglio gestire lo stato yellow.
16
17 - Schema per un led RGB: https://lab.piffa.net/schemi/rgb.jpg
18 - Schema per un bottone: https://www.arduino.cc/en/uploads/Tutorial/inputPullupButton.png
19    */
20
21 #include <common.h>
22 const byte input = 2; // PIN del bottone
23 int pausa = 3000;
24 long timer ;
25 enum states_available { // Stati della FMS
26     turn_green,    // Transizione
27     green,         // Statico
28     wait_button,   // Evento - Stimolo
29     turn_yellow,   // transizione
30     yellow,        // Statico
31     turn_red,      // transizione
32     red            // Statico
33 };
34
35 states_available FSM1  ;
36 states_available FSM2  ;
37
38
39 void setup() {
40   pinMode(input, INPUT_PULLUP);
41   Serial.begin(9600);
42   timer = millis();
43 }
44
45 RGBLed led1(11, 10, 9); //Istanziamo un oggetto led facente parte
46 RGBLed led2(8,7,6); //Istanziamo un oggetto led facente parte
47                        // della classe RGBLed
48
49 void loop() {
50 switch (FSM1) {
51     case turn_green :
52     led1.Green();    
53     FSM1 = green ;  // Setta il prossimo state
54     FSM2 = red ;    // Setta il prossimo state
55     break;
56
57     case green:
58     if (millis() - timer >= pausa * 2/3) {
59     FSM1 = wait_button ;
60     timer += pausa * 2/3;
61     }
62     break;
63
64     case wait_button:
65     if (digitalRead(input) == LOW) { 
66     delay(20); // Debouncing, si potrebbe fare con millis() o un interrupt
67     FSM1 = turn_yellow ; 
68     timer = millis();
69     };
70
71     break;
72
73     case turn_yellow :
74     led1.Yellow();
75     FSM1 = yellow ;
76     break;
77
78     case yellow :
79     if (millis() - timer >= pausa * 2/3) {
80         FSM1 = turn_red ;
81         timer += pausa * 2/3 ;
82     }
83     break;
84
85     case turn_red :
86     led1.Red();
87     FSM1 = red ;
88     FSM2 = turn_green ;
89     break;
90
91     case red :
92     break;
93
94     default:    // In caso di default si fa giallo lampeggiante
95     led1.Yellow();
96     delay(pausa/3);
97     led1.Off();
98     delay(pausa/3);
99     break;
100
101 }
102 switch (FSM2) {
103     case turn_green :
104     led2.Green();
105     FSM2 = green ; // Setta il prossimo state
106     break;
107
108     case green:
109     if (millis() - timer >= pausa * 2/3) {
110     FSM2 = turn_yellow;
111     timer += pausa * 2/3;
112     }
113     break;
114
115     case turn_yellow :
116     led2.Yellow();
117     FSM2 = yellow ;
118     break;
119
120     case yellow :
121     if (millis() - timer >= pausa / 3) {
122     FSM2 = turn_red ;
123     timer += pausa * 2/3;
124     }
125     break;
126
127     case turn_red :
128     FSM2 = red ;
129     FSM1 = turn_green;
130     break;
131
132     case red :
133     led2.Red(); // Aggiorniamo il LED in questo stato invece che nel precedente
134                 // per entrare nel primo ciclo di esecuzione con il LED rosso
135     break;
136
137     default:    // In caso di default si fa giallo lampeggiante
138     led2.Yellow();
139     delay(pausa/3);
140     led2.Off();
141     delay(pausa/3);
142     break;
143 }
144
145 Serial.print(millis()); 
146 Serial.print(" \t Stato attuale FSM1: ");
147 Serial.print(FSM1);
148 Serial.print(" - FSM2: ");
149 Serial.println(FSM2);
150 }
151
152 /* Domande:
153  1. E' piu' semplice ora inserire degli altri oggetti nello sketch?
154  2. Gli eventi sono condivisi? Le varie FSM hanno modo di scambiarsi
155     informazioni sui relativi stati?
156  3. Creare un dispatcher degli eventi al quale le varie FSM possono
157     riferirsi.
158 .
159 .
160 .
161 .
162 .
163 .
164 .
165 .
166 .
167 .
168   Soluzioni
169 1. Si, per quanto le 2 FSM non siano indipendenti l'una dall'altra.
170 2. No, c'e' un solo flusso degli eventi, il blocco di una delle FSM 
171    puo' causare lo stop di tutto il sistema.
172  */