Incrocio Semaforico a 4 postazioni

Buonasera gente. Come da titolo ho creato con thinkercad un progetto di un incrocio semaforico a 4 postazioni (lo so che è semplicissimo,ma mettete in conto che io sto cominciando ora a smanettare con arduino).

Il progetto è completo e funzionante,ma il codice è molto lungo....ho impostato i pin con #define,nel setup ho assegnato i 12 led (3 per semaforo),mentre nel loop ho immesso tutta la sequenza di accensione sincronizzata per tutti i led....

Ora,per esercitarmi e capire meglio le funzioni,vorrei rendere più snello il codice...
Allego le immagini del codice (ovviamente non funziona,perciò vorrei capire cosa sbaglio e come procedere). Grazie.

#define RossoS1  2         //Il rosso del semaforo1 è il pin 2
#define GialloS1 3         //Il giallo del semaforo1 è il pin 3
#define VerdeS1 4          //Il Verde del semaforo1 è il pin 4

#define RossoS2 7          //Il rosso del semaforo2 è il pin 7
#define GialloS2 6         //Il giallo del semaforo2 è il pin 6
#define VerdeS2 5          //Il verde del semaforo2 è il pin 5

#define RossoS3 8          //Il rosso del semaforo3 è il pin 8
#define GialloS3 9         //Il giallo del semaforo3 è il pin 9
#define VerdeS3 10         //Il verde del semaforo3 è il pin 10

#define RossoS4 11          //Il rosso del semaforo4 è il pin 11
#define GialloS4 12         //Il giallo del semaforo4 è il pin 12
#define VerdeS4 13         //Il verde del semaforo4 è il pin 13

int Semaforo1[6] = {VerdeS1, GialloS1, RossoS1, RossoS1, RossoS1, RossoS1}; //array per accendere i led nell'ordine stabilito
int Semaforo2[6] = {RossoS2, RossoS2, RossoS2, VerdeS2, GialloS2, RossoS2}; //array per accendere i led nell'ordine stabilito
int Semaforo3[6] = {VerdeS3, GialloS3, RossoS3, RossoS3, RossoS3, RossoS3}; //array per accendere i led nell'ordine stabilito
int Semaforo4[6] = {RossoS4, RossoS4, RossoS4, VerdeS4, GialloS4, RossoS4}; //array per accendere i led nell'ordine stabilito

int conteggio = 0 //variabile per accendere i semafori in sequenza
  
void setup(){
  
  for (int i = 0; i < 6; i++) pinMode(Semaforo1[i], OUTPUT); //dichiaro che i pin dei led dell'array Semaforo1 sono OUTPUT
  for (int i = 0; i < 6; i++) pinMode(Semaforo2[i], OUTPUT); //dichiaro che i pin dei led dell'array Semaforo2 sono OUTPUT
  for (int i = 0; i < 6; i++) pinMode(Semaforo3[i], OUTPUT); //dichiaro che i pin dei led dell'array Semaforo3 sono OUTPUT
  for (int i = 0; i < 6; i++) pinMode(Semaforo4[i], OUTPUT); //dichiaro che i pin dei led dell'array Semaforo4 sono OUTPUT
  
}

void loop(){
  digitalWrite(Semaforo1[conteggio], HIGH); //accendo il led presente nella variabile conteggio dell'array Semaforo1
  digitalWrite(Semaforo2[conteggio], HIGH); //accendo il led presente nella variabile conteggio dell'array Semaforo2
  digitalWrite(Semaforo3[conteggio], HIGH); //accendo il led presente nella variabile conteggio dell'array Semaforo3
  digitalWrite(Semaforo4[conteggio], HIGH); //accendo il led presente nella variabile conteggio dell'array Semaforo4
  
  long tempo = 4000 + millis(); //la variabile tempo assume il valore della funzione millis() + 4000

  while (tempo >= millis()) {   //aspetto 4 secondi nel ciclo while
    
}
  
  digitalWrite(Semaforo1[conteggio], LOW); //spengo il led presente nella variabile conteggio dell'array Semaforo1
  digitalWrite(Semaforo2[conteggio], LOW); //spengo il led presente nella variabile conteggio dell'array Semaforo2
  digitalWrite(Semaforo3[conteggio], LOW); //spengo il led presente nella variabile conteggio dell'array Semaforo3
  digitalWrite(Semaforo4[conteggio], LOW); //spengo il led presente nella variabile conteggio dell'array Semaforo4

  if (conteggio > 6) {  //se il conteggio è 7 devo riazzerarlo
    conteggio = 0  //azzero il conteggio
  }else{
    conteggio++;  //altrimenti se il conteggio è minore di 6 incremento il conteggio di 1
  }
}

