Tutorial‎ > ‎Arduino‎ > ‎In pratica‎ > ‎per chi inizia‎ > ‎

Il semaforo

pubblicato 24 ago 2011, 21:47 da Massimiliano D'Ambrosio   [ aggiornato in data 24 set 2011, 21:26 ]
In questo esempio Arduino viene usato in un contesto semaforico dove si trova a gestire 2 semafori.

Cosa deve lavorare il nostro semaforo?
Il nostro Arduino deve gestire le normali condizione luminose di un semaforo come previste dal codice della strada.
In dettaglio deve:
  • i primi  7 secondi dall'accensione i due semafori devono essere nella condizione di GIALLO lampeggiare.
  • poi il semaforo UNO deve passare in VERDE per 5 secondi e poi commutare.
  • il semaforo DUE deve passare in VERDE e rimanerci per 10 secondi.
  • il GIALLO di passaggio verde/rosso deve essere di almeno 4 secondi per entrambi i semafori
  • ci deve essere almeno 1 secondo in cui i semafori siano in ROSSO prima di commutare tra uno e altro.
Hardware
La realizzazione hardware è semplice e si compone di:
  • 1 Arduino UNO
  • 6 resistenze di valore adeguato che trovate nel cassetto. Io ho usato da 330ohm
  • 2 led rossi
  • 2 led gialli
  • 2 led verdi
  • Se avete una breadboard tanto meglio. In caso contrario una basetta millefori o semplificante collegati al volo vanno bene visto la semplicità di realizzazione

Procurato il materiale, ora cablate il tutto come dallo schema qui sotto

Arduino e 2 semafori

Parte hardware finita.

Ora passiamo al software

Abbiamo letto all'inizio come deve lavorare il nostro semaforo. Questo è un comportamento da gestire completamente tramite il software che andiamo a scrivere.
Il codice qui sotto è stato scritto all'alba. Esso è migliorabile in diversi punti ma cosi dovrebbe essere chiaro anche ai nuovi. 
Lo trovate tra gli allegati da poter usare e modificare con IDE.

Leggendo quanto richiesto per il funzionamento del semaforo dobbiamo prevedere dei blocchi di codice che permettano di gestire le condizioni richieste, dove:

  1. un blocco che faccia lampeggiare il GIALLO dei due semafori.
  2. il blocco al punto 1 deve essere mantenuto per 7 secondi.
  3. doppiamo prevedere il blocco che permetta di far funzionale regolarmente il semaforo.
  4. è richiesto che il semaforo UNO rimanga in VERDE per 5 secondi e il numero DUE per 10 secondi. Quindi i tempi per un ciclo completo dei due semafori non è al 50% 50%, ma il semaforo UNO è al 25% del tempo totale VERDE e  il DUE al 75%.
  5. poi vanno previste le condizioni di commutazioni tra i due semafori che sono
    • verde>giallo per 4 secondi>rosso per entrambi per 1 secondo>commutazione
  6. aggiungiamo anche un blocco che spenga i vari led del semaforo

Partiamo cominciando a scrivere il primo blocco con alcune assegnazioni dei pin I/O digitali che useremo e delle variabili

const unsigned int LED_R1 = 13; //assegnato al pin I/O 13 led rosso semaforo 1
const unsigned int LED_G1 = 12; //assegnato al pin I/O 12 led giallo semaforo 1
const unsigned int LED_V1 = 11;  //assegnato al pin I/O 11 led verde semaforo 1
const unsigned int LED_R2 = 10; //assegnato al pin I/O 10 led rosso semaforo 2
const unsigned int LED_G2 = 9; //assegnato al pin I/O 9 led giallo semaforo 2
const unsigned int LED_V2 = 8; //assegnato al pin I/O 8 led verde semaforo 2
int semaforoON = 1; // definiamo una variabile per sapere quale semaforo è acceso e la inizializziamo con 1 ON.
unsigned long time; // variabile che useremo per sapere da quanto è acceso il semaforo.

Con semaforoON=1 indichiamo che il semaforo uno deve essere verde per primo.

Ora incontriamo il blocco setup

