]> git.piffa.net Git - sketchbook_andrea/blob - advanced_projects/state_machine/semaforo_5_doppia_fsm/semaforo_5_doppia_fsm.ino
d7e914609b0d5853ff98ad0b9d2f42655cc9257c
[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 * 1/3) {
80         FSM1 = turn_red ;
81         timer += pausa * 1/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.Blue();
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     timer = millis();
131     break;
132
133     case red :
134     led2.Red(); // Aggiorniamo il LED in questo stato invece che nel precedente
135                 // per entrare nel primo ciclo di esecuzione con il LED rosso
136     break;
137
138     default:    // In caso di default si fa giallo lampeggiante
139     led2.Yellow();
140     delay(pausa/3);
141     led2.Off();
142     delay(pausa/3);
143     break;
144 }
145
146 Serial.print(millis()); 
147 Serial.print(" \t Stato attuale FSM1: ");
148 Serial.print(FSM1);
149 Serial.print(" - FSM2: ");
150 Serial.println(FSM2);
151 }
152
153 /* Domande:
154  1. E' piu' semplice ora inserire degli altri oggetti nello sketch?
155  2. Gli eventi sono condivisi? Le varie FSM hanno modo di scambiarsi
156     informazioni sui relativi stati?
157  3. Creare un dispatcher degli eventi al quale le varie FSM possono
158     riferirsi.
159 .
160 .
161 .
162 .
163 .
164 .
165 .
166 .
167 .
168 .
169   Soluzioni
170 1. Si, per quanto le 2 FSM non siano indipendenti l'una dall'altra.
171 2. No, c'e' un solo flusso degli eventi, il blocco di una delle FSM 
172    puo' causare lo stop di tutto il sistema.
173  */