Semaforo Complesso OK-Flip Flop Semplice ( e non ci salto fuori).

io quoto intero quello che dice Claudio_FF

sono un pochino più ottimista sui tempi

in particolare if else secondo me è veloce veloce da imparare

i cicli son un po' la bestia nera della programmazione

i puntatori sono la bestia nera del C

ma per cominciare se ne puo' fare a meno

certamente tipi di variabili e operatori sono la base senza la quale nemmeno si puo' pensare a programmare

io consiglio sempre di scriversi il programma in italiano

e poi lentamente tradurlo in linguaggio

del tipo:

se premo il pulsante accendo il led

diventa 1) devo dichiarare il pulsante pinmode........... 2) devo dichiarare il led pinmode..... 3) test sul pulsante if (pulsante......... e qui metto subito le 2 graffe (mica di dimenticare di chiuderle)

quindi

pinMode(3,INPUT);
pinMode(4, OUTPUT);

if (digitalRead(3)){
degitalwrite(4,....
}
finito

e intanto mi ricordo che i pinmode vanno nella setup

e il resto nella loop

il processo di traduzione italiano->C non è immediato vado passo a passo

anche perchè nel frattempo mi accorgo che: 1) mi spno dimenticato cosa fare se NON premo il pulsante 2) mi sono dimenticato anche come rimettere a posto il led quando non premo più il pulsante

a questo punto diventa:

if (digitalread(3)){
digitalwrite(4,HIGH);
}
else{
digitalWrite(4,LOW);
}

solo che a questo punto mi sono accorto che la if non mi serve più

perchè la condizione è uguale all'uscita

quindi scriverò solo

digitalWrite(4,digitalRead(3));

Lo ammetto ho fatto un po di casino, ma prima o poi ce la farò.

Parti dal poco, un led che lampeggia con millis

Poi un tasto che cambia il tempo

E poi... .

Per un po non scrivo più

leggo solo prima voglio capire sto millis() e ste variabili , è facile fare copia incolla, ma appena cambi qualkosa ti rendi conto che ........o lo sai fare oppure no.

ed io voglio imparare non copiare.

Vi ringrazio a tutti per la pazienza appena riesco a fare qualkosa di concreto... nella mia ignoranza, lo metto nel forum per il momento GRAZIE SIETE GRANDI

prego

Ciao dunque sto studiando e mi sono creato uno skecth per capire meglio il MILLIS

ho notato che ci sono diversi modi per utilizzarlo quindi sto tentando capire le differenze...pero mi sono perso qualkosa.

Questo è lo sketch che dovrebbe utilizzando il pulsante INT P1=0;

accendere led in sequenza e finquì tutto ok.

Poi col pulsante INT PAUT=0; era mia intenzione mettere in automatico la sequenza di P1 utilizzando una modalità MILLIS

però i led si accendono come gli pare a loro.

unsigned long A;
unsigned long B;
unsigned long C;
unsigned long D;
unsigned long on1=1000;
unsigned long off1=1000;
unsigned long on2=2000;
unsigned long off2=5000;
int P1=0;
int PAUT=0;

void setup()
{
 pinMode(2,OUTPUT);
 pinMode(3,OUTPUT);
 pinMode(4,OUTPUT);
 pinMode(12,INPUT);
 pinMode(8,OUTPUT);
 pinMode(9,OUTPUT);
 pinMode(10,OUTPUT);
 pinMode(11,INPUT);
}

