Problema con ciclo ripetuto

Salve ragazzi ho un problema con la ciclica di un programma che serve per una piattaforma.Mi spiego: questa piattaforma si alza e si abbassa comandata da tasti di salita e discesa, una volta che le condizioni sono vere posso tramite i comandi case azionare delle uscite.Ecco il problema....quando premo discesa e la condizione è favorevole la piattaforma dovrebbe prima alzarsi per un secondo e poi abbassarsi.Cosa avviene: se premo discesa e tengo premuto la ciclica fa si che la piattaforma si alza per un secondo e poi si abbassa ..per poi tornare ad alzarsi e poi abbassarsi...
Insomma se mi sono spiegato io una volta premuto discesa dovrei vedere la piattaforma alzarsi per un secondo per poi continuare ad abbassarsi fino a che ho il tasto premuto...invece il ciclo viene continuamente ripetuto.

Non è possibile darti risposte senza vedere il codice!

Potresti aiutarvi a trovare l'errore postandonil codice che utilizzi.
Comunque, senza conoscerlo, ti consiglio di utilizzare una macchina a stati:

Es:

Il pulsante NON é premuto
{
Rendo stato=0
}
Il pulsante é premuto
{
Lo stato é 0
{
Alzo 1 
Stato=1
}
Stato é 1
{
Abbasso
}}

Tutto questo condito con un antirimbalzo del pulsante.

ais26:
Insomma se mi sono spiegato io una volta premuto discesa dovrei vedere la piattaforma alzarsi per un secondo per poi continuare ad abbassarsi fino a che ho il tasto premuto…invece il ciclo viene continuamente ripetuto.

La maggior parte di questi problemi si risolvono disegnando un diagramma di flusso su un foglio di carta e seguendolo col dito (sono cose che una volta si facevano ben prima di iniziare a scrivere qualche riga di codice)… Evidentemente vai a ricontrollare la condizione prima di aver terminato la discesa e rilasciato il pulsante, ovvero la logica attuale non contempla tutte le possibili diverse situazioni in cui ti puoi trovare: rilasciato e fermo → premuto e in movimento → premuto e arrivato → rilasciato e fermo. Solo al riconoscimento del rilascio deve ritornare “attiva” la possibilità di riconoscere una nuova pressione.

Grazie ragazzi per l'interessamento, allego codice il case interessato è quello della discesa

int condizione = 0;
 bool ftcrit;
 
long interval = 2000; 
unsigned long currentMillis = millis();  


void setup() {
  pinMode ( 2, INPUT_PULLUP ); //Pulsante salita P1
  pinMode ( 3, INPUT_PULLUP ); //Pulsante stazionamento P2
  pinMode ( 4, INPUT_PULLUP ); //Pulsante sblocco P3
  pinMode (5, INPUT_PULLUP ) ; // Pulsante discesa P4
  pinMode (6, INPUT_PULLUP );// fotocellula FTC1 no
  pinMode (7, INPUT_PULLUP ); // finecorsa paratia sx FCP1
  pinMode (8, INPUT_PULLUP ); // finecorsa paratia dx FCP2
  pinMode (9, INPUT_PULLUP ); // finecorsa rifasamento sx FCR1
  pinMode (10, INPUT_PULLUP ); // finecorsa rifasamento dx FCR2
   pinMode (11, INPUT_PULLUP ); // pressostato alto PR1
   
  pinMode (14, OUTPUT ); // teleruttore salita K1
  pinMode (15, OUTPUT ); // ev aria EV2
   pinMode (16, OUTPUT ); // ev olio discesa EV3
    pinMode (17, OUTPUT ); // ev rifasamento EV4
     pinMode (18, OUTPUT ); // spia anomalia
     
digitalWrite(14, HIGH );// teleruttore salita K1
digitalWrite(15,HIGH);// ev aria EV2
digitalWrite(16, HIGH );// ev olio discesa EV3
digitalWrite(17,HIGH);// ev rifasamento EV4
digitalWrite(18,HIGH);// spia anomalia
Serial.begin(9600);
  
}

