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