void loop()
{
  if(digitalRead(11)==HIGH)
{
   delay(250);
   ++PAUT;
     if(PAUT>=2){PAUT=0;}
 }
 if(PAUT==0)
 {
  digitalWrite(8,LOW);
  digitalWrite(9,LOW); 
  digitalWrite(10,LOW);
 }
 if(PAUT==1)
 {
  digitalWrite(8,HIGH);
  digitalWrite(9,LOW); 
  digitalWrite(10,LOW);
  digitalWrite(12,LOW);                                  // questo l'ho aggiunto durante i vari tentativi
  
   if(millis()> A +500){P1=1+P1;}                    // qui è dove non funziona anche mettendo ++P1
   if(millis()> A +1000){P1=1+P1;A=millis();}      // qui è dove non funziona anche mettendo ++P1
   if(P1>=5){P1=0;}                                     // questo l'ho aggiunto durante i vari tentativi
 }
 if(digitalRead(12)==HIGH)
{
   delay(250);
   ++P1;
     if(P1>=5){P1=0;}
}
 switch(P1)
 {
 case 0:
  digitalWrite(2,LOW);
  digitalWrite(3,LOW); 
  digitalWrite(4,LOW); 
 break; 
 case 1:
  digitalWrite(2,HIGH);
  digitalWrite(3,LOW); 
  digitalWrite(4,LOW); 
 break;   
 case 2:
  digitalWrite(2,LOW);
  digitalWrite(3,HIGH); 
  digitalWrite(4,LOW); 
 break;  
 case 3:  
  digitalWrite(2,LOW);
  digitalWrite(3,LOW); 
  digitalWrite(4,HIGH); 
 break;
 case 4:
  digitalWrite(2,HIGH);
  digitalWrite(3,HIGH); 
  digitalWrite(4,HIGH);
 break;
 }
 
 if(digitalRead(11)==HIGH)
{
   delay(250);
   ++PAUT;
     if(PAUT>=2){PAUT=0;}
}
 
 
 
}

in pratica i led si accendono in sequenze diverse dai casi che ho messo nello SWITCH.

mi aiutate per favore

Guarda che noi ti abbiamo aiutato....

te la ricordi la barzelletta del pio uomo che durante una alluvione aspetta di essere salvato da Dio?

Il fiume stava straripando e le acque stavano raggiungendo la casa di Jim. Erano arrivate al portico, dove lui si trovava. Un uomo in barca a remi si avvicinò e lo chiamò: “Salta dentro che ti porto in salvo”. Jim rispose: “No, il mio Dio mi salverà!” Salì poi di corsa fino al primo piano. Il fiume continuava a salire e raggiunse le finestre del primo piano. Un uomo in un motoscafo si avvicinò e lo chiamò: “Salta dentro che ti porto in salvo”. E Jim di rimando: “No, il mio Dio mi salverà!” Poi Jim corse sul tetto. Ben presto il fiume lambì il tetto della casa. Jim era seduto sul bordo, con le acque che gli mulinavano attorno ai piedi. Vide un elicottero sorvolarlo e sentì la gente urlare attraverso il megafono: “Afferra la corda e issati, ti porteremo in salvo”. E Jim, di rimando: “No, il mio Dio mi salverà!” Il fiume continuò a salire e, infine, travolse tutta la casa. Jim annegò. Un istante dopo, si rese conto di essere al cospetto di Dio. In collera, Jim gli chiese: “Ho riposto la mia fiducia in te. Perché mi hai abbandonato?” Dio sorrise e rispose: “Non ti ho mai abbandonato. Ho inviato una barca a remi, un motoscafo e un elicottero. Perché non ci sei salito sopra?”

Ecco, qui siamo

la millis te la abbiamo spiegata di leggere il reference te lo abbiamo detto di scrivere il codice dentro i tag code, pure un esempio di millis te lo ho messo anch'io come organizzare le paline te lo ho detto come scrivo un programma, ti ho fatto un esempio di partire col poco, te lo abbiamo detto in varii di più................ non so

una spazzola scrive e un campo legge io non sono ne la spazzola ne il campo

Ricordo a tutti che in conformità al regolamento, punto 7, dovete [u]editare[/u] i vostri post (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del post) e [u]racchiudere il codice all'interno dei tag CODE/u.

Resto in attesa delle correzioni [u]nell'intero thread[/u] !

Guglielmo

Guarda i commenti interni al codice. La millis è implementata male.

unsigned long A;
unsigned long B;
unsigned long C;
unsigned long D;
unsigned long on1 = 1000;
unsigned long off1 = 1000;
unsigned long on2 = 2000;
unsigned long off2 = 5000;
int P1 = 0;
int PAUT = 0;

