Re: programma per semplice semaforo

Ciao a tutti, questo è il mio primo post, sto giocando con Arduino da pochi giorni e scrivo perchè ho qualche dubbio su quello che ho scritto.
Ho utilizzato Arduino 2009 con ATmega328, il codice funziona e fa quello che volevo facesse: si tratta di un semaforo doppio (all'incrocio fra due strade) con il verde acceso per 14 secondi, il giallo per 2 e il rosso per 14 per un totale di 30 secondi a loop; i semafori sono due e sono sincronizzati per evitare incidenti. La durata totale l'ho impostata a 18 ore - come se di notte ad una certa ora staccasse (da qui l'uso del count che "spegne" l'esecuzione del codice) e si accendesse il giallo lampeggiante nelle restanti sei ore (insomma come un semaforo simile alla realtà).

/*
  SEMAFORO DOPPIO:
 S1 VERDE & S2 ROSSO
 S1 GIALLO & S2 ROSSO
 S1 ROSSO & S2 VERDE
 S1 ROSSO & S2 GIALLO
 loop
 */
 //S1
#define ledGreen1 11
#define ledYellow1 12
#define ledRed1 13
//S2
#define ledGreen2 8
#define ledYellow2 9
#define ledRed2 10

int count=0;

void setup() { 
  //SEMAFORO 1 
  pinMode(ledGreen1, OUTPUT);
  pinMode(ledYellow1, OUTPUT);
  pinMode(ledRed1, OUTPUT); 
  //SEMAFORO 2 
  pinMode(ledGreen2, OUTPUT);
  pinMode(ledYellow2, OUTPUT);
  pinMode(ledRed2, OUTPUT); 
}

void loop() 
{
  if(count<=2160) 
  {  //18 ORE * 60 MINUTI *2CICLI/MINUTO = 2160 CICLI
    digitalWrite(ledGreen1, HIGH); //S1 VERDE
    digitalWrite(ledRed2, HIGH);   //S2 ROSSO
    delay(14000);              
    digitalWrite(ledGreen1, LOW);       
    digitalWrite(ledYellow1, HIGH); //S1 GIALLO
    digitalWrite(ledRed2, HIGH);    //S2 ROSSO  
    delay(2000);
    digitalWrite(ledRed2, LOW);  
    digitalWrite(ledYellow1, LOW);       
    digitalWrite(ledRed1, HIGH);    //S1 ROSSO
    digitalWrite(ledGreen2, HIGH);  //S2 VERDE
    delay(14000);              
    digitalWrite(ledRed1, HIGH);    //S1 RIMANE ALTRI DUE SECONDI SUL ROSSO
    digitalWrite(ledGreen2, LOW);   //S2 SPEGNE IL VERDE...
    digitalWrite(ledYellow2, HIGH);  //S2 ACCENDE IL GIALLO PER DUE SECONDI
    delay(2000);
    digitalWrite(ledRed1, LOW);      //S1 SPEGNE IL ROSSO, FINE LOOP -> VERDE (START LOOP)
    digitalWrite(ledYellow2, LOW);  //S2 SPEGNE IL GIALLO, FINE LOOP -> ROSSO (START LOOP)
    count++;  
  }
}

domande:
1-come si potrebbe scrivere il codice in maniera più fluida e meno grezza come ho fatto io?
2-ho letto nel forum che spesso e volentieri è meglio usare millis piuttosto che delay, è possibile farlo anche in questo esempio considerando che l'intervallo di tempo per i tre led non è lo stesso? facendo due #define magari in questa maniera?

#define time1 14000  //Intervallo di tempo ROSSO E VERDE
#define time2 2000  //Intervallo di tempo ROSSO E GIALLO
long previousMills = 0;
.
.
void loop()
{
  if (millis() -  previousMills > time1 ){
    previousMills = millis();  

    //Se il LED è spento lo accende e viceversa
    if (value == LOW)
      value = HIGH;
    else
      value = LOW;

    digitalWrite(ledPin1, value);
}
void loop()
{
  if (millis() -  previousMills > time2 ){
    previousMills = millis();  //Tiene in memoria l'ultimo lampeggio

    if (value == LOW)
      value = HIGH;
    else
      value = LOW;

    digitalWrite(ledPin2, value);
}

quello di sopra è solo una idea, dovrei capire come adattarlo al mio problema, devo ancora capire come ragiona il millis() rispetto al delay col quale non ho problemi
p.s: la parte finale del codice sarebbe la seguente

 if((count>2160)&&(count<218160))
  { //6 ORE * 60 MINUTI *60CICLI/MINUTO =216000 CICLI IN SEI ORE
    digitalWrite(ledYellow1, HIGH);   // set the LED on
    digitalWrite(ledYellow2, HIGH);   // set the LED on  
    delay(500);              // wait for a second
    digitalWrite(ledYellow1, LOW);   // set the LED on 
    digitalWrite(ledYellow2, LOW);   // set the LED on 
    delay(500); 
    count++; 
  }

questa simula il giallo lampeggiante da mezzo secondo per sei ore a partire dalla fine delle 18 ore di verde, giallo, rosso

grazie per l'attenzione
so che potrei suscitare le vostre risate ma sono alle prime armi, abbiate pietà, ogni suggerimento è bene accetto
Tsu

Per scrivere un programma per semafori devi utilizzare nel codice la logica dei semafori.
Ti conviene crearti una funzione a cui passi colore e tempo di accensione. Poi con la millis() controlli i periodi di accensione e di spegnimento.
Il tuo ragionamento ti deve portare a ragionare su più cicli del programma e non su uno solo, verificando con appositi controlli il verificarsi di eventi che permettono l'accensione e lo spegnimento dei diversi colori.
Dopo aver letto ciò.. se avevi le idee confuse: adesso le avrai incasinate. :grin: :grin:

Benvenuto nel Forum. :wink:

--> http://www.labarduino.eu/tutorial/arduino/inpratica/per-chi-inizia/ilsemaforo

PaoloP:
Per scrivere un programma per semafori devi utilizzare nel codice la logica dei semafori.

Non fa una piega :wink:

leo72:

PaoloP:
Per scrivere un programma per semafori devi utilizzare nel codice la logica dei semafori.

Non fa una piega :wink:

Concordo :grin: Diciamo che ti conviene pensare e scrivere il codice in modo dinamico :wink:

se cerchi su gugul di esempi sui semafori ne trovi a pacchi, uno che usa un millis lo trovi qui Tutorial Arduino 5: “Semaforo UK Interattivo” – Progetti con Arduino hai pure quello dei pedoni :slight_smile:

Ricordo un lavoro fatto nel 2000 per la programmazione di una centralina semaforica.

Si parlava di "verdi nemici" e tempi variabili di ciclo a fascie orarie, sensori (spire) di flusso veicolare, pulsanti pedonali, watchdog, ecc.

La materia, nella realtà, è molto più complicata di quanto possa sembrare.

Comunque, nella tua "tabella della verità" iniziale ha dimenticato il caso "tutto rosso" (un telecomando a bordo di un mezzo di soccorso fa scattare il rosso su tutte le direzioni).

Lascia perdere il delay() ed utilizza il millis() usando unsigned long e ricordando che dopo 55 giorni il timer interno si azzera e prevedendo questo caso.

Molto meglio se usassi un interrupt da timer/counter overflow per avere una base oraria affidabile, ma per iniziare va bene il millis

PaoloP:
Per scrivere un programma per semafori devi utilizzare nel codice la logica dei semafori.
.
..
Dopo aver letto ciò.. se avevi le idee confuse: adesso le avrai incasinate. :grin: :grin:
Benvenuto nel Forum. :wink:
--> http://www.labarduino.eu/tutorial/arduino/inpratica/per-chi-inizia/ilsemaforo

Grazie della risposta e grazie del benvenuto, guarda caso proprio da un utente di Cagliari come me (dovrò sistemarmi il profilo)!!!!
Leggendo due tre (quattro) volte il tuo commento, prima ancora di analizzare il prezioso link, ho capito cosa intendi per logica del semaforo! Di per se una strada ha almeno 4 semafori e come ha ricordato pablos ci sono da considerare pure i pedoni!!! Mettiamola così, ho abbozzato un senso unico alternato regolato da quello che ho scritto (magari senza giallo notturno lampeggiante o facciamo incidente).

pablos:
Tutorial Arduino 5: “Semaforo UK Interattivo” – Progetti con Arduino hai pure quello dei pedoni :slight_smile:

grazie, perfetto, meglio di così non avrei potuto imparare! come da regolamento provo a sbatterci la testa, pedoni compresi e poi mi vedo il buon mills()

grazie cyberhs, il tuo è l'ennesimo commento che leggo sul millis() vs delay, cmq è il mio primo codice, scritto il secondo giorno dopo l'arrivo a casa di Arduino, devo migliorare su tutto...ed ho anche visto qualcosa su vari post circa l'azzeramento del timer.

Arduino ha per caso un orologio interno o esiste una libreria che regola l'orologio (come un pc ma senza la batteria del bios) che mi permetta ad esempio di far scattare il giallo ad una cerca ora piuttosto che andare a contare i cicli? Insomma, un altro strumento di sincronizzazione con tempo reale?

grazie in anticipo per quello che imparerò
Matteo

cyberhs:
Ricordo un lavoro fatto nel 2000 per la programmazione di una centralina semaforica.

Si parlava di "verdi nemici" e tempi variabili di ciclo a fascie orarie, sensori (spire) di flusso veicolare, pulsanti pedonali, watchdog, ecc.

La materia, nella realtà, è molto più complicata di quanto possa sembrare.

Comunque, nella tua "tabella della verità" iniziale ha dimenticato il caso "tutto rosso" (un telecomando a bordo di un mezzo di soccorso fa scattare il rosso su tutte le direzioni).

Lascia perdere il delay() ed utilizza il millis() usando unsigned long e ricordando che dopo 55 giorni il timer interno si azzera e prevedendo questo caso.

Molto meglio se usassi un interrupt da timer/counter overflow per avere una base oraria affidabile, ma per iniziare va bene il millis

forse questo telecomando esiste ma non in italia :stuck_out_tongue_closed_eyes:

No, Arduino non ha orologi interni, solo timer. Un orologio ovvero un RTC (Real Time Clock) può essere implementato nel codice via software (cerca swRTC sul forum) oppure aggiunto come hardware (cerca DS1307 o simili)
Per sincronizzare l'orario ci sono vari metodi: seriale o usb (da pc), internet (con Ethernet Shield e server NTP), radio (con segnale DCF77).

ciao, come fai quando ha finito di fare il ciclo notte. C'è il count++ che fa andare avanti il conteggio, come fai a dirgli di iniziare di nuovo il conteggio da 0. Io pensavo a una cosa del genere

#define ledGreen1 11
#define ledYellow1 12
#define ledRed1 13
#define ledGreen2 8
#define ledYellow2 9
#define ledRed2 10

int count=0;

void setup(){
  pinMode(ledGreen1, OUTPUT);
  pinMode(ledYellow1, OUTPUT);
  pinMode(ledRed1, OUTPUT); 
  pinMode(ledGreen2, OUTPUT);
  pinMode(ledYellow2, OUTPUT);
  pinMode(ledRed2, OUTPUT); 
}

void loop(){
  if(count<=6)
  {
    digitalWrite(ledGreen1, HIGH);  
    digitalWrite(ledYellow1, LOW);  
    digitalWrite(ledRed1, LOW);   
    digitalWrite(ledGreen2, LOW);   
    digitalWrite(ledYellow2, LOW);  
    digitalWrite(ledRed2, HIGH);  
    delay(14000);
    digitalWrite(ledGreen1, LOW);  
    digitalWrite(ledYellow1, HIGH);  
    digitalWrite(ledRed1, LOW);   
    digitalWrite(ledGreen2, LOW);   
    digitalWrite(ledYellow2, LOW);  
    digitalWrite(ledRed2, HIGH);
    delay(2000);
    digitalWrite(ledGreen1, LOW);  
    digitalWrite(ledYellow1, LOW);  
    digitalWrite(ledRed1, HIGH);   
    digitalWrite(ledGreen2, HIGH);   
    digitalWrite(ledYellow2, LOW);  
    digitalWrite(ledRed2, LOW);
    delay(14000);
    digitalWrite(ledGreen1, LOW);  
    digitalWrite(ledYellow1, LOW);  
    digitalWrite(ledRed1, HIGH);   
    digitalWrite(ledGreen2, LOW);   
    digitalWrite(ledYellow2, HIGH);  
    digitalWrite(ledRed2, LOW);
    delay(2000);
    count++;
  }
if((count>6)&&(count<30))
  {
    digitalWrite(ledGreen1, LOW);  
    digitalWrite(ledYellow1, HIGH);  
    digitalWrite(ledRed1, LOW);   
    digitalWrite(ledGreen2, LOW);   
    digitalWrite(ledYellow2, HIGH);  
    digitalWrite(ledRed2, LOW);   // set the LED on  
    delay(500);              // wait for a second
    digitalWrite(ledGreen1, LOW);  
    digitalWrite(ledYellow1, LOW);  
    digitalWrite(ledRed1, LOW);   
    digitalWrite(ledGreen2, LOW);   
    digitalWrite(ledYellow2, LOW);  
    digitalWrite(ledRed2, LOW);   // set the LED on 
    delay(500); 
    count++; 
  }
if((count<=30)&&(count-30))
}

Grazie per il vostro aiuto.