void loop() {

  int salita = digitalRead (2);
int rifasamento = digitalRead(3);
int sblocco= digitalRead(4);
int discesa= digitalRead (5);
int ftc= digitalRead (6);
int paratiaSx = digitalRead(7);
int paratiaDx = digitalRead(8);
int rifasamentoSx = digitalRead(9);
int rifasamentoDx = digitalRead(10);
int pressostato = digitalRead(11);

//delay (100);}
//if (discesa==LOW){Serial.println("discesa");
//delay (100);}
//if (paratiaSx==LOW){Serial.println("paratiaSX");
//delay (100);}
//if (paratiaDx==LOW){Serial.println("patatiaDX");
//delay (100);}
//if (pressostato==LOW){Serial.println("pressostato");
//delay (100);}
//if (ftc==LOW){Serial.println("ftc");
//delay (100);}
  
  // codice allarmi

if (ftc==HIGH){
  digitalWrite(18, LOW);// spia anomalia   
delay(200);
digitalWrite(18, HIGH); // spia anomalia
//Serial.println("case4");
delay(200);
}

if ((paratiaSx==HIGH)||(paratiaDx==HIGH)){
  digitalWrite(18, LOW);// spia anomalia   
delay(1000);
digitalWrite(18, HIGH); // spia anomalia
//Serial.println("case4");
delay(1000);
}

 // codice salita


//if((salita=LOW)  &&  (ftc==LOW)){
  //( millis() - currentMillis >= interval)
  //ftcrit = LOW;}
  //else{
 //ftcrit = HIGH;
// }
if (( salita == LOW  )&& (discesa == HIGH)&&  (paratiaSx == LOW) && (paratiaDx == LOW) && (pressostato == LOW) && (ftc == LOW )){

    delay (100);
 condizione=1;
 
    }


    
//codice discesa


  if (( discesa == LOW  )&&( salita == HIGH  )&& (paratiaSx == LOW) && (paratiaDx == LOW)&&(rifasamentoSx==HIGH)&&(rifasamentoDx==HIGH)&& (ftc == LOW ))
  {
    delay (200);
   condizione=2;
  }
  

//codice stazionamento(SBLOCCO)
  if (sblocco == LOW)  
 {
   delay (200);
 condizione=3;
    }

// codice sfasamento ALLARME

//if ((paratiaSx == HIGH) || (paratiaDx == HIGH)){
//delay(200);
  //condizione=4;
// }


   
  switch(condizione){
  
  case 1: //salita
 digitalWrite(14, LOW );// teleruttore salita K1
  interval = 0;
digitalWrite(15,LOW);// ev aria EV2
digitalWrite(16, HIGH );// ev olio discesa EV3
digitalWrite(17,LOW);// ev rifasamento EV4
digitalWrite(18,HIGH);// spia anomalia
//Serial.println("case1");
 
  
 delay (50);

 condizione = 0;
break;

 case 2: //DISCESA
 
 digitalWrite(14, LOW );// teleruttore salita K1
 delay(1000);
digitalWrite(14, HIGH );// teleruttore salita K1
delay(500);
digitalWrite(15,LOW);// ev aria EV2
delay(1000);// ritardo intervento valvola di discesa
digitalWrite(16, LOW );// ev olio discesa EV3
digitalWrite(17,HIGH);// ev rifasamento EV4
digitalWrite(18,HIGH);// spia anomalia
//while(discesa==HIGH);

delay (500);
condizione=0;
break;

case 3: //SBLOCCO
digitalWrite(14, HIGH );// teleruttore salita K1
digitalWrite(15,LOW);// ev aria EV2
digitalWrite(16, HIGH );// ev olio discesa EV3
digitalWrite(17,HIGH);// ev rifasamento EV4
digitalWrite(18,LOW);// spia anomalia
//Serial.println("case3");
//delay (50);
// condizione=0;
break;

case 4: //ANOMALIA
digitalWrite(18, LOW);// spia anomalia   
delay(1000);
digitalWrite(18, HIGH); // spia anomalia
//Serial.println("case4");
delay(1000);
condizione=0;
break;

case 0:
digitalWrite(14, HIGH );// teleruttore salita K1
digitalWrite(15,HIGH);// ev aria EV2
digitalWrite(16, HIGH );// ev olio discesa EV3
digitalWrite(17,HIGH);// ev rifasamento EV4
digitalWrite(18,HIGH);// spia anomalia
//Serial.println("case0");
delay (50);

break;
  }
}

La logica del programma è impostata male, quando ti trovi nello switch() il codice di ogni case, viene eseguito molto rapidamente, premi il pulsante in frazioni di secondo ti ritrovi al case zero. Per cui passa in frazioni di secondo da fare una cosa a farne un altra. Passa a case zero condizione=0, poi trova il pulsante ancora premuto e condizione torna a condizione=2, per cui ripete fino a quando hai il pulsante premuto.
Adesso non riesco a comprendere bene il tuo codice, però penso che invece di correggerlo sia meglio pensare a soluzioni diverse.

torn24 hai pienamente centrato il problema, che tipo di ciclica dovrei usare secondo te?

Dovresti ripensare al programma :slight_smile: :slight_smile:

Una soluzione che mi viene in mente, forse ci sono soluzioni migliori ma a me viene in mente questo :slight_smile:
Ma aspetta, magari qualcuno ha altre soluzioni...

Esempio:
Uso una variabile stato

  1. Premo il pulsante e stato vale 1 stato=1
    2)Se stato vale uno mi sollevo per un secondo
  2. entro in un while(stato==1) che abbassa, nel while leggo continuamente il pulsante
    4)Se il pulsante è rilasciato stato=0 e il ciclo termina.

Nel suo caso, avendo creato una logica mista sia a "stati" (la variabile 'condizione') che procedurale bloccante (con i delay nei singoli case), non parlerei di ciclo di loop veloce (come minimo quel case dura tre secondi).
Banalmente basta attendere il rilascio del pulsante, come già aveva tentato di fare con:
//while(discesa==HIGH);... solo che così si confronta una variabile, non il vero ingresso.

E poi il codice va indentato.

Invece di usare dei case, perche' non usi semplicemente una serie di if con condizioni multiple ?

Cosi potresti fare ad esempio ... usi una flag (qualsiasi variabile byte) associata al pulsante ... se in un ciclo del loop vedi che il pulsante e' premuto, ma la flag non e' ad 1, significa che l'hai appena premuto, metti la flag ad 1 ed inizi a fare quello che devi (alzare un secondo, poi abbassare, o qualsiasi altra cosa tu voglia, facendo ovviamente le temporizzazioni con millis e non con delay, in modo da non bloccare la lettura dei pulsanti), se poi nei successivi cicli del loop il pulsante e' premuto ma la flag e' ad 1, sai che il pulsante era gia premuto da prima, quindi non ripeti le operazioni dall'inizio, ma continui con la tua sequenza, controllando solo che nel frattempo il pulsante non venga rilasciato ... nel momento in cui il pulsante viene rilasciato, interrompi e rimetti la flag a 0, cosi puoi rilevare correttamente la prossima nuova pressione del pulsante ... e cosi via ...

Grazie per i suggerimenti. Farò le opportune modifiche.