void setup()
{
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(12, INPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, INPUT);

  // manca lo stato iniziale dei pin 2,3,4,8,9 e 10.
  // sono HIGH o LOW?

  // perche non aggiungi la seriale per capire cosaa fa il programma?
}

void loop()
{
  if (digitalRead(11) == HIGH) // controlla i collegamenti ed eventualmente metti un pull-donw
  {
    delay(250);       // come debounce bastano 50 millisecondi.
    ++PAUT;           // su singola riga PAUTT++ o ++PAUT è indifferente.
    if (PAUT >= 2) {
      PAUT = 0;
    }
  }

  if (PAUT == 0)
  {
    // dovresti stampare via seriale che sei all'interno di questo if.
    digitalWrite(8, LOW);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
  }

  if (PAUT == 1)
  {
    // dovresti stampare via seriale che sei all'interno di questo if.
    digitalWrite(8, HIGH);
    digitalWrite(9, LOW);
    digitalWrite(10, LOW);
    digitalWrite(12, LOW);    // questo l'ho aggiunto durante i vari tentativi
    // mettere LOW in pin di input non serve

    if (millis() > A + 500) {
      P1 = 1 + P1; // qui è dove non funziona anche mettendo ++P1
    }
    if (millis() > A + 1000) {
      P1 = 1 + P1;  // qui è dove non funziona anche mettendo ++P1
      A = millis();
    }
    if (P1 >= 5) {
      P1 = 0; // questo l'ho aggiunto durante i vari tentativi
    }
  }

  if (digitalRead(12) == HIGH) // controlla i collegamenti ed eventualmente metti un pull-down
  {
    delay(250);
    ++P1;
    if (P1 >= 5) {
      P1 = 0;
    }
  }

  switch (P1)
  {
    // dovresti stampare via seriale il valore di P1
    case 0:
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      break;
    case 1:
      digitalWrite(2, HIGH);
      digitalWrite(3, LOW);
      digitalWrite(4, LOW);
      break;
    case 2:
      digitalWrite(2, LOW);
      digitalWrite(3, HIGH);
      digitalWrite(4, LOW);
      break;
    case 3:
      digitalWrite(2, LOW);
      digitalWrite(3, LOW);
      digitalWrite(4, HIGH);
      break;
    case 4:
      digitalWrite(2, HIGH);
      digitalWrite(3, HIGH);
      digitalWrite(4, HIGH);
      break;
  }

  // perchè fai il controllo 2 volte?
  if (digitalRead(11) == HIGH)  // controlla i collegamenti ed eventualmente metti un pull-down
  {
    delay(250);
    ++PAUT;
    if (PAUT >= 2) {
      PAUT = 0;
    }
  }
}

Puso: ho notato che ci sono diversi modi per utilizzarlo quindi sto tentando capire le differenze

Il modo in cui l'hai usato (confrontare direttamente il valore restituito da millis() con qualcosa) soffre del problema dell'overflow.

Tornando al cerchio delle ore è come voler confrontare direttamente l'ora di un orologio (0..11) con un valore ottenuto da un'ora di partenza (facciamo le 8 ) sommato a una durata (facciamo 6 ore). Se l'"ora di arrivo" supera la mezzanotte allora anche tutte le ore comprese tra quella iniziale e la mezzanotte risulteranno matematicamente maggiori (quindi il test millis()>A+n contiene un errore di logica):

Ma comunque, tornando al semaforo iniziale e al pulsante da ascoltare durante le attese, se la funzione millis intanto è "complicata", e fermo restando che il suo uso assieme alla logica del ciclo continuo senza delay è la via più generale per scrivere qualsiasi programma multitasking... un minimultitasking lo si fa anche con dei piccoli delay... ad esempio se il problema è leggere un pulsante durante un'attesa (e oltre ad attendere e leggere il pulsante non c'è bisogno di fare altro... altrimenti saremmo da capo), una soluzione come questa è sicuramente più "semplice":

// Attesa circa 40 secondi e campionamento pulsante ogni 0.1s
for(unsigned int t = 0;  t < 400;  t++)
    if(digitalRead(input_pin) == HIGH) break; else delay(100);

Intanto GRAZIE a TUTTIper la pazienza:

DOCSAVAGE innazitutto sto studiando e sto facendo tesoro di quello che mi avete insegnato, part dal principio che quando mi sino iscritto su questo url,avevo a malapena capito la differenza chedentro le parentesi tonde e quelle e graffe e grazie al vostro aiuto il mio ultimo schetch postato,me lo sono fatto quasi tutto da solo a memoria,ricontrollando tutto ed andando a copiare solo quando non ci saltavo fuori…ed io non sono jim e non credo nelle parabole.

gpb01 non ho capito ne cosa hai detto e neppure se era riferito a me…ti chiedo scusa.

Claudio_FF l’esempio sull’orologio è stato chiarissimo e mi ha fatto comprendere il millis ora ( se non ho studiato male, posso mettere vari orologi),ma non ora prima voglio capire in quanti modi posso utilizzarlo…non mi preoccupo neppure di azzerarlo per il momento…però grazie è stata un ottima spiegazione

PaoloP ti ringrazio nuovamente…ho rifatto un nuovo schetch molto più corto riprovando piu volte con tentativi diversi,ma il problema persiste è sempre lo stesso con millis incremeta gli INT fino a 2 e poi torna 0 (incrementarlo a 3…NON CI PENSA PROPRIO).

Premesso che sto utillizzando tinkercad per fare gli schect commento solo i codici che mi danno problemi…i codici inutili sono solo per fare esperienza e per scrivere senza copiare:

int P1=0;
unsigned long T1= millis();
unsigned long T2= millis();
unsigned long startime;
int A=0;

void setup() {
 Serial.begin(9600);
 pinMode(2, OUTPUT);
 pinMode(3, INPUT);
 startime = millis();
}

void loop() {
 if(digitalRead(3))
 {
   while(digitalRead(3)){;}
 
  ++P1;++A;Serial.println(A);Serial.println(P1);}
 
 if(P1>=3){P1=0;}
 if(A>=2){A=0;}
 if(A==0){digitalWrite(2,LOW);Serial.println(A);Serial.println(P1);}
 if(A==1){digitalWrite(2,HIGH);Serial.println(A);Serial.println(P1);}
 if(P1==3)
 {
 Serial.println(A);
 if(startime>=T1+500){++A;}
   if(startime>=T2+1000){++A;}}                                           // qui incrementa solo fino a 2 a 3 NO
}

Lo schetc è corretto unico problema l’incremento,poi se magari potessi vedere in serial monitor i dati incolonnati siù colonne diverse sarebbe meglio,ma non ci sono ancora arrivato.

Per il momento Grazie a tutti.

Puso:
PaoloP ti ringrazio nuovamente…ho rifatto un nuovo schetch molto più corto riprovando piu volte con tentativi diversi,ma il problema persiste è sempre lo stesso con millis incremeta gli INT fino a 2 e poi torna 0 (incrementarlo a 3…NON CI PENSA PROPRIO).

omissis, ma mettendo il tag code

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

Lo schetc è corretto unico problema l’incremento,poi se magari potessi vedere in serial monitor i dati incolonnati siù colonne diverse sarebbe meglio,ma non ci sono ancora arrivato.

Lo Scjetch é corretto cosa?
che non ti incrementa fino a tre perché tu stesso lo castri a due?

la vedi l’unica linea che ti ho citato?
tra l’altre cose scritta tra i tag code, che non è mica difficile, basta volerlo, si vede che qualcuno non vuole…

significa:
se A è maggiore o uguale a due lo riporto a zero

quindi TRE non lo sarà mai, ma non è colpa della millis

è colpa del tuo programma

ripeto, partire dal poco? per fare un solo errore per volta? per fare in fretta a capire e correggere?

si vede che ti da fastidio…

oh e te lo dico subito

non cominciare con la manfrina del

vorrei capire ma mi mancano le basi grazie del tempo che spendete per me ci sono quasi, mi manca poco

Non attacca....... gente che dice frasi del genere vengono via a due soldi la dozzina cerca di elevarti sopra la massa, che ci farai solo bella figura

ti metti d'impegno a fare quello che ti si consiglia, a partire dal mettere il codice tra i tag code, che non è difficile

