Incrocio Semaforico a 4 postazioni

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?

Accoppiando i semafori, hai solo 4 condizioni:

rosso verde DURV
rosso giallo DURG
verde rosso DURV
giallo rosso DURG

0ppure 6 condizioni, se vuoi fare come nella realtà, con uno o due secondi di rosso per tutti:

rosso verde
rosso giallo
rosso rosso
verde rosso
giallo rosso
rosso rosso

Puoi fare 4 o 6 #define e poi richiamarle in sequenza:

#define stato1 spegniTutto();digitalWrite(rosso1,HIGH);digitalWrite(verde2,HIGH)

#define stato2 spegniTutto();digitalWrite(rosso1,HIGH);digitalWrite(giallo2,HIGH)
// #define stato2 spegniTutto();digitalWrite(rosso1,HIGH);digitalWrite(verde2,HIGH);digitalWrite(giallo2,HIGH)

#define stato3 spegniTutto();digitalWrite(verde1,HIGH);digitalWrite(rosso2,HIGH)

#define stato4 spegniTutto();digitalWrite(giallo1,HIGH);digitalWrite(rosso2,HIGH)
// #define stato4 spegniTutto();digitalWrite(verde1,HIGH);digitalWrite(giallo1,HIGH);digitalWrite(rosso2,HIGH)

void spegniTutto()
{
digitalWrite(rosso1,LOW);
digitalWrite(giallo1,LOW);
...
}

Se utilizzi solo la porta D da D0 a D5 (I/O da 0 a 5) per comandare le luci, puoi scrivere più semplicemente:
void spegniTutto() {PORTD&=0b11000000;}


// Durata dei verdi:
#define DURV 10

// Durata dei gialli:
#define DURG 3

unsigned long t;

void setup()
{
t=millis()/1000;
}

void loop()
{
if (millis()/1000-t>=DURV+DURG+DURV+DURG) t=millis/1000;

if      (millis()/1000-t>=DURV+DURG+DURV) stato4;
else if (millis()/1000-t>=DURV+DURG) stato3;
else if (millis()/1000-t>=DURV) stato2;
else stato1;

/*In maniera forse più comprensibile, si può anche scrivere:
if      (millis()/1000-t<DURV) stato1;
else if (millis()/1000-t<DURV+DURG) stato2;
else if (millis()/1000-t<DURV+DURG+DURV) stato3;
else stato4;
*/
}

P.S.: non ho verificato bene le condizioni. Potrebbe esserci qualche errore...
P.P.S.: il punto e virgola alla fine dei #define stato1, ... può essere omesso, in quanto vengono aggiunti negli "if" :slight_smile:

Dalle mie parti il giallo si accende senza spegnere il verde, visto che hai aggiunto i 2 secondi di rosso per tutti...

Fatto così, ci vuole poco a modificarlo come si preferisce :slight_smile:
Ecco: ho corretto qualche errore e ho aggiunto due righe, poste come commento, che possono essere sostituite a quelle che le precedono per avere giallo+verde.

sono tornato, dopo notti di bagordi...
vorrei spiegare perchè ho fatto tuuuttoo quel lavoro su strutture e membri per un semplice semaforo
a parte che sto provando ad imparare, ma l'idea generale sarebbe di spostare la complessità dal programma al dato, come dico spesso io
se un incrocio viene dichiarato come array di semafori che si inizializzano da soli (fanno loro le loro stesse pinmode) descriverne il funzionamento è poco più che elencarne gli stati successivi e come si alternano, che a sua volta viene bene con struct e array, mi sembra)