Modifica a codice semaforo

Ciao ragazzi,sono alle prime armi con arduino.Ho creato un piccolo semaforo con arduino micro,non ho problemi con il codice ,che funziona,ma vorrei una mano per una modifica.Le luci del semaforo si accendono tutte per lo stesso tot di secondi,ma vorrei che solo la luce gialla,corrispondente allo stato numero 2, durasse meno delle altre.E poi ovviamente deve tornare alla luce rossa iniziale. Come dovrei modificare questo codice?
Grazie

const int ledPinR =  4;
const int ledPinY =  3;
const int ledPinG =  2;

int state = 0;
unsigned long previousMillis = millis();

void setup() {
  // set the digital pin as output:
  pinMode(ledPinR, OUTPUT);
  pinMode(ledPinY, OUTPUT);
  pinMode(ledPinG, OUTPUT);

  digitalWrite(ledPinR, LOW);
  digitalWrite(ledPinY, LOW);
  digitalWrite(ledPinG, LOW);

}

void loop() {

  if (millis() - previousMillis >= 8000) {     

    previousMillis = millis();
    state ++;

    if (state > 2) {
      state = 0;
    }
  }


  switch (state) {

    case 0:
      digitalWrite(ledPinR, HIGH);
      digitalWrite(ledPinY, LOW);
      digitalWrite(ledPinG, LOW);
      break;

    case 1:
      digitalWrite(ledPinR, LOW);
      digitalWrite(ledPinY, LOW);
      digitalWrite(ledPinG, HIGH);
      break;

    case 2:
      digitalWrite(ledPinR, LOW);
      digitalWrite(ledPinY, HIGH);
      digitalWrite(ledPinG, LOW);
      break;

  }
}

Gentilmente prima di postare il codice, formattalo con CTRL-T.

Al posto del valore 8000 ci puoi mettere una variabile a cui assegni il valore nel setup e lo modifichi all'occorenza in ogni case.

Ciao.

Io avevo scritto tempo fa un timer ciclico

Mi sembra fosse il seguito de il mio "il tempo delle librerie"

Prova a cercare dentro in "aiutateci ad aiutarvi" o in "la pappa è fatta "

Basta modificare
if (millis() - previousMillis >= 8000)
in qualcosa come:
if (millis() - previousMillis >= t[state])
dichiarando all'inizio le variabili t[0], t[1], t[2] con i tempi che desideri in millisecondi.

Nota:
questi non servono:

digitalWrite(ledPinR, LOW);
digitalWrite(ledPinY, LOW);
digitalWrite(ledPinG, LOW);

@Datman Le variabili di che tipo?Per ognuna di queste variabili devo mettere un if diverso?

@Maurotec scusami, non sapevo.

3 variabili int (o unsigned int). L'if è uno solo.
Procedi, poi mettiamo i colori al posto dei numeri.

Stasera se l'insonnia mi attanaglia unisco "passo a passo a spasso nel tempo" con "per qualche lucina in più", prendendo ispirazione da "albe ed aurore fin boreali"
Per fare un semaforo (che è un po' che ci penso, un problema che torna ciclicamente, come il cancello che non si ferma dei primi esperimenti dei novelli)

Inoltre, io farei così per fare i digitalWrite solo quando è necessario:

const int ledPinR = 4;
const int ledPinY = 3;
const int ledPinG = 2;

int state = 0;
unsigned long previousMillis = millis();

void setup() 
{
// set the digital pin as output:
pinMode(ledPinR, OUTPUT);
pinMode(ledPinY, OUTPUT);
pinMode(ledPinG, OUTPUT);
}

void loop()
{
if (millis()-previousMillis >= 8000) 
  {
  previousMillis = millis();
  state ++;
  if (state>2) {state=0;}
  switch (state) 
    {
    case 0:
      digitalWrite(ledPinR, HIGH);
      digitalWrite(ledPinY, LOW);
      digitalWrite(ledPinG, LOW);
    break;

    case 1:
      digitalWrite(ledPinR, LOW);
      digitalWrite(ledPinY, LOW);
      digitalWrite(ledPinG, HIGH);
    break;

    case 2:
      digitalWrite(ledPinR, LOW);
      digitalWrite(ledPinY, HIGH);
      digitalWrite(ledPinG, LOW);
    break;
    }  // END switch
  } // END if (millis() ...)
} // END loop

Per il tipo di programma non cambia nulla, ma concettualmente è sbagliato fare i digitalWrite a ogni giro di loop.

P.S.: Metti a posto il codice che hai pubblicato!

@Carlo30: in conformità al REGOLAMENTO , punto 7, cortesemente edita il tuo primo post più sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone a forma di piccola matita :pencil2: che si trova in basso del tuo post), seleziona TUTTA la parte di codice e premi l'icona </> nella barra degli strumenti per contrassegnarla come codice.

