Ora servirebbero un po' di switch e qualche case, o no?

Buona sera a tutti , mentre mi districavo tra una serie di if e di comparatori ero consapevole dell'esistenza del costrutto switch/ case di cui ho letto e riletto (invano) . Ma non riesco a comprenderlo ; posto il codice su cui sto lavorando e che funziona per quella che al momento è la versione di base .
Magari vi va di darmi un calcio nella giusta direzione :wink:
Grazie mille.

//******VERSIONE 0.2 DEL TESTER DI BATTERIE************//
/*FUNZIONAMENTO : ACCENDO E IL DISPLAY MOSTRA LA SCRITTA DEL SETUP. DOPO 2 SECONDI :
SE LA BATTERIA E' INFERIORE A 0,9V ( O NON E' COLLEGATA ) SCRIVO SUL DISPLAY "INSERIRE BATTERIA" 
ALTRIMENTI LEGGO LA TENSIONE PRESENTE IN TEMPO REALE.
SE LA BATTERIA CONNESSA HA UNA TENSIONE MAGGIORE DI 2,8 V E' POSSIBILE AVVIARE IL CICLO DI TEST CHE SI PUO' AVVIARE PREMENDO IL PULSANTE START.
A QUESTO PUNTO IL FUNZIONAMENTO E' AUTOMATICO E A SECONDA DEI  PARAMETRI IMPOSTATI SI AVRA' UN RISULTATO POSITIVO O NEGATIVO.*/
//******FUNZIONA CORRETTAMENTE**********//

//******PASSO ALLA VERSIONE 0.3**********//

#include <Wire.h>
#include <PCF8574_HD44780_I2C.h>
PCF8574_HD44780_I2C lcd(0x27,16,2);

// VOLTMETRO A0             //ingresso voltmetro
// AMPEROMETRO A1           //ingresso amperometro
// TASTO START PIN2         //avvio ciclo di inserzione carico
// SCL $ SDA DIPLAY I2C
// RELE DI CARICO PIN 6     //rele di carico
// LED BLU PIN 7            //led blu di scarica in corso (sarebbe bello se lampeggiasse)
// LED VERDE PIN 8          //led rosso di fine scarica con esito negativo
// LED ROSSO PIN 9          //led verde di fine scarica con esito positivo

#define tasto_start 2       //Definizione pin pulsante di avvio 
#define carico 6            //rele di carico
#define led_blu 7           //led blu di scarica in corso (sarebbe bello se lampeggiasse)
#define led_verde 8         //led rosso di fine scarica con esito negativo
#define led_rosso 9         //led verde di fine scarica con esito positivo

int era_tasto_start ;       // Variabile valore tasto di avvio
float voltmetro ;           //qui assegno la tensione rilevata sul pin A0
float amperometro ;         //qui assegno la corrente rilevata sul pin A1

unsigned long millis_iniziali ;  
unsigned long ritardo = 60000;         //al momento un minuto(sarà poi da impostare con encoder)
int ciclo =0;

void setup() {
  lcd.init();                       
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print(" BATTERY TESTER");
  lcd.setCursor(0, 1);
  lcd.print("  VERSIONE V 0.2");        //VERSIONE 0.2
  
  pinMode (tasto_start, INPUT_PULLUP);  //pin tasto_start ingresso
  pinMode (carico, OUTPUT);             //pin relè carico
  pinMode (led_blu, OUTPUT);            //ciclo in corso
  pinMode (led_verde, OUTPUT);          //ciclo finito con esito positivo
  pinMode (led_rosso, OUTPUT);          //ciclo finito con esito negativo

  millis_iniziali = millis() ;          //tengo traccia del tempo dall'avvio
  
  era_tasto_start = digitalRead(tasto_start) ;
  voltmetro = digitalRead (A0);
  amperometro = digitalRead (A1);
  delay(2000);
}