docsavage: a partire dal mettere il codice tra i tag code, che non è difficile

Si come no, per loro è più facile postare 1000 righe di codice senza usare il corretto tag che capire come va usato , questo fino a che il moderatore non si scoccia di essere preso per i fondelli, dopo l'ennesimo richiamo, e prima scatta la chiusura del thread, poi se ce la recidiva il ban.

bè docsavage intanto Grazie che mi hai fatto capire dove ho sbagliato(domani provo a correggere e...vedrò di starci più attento la prossima volta...ripeto sono ignorantissimo sulla programmazione sono alle prime armi,ma mi sto impegnando). Per ringraziarti ti racconto anchio una storiella(senza offesa....è solo come la vedo io):

Una volta un uomo voleva arrivare in cima ad una montagna;

chi lo conosceva gli consigliò di lasciare perdere perche non ci saqrebbe mai arrivato;

l'uomo partì lo stesso, e durante il suo percorso chiese aiuto su come raggiungere la vetta;

incontrò persone che gli dissero che non era possibile ed altre che gli dissero come avvicinarsi alla cima;

l'uomo non arrivò mai in cima, ma ci arrivò più vicino, di chi gli aveva consigliato di lasciar perdere o di chi gli disse che non era possibile.

e durante il rientro incontro un altro uomo che gli chiese come arrivare in cima alla montagna.

astrobeed seper mettere i tag intendi mettere tra//il spiegare la riga metto nel forum solo quelle che non capisco quelle semplici mi sembra inutile metterle

Grazie per la storiella non la conoscevo e mi è piaciuta

sembra però saggezza orientale

la saggezza orientale contiene sempre un lato "oscuro", non per niente gli orientali tentano tutti di vivere alla occidentale

in particolare la storiella non dice se l'uomo è arrivato anche più in la di chi gli consigliava, o se non è riuscito nemmeno ad eguagliare i suoi consiglieri, quelli buoni intendo

ecco, vedi di non essere così...

comunque, io parla che ti parla, mettendo in pratica i MIEI consigli il semaforo lo ho fatto, a tempo perso....

naturalmennte ho cominciato con il descrivere l'obbiettivo

altrimenti non saprei nemmeno da che parte si troverebbe la montagna

// simulazione semaforo
// 2 vie a 90 gradi, 4 paline
// per i pedoni, tutte le via unificate
// verde senza giallo, con rosso semplicemente negato in hardware
// un buzzer che bippa lento per i ciechi
// durante il "giallo" per i pedoni il buzzer bippa veloce

// un pulsante di chiamata pedonale
// un led di conferma chiamata pedonale presa in carico
// per tranquillizzare chi preme il pulsante
// un interruttore per servizio notturno lampeggiante

come vedi il tag code funziona

poi ho descritto il campo giochi

ho messo le paline (scusate il gioco di parole)

che significa letteralmente ho descritto i collegamenti tra arduino e le paline dei semafori

// definizione paline

byte const P1R     = 2; // palina 1 (e 3) rosso
byte const P1G     = 3; // palina 1 (e 3) giallo
byte const P1V     = 4; // palina 1 (e 3) verde

byte const P2R     = 5; // palina 2 (e 4) rosso
byte const P2G     = 6; // palina 2 (e 4) giallo
byte const P2V     = 7; // palina 2 (e 4) verde

// per i pedoni
byte const PPV     = 8; // verde per pedoni sottinteso rosso è negato
byte const PPG     = 9; // Giallo per i pedoni
byte const CHI    = 10; // led di conferma chiamate pedone presa in carico
byte const PUL    = 11; // pulsante di chiamata pedone

byte const NOT    = 12; // selettore servizio notturno
byte const SEG    = 13; // Led lampeggiante per indicare impianto in servizio




// le paline 1 e 3 sono su una via e danno il verde assieme
// le paline 2 e 4 sono su altra via e danno il verde assieme

poi ho pensato che un semaforo è un oggetto ciclico

quindi basta scrivere una sequenza di azioni che si richiamano una con l'altra

e quindi mi son detto:

una bella tabella, scritta in codice parlante (vuol dire che si capisca cosa dice) con la prima lettera comada la prima palina, e cos' via

// stabiliamo la sequenza di segnali

// 0 Palina Spenta
// R palina su rosso
// G palina su giallo - con verde acceso
// V palina su verde
// L palina con giallo senza verde
// per i segnali pedonali
// P luce verde al pedone, rosso sottinteso negato, basta la prima palina, lo raddoppio sulla seconda solo per estetica
// W luce verde al pedone, rosso sottinteso negato, buzzer inermittente per indicare giallo

// tempistica
// da definire
// A 1 secondo (usato per il giallo lampeggiante)
// B 5 secondi (sovrapposizione tra i due rossi, cambio tra auto e pedoni)
// C 15 seconfi (giallo prima del verde)
// D un minuto (usato per la via 1)
// E due minuti (usato per la via 2)

//sequenze:
// si legge: numero, non registrato, indice dello array
// stato palina 1, stato palina 2, durata, riga da leggere per la prossima

poi mi sono scritto come dovrebbe essere la sequenza delle azioni del semaforo

// sequenza normale

/* alternativa
  0RRB1   due vie rosse, pronti per la via 1
  1VRD2
  2GRC3
  3RRB4
  4RVE5
  5RGC0
  che forse va anche meglio
*/



// sequenza di via pedone libera, parte da via 1 gialla
// attende lo stato 1GRC2....
// 6RRB7 vie impedite // non serve, ci siamo già
// 7PPD8 vie impedite, vie pedoni libere
// 8WWB0 vie impedite, vie pedoni libere, allarem pedoni affreettarsi
// da qui riprende ciclo normale,

// lampggio notturno
// 9LLA: occhio interessante usare : come 10
// :00A9  anello rapido di lampeggio

dove la sola cosa difficile è che avendo 11 righe ho dovuto usare il carattere successivo al 9 per indicare il 10 il carattere successivo al 9 è il duepunti

e si tratta di una tabella di 11 righe che contiene le sole 11 configurazioni possibili del semaforo (anzi, 10, perchè una è risultata inutile, ma non sono stato li a toglierla)

a questo punto le variabili globali

e qui ho truccato, non le ho scritte tutte subito

mano a mano che mi sono servite le ho aggiunte

char sequenza[11][5] = {"RRB1", "VRD2", "GRC3", "RRB4", "RVE5", "RGC0", "RRB7", "PPD8", "WWB0" , "LLA:" , "00A9"}; // array di sequenza delle luci

unsigned long tempo = 0; //istante del prossimo cambio luci
unsigned long tempseg = 0; //istante del prossimo lampeggio led


byte stato = 0; // punto in esecuzione nel ciclo
byte chiamata = 0; // presenza chiamata pedonale
byte buzzer = 0; //lampeggio per simulare il buzzer
byte servizio = 0; // 0 servizio diurno, uno servizio notturno

in fondo sono quasi obbligate... non c'è storia...

pure la setup è quasi obbligata

void setup() {
  // uscite
  pinMode(P1R, OUTPUT);
  pinMode(P1G, OUTPUT);
  pinMode(P1V, OUTPUT);
  pinMode(P2R, OUTPUT);
  pinMode(P2G, OUTPUT);
  pinMode(P2V, OUTPUT);
  pinMode(PPV, OUTPUT);
  pinMode(PPG, OUTPUT);
  pinMode(CHI, OUTPUT);
  pinMode(SEG, OUTPUT);
  // ingressi
  pinMode(PUL, INPUT_PULLUP);
  pinMode(NOT, INPUT_PULLUP);

  // inizializzo seriale
  Serial.begin(9600);
  Serial.println(F("Programma di prova semaforo a due vie"));
  // faccio partire il semaforo
  luci(sequenza[0]);
}

la sola cosa particolare è la chiamata della luci(sequenza[0])

sequenza indice zero è la prima configurazione utile del semaforo la funzione luci(stringa) accende e/o spegne le paline secondo la configurazione data dalla stringa in ingresso

ecco la funzione luci()