void setup() {               
  // questo blocco ci deve essere sempre e serve per inizializzare alcune cose 
  // Inizializziamo 6 porte digitali I/O come uscite
  // 3 per una semaforo (RGV) e 3 per l'altro
  // assegnare in setup le I/O è obbligatoria 
  pinMode(LED_R1, OUTPUT);
  pinMode(LED_G1, OUTPUT);
  pinMode(LED_V1, OUTPUT);
  pinMode(LED_R2, OUTPUT);
  pinMode(LED_G2, OUTPUT);
  pinMode(LED_V2, OUTPUT);
 
  /*
  se non usavamo le const unsigned int andavano dichiarati cosi 
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(8, OUTPUT);
  */
 
  off_led(); // inizializziamo il tutto spegnendo i LED richiamando la funzione off_led definita più sotto
   
}

Visto che è stata chiamata la funzione off_led che non fa altro che spegnere i sei LED.

void off_led() {
  // spegnamo il semaforo, tutti i LED spenti
  
  digitalWrite(LED_R1, LOW);// queste 6
  digitalWrite(LED_R2, LOW); // righe
  digitalWrite(LED_G1, LOW); // spengono
  digitalWrite(LED_G2, LOW); // i led ROSSI, GIALLI e VERDI
  digitalWrite(LED_V1, LOW);  // del primo semaforo
  digitalWrite(LED_V2, LOW);  // e del secondo

}

Il blocco che fa lampeggiare il GIALLO dei due semafori