Ho ripulito il thread così resta solo la discussione tecnica :slight_smile:

Guglielmo

L'IF con l'utilizzo di mills() in quel modo è errato ... studia QUI come usare millis() per le temporizzazioni :wink:

Guglielmo

Tra l'altro usare millis solo per attendere quattro secondi senza fare niente altro ha poco senso, allora tantovale usare delay(4000).

Due domande:

  1. Quando scatta il giallo si spegne il verde?
  2. Perchè tratti i 4 semafori in modo indipendente e non li accoppi a due a due? Gli opposti dovrebbero essere uguali
  3. Questa è la versione ottimizzata che non funziona, quella funzionante com'era?
  4. Hai dimestichezza con un po' di elettronica digitale? Sistemato questo codice, vuoi uno spunto per semplificare al massimo il software delegando un pelo all'hardware? Solo dopo aver sistemato questo però :stuck_out_tongue:

Si, ho barato quando ho detto che le domande erano solo due :wink:

maubarzi:
Due domande:

  1. Quando scatta il giallo si spegne il verde?
  2. Perchè tratti i 4 semafori in modo indipendente e non li accoppi a due a due? Gli opposti dovrebbero essere uguali
  3. Questa è la versione ottimizzata che non funziona, quella funzionante com'era?
  4. Hai dimestichezza con un po' di elettronica digitale? Sistemato questo codice, vuoi uno spunto per semplificare al massimo il software delegando un pelo all'hardware? Solo dopo aver sistemato questo però :stuck_out_tongue:

Si, ho barato quando ho detto che le domande erano solo due :wink:

Nella versione originale i semafori li ho accoppiati due a due (immagina un quadrivio con due coppie di semafori alternati). Ti posto qui il codice usato (semplicemente accendendo e spegnendo i led con delay)

void setup()
{
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
}

void loop()
{
  // Inizio Blocco1
  // Accendo Rosso semafori 1 e 3 - Verde semaforo 2
  // e 4
  digitalWrite(2, HIGH);
  // Accendi Rosso1
  digitalWrite(3, LOW);
  // Spegni Giallo1
  digitalWrite(4, LOW);
  // Spegni Verde1
  digitalWrite(5, HIGH);
  // Accendi Verde2
  digitalWrite(6, LOW);
  // Spegni Giallo2
  digitalWrite(7, LOW);
  // Spegni Rosso2
  digitalWrite(8, HIGH);
  // Accendi Rosso3
  digitalWrite(9, LOW);
  // Spegni Giallo3
  digitalWrite(10, LOW);
  // Spegni Verde3
  digitalWrite(13, HIGH);
  // Accendi Verde4
  digitalWrite(12, LOW);
  // Spegni Giallo4
  digitalWrite(11, LOW);
  // Spegni Rosso4
  // Fine Blocco1
  delay(5000); // Wait for 5000 millisecond(s)
  // Inizio Blocco2
  // Spengo Verde 2 e 4 - accendo Giallo 2 e 4
  digitalWrite(5, LOW);
  // Spegni Verde2
  digitalWrite(13, LOW);
  // Spegni Verde4
  digitalWrite(6, HIGH);
  // Accendi Giallo2
  digitalWrite(12, HIGH);
  // Accendi Giallo4
  // Fine Blocco2
  delay(5000); // Wait for 5000 millisecond(s)
  // Inizio Blocco3
  // Spengo Giallo 2 e 4 - Accendo Rosso 2 e 4
  digitalWrite(6, LOW);
  // Spegni Giallo2
  digitalWrite(12, LOW);
  // Spegni Giallo4
  digitalWrite(7, HIGH);
  // Accendi Rosso2
  digitalWrite(11, HIGH);
  // Accendi Rosso4
  // Fine Blocco3
  delay(5000); // Wait for 5000 millisecond(s)
  // Inizio Blocco4
  // Accendo Verde 1 e 3 -
  digitalWrite(4, HIGH);
  // Accendi Verde1
  digitalWrite(10, HIGH);
  // Accendi Verde3
  digitalWrite(2, LOW);
  // Spegni Rosso1
  digitalWrite(8, LOW);
  // Spegni Rosso3
  // Fine Blocco4
  delay(5000); // Wait for 5000 millisecond(s)
  // Inizio Blocco5
  // Spengo Verde 1 e 3 - Accendo Giallo 1 e 3
  digitalWrite(4, LOW);
  // Spegni Verde1
  digitalWrite(10, LOW);
  // Spegni Verde3
  digitalWrite(3, HIGH);
  // Accendi Giallo1
  digitalWrite(9, HIGH);
  // Accendi Giallo3
  // Fine Blocco5
  delay(5000); // Wait for 5000 millisecond(s)
  // Inizio Blocco6
  // Spengo Giallo 1 e 3 - Accendo Rosso 1 e 3
  digitalWrite(3, LOW);
  // Spengo Giallo1
  digitalWrite(9, LOW);
  // Spengo Giallo3
  digitalWrite(2, HIGH);
  // Accendo Rosso1
  digitalWrite(8, HIGH);
  // Accendo Rosso3
  delay(5000); // Wait for 5000 millisecond(s)
  // Fine Blocco6
}

