Come interrompere l'esecuzione di una parte di codice,tramite uno switch

Salve,quello che vorrei poter fare e' questo:
L'utente preme il tasto PET,e lo sketch esegue le sue operazioni. Ad un certo punto l'utente vuole arrestare questo ciclo,perche ha finito,e invece di aspettare lo scadere del timer,decide di premere il tasto PS,per poter eseguire la relativa parte dello sketch.
Ho inserito a fine ciclo while:

if (digitalRead(PET) == LOW)
                     break;
                     if (digitalRead(PS) ==  LOW)
                     break;

Ma non funziona.
I pin degli switch relativi,sono cosi' dichiarati:
pinMode(PET,INPUT_PULLUP);
pinMode(PS,INPUT_PULLUP);

Ecco il codice:

while (stato <1)
                 {
                   if (!smartcard.IsCardPresent(1))
                   stato=1;   
                   duration =millis() - startTime;
               
                       if ( duration > Timeout) 
                        {   
                          stato = 1;
                           // Manda l'impulso solo se non l'ha già mandato prima
                            if (impulso_mandato == false)
                               {
                                Serial.println("BLOCCATO"); 
                                impulso_mandato = true;
                               }
                        }
                   
                 else   
                {
                 
                 
                    // SCELTA PET
             
                    if (pulsantePremuto(PET) == true && giaPremuto == false)
                        {
                         stato = 1;
                         giaPremuto = true;
                         Serial.println("Scelta effettuata : PET");
                         apriportelloPET();
                         Contatore_PET=0;
                         contaPET();
                   
                           }
                   
                    //SCELTA PS
                  
                     if (pulsantePremuto(PS) == true && giaPremuto == false)
                         {
                        stato = 1;
                        giaPremuto = true;
                        Serial.println("Scelta effettuata : PS");
                        // apriportelloPS();
                        Contatore_PS=0;
                        contaPS();
                   
                         } 
                 }
                      
                     if (digitalRead(PET) == LOW)
                     break;
                     if (digitalRead(PS) ==  LOW)
                     break;  
                } // CHIUSURA  CICLO WHILE

Tu vuoi uscire da un ciclo se è passato un certo tempo oppure al verificarsi di un evento.
A te serve un doppio controllo, un timeout per controllare il tempo ed un check su una condizione che vuoi verificare, ad esempio la pressione di un pulsante

Ho da poco scritto un articolo sui timeout, credo che ti potrà tornare utile. :wink:

Si il timeout gia' funziona alla perferzione...il problema e' solo uscire dal ciclo con la pressione di un tasto!

Lo hai letto l'articolo che ti ho linkato?

leo72:
Tu vuoi uscire da un ciclo se è passato un certo tempo oppure al verificarsi di un evento.
A te serve un doppio controllo, un timeout per controllare il tempo ed un check su una condizione che vuoi verificare, ad esempio la pressione di un pulsante

leo72:
Lo hai letto l'articolo che ti ho linkato?

leo72:
Tu vuoi uscire da un ciclo se è passato un certo tempo oppure al verificarsi di un evento.
A te serve un doppio controllo, un timeout per controllare il tempo ed un check su una condizione che vuoi verificare, ad esempio la pressione di un pulsante

Si,ma utilizzando il tuo metodo,dovrei reimpostare TUTTO il codice e nel mio caso non e' semplice......

Se vuoi fare la cosa con un timeout, devi cambiare un pò di codice, non tutto il codice :wink:
Devi cambiare i controlli, solo i blocchi dove fai la lettura dei comandi. La gestione degli stessi resta invariata.

Ciao mooger, felice di rileggerti.

La butto lì:

if (digitalRead(PET) == LOW || digitalRead(PS) ==  LOW)
                     break;

Brado:
Ciao mooger, felice di rileggerti.

La butto lì:

if (digitalRead(PET) == LOW || digitalRead(PS) ==  LOW)

break;

Ciao Brado!:slight_smile: Purtroppo non va,da quanto ho capito la variabile "giaPremuto" alla prima esecuzione diventa true e mai più false, quindi entrambi gli if di "pulsantePremuto"falliscono!Forse questo e' il problema? :~

Hai ragione, in quel pezzo di sketch non rimetti mai a false giaPremuto.
Ora che più o meno mi ricordo lo sketch completo, prima dell'uscita dalle sub ContaPET e ContaPS, prova a settare giaPremuto = false.

Brado:
Hai ragione, in quel pezzo di sketch non rimetti mai a false giaPremuto.
Ora che più o meno mi ricordo lo sketch completo, prima dell'uscita dalle sub ContaPET e ContaPS, prova a settare giaPremuto = false.