void luci(char comando[]) {
  // per debug, la mando in seriale
  Serial.println(comando);


  // poi carico il tempo
  // che e' codificato nel terzo carattere
  switch (comando[2]) {
    case 'A':
      tempo = millis() + 1000;
      break;
    case 'B':
      tempo = millis() + 5000;
      break;
    case 'C':
      tempo = millis() + 15000;
      break;
    case 'D':
      tempo = millis() + 60000;
      break;
    case 'E':
      tempo = millis() + 120000;
      break;

  }

  // prenoto la prossima configurazione
  // che e' codificata nel quarto carattere
  stato = comando[3] - '0';

  // tutto il lavoro delle luci è dato dai due primi caratteri

  // palina 1
  switch (comando[0]) {
    case '0':
      // palina spenta
      digitalWrite(P1R, LOW);
      digitalWrite(P1G, LOW);
      digitalWrite(P1V, LOW);
      digitalWrite(PPV, LOW);
      digitalWrite(PPG, LOW);
      buzzer = 0;
      break;


    case 'R':
      // rosso
      digitalWrite(P1R, HIGH);
      digitalWrite(P1G, LOW);
      digitalWrite(P1V, LOW);
      digitalWrite(PPV, LOW);
      digitalWrite(PPG, LOW);
      buzzer = 0;
      break;

    case 'G':
      // giallo
      digitalWrite(P1R, LOW);
      digitalWrite(P1G, HIGH);
      digitalWrite(P1V, HIGH);
      digitalWrite(PPV, LOW);
      digitalWrite(PPG, LOW);
      buzzer = 0;
      break;

    case 'V':
      // Verde
      digitalWrite(P1R, LOW);
      digitalWrite(P1G, LOW);
      digitalWrite(P1V, HIGH);
      digitalWrite(PPV, LOW);
      digitalWrite(PPG, LOW);
      buzzer = 0;
      break;
    case 'L':
      // giallo del lampeggio
      digitalWrite(P1R, LOW);
      digitalWrite(P1G, HIGH);
      digitalWrite(P1V, LOW);
      digitalWrite(PPV, LOW);
      digitalWrite(PPG, LOW);
      buzzer = 0;
      break;

    case 'P':
      // verde ai pedoni
      digitalWrite(P1R, HIGH);
      digitalWrite(P1G, LOW);
      digitalWrite(P1V, LOW);
      digitalWrite(PPV, HIGH);
      digitalWrite(PPG, LOW);
      buzzer = 0;
      break;
    case 'W':
      // giallo ai pedoni, che lampegggia come buzzer
      digitalWrite(P1R, HIGH);
      digitalWrite(P1G, LOW);
      digitalWrite(P1V, LOW);
      digitalWrite(PPV, HIGH);
      digitalWrite(PPG, HIGH);
      buzzer = 1;
      break;
    default:
      break;

  }
  // palina 2 alcune voci non servono
  switch (comando[1]) {
    case '0':
      // palina spenta
      digitalWrite(P2R, LOW);
      digitalWrite(P2G, LOW);
      digitalWrite(P2V, LOW);
      break;


    case 'R':
      // rosso
      digitalWrite(P2R, HIGH);
      digitalWrite(P2G, LOW);
      digitalWrite(P2V, LOW);
      break;

    case 'G':
      // giallo
      digitalWrite(P2R, LOW);
      digitalWrite(P2G, HIGH);
      digitalWrite(P2V, HIGH);
      break;

    case 'V':
      // Verde
      digitalWrite(P2R, LOW);
      digitalWrite(P2G, LOW);
      digitalWrite(P2V, HIGH);
      break;
    case 'L':
      // giallo del lampeggio
      digitalWrite(P2R, LOW);
      digitalWrite(P2G, HIGH);
      digitalWrite(P2V, LOW);
      break;

    default:
      break;

  }

}

come si vede è una pura unumerazione di casi e accendi spegni...

una noia scriverla.........

le cose interessanti:

la variabile stato, letta dal 4 carattere, converito da ASCII a numerico col semplice trucco di togliere il valore '0'

la variabile stato NON è lo stato attuale, ma lo stato FUTURO