Aiuto a pulire il codice

Salve a tutti... Ho fatto un programmino stupido per esercitarmi...

E' la prima volta che mi cimento in un programma del genere (con la funzione switch), quindi non sò se ho usato la forma "corretta".
Vi chiedo cosa posso migliorare, per avere meno problemi e un programma più "bello"
Inoltre la logica che ho usato per far stampare a schermo una sola volta i vari messaggi mi fà orrore, e mi chiedo se c'è qualcosa di meglio che possa fare.

void setup() {
 Serial.begin (9600);
 pinMode( 13, OUTPUT );
 pinMode( 12, OUTPUT );
}

char caso;
int statoled = 0;

int richiestatit = 0;
int a = 0;
int b = 0;
int c = 0;
int o = 0;

unsigned long int curtime;
unsigned long int ledtimea =0;
unsigned long int ledtimeb =0;
unsigned long int ledtimec =0;
unsigned long int interleda = 50;
unsigned long int interledb = 500;
unsigned long int interledc = 1000;

void loop() 
{  
  delay(50);
  
  curtime = millis();
  
  if ( richiestatit == 0)
  {
  Serial.println("Inserisci a, b oppure c.\nDigita 'o' per spegnere il sistema.\n");
  richiestatit++;
  }
  
  if ( Serial.available() )
  {
     caso = Serial.read();
     
    if ( caso != 'a' && caso != 'b' && caso != 'c' && caso != 0 && caso != 'o')
    {
      Serial.println("Il valore non e' stato riconosciuto.\n");
      digitalWrite( 13, HIGH);
      digitalWrite( 12, LOW);
      richiestatit=0;
      a=0;
      b=0;
      c=0;
      o=0;
    }
  } 
  
  switch (caso)
  {
    case 'a':
      Funzionea();
      break;
     
    case 'b':
      Funzioneb();
      break;
    
    case 'c':
      Funzionec();
      break;
  }  
  
  if ( caso == 'o')
  {
    digitalWrite( 13, LOW);
    digitalWrite( 12, LOW);
   
    if ( o == 0 )
    {
      Serial.println ( "Il sistena e' spento\n" );
  
      o++;
      c=0;
      a=0;
      b=0;
    }  
  }
}
void Funzionea()
{
  if ( a == 0)
    Serial.println( "Sei nella funzione a\n" );
  
  if ( curtime > ledtimea + interleda)
  {
    statoled = 1 - statoled; 
    digitalWrite( 12, statoled);
    digitalWrite( 13, LOW);
    ledtimea = millis();
  }
  
  a++;
  b=0;
  c=0;
  o=0;
}
void Funzioneb()
{
  if (b == 0)
    Serial.println( "Sei nella funzione b\n" );
  
  if ( curtime > ledtimeb + interledb)
  {
    statoled = 1 - statoled; 
    digitalWrite( 12, statoled);
    digitalWrite( 13, LOW);
    ledtimeb = millis();
  }
  b++;
  a=0;
  c=0;
  o=0;
}
void Funzionec()
{
  if ( c==0 )
    Serial.println( "Sei nella funzione c\n" );
       
  if ( curtime > ledtimec + interledc)
  {
    statoled = 1 - statoled; 
    digitalWrite( 12, statoled);
    digitalWrite( 13, LOW);
    ledtimec = millis();
  }
  c++;
  a=0;
  b=0;
  o=0;
}

Inoltre ho un paio di domande:

Perchè se metto "case 1" al posto di "case '1' " non funziona? (è un esempio, per aggirare questo problema ho messo i caratteri...)

Perchè se metto un println(caso) subito dopo il serialread mi stampa quello che penso sia il corrispettivo in ascii?
E perchè se metto un serialwrite melo stampa direttamente? Ero abbastanza sicuro che fosse il contrario :disappointed_relieved:

Grazie :slight_smile:

Ciao, se gentilmente ci dici cosa deve fare il programma è meglio, altrimenti dobbiamo leggere tutto il codice.
Cosi vediamo come impostare il programma in modo semplice e correggiamo eventuali errori.
Ciao

ulver85:
Ciao, se gentilmente ci dici cosa deve fare il programma è meglio, altrimenti dobbiamo leggere tutto il codice.
Cosi vediamo come impostare il programma in modo semplice e correggiamo eventuali errori.
Ciao

Certo! :slight_smile:

Allora il programma inizia chiedendo di inserire a, b oppure c.
O di inserire o per spegnere il tutto.

Se si inserisce a, un led collegato al pin 12 lamppeggia velocemente e il programma riporta che stiamo nella funzione a;
Se si inserisce b, un led collegato al pin 12 lamppeggia ogni 500ms e il programma riporta che stiamo nella funzione b;
Se si inserisce c, un led collegato al pin 12 lamppeggia ogni secondo e il programma riporta che stiamo nella funzione c;

Se si digita un qualsiasi altro valore il programma stampa "valore non riconosciuto" e accendo un led al pin 13 spegnendo l'altro.

Se si digita o si spengono entrambi i led.

E' un programma stupidissimo, ma sono alle prime armi :blush:

Allora il programma che descrivi si può realizzare in questo modo:

void setup(){
 Serial.begin(9600);
 pinMode(13, OUTPUT);
 pinMode(12, OUTPUT);
 Serial.println("inserisci comando (a,b,c,o,...)");
}

void loop(){
  if(Serial.available()){
    char c = Serial.read();
    
    switch(c)
    {
      case 'a':
        funzione_a();
        break;
        
      case 'b':
        funzione_b();
        break;
        
      case 'c':
        funzione_c();
        break;
        
      case 'o':
        funzione_o();
        break;
        
      default:
        funzione_default();
      break;  
    }
  }
}


void funzione_a(){
  Serial.println("sei nella funzione a");
  while(1){
    if(Serial.available()){
      break;
    }
    digitalWrite(12, HIGH);
    delay(100);
    digitalWrite(12, LOW);
    delay(100);
  }
}

void funzione_b(){
   Serial.println("sei nella funzione b");
    while(1){
      if(Serial.available()){
        break;
      }
      digitalWrite(12, HIGH);
      delay(500);
      digitalWrite(12, LOW);
      delay(500);
    }
}

void funzione_c(){
   Serial.println("sei nella funzione c");
    while(1){
      if(Serial.available()){
        break;
      }
      digitalWrite(12, HIGH);
      delay(1000);
      digitalWrite(12, LOW);
      delay(1000);
    }
}
void funzione_o(){
  Serial.println("sei nella funzione o");
  digitalWrite(12, LOW);
  digitalWrite(13, LOW);
}

void funzione_default(){
  Serial.println("sei nella funzione default, valore non riconosciuto");
  digitalWrite(12, HIGH);
  digitalWrite(13, LOW);
}

Come vedi fa uso del costrutto switch, della comunicazione seriale e delle funzioni che chiedi di implementare.

Partiamo dal costrutto switch, questa struttura ti permette di prendere delle decisioni in base al valore di una variabile, è un pò come il costrutto if/else annidato ma meno complesso nella gestione, il suo funzionamento si basa sulla comparazione di una variabile con i diversi casi previsti nel costrutto, la struttura è:

switch(a) {  // 'a' è la variabile di controllo
  
   case '1':  // se la variabile a è uguale a '1' allora lo switch seleziona il caso 1 ed esegue il codice al suo interno
   //codice da eseguire
   break;

   case '2':  // se la variabile a è uguale a '2' allora lo switch seleziona il caso 2 ed esegue il codice al suo interno
   //codice da eseguire
   break;
   
   default:  // se la variabile a non è uguale a nessuno dei casi previsti allora lo switch esegue ciò che si trova nel blocco defaultì
   //codice da eseguire
   break;
}

L'istruzione break serve per uscire dal caso specifico dello switch dopo aver eseguito il codice ad esso associato.

La comunicazione seriale è più complessa da spiegare in due parole, però come puoi comprendere almeno per adesso noi la usiamo per comunicare con il pc e mandare messaggi ad arduino.
Per poterla usare occorre inizializzare la connessione con Serial.begin(9600); nella funzione setup e rispettare il baud rate, cioè quel numero 9600 come parametro della Serial.begin(), ciò significa che quando usi il serial monitor nell'ide di arduino in basso a destra della finestra del terminale dovrai settare il valore del baud rate a 9600.

Ora veniamo al programma, dopo aver inizializzato la connessione seriale nella funzione setup e impostato i pin di output per gestire i led, stampiamo via seriale il messaggio che avvisa l'utente che è tutto pronto per iniziare a ricevere comandi.
Passiamo alla funzione loop, qui la prima cosa da fare e capire se c'è qualche carattere scritto via seriale con la funzione Serial.available() che restituisce true come valore logico se abbiamo inviato qualche carattere ad arduino, a questo punto dobbiamo capire di che carattere si tratta e quindi leggerlo con la funzione Serial.read(); che restituisce appunto il carattere letto sulla seriale, lo salviamo in una variabile 'char c' e successivamente lo processiamo con lo switch per capire come comportarci.
Nei casi previsti dallo switch ci sono i caratteri a, b, c, o, se lo switch rileva uno di questi caratteri avviera la sua funzione associata presente nella parte finale del codice dopo il loop. Se lo switch riceve un qualsiasi carattere non presente tra i suoi casi avviera il blocco default e la sua relativa funzione associata.

Questo è quanto, ovviamente non commento le funzioni perchè elementari si tratta di far lampeggiare un led con frequenze diverse gestite con la funzione delay, però l'unica cosa che voglio farti notare è che se non digiti altri caratteri rimani fermo all'interno dell'ultima funzione chiamata, questo perchè ho usato un cilco while(1) che è infinito come la funzione loop, ne esci solo quando sulla seriale arduino trova un altro carattere da processare è questo comportamento lo implementi con l'istruzione:

if(Serial.available()){
      break; //se si invia un carattere alla seriale il break viene eseguito ed esci dal cilco while(1)
    }

Spero di essere stato chiaro, guardati un pò il codice e cerca di capire come funziona, se hai altri dubbi chiedi pure.
Ciao