In che senso?Settarlo qui? (in questo caso ho settato giaPremuto da True a False)

// SCELTA PET

if (pulsantePremuto(PET) == true && giaPremuto == false)
{
stato = 1;
giaPremuto = false; // modifica!!!!
Serial.println("Scelta effettuata : PET");
apriportelloPET();
Contatore_PET=0;
contaPET();

}

//SCELTA PS

if (pulsantePremuto(PS) == true && giaPremuto == false)
{
stato = 1;
giaPremuto = false; // modifica!!!
Serial.println("Scelta effettuata : PS");
// apriportelloPS();
Contatore_PS=0;
contaPS();

}

No, non ha senso.

Dentro le sub contaPS() e contaPET(), quelle fuori dal loop

Allora avevo capito bene,ma non c'e' la variabile giaPremuto in queste subroutine!

  void contaPET()        // Funzione che conta i pezzi del materiale PET,rilevati dal sensore 
  {
    Timer = millis();  // PARTE IL TIMER
     while((millis() - Timer) < Timeout) {   // Mentre t < timeout 
        distance = Dist.getDistanceCentimeter(); // Acquisisci dati dal sensore
         if (distance>=7) { // Se la distanza e' maggiore di 7,non contare
            premuto = false;
                          }
            if ((distance<7) && premuto == false) {  // Se la distanza e'minore di 7 comincia a contare
              Contatore_PET ++;  // incrementa contatore
              Timer = millis();  // timer partito/resettato
              premuto = true;
              Serial.print("Contatore PET: ");
              Serial.println(Contatore_PET);
              Scrivi_numero_pezzi(Contatore_PET);  // Scrivi il numero di pezzi relativi al materiale PET,su SMARTCARD
                    }
          
              if (!smartcard.IsCardPresent(1))         // Verifico presenza card     <<< Modifica proposta
              Timer = millis()+millis();           // Faccio scadere il timeout      
              }
  }

Infatti la mettiamo.
Se giaPremuto l'hai dichiarata insieme alle costanti, all'inizio del listato, la puoi vedere in tutto lo sketch.
Quindi, secondo me, potresti provare così:

  void contaPET()        // Funzione che conta i pezzi del materiale PET,rilevati dal sensore 
  {
    Timer = millis();  // PARTE IL TIMER
     while((millis() - Timer) < Timeout) {   // Mentre t < timeout 
        distance = Dist.getDistanceCentimeter(); // Acquisisci dati dal sensore
         if (distance>=7) { // Se la distanza e' maggiore di 7,non contare
            premuto = false;
                          }
            if ((distance<7) && premuto == false) {  // Se la distanza e'minore di 7 comincia a contare
              Contatore_PET ++;  // incrementa contatore
              Timer = millis();  // timer partito/resettato
              premuto = true;
              Serial.print("Contatore PET: ");
              Serial.println(Contatore_PET);
              Scrivi_numero_pezzi(Contatore_PET);  // Scrivi il numero di pezzi relativi al materiale PET,su SMARTCARD
                    }
          
              if (!smartcard.IsCardPresent(1))         // Verifico presenza card     <<< Modifica proposta
              Timer = millis()+millis();           // Faccio scadere il timeout      
              }
    giaPremuto=false;
  }

Niente da fare,ti allego la parte dello sketch interessata con le subroutine e le modifiche effettuate!Quando seleziono ad esempio PET,comincia a conteggiare,se premo il tasto PS,dovrebbe fermarsi la conta di PET e cominciare quella di PS,ma non va!