void blink_yellow() {
  // questo blocco di codice è chiamata una funzione in cui definiamo qualche cosa da fare.
  // nel nostro caso i LED GIALLI dei due semafori devono lampeggiano
  // usare le definizioni e procedure permette di rendere il codice più leggibile e più semplice da aggiornare
     
  digitalWrite(LED_G1, HIGH);  // ora accendiamo il giallo del primo semaforo
  digitalWrite(LED_G2, HIGH);  // e del secondo
  delay(1000);                // aspettiamo 1 secondo (1000ms millisecondi). Modifica i ms per cambiare la durate dell'accesso                                    e sotto per spendo
  digitalWrite(LED_G1, LOW);  // ora gli spegniamo, spetto il giallo del primo
  digitalWrite(LED_G2, LOW);  // e del secondo
  delay(1000);               // attendiamo un altro secondo e poi ripartiamo. Se modifica il delay precedente per mantere lo                                     stesso rapporto ON/OFF al 50% devono avere lo stesso ritardo.
 

Il tutto dura 2 secondi pari al 50% accesso e 50% spento. Come vedete in questa funzione fa semplicemente accendere il giallo e mantenerlo per un secondo e poi spegnerlo inserendo un ritardo di 1 secondo. Fa un solo ciclo e poi basta. Pertanto per i 7 secondi della durata in condizioni di lampeggio lo definiamo in qualche altra parte.

Ora vediamo la funzione che fa funzionare in condizioni normali

// La funzione qui attiva il semaforo nelle vari condizioni operative normali.
void semaforo() {
   if (semaforoON == 1) { // se 1 devi far diventare verde per il semaforo 1
     // vengono inizializzati i vari LED dallo stato precedente
     digitalWrite(LED_R2, HIGH);  // inizializzato a ROSSO acceso semaforo 2
     digitalWrite(LED_R1, HIGH); // inizializzato a ROSSO acceso semaforo 1
     digitalWrite(LED_G1, LOW);  // inizializzato a GIALLO spento semaforo 1
     digitalWrite(LED_G2, LOW);  // inizializzato a GIALLO spento semaforo 2
     digitalWrite(LED_V2, LOW);  // inizializzato a VERDE spento semaforo 2
     delay(1000); // attenti 1 secondo con il ROSSO per tutti
     digitalWrite(LED_V1, HIGH);  // accendo il VERDE per il semaforo 1
     digitalWrite(LED_R1, LOW);  // spegni il ROSSO del semaforo 1
   }
   else { // altrimenti è 0 allora è verde per semaforo 2
     digitalWrite(LED_R2, HIGH); // inizializzato a ROSSO acceco semaforo 2
     digitalWrite(LED_R1, HIGH); // inizializzato a ROSSO acceso semaforo 1
     digitalWrite(LED_G1, LOW); // inizializzato a GIALLO spento semaforo 1
     digitalWrite(LED_G2, LOW); // inizializzato a GIALLO spento semaforo 2
     digitalWrite(LED_V1, LOW); // inizializzato a VERDE spento semaforo 2
     delay(1000); // attenti 1 secondo con il ROSSO per tutti
     digitalWrite(LED_V2, HIGH); // accendo il VERDE per il semaforo 2
     digitalWrite(LED_R2, LOW); // spegni il ROSSO del semaforo 2
     
   }

Tramite una variabile e con IF/ELSE vediamo la condizione di quale dei due semafori deve essere verde. Poi gestiamo le condizioni dei due semafori in ROSSO per 1 secondo nella fase di transito dal VERDE tra i due semafori. Dopo 1 secondo accendiamo il VERDE sul uno dei due semafori come da condizione del problema previsto.

Ora passiamo a vedere il blocco finale loop 

// questo è il blocco loop dove da tutto inzia nelle condizioni normali, c'è sempre
void loop() {
   
  /* Il seguente blocco serve per definire da quanto tempo abbiamo accesso il semaforo 
  e decidiamo di far lampeggiare in giallo il semaforo per un determinato tempo prima di eseguire
  le normali funzioni di un semaforo.
  nota: le istruzioni delay e millis lavorano in millisecondi (ms) quindi 1000 = 1 secondo.
  Cambiando tale valore in millisecondi variamo anche i tempi delle varie condizioni dei semafori
  */
  time = millis(); // prendiamo il tempo da quanto siamo partiti
    while (time < 7000)  { // se il time da quando siamo partiti è inferiore a 7 secondi esegui quanto sotto, altrimenti salta          al commento // SemaforoOperativo
      blink_yellow(); // decidiamo di far lampeggiare i led gialli per 7 secondi richiamando blink_yellow
      time = millis(); // riassegnato time e se poi riparte da while, se ora sarà + di 7 secondi adiamo oltre.
    }
 
  // SemaforoOperativo
  semaforo(); // passiamo alla funzione semaforo dove attiverà il funzionamento del semaforo
  
  if (semaforoON==1) { // intanto vediamo se il semaforo1 è ROSSO o VERDE,
     delay(5000); // il VERDE lo lasciamo per 5 secondi
     digitalWrite(LED_V1, LOW); // trascorsi i 5 secondi mettiamo in GIALLO il semaforo1
     digitalWrite(LED_G1, HIGH); // spegnendo il VERDE
     semaforoON=2; // ora diciamo che Vogliamo che diventi VERDE il semaforo2
     }
     else { // è VERDE per il semaforo2
     delay(10000); // il VERDE lo lasciamo questa volta per 10 secondi
     digitalWrite(LED_V2, LOW); // trascorsi i 10 sec. mettiamo in GIALLO il semaforo2
     digitalWrite(LED_G2, HIGH); // spegnendo il VERDE
     semaforoON=1; // ora diciamo che Vogliamo che diventi VERDE il semaforo1
     }
  delay(4000); // aspettiamo che il giallo rimanga per 4 sec.
  // ora ricomincia il loop invertendo i ciclo semaforo1/semaforo2
  // come hai notato il semaforo1 rimane verde per 5 sec. mentre il semaforo2 per 10. Prova a varie il valore in di s ms dei due delay(s000) e vedi che succede
 
}

Evidenziato in arancio vediamo il codice che determina da quanto tempo i semafori sono accesi. Questo tramite la funzione millis che legge il tempo in millisecondi da quando Arduino  sta eseguendo il codice e l'istruzione while. Se siamo sotto i 7 secondi viene richiamato il ciclo del lampeggio dei due semafori in giallo. While mantiene bloccato il ciclo su lettura tempo trascorso e lampeggio per 7 secondi (time<7000), dopo esce da questo blocco e viene eseguito il codice che segue per le altre condizioni dei semafori.
Successivamente viene eseguito il codice della funzione semaforo() dove viene messo in verde il semaforo 1. Questo perché abbiamo inizializzato la variabile semaforoON sul numero 1 nel blocco iniziale. All'interno del blocco loop vediamo con IF/ELSE quale dei due è in verde ed attendiamo 5 secondi se il semaforo numero 1 o 10 secondi se il numero 2. Trascorso il tempo mettiamo in giallo il semaforo e spegniamo il verde. Impostiamo la variabile semaforoON sul altro semaforo. Attendiamo 4 secondi in giallo fisso e ricominciamo a condizioni invertite.

Abbiamo finito. Spero che sia stato comunque leggibile e se avete commenti da fare scrivete qui sotto o tramite


ċ
due_semafori.pde
(7k)
Massimiliano D'Ambrosio,
25 ago 2011, 13:57
Comments