void loop() {
  
/****calcolo ampere****/

  float Acslettura=0.0,campioni=0.0,media=0.0;
  for (int a = 0; a < 150; a++){           //ricavo 15 valori
  Acslettura = analogRead(A1) ;            //leggo valore ritorno acs712 c.to 1
  campioni = campioni + Acslettura;        //sommo i valori per calcolare la media
  delay (10);  }
  media=(campioni/150);                   //calcolo la media dei valori
  amperometro = (2.5 - (media * (5.0 / 1024.0)) )/0.0315;  //formula per ottenere il valore definitivo
  if (amperometro < 0.10){
    amperometro = 0.00;}
  delay(20); 
    
/****calcolo volt****/  

  voltmetro = ((5.0/1024.0)*analogRead(A0))*((30+7.5)/7.5); 
  delay(20); 

 int ora_tasto_start = digitalRead(tasto_start) ;  // Leggo valori tempo reale

   if((ora_tasto_start != era_tasto_start)&&(voltmetro > 2.8)){
    digitalWrite(carico, HIGH);
    digitalWrite(led_blu, HIGH);
    ciclo = 1;  
    ora_tasto_start = era_tasto_start ;
}
   
   if(((voltmetro <= 2.8) && ((millis()-millis_iniziali) <= ritardo)) && (ciclo == 1)){ 
    ciclo = 2;                           //mi serve per impedire l'accavallamento dei due fine ciclo.
    millis_iniziali = millis();          //aggirno millis
    digitalWrite(carico, LOW);
    digitalWrite(led_blu, LOW);
    digitalWrite(led_rosso, HIGH);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("BATTERIA DA ");
    lcd.setCursor(0, 1);
    lcd.print("BUTTARE   ");
    delay(250);  
 }

 if(((voltmetro <= 2.8) && ((millis()-millis_iniziali) >= ritardo)) && (ciclo == 1)){ 
    ciclo = 3;                           //mi serve per impedire l'accavallamento dei due fine ciclo.
    millis_iniziali = millis();          //aggirno millis
    digitalWrite(carico, LOW);
    digitalWrite(led_blu, LOW);
    digitalWrite(led_verde, HIGH);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("BATTERIA DA ");
    lcd.setCursor(0, 1);
    lcd.print("UTILIZZARE ");
    delay(250);    
 }

  if ((voltmetro > 2.8) && (ciclo == 1)){
   lcd.clear();
   lcd.setCursor(4, 0);
   lcd.print("SCARICA ");
   lcd.setCursor(0, 1);
   lcd.print("V= ");
   lcd.setCursor(3, 1);
   lcd.print(voltmetro);
   lcd.setCursor(8, 1);
   lcd.print("A= ");
   lcd.print(amperometro);
   delay(2000); 
  }
  
  if ((ciclo == 0) &&(voltmetro >= 0.8)){  
    
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("TENSIONE ");
    lcd.setCursor(0, 1);
    lcd.print("V= ");
    lcd.setCursor(4, 1);
    lcd.print(voltmetro);
    delay(250);   
  }

  if ((ciclo == 0) &&(voltmetro <= 0.8)){  
    
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("INSERIRE ");
    lcd.setCursor(0, 1);
    lcd.print("BATTERIA");
    delay(250);   
  }
  
  }

in arduino lo switch accetta verifiche su variabili tipo int o char; nei tuoi if ci sono anche dei float...quindi sarebbe un misto di switch per ciclo, e di if per i float...però guardando bene il tuo codice si potrebbe semplificare molto...considera quanto usi "ciclo" e che valori può avere...poi considera quante volte e cosa "scrivi" sul monitor lcd...ed attenzione al >= e <= finali.

ok, grazie mille. "ciclo" l'ho creato per poter avere dei riferimento per le varie fasi , altresì non saprei come fare. nel proseguo vorrei che fosse "universale" , quindi con la possibilità di inserire i parametri. :crossed_fingers: :crossed_fingers:

Beh non con switch...case ma nel tuo caso direi che ti basterebbe dare una "ordinata" logica alle condizioni, ad esempio raggruppando in singole if() insieme quelle relative a "voltmetro", dentro a queste aggiungere le altre condizioni. Oltre comunque a verificare meglio le condizioni, ad esempio in ciclo=0 hai una if con "voltmetro >= 0.8" e poi una con "voltmetro <= 0.8" quindi formalmente se "voltmetro" dovesse essere esattamente pari a 0.8 verrebbero eseguite entrambe. Togli l'uguale da una delle due, oppure usa "else".
Insomma, una cosa di questo tipo:

  switch (ciclo) {
    case 0:
      if (voltmetro >= 0.8) {      
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("TENSIONE ");
        lcd.setCursor(0, 1);
        lcd.print("V= ");
        lcd.setCursor(4, 1);
        lcd.print(voltmetro);
        delay(250);   
      } else {
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("INSERIRE ");
        lcd.setCursor(0, 1);
        lcd.print("BATTERIA");
        delay(250);   
      }
      break;
      
    case 1:
      if(voltmetro <= 2.8) {
        if (millis()-millis_iniziali <= ritardo) { 
          ciclo = 2;                           //mi serve per impedire l'accavallamento dei due fine ciclo.
          millis_iniziali = millis();          //aggirno millis
...
          delay(250);  
       } else {
          ciclo = 3;                           //mi serve per impedire l'accavallamento dei due fine ciclo.
          millis_iniziali = millis();          //aggirno millis
...
          delay(250);    
       }
       break;
     
     // Aggiungi qui tutti gli eventuali altri stati
     case 2:
      // eccetera....
      ...
    }
  }

Grazie mille, il mio dilemma principale é : chi/come chiama switch (ciclo) case (numero) ? Lo può fare in automatico al cambio della variabile ?
Scusa , ma proprio non ci arrivo...uff.

switch(tasto_start){
     case 1: loop1(); break;
     case 2: loop2(); break;
     case 3: loop3(); break;
     case 4: loop4(); break;
     case 5: loop5(); break;
     case 6: loop6(); break;
     case 7: loop7(); break;
     case 8: loop8(); break;
     case 9: loop9(); break;
    }

può essere un buon punto di partenza?
ad ogni pressione del tasto cambio case , e trascorso un certo tempo lo attivo ; è così ?

Più o meno si, comunque nessuno "chiama" questa parte di codice, che devi semplicemente mettere nel loop() del tuo sketch in modo che ad ogni iterazione effettua le azioni previste.

Considera che questo è il metodo usato per implementare una "macchina a stati finiti" o FSM. In poche parole, una FSM puoi progettarla disegnando su un foglio un grafo composto da cerchi, gli stati, e da frecce che vanno da un cerchio ad un altro (o anche lo stesso) che rappresentano le transizioni di stato. Ogni freccia è etichettata con una condizione (quella che fa "attivare" quel percorso) ed una eventuale azione (ossia cosa deve fare il sistema quando rileva la condizione).
Nel tuo caso a me sembra che "ciclo" corrisponda allo stato della macchina, per come lo hai scritto. Poi all'interno dello stato hai la distinzione in base alla lettura del voltmetro (la "condizione") ed in base a questa tu fai qualcosa sullo schermo (l'"azione") e poi imposti un nuovo stato.
Ad esempio per "ciclo=0" ossia lo stato iniziale, se il voltmetro misura più di 0.8 V (condizione) scrivi sull'LCD la lettura (azione). Se premi il tasto di avvio ed il voltmetro è maggiore di 2.8 (condizione) allora accendi i led (azione) e passi allo stato 1.
Se lo stato è 1, allora se il voltmetro misura più di 2.8 V (condizione) se è passato il tempo di ritardo accendi i LED e scrivi sul display (azione) e passi allo stato 3.
E così via.

Un consiglio: quando devi realizzare qualcosa con una FSM fatti un disegnino proprio con cerchi (dentro i quali ci scrivi il nome dello stato e magari il suo valore numerico) e frecce (con una descrizione della condizione ed eventuale azione). Una cosa di questo tipo:
image

Puoi trovare altre informazioni QUI, è una piccola libreria che scrissi per me stesso qualche anno fa, ma può essere utile anche ad altri.

Ottimo , per il momento ti ringrazio molto. intanto mi cimento col compasso :grinning:

Scrivo d'impulso , senza quesiti o perché , ma solamente per ringraziarti davvero molto. Eh già , ho capito! :muscle:

Può sembrare banale e sciocco , ma la "storia" dei cerchi in combinazione di penne colorate e un notes mi ha sbloccato l'ingresso principale , ora posso entrare ; basta sbirciare da fuori. :wink:

Grazie ancora.
Claudio

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