if ((VAL_CTRL1==LOW) || (VAL_CTRL2==LOW)) { // simulazione errori tramite i pulsanti
         
         Serial.println("Attenzione!Errore!");
          } 
          
        else {
              Serial.println ("Effettua la scelta del materiale da conferire entro 10 secondi.."); 
              // Parte il conto alla rovescia per la scelta del materiale da conferire:
               impulso_mandato = false;
               giaPremuto = false;
               stato=0;
                
                while (stato <1)
                 {
                    if (!smartcard.IsCardPresent(1))
                    stato=1;   
                    duration =millis() - startTime;
               
                   if ( duration > Timeout) 
                   {   
                    stato = 1;
                    // Manda l'impulso solo se non l'ha già mandato prima
                    if (impulso_mandato == false)
                     {
                      Serial.println("BLOCCATO"); 
                      impulso_mandato = true;
                      }
                    }
      
                else   
                {
                 
                 
                    // SCELTA PET
             
                    if (pulsantePremuto(PET) == true && giaPremuto == false)
                        {
                         stato = 1;
                         giaPremuto = true;
                         Serial.println("Scelta effettuata : PET");
                         apriportelloPET();
                         Contatore_PET=0;
                         contaPET();
                   
                           }
                   
                    //SCELTA PS
                  
                     if (pulsantePremuto(PS) == true && giaPremuto == false)
                         {
                        stato = 1;
                        giaPremuto = true;
                        Serial.println("Scelta effettuata : PS");
                        // apriportelloPS();
                        Contatore_PS=0;
                        contaPS();
                   
                           } 
                    }
                    
                    if (digitalRead(PET) == LOW || digitalRead(PS) ==  LOW)
                     break;
                   
                  } 
            }
      } // CHIUSURA PARENTESI if ascii
      
       else
       
        { 
         //Se la simcard non e' riconosciuta,spegni il led
         digitalWrite(2, LOW);
        Serial.println("Simcard non valida!");
        Serial.println();
      }
      chiudiportelloPET(); // Chiude portello PET quando si estrae la scheda.
      Serial.print("Estrarre la SIMCARD,Grazie...");
      Serial.println();
      
      smartcard.PowerOffSC();
     //wait smartcard extraction
      while(smartcard.IsCardPresent(1)){
        delay(500);  
      }
      Serial.println("Operazione conclusa");
      Serial.println();
      
      
  } // Fine LOOP
  
 
 ///////////////////////////////////////////////////////////////////////

 
  void apriportelloPET ()  // Funzione per l'apertura del portello PET
  {
    digitalWrite (Rele_PET,HIGH); // pin 9
    Serial.print("PREGO CONFERIRE PET");
    Serial.println();
  }
      
  
  void chiudiportelloPET () // Funzione per la chiusura del portello PET
  {
    digitalWrite (Rele_PET,LOW); // pin 9
    
  }
      
  void contaPET()        // Funzione che conta i pezzi del materiale PET,rilevati dal sensore 
  {
    Timer = millis();  // PARTE IL TIMER
     while((millis() - Timer) < Timeout) {   // Mentre t < timeout 
        distance = Dist.getDistanceCentimeter(); // Acquisisci dati dal sensore
         if (distance>=7) { // Se la distanza e' maggiore di 7,non contare
            premuto = false;
                          }
            if ((distance<7) && premuto == false) {  // Se la distanza e'minore di 7 comincia a contare
              Contatore_PET ++;  // incrementa contatore
              Timer = millis();  // timer partito/resettato
              premuto = true;
              Serial.print("Contatore PET: ");
              Serial.println(Contatore_PET);
              Scrivi_numero_pezzi(Contatore_PET);  // Scrivi il numero di pezzi relativi al materiale PET,su SMARTCARD
                    }
          
              if (!smartcard.IsCardPresent(1))         // Verifico presenza card     <<< Modifica proposta
              Timer = millis()+millis();           // Faccio scadere il timeout      
              }
              giaPremuto=false;
  }

   void contaPS() 
  {
    Timer = millis();  // PARTE IL TIMER
     while((millis() - Timer) < Timeout) {   // Mentre t < timeout 
        distance1 = Dist1.getDistanceCentimeter(); // Acquisisci dati dal sensore
         if (distance1>=7) { // Se la distanza e' maggiore di 7,non contare
            premuto = false;
                          }
            if ((distance1<7) && premuto == false) {  // Se la distanza e'minore di 7 comincia a contare
              Contatore_PS ++;  // incrementa contatore
              Timer = millis();  // timer partito/resettato
              premuto = true;
              Serial.print("Contatore PS: ");
              Serial.println(Contatore_PS);
              Scrivi_numero_pezzi(Contatore_PS);  // Scrivi il numero di pezzi relativi al materiale PS,su SMARTCARD
                    }
          
              if (!smartcard.IsCardPresent(1))         // Verifico presenza card    
              Timer = millis()+millis();           // Faccio scadere il timeout      
              }
              giaPremuto=false;
  }
  
  bool pulsantePremuto(int pinPulsante)
  {
  // pulsante premuto
  if (digitalRead(pinPulsante) == LOW) 
  {
    delay(20);  // ritardo antiribalzo 
    
    // conferma pulsante premuto
    if (digitalRead(pinPulsante) == LOW )
    {       
      //Pulsante premuto, ritorna true e ferma la funzione
      return true;
    }
  }
  
  //Nessun pulsante è stato premuto, la funzione ritorna false
  return false;
}

Ok, diciamo che con la modifica inserita, se l'utente lasciasse scadere il timeout, potrebbe tornare a selezionare il pulsante differente rispetto a quanto fatto in precedenza.