Ok, quindi alla 1 capisco che la risposta è SI, quando si accende il giallo voglio che si spenga il verde.
Per la 2 intendevo che con un singolo comando, cioè 3 pin, pilotavi due semafori, quindi ogni pin 2 led dello stesso colore per i semafori opposti.
Comunque, non cambia molto, era solo una mia curiosità.

Ora entriamo nel merito con altre domande:

Perchè dici che non funziona? che problema riscontri?

Hai capito cosa ti è stato scritto ai post 2 e 3? cioè come usare millis() ?

Hai capito a cosa serve impostare il pinMode nel setup?
Perchè fai 4 for identici e non uno solo?
Perchè non hai fatto semplicemente un for da 2 a 13?

astroboy81:
...ho creato con thinkercad un progetto di un incrocio semaforico a 4 postazioni ...Il progetto è completo e funzionante

Scusa, 2 curiosità.

  1. In thinkercad hai creato un progetto elettrico e in qualche modo lui ha generato il codice Arduino ?
  2. lui lo simula ? E poi lo hai provato nella realtà e funziona ?

nid69ita:
Scusa, 2 curiosità.

  1. In thinkercad hai creato un progetto elettrico e in qualche modo lui ha generato il codice Arduino ?
  2. lui lo simula ? E poi lo hai provato nella realtà e funziona ?
  1. SI, NO
  2. SI
  3. per questo specifico progetto non sappiamo, ma in genere si :slight_smile:

Ma se non sai cosa sia TinkerCad, perché non gli dai un'occhiata? A volte è anche comodo provare e sperimentare senza dover necessariamente costruire il prototipo (per cose abbastanza "basic", ma va benino entro certi limiti).

docdoc:
(per cose abbastanza "basic", ma va benino entro certi limiti)

I limiti alla fine sono nella mancanza dell'hardware, non si vedono bene le variazioni li luminosità dei led pwm per esempio. E in qualche caso bisogna aggiungere un delay(10) nel loop per far avanzare il tempo simulazione correttamente (altrimenti va lentissimo).

Una domanda, ma come si chiama il singolo semaforo? Incrocio sono tutti assieme e semaforo il singolo?

Comunque, e qui dico la mia, un incrocio siffatto è un caso particolare di una macchina a stati finiti, particolare perché gli stati si seguono sempre, senza mai salti o deviazioni
Insomma vanno passo a passo a spasso (per chi ha voglia di cercare)

docdoc:
Ma se non sai cosa sia TinkerCad, perché non gli dai un'occhiata? A volte è anche comodo provare e sperimentare senza dover necessariamente costruire il prototipo (per cose abbastanza "basic", ma va benino entro certi limiti).

Grazie.
Lo conosco solo per il disegno 3D, la parte circuito non l'ho provato. Sarei curioso di vedere il progetto di @astroboy81,
@astroboy81, è pubblico? che nome ha ? "Quadruplo semaforo per incrocio" ?

Perchè dici che non funziona? che problema riscontri?

Hai capito cosa ti è stato scritto ai post 2 e 3? cioè come usare millis() ?

