/*
Semaforo RGB
+
+Version: singolo semaforo + millis + memoria giallo
Un singolo semaforo costruito col paradigma delle macchine a stato.
Viene utilizzato un oggetto della libreria common per gestire il LED.
+ Uno stimolo esterno rappresentato dalla pressione di un bottone
+ causa il passaggio di stato.
+ Il semaforo resta verde fino a quando non riceve lo stimolo
+ (es passaggio pedonale).
+
+ Implementata con millis() invece che con delay(),
+
*/
+
#include <common.h>
+const byte input = 2; // PIN del bottone
int pausa = 3000;
+long timer ;
+boolean wait = 0; // Memoria bottone
+
enum states_available { // Stati della FMS
- turn_green, // Dinamico, transizione
green, // Statico
- turn_red,
- red
+ yellow, // Statico
+ red // Statico
};
states_available state ;
void setup() {
- Serial.begin(9600);
- Serial.flush();
+ pinMode(input, INPUT_PULLUP);
+ Serial.begin(9600);
+ timer = millis();
}
-RGBLed led(11, 10, 9); //Istanziamo un oggetto led facente parte
- // della classe RGBLed
+RGBLed led(11, 10, 9);
void loop() {
-switch (state) {
- case turn_green :
- led.Green();
- state = green ; // Setta il prossimo state
- break;
+ switch (state) {
case green:
- delay(pausa * 2/3);
- state = turn_red ;
- break;
-
- case turn_red :
- led.Yellow();
- delay(pausa/3);
- led.Red();
- delay(pausa);
- state = red ;
- break;
+ led.Green();
+ if (wait && (millis() - timer >= pausa * 2/3)) {
+ state = yellow;
+ timer = millis();
+ }
+
+ if (digitalRead(input) == LOW) {
+ wait = 1;
+ }
+ break;
+
+
+ case yellow :
+ led.Yellow();
+ if (millis() - timer >= pausa /3) {
+ state = red ;
+ wait = 0 ;
+ timer += pausa /3;
+ }
+ break;
case red :
- delay(pausa);
- state = turn_green ;
- break;
+ led.Red();
+ if (millis() - timer >= pausa) {
+ state = green ;
+ timer += pausa ;
+ }
+ break;
- default: // In caso di default si fa giallo
- led.Yellow();
- delay(pausa/3);
- led.Off();
- delay(pausa/3);
- break;
+ default: // In caso di default si fa giallo lampeggiante
+ led.Yellow();
+ delay(pausa/3);
+ led.Off();
+ delay(pausa/3);
+ break;
-}
-Serial.print(millis());
-Serial.print(" \t Stato attuale ");
-Serial.println(state);
+ }
+
+ //Debug:
+ Serial.print(millis());
+ Serial.print(" \t Stato attuale ");
+ Serial.print(state);
+ Serial.print(" \t Wait: ");
+ Serial.println(wait);
}
/* Domande:
- 1. Come legare il passaggio di stato ad un evento esterno,
- ad es. la pressione di un bottone?
+ 1. Introdurre un secondo semaforo che cambia stato quando viene attivato
+ lo stimolo.
+ 2. L'uso di delay() puo' essere limitativo: come rimediare?
+.
+.
+.
+.
+.
+.
+.
+.
+.
+.
+ Soluzioni
+2. Si potrebbe utilizzare un interrupt per gli stimoli oppure millis()
+ per gestire le pause.
*/