Allora, bisogna inserire nel while presente nelle sub ContaPET e ContaPS il controllo sulla pressione dell'altro tasto.

  void contaPET()        // Funzione che conta i pezzi del materiale PET,rilevati dal sensore 
  {
    Timer = millis();  // PARTE IL TIMER
     while((millis() - Timer) < Timeout) {   // Mentre t < timeout 
        distance = Dist.getDistanceCentimeter(); // Acquisisci dati dal sensore
         if (distance>=7) { // Se la distanza e' maggiore di 7,non contare
            premuto = false;
                          }
            if ((distance<7) && premuto == false) {  // Se la distanza e'minore di 7 comincia a contare
              Contatore_PET ++;  // incrementa contatore
              Timer = millis();  // timer partito/resettato
              premuto = true;
              Serial.print("Contatore PET: ");
              Serial.println(Contatore_PET);
              Scrivi_numero_pezzi(Contatore_PET);  // Scrivi il numero di pezzi relativi al materiale PET,su SMARTCARD
                    }
          
              if (!smartcard.IsCardPresent(1))         // Verifico presenza card     <<< Modifica proposta
              Timer = millis()+millis();           // Faccio scadere il timeout      
              
              if (pulsantePremuto(PS) == true) {
              //inserire e gestire il ritorno
              }
        }
    giaPremuto=false;
  }

L'ho fatto per PET, ovviamente in PS controllerai il tasto PET. Se poi dovrai inserire altri materiali, li metterai tutti.

Ora devi gestire il ritorno volontario, e non per timeout o assenza smartcard.
Credo che tu debba inserire un'ulteriore variabile di controllo.

Allora ci sono passi avanti,ho modificato lo sketch come segue,riesco a passare da un materiale all'altro,premendo gli appositi switch,il conteggio risulta esatto ma la scrittura degli stessi su smart card no.
Se inserisco la scheda,seleziono PET e poi la estraggo oppure faccio scadere il timeout,scrive correttamente,cosi' come se seleziono PS.. Il problema si pone se per esempio da PET passo a PS,il conteggio è esatto ma i punti accumulati su smart card risultano sballati!Forse mi sfugge qualcosa?Ecco il codice modificato!