Ho capito che è una funzione che restituisce un valore a un tot di tempo dall'accensione della scheda

Hai capito a cosa serve impostare il pinMode nel setup?

Il pinMode dovrebbe servire ad impostare i pin della scheda come input o output

Perchè fai 4 for identici e non uno solo?
Perchè non hai fatto semplicemente un for da 2 a 13?

il for non l'ho capito tanto bene,dovrei rileggermi un po qualche guida

Scusa, 2 curiosità.

  1. In thinkercad hai creato un progetto elettrico e in qualche modo lui ha generato il codice Arduino ?
  2. lui lo simula ? E poi lo hai provato nella realtà e funziona ?

Ho creato il progetto in thinkercad posizionando i componenti e i collegamenti.
Per quanto riguarda il codice lo devi creare tu,ma hai 2 possibilità:
1.Posizionando dei blocchi con le funzioni (utile ai principianti che vogliono capire come funziona)
2.Scrivendo direttamente il codice.

Nel primo caso (selezionando nella schermata "blocchi+testo" o solo "blocchi") thinkercad ti scrive il codice in base a come posizioni i blocchi. Nel secondo caso invece il codice lo devi scrivere tu.
In tutti e due i casi,comunque non puoi tornare all'altra visualizzazione,cioè,se crei il codice con blocchi o blocchi+testo,selezionando solo testo,il codice si azzera...stessa cosa se passi da solo testo a blocchi o blocchi+testo.

Ultimato circuito elettronico e codice puoi fare la simulazione,e in caso di errori nel codice te lo segnala cosi da poter apportare le modifiche necessarie.

Una domanda, ma come si chiama il singolo semaforo? Incrocio sono tutti assieme e semaforo il singolo?

Banalmente li ho chiamati Semaforo1,semaforo2,semaforo3 e semaforo4... si trovano di fronte 1 con 3 e 2 con 4

Sarei curioso di vedere il progetto di @astroboy81,
@astroboy81, è pubblico? che nome ha ?

Semaforo a 4 postazioni

Qesta è la versione originale funzionante (con il codice lungo).

nid69ita:
Lo conosco solo per il disegno 3D, la parte circuito non l'ho provato.

La parte simulazione è fatta abbastanza bene (nulla di eccezionale, sei limitato ad esempio ai componenti "virtuali" a disposizione ed alle sole librerie che ti mettono a disposizione), ha anche ovviamente il serial monitor, anche grafico.
Io ogni tanto lo uso per "sketchare" :wink: al volo qualcosa che voglio verificare magari una funzione specifica, ma la cosa molto comoda è la possibilità di andare anche in debug, con breakpoint e visualizzazione del valore delle variabili.

Tu piazzi Arduino, una breadboard, ed inizi ad aggiungere componenti, quindi vai in "Codice" ed inserisci il tuo codice, quindi con "Avvia simulazione" lo "accendi".

Sarei curioso di vedere il progetto di @astroboy81

Bah vabbè avrà messo 12 LED (Tinkercad ti avvisa pure se non metti la resistenzina...:smiley: ) e al massimo un pulsante di start/stop, che altro ci sarà mai su quel circuito? :wink:

astroboy81:

Perchè dici che non funziona? che problema riscontri?

Ho creato il progetto in thinkercad posizionando i componenti e i collegamenti.

Ma l'errore (almeno questo mostrato) è chiaro...
Definisci un array a 4 valori e ne inizializzi 6?

Poi ci sono altri problemi ma, scusami, se non indenti decentemente mi rifiuto di proseguire, perché ti basta fare un Ctrl-T nell'IDE e postare il codice indentato "bene".

E già allora puoi forse anche tu vedere qualcuno degli altri errori...

Ma l'errore (almeno questo mostrato) è chiaro...
Definisci un array a 4 valori e ne inizializzi 6?

in effetti volevo capire bene come utilizzare questa funzione....

Poi ci sono altri problemi ma, scusami, se non indenti decentemente mi rifiuto di proseguire, perché ti basta fare un Ctrl-T nell'IDE e postare il codice indentato "bene".

E già allora puoi forse anche tu vedere qualcuno degli altri errori...

tieni conto sempre che non sono esperto,e magari qualcosa non la so....

