]> git.piffa.net Git - sketchbook_andrea/blobdiff - advanced_projects/state_machine/semaforo_rgb/semaforo_rgb.ino
Merge branch 'master' of kim:/home/git/sketchbook_andrea
[sketchbook_andrea] / advanced_projects / state_machine / semaforo_rgb / semaforo_rgb.ino
index 1318a089adb903fdc316943ff7304615b919a51c..5d86aa95778c48f47bf4a858b90fa03bb3f1db35 100644 (file)
 /*
    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.
  */