if ((VAL_CTRL1==LOW) || (VAL_CTRL2==LOW)) // simulazione errori tramite i pulsanti
      { 
       Serial.println("Attenzione!Errore!");
      } 
      else 
      {
        Serial.println ("Effettua la scelta del materiale da conferire entro 10 secondi.."); 
        // Parte il conto alla rovescia per la scelta del materiale da conferire:
         impulso_mandato = false;
         giaPremuto = false;
         stato=0;
                
          while (stato <1)
           {
            if (!smartcard.IsCardPresent(1))
                stato=1;   
                duration =millis() - startTime;
            if (duration > Timeout) 
               {   
                stato = 1;
                // Manda l'impulso solo se non l'ha già mandato prima
                  if (impulso_mandato == false)
                     {
                      Serial.println("BLOCCATO"); 
                      impulso_mandato = true;
                     }
                }
            else   
                {
                 // SCELTA PET
                 if (pulsantePremuto(PET) == true && giaPremuto == false)
                    {
                     stato = 1;
                     giaPremuto = true;
                     Serial.println("Scelta effettuata : PET");
                     apriportelloPET();
                     Contatore_PET=0;
                     contaPET();
                     }
                   
                 //SCELTA PS
                  if (pulsantePremuto(PS) == true && giaPremuto == false)
                     {
                      stato = 1;
                      giaPremuto = true;
                      Serial.println("Scelta effettuata : PS");
                      // apriportelloPS();
                      Contatore_PS=0;
                      contaPS();
                     } 
                  }
                   if (digitalRead(PET) == LOW || digitalRead(PS) ==  LOW)
                       break;
                   
            } 
         }
      } // CHIUSURA PARENTESI if ascii
      
       else
        { 
         //Se la simcard non e' riconosciuta,spegni il led
         digitalWrite(2, LOW);
         Serial.println("Simcard non valida!");
         Serial.println();
         }
      chiudiportelloPET(); // Chiude portello PET quando si estrae la scheda.
      Serial.print("Estrarre la SIMCARD,Grazie...");
      Serial.println();
      smartcard.PowerOffSC();
      //wait smartcard extraction
      while(smartcard.IsCardPresent(1)){
        delay(500);  
      }
      Serial.println("Operazione conclusa");
      Serial.println();
      
      
  } // Fine LOOP
  
 
 ///////////////////////////////////////////////////////////////////////

 
  void apriportelloPET ()  // Funzione per l'apertura del portello PET
  {
    digitalWrite (Rele_PET,HIGH); // pin 9
    Serial.print("PREGO CONFERIRE PET");
    Serial.println();
  }
      
  void chiudiportelloPET () // Funzione per la chiusura del portello PET
  {
    digitalWrite (Rele_PET,LOW); // pin 9
  }
      
 void contaPET()        // Funzione che conta i pezzi del materiale PET,rilevati dal sensore 
  {
    Timer = millis();  // Parte il timer
     while((millis() - Timer) < Timeout) // Mentre t < timeout 
     {   
        distance = Dist.getDistanceCentimeter(); // Acquisisci dati dal sensore
        if (distance>=7) // Se la distanza e' maggiore di 7,non contare
         { 
          premuto = false;
         }
        if ((distance<7) && premuto == false)  // Se la distanza e'minore di 7 comincia a contare
           {  
             Contatore_PET ++;  // incrementa contatore
             Timer = millis();  // timer partito/resettato
             premuto = true;
             Serial.print("Contatore PET: ");
             Serial.println(Contatore_PET);
             Scrivi_numero_pezzi(Contatore_PET);  // Scrivi il numero di pezzi relativi al materiale PET,su SMARTCARD
           }
          
         if (!smartcard.IsCardPresent(1))         // Verifico presenza card     <<< Modifica proposta
            Timer = millis()+millis();           // Faccio scadere il timeout      
         if (pulsantePremuto(PS) == true) 
           { //inserire e gestire il ritorno
             Serial.println("Fine conferimento PET,Selezionato PS");
             chiudiportelloPET();
             premuto = false;
             Contatore_PS=0;
             contaPS();
              
           }
      }
    giaPremuto=false;
  }
  
 /* void apriportelloPS ()  // Funzione per l'apertura del portello PS
  {
    digitalWrite (Rele_PS,HIGH); // pin 9
    Serial.print("PREGO CONFERIRE PS");
    Serial.println();
  }*
      
  
  void chiudiportelloPS ()    // Funzione per la chiusura del portello PS
  {
    digitalWrite (Rele_PS,LOW); // pin 9
    
  }
  */
   void contaPS() 
   {
     Timer = millis();  // Parte il timer
     while((millis() - Timer) < Timeout) // Mentre t < timeout 
      {   
        distance1 = Dist1.getDistanceCentimeter(); // Acquisisci dati dal sensore
        if (distance1>=7) // Se la distanza e' maggiore di 7,non contare
           { 
            premuto = false;
           }
        if ((distance1<7) && premuto == false) // Se la distanza e'minore di 7 comincia a contare
           {  
             Contatore_PS ++;  // incrementa contatore
             Timer = millis();  // timer partito/resettato
             premuto = true;
             Serial.print("Contatore PS: ");
             Serial.println(Contatore_PS);
             Scrivi_numero_pezzi(Contatore_PS);  // Scrivi il numero di pezzi relativi al materiale PS,su SMARTCARD
           }
          
         if (!smartcard.IsCardPresent(1))         // Verifico presenza card    
             Timer = millis()+millis();           // Faccio scadere il timeout   
             if (pulsantePremuto(PET) == true)
              {   // Gestione ritorno
               Serial.println ("Hai premuto PET");
               Serial.println("Fine conferimento PS,Selezionato PET");
               //chiudiportelloPS();
               premuto = false;
               apriportelloPET();
               Contatore_PET=0;
               contaPET();
              }
                 
       } 
        giaPremuto=false;
   }

Mi sono perso, dov'è che scrivi su smartcard i punti accumulati ?

Ad esempio nella void "conta_PET"
Scrivi_numero_pezzi(Contatore_PET); // Scrivi il numero di pezzi relativi al materiale PET,su

la funzione Scrivi_numero_pezzi,permette di scrivere su smartcard

Come non detto ... :wink:

Se chiami contaPET o contaPS e basta, Scrivi_numero_pezzi scrive senza problemi sulla smartcard.
Se da contaPET passi a contaPS (o viceversa), Scrivi_numero_pezzi scrive solo il conteggio del primo materiale. Giusto ?

Secondo me gestendo così si genera un probabile casino, mi spiego meglio.
Poni che io sia un utente particolarmente bastardo e che non abbia nulla da fare.
Devo inserire 100 pezzi di pet e 100 di ps, ma decido di conferire un pet e poi passare ad un ps, per tornare al pet e passare ancora al ps, e così via ...
Non so se c'è un limite massimo di nidificazioni per le function.

In effetti hai ragione,non ci avevo pensato!Forse mi converrebbe creare per ogni materiale una funzione diversa di scrittura?