Si, tranquillo, si era notato un cicinin.
Scusa se faccio sempre domande, ma perchè, conoscendo poco niente del linguaggio di programmazione, ti stavi ponendo il problema di ottimizzare il codice?
Cioè, se hai solo una vaga idea di cosa sia un ciclo for, che tipo di ottimizzazioni pensavi di fare?
Visto che hai una base di partenza funzionante, studiati bene quella e poi cerca di modificare un singolo pezzo per volta.
Ad es. da

void setup()
{
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(11, OUTPUT);
}

a

void setup()
{
  for (byte i = 2; i <= 13; i++) {
    pinMode(i, OUTPUT);
  }
}

cercando di imparare, applicandoli, i fondamentali.
Che puoi trovare un po' ovunque cercando guide o documenti sul linguaggio C o C++.

Grazie per le info :slight_smile:

stanotte, invece di dormire ho pensato
e invece di pensare ad "aiutatemi ad aiutarvi" ho pensato al semaforo (vergogna vergogna.....)
e ho tirato fuori questo:

// di Nelson "StandardOil"
// Idea da sviluppare:
// Semaforo alternativo

enum statisemaforo {SEM_SPENTO, SEM_VERDE, SEM_GIALLO, SEM_ROSSO, SEM_LAMPEGGIO, SEM_INIT};
// stati possibili di un semaforo, dove SEM_INIT è monostabile su SEM_SPENTO


typedef struct Semaforo_struct
{

    byte verde; // pin luce verde
    byte rosso; // pin loce rossa
    byte giallo; // pin luce gialla
    statisemaforo statoattuale; // lo stato attuale del semforo
    statisemaforo inizializza(void)
    {
        // inizializza il semaforo
        // provando anche le sue lampade
        pinMode(verde, OUTPUT);
        digitalWrite(verde, HIGH);
        delay(100);
        digitalWrite(verde, LOW);
        pinMode(rosso, OUTPUT);
        digitalWrite(rosso, HIGH);
        delay(100);
        digitalWrite(rosso, LOW);
        pinMode(giallo, OUTPUT);
        digitalWrite(giallo, HIGH);
        delay(100);
        digitalWrite(giallo, LOW);
        statoattuale = SEM_SPENTO;
        return statoattuale;
    }
    statisemaforo stato(void)
    {
        return statoattuale;
    }

    statisemaforo azione(statisemaforo comando)
    {
        statoattuale = comando;

        switch (comando)
        {
            case SEM_SPENTO:
                digitalWrite(verde, LOW);
                digitalWrite(rosso, LOW);
                digitalWrite(giallo, LOW);
                break;

            case SEM_VERDE:
                digitalWrite(verde, HIGH);
                digitalWrite(rosso, LOW);
                digitalWrite(giallo, LOW);
                break;

            case  SEM_GIALLO:
                digitalWrite(verde, HIGH);
                digitalWrite(rosso, HIGH);
                digitalWrite(giallo, LOW);
                break;

            case SEM_ROSSO:
                digitalWrite(verde, LOW);
                digitalWrite(rosso, LOW);
                digitalWrite(giallo, HIGH);
                break;

            case SEM_LAMPEGGIO:
                // lampeggio sarà il problema
                digitalWrite(verde, LOW);
                digitalWrite(rosso, LOW);
                digitalWrite(giallo, LOW);
                break;

            case SEM_INIT:
                // ntd, ci pensa una funzione apposta
                statoattuale = inizializza();
                break;

            default:
  
                break;
        }
        return statoattuale;
    }
} Semaforo;


Semaforo semafori[] = {{2, 3, 4}, {5, 6, 7,}, {8, 9, 10}, {11, 12, 13}};
// dichiaro un array di semafori, ognuno con 3 pin di uscita (rosso, giallo, verde) e lo stato iniziale a zero
byte Nsemafori = sizeof(semafori) / sizeof(semafori[0]);


void setup(void)

{
    // inizializzo i semafori
    for (byte i = 0; i < Nsemafori; i++)
    {
        semafori[i].azione(SEM_INIT);
        // invoco il metodo azione con argomento lo stato di inizializzazione del sameforo
        // in alterativa potevo invocare direttamente il metodo inizializza() senza argomento
    }
}

void loop(void)
{
    static byte passo = 0;
    passo = passo % numerostati;
}

poi però è arrivato il sonno e non ho finito, ma manca poco, sono al 90perccenttooo del lavoro, ancoa
vi piace?