Inoltre, così com'è, non è molto leggibile ... assicurati di averlo correttamente indentato nell'IDE prima di inserirlo (questo lo si fa premendo ctrlT su un PC o cmd T su un Mac all'intero del IDE). Per maggiori informazioni ... punto 17.2 del succitato regolamento.

Grazie.

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà sistemato il
codice, nel rispetto del suddetto regolamento nessuno ti
risponderà
, quindi ti consiglio di fare il tutto al più presto. :wink:

@gpb01 ok ho corretto scusami. :wink:

@Datman ok.Provo con le 3 variabili int,come suggerito.Ma ancora non ho ben chiaro come sistemare quell'if per non farne più di uno. Sto proprio imparando :laughing:

Grazie per avere sistemato e formattato il codice.

Intanto ci sono almeno due modi, uno è quello suggerito da @Datman. Io ti suggerisco di modificare la if in questo modo:

if (millis() - previousMillis >= intervallo ) {     

    previousMillis = millis();
    state ++;

    if (state > 2) {
      state = 0;
    }
  }

La variabile intervallo la dichiari uint16_t, word o unsigned int che sono sinonimi, quindi:

uint16_t intervallo = 8000;

All'interno di ogni case quando questo viene eseguito puoi modificare il valore della variabile intervallo.

Prima però è proprio il caso di creare delle costanti da usare al posto dei numeri in ogni case. Es:

#define ROSSO 2

// nel case 
   case ROSSO:

Allora diventa più chiaro per il programmatore. Il compilatore (o meglio il preprocessore C/C++) sostituisce la macro ROSSO con il valore 2.

Procedi a questa modifica prima di andare avanti.

Ciao.

Con l'array, però, tutti i tempi stanno all'inizio del codice e non bisogna andare a cercarli per modificarli.

Certamente ed è anche interessante fare notare che il codice funziona grazie al fatto che la variabile di stato state assume valori compatibili con l'indice dell'array dei tempi.

Visto che @Carlo30 sta imparando è bene che implementi entrambe la varianti, prima senza array e poi con array.

Ciao.

2 Likes

@Maurotec ti ringrazio!! Grazie ai tuoi consigli ho ottenuto ciò che volevo. Una sola curiosità. Come hai visto precedentemente ho settato la variabile "state" a zero... Quindi appena il semaforo viene collegato parte con la luce rossa. Dichiarando l'altra variabile,"intervallo", se la lascio senza valore iniziale il semaforo parte con il verde(preciso che i valori voluti li ho settati successivamente dentro gli Switch) .se invece ,come hai detto tu, la setto a 8000 da subito, parte correttamente con luce rossa come voglio io. Come mai questa cosa?

Facciamo scommessa che se non inizializzi il tempo parte rosso ed entro 0 millisecondi (cioè subito) passa verde?
Prova a stampare la variabile di stato, dali dovresti capire...

Questo non lo so di preciso, non ho idea di quale sia il case che accende il rosso e quale accende il verde. Quasi certamente @Standardoil ha intuito il perché ma è meglio che posti il codice con le modifiche che ti ho suggerito (tutte).

PS: le variabili globali non inizializzate esplicitamente assumono il valore di default, valore che per le variabili numeriche è zero.

Ciao.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.