while (startState == HIGH)

Ho una funzione che gestisce un programmino di un forno.
Il suo interno è strutturato:

while (startState == HIGH) {
for () {
while (
) {

Ovviamente ho necessità di uscire quando premo il pulsante start (che funziona da start/stop) ma una volta avviato il tutto non vuole saperne di leggermi il pulsante.

int temperature () {
  long timeStepMillis;                                                                //Variabile contenente la durata dello step in millisecondi
  long timeStepNow;                                                                   //Variabile contenente il tempo trascorso dall'avvio dello step-
  long timeTemperature;                                                               //Variabile di appoggio per il calcolo della formula.
  int temperatureStepDiff;                                                            //Variabile contenente la differenza di temperatura tra i due step
  long temperatureNowStep;                                                            //Temperatura da sottrarre o addizionare allo step precedente
  long temperatureNow;                                                                //Variabile della temperatura attuale in base al tempo trascorso

  if (buttonStartState == HIGH && lastStartState == startState) {
    startState = LOW;
  }

  while (startState == HIGH) {                                                       //fino a quando startState che avvia il programma è alto
    for (int control = 0; control < 6; control++) {                                   //regola "control" in modo che cicli da 0 a 4 (gli step)
      if (control == 5) {
        startState = LOW;
        break;
      }

      timeStepMillis = timeStep[control] * 60000;                                           //converte il timeStep in millisecondi
      while (timeStepStart + timeStepMillis > millis()) {                                   //ciclo fino a quando il tempo di partenza + durata Step è maggiore di millis
        if (control == 0) {
          temperatureNow = temperatureIn;
        }
        else if (control == 1) {
          timeTemperature = timeStepNow * temperatureStep[control];                         //si esegue la formula tempo trscorso per temperatura impostata (a capo)
          temperatureNow = timeTemperature / timeStepMillis;                                //diviso la durata dello step (tempo trascorso x temperatura impostata)/durata Step
        }
        else {
          if (temperatureStep[control] < temperatureStep[control - 1]) {                    //si controlla prima qual'è lo step con temperatura maggiore
            temperatureStepDiff = temperatureStep[control - 1] - temperatureStep[control];  //si calcola la differenza di temperatura tra lo step precedente e quello attuale
            timeTemperature = timeStepNow * temperatureStepDiff;                            //tempo trascorso x differenza di temperatura
            temperatureNowStep = timeTemperature / timeStepMillis;                          //calcolo del valore da sottrarre allo step precedente
            temperatureNow = temperatureStep[control - 1] - temperatureNowStep;             //sottrazione di temperatura, perché più freddo, allo step precedente
          }
          else {
            temperatureStepDiff = temperatureStep[control] - temperatureStep[control - 1];  //si calcola la differenza di temperatura tra lo step attuale e quello precedente
            timeTemperature = timeStepNow * temperatureStepDiff;                            //tempo trascorso x differenza di temperatura
            temperatureNowStep = timeTemperature / timeStepMillis;                          //calcolo del valore da addizionare allo step precedente
            temperatureNow = temperatureStep[control] - temperatureNowStep;                 //addizione di temperatura allo step precedente perché più caldo
          }
        }

        timeStepNow = millis() - timeStepStart;                                             //Calcola il tempo trascorso dall'inizio dello step
        sensors.requestTemperatures();
        temperatureIn = sensors.getTempCByIndex(0);
        if (temperatureNow - 2 < temperatureIn) {                                        //se la temperatura al momento è minore di 2 gradi
          ;                                                                              //accende la resistenza
        }
        else if (temperatureNow + 2 > temperatureIn) {                                   //se la temperatura è maggiore di 3 gradi
          ;                                                                              //spegni la resistenza
        }
        hhFloat = (timeStepNow) / 60000; //DIVIDE I MILLISECONDI TRASCORSI PER 60000 E CALCOLO I MINUTI
        hh = (int (hhFloat) / 60);
        hhINT = hh * 60;
        mm = (int (hhFloat) - hhINT); // TRASFORMO I MINUTI DA DECIMALE A SESSADECIAMALE
        if (control == 0) {
          lcd.setCursor (0, 0);
          lcd.print (" PARTENZA RIT.");
          lcd.setCursor(0, 1);
          if (hh < 10) {
            lcd.print ("  Tempo 0");
            lcd.print (hh); //L' INTERO DELLA VARIABILE "H" SONO LE ORE
          }
          else {
            lcd.print ("  Tempo ");
            lcd.print(hh); //L' INTERO DELLA VARIABILE "H" SONO LE ORE
          }
          lcd.print (":");
          if (mm < 10) {
            lcd.print ("0");
            lcd.print (mm);
          }
          else {
            lcd.print(mm);//L'INTERO DELLA VARIABILE "M" CONTIENE I MINUTI
          }
        }                                                                                  //il tempo di partenza + durata Step raggiunge millis (scade il timeStep)
        else {
          lcd.setCursor (0, 0);
          lcd.print ("STEP");
          lcd.print (control);
          if (hh < 10) {
            lcd.print (" 0");
            lcd.print (hh); //L' INTERO DELLA VARIABILE "H" SONO LE ORE
          }
          else {
            lcd.print (" ");
            lcd.print(hh); //L' INTERO DELLA VARIABILE "H" SONO LE ORE
          }
          lcd.print (":");
          if (mm < 10) {
            lcd.print ("0");
            lcd.print (mm);
          }
          else {
            lcd.print(mm);//L'INTERO DELLA VARIABILE "M" CONTIENE I MINUTI
          }
          lcd.setCursor (0, 1);
          lcd.print (char(223));
          lcd.print ("C ");
          lcd.print (temperatureIn);
          lcd.print (" di ");
          lcd.print (temperatureStep[control]);
        }
      }
      lcd.clear();
      timeStepStart = millis();                                                          //resetta il valore a millis() per calcolare lo step successivo
    }                                                                                    //fine del ciclo for
  }
  //spegni la resistenza
  counterMenu = 0;                                                                       //esce dal ciclo while, startState è basso e torna al menu 0
}

ciao…non ho guardato a fondo lo sketch ma quello che posso dirti è che se salvi in una variabile lo stato di un pin e poi metti questa variabile in un while…per poterne uscire, all’interno del while, devi mettere qualche cosa che ne possa variare il valore…altrimenti la resta…se hai un secondo while annidato nel primo…doppia attenzione.

altra cosa...nella funzione temperature() inserisci una serie di variabili locali long ed una int...quella riferita a millis() dovrebbe essere unsigned...e comunque sai che scritte così vengono create e distrutte ad ogni ciclo vero!?

ORSO2001:
altra cosa...nella funzione temperature() inserisci una serie di variabili locali long ed una int...quella riferita a millis() dovrebbe essere unsigned...e comunque sai che scritte così vengono create e distrutte ad ogni ciclo vero!?

si c'è un secondo while annidato nel primo e stavo cercando di capire se il problema fosse quello, prima del secondo while c'è un for e da lì all'ultimo esce con il break in un "if" se i == 5.
Ho provato a cambiare lo stato dall'interno del primo while, dal secondo e da fuori come quello ho postato ma lo stato non cambia, il pulsante non viene letto (provato con Serial.print).
Le variabili DEVONO essere distrutte ad ogni ciclo perché ognuno ha valori diversi presi da array; non solo: alcune di loro cambiano sempre poiché la formula che gestisce la temperatura è
"temperatura al momento = (tempo trascorso x temperatura impostata) / durata di ogni ciclo quindi è in funzione di timeStepNow (tempo trascorso) che cambia in ogni istante.

Sono d'accordo con Orso, nel ciclo White NON rileggi mai il tasto

nid69ita:
Sono d’accordo con Orso, nel ciclo White NON rileggi mai il tasto

ho provato a metterlo nel secondo while (dove resta per tutto il tempo del programma di solito 5 ore) ma non mi legge il tasto .
Ho appena provato così…niente

int temperature () {
  long timeStepMillis;                                                                //Variabile contenente la durata dello step in millisecondi
  long timeStepNow;                                                                   //Variabile contenente il tempo trascorso dall'avvio dello step-
  long timeTemperature;                                                               //Variabile di appoggio per il calcolo della formula.
  int temperatureStepDiff;                                                            //Variabile contenente la differenza di temperatura tra i due step
  long temperatureNowStep;                                                            //Temperatura da sottrarre o addizionare allo step precedente
  long temperatureNow;                                                                //Variabile della temperatura attuale in base al tempo trascorso

  while (startState == HIGH) {                                                       //fino a quando startState che avvia il programma è alto
    for (int control = 0; control < 6; control++) {                                   //regola "control" in modo che cicli da 0 a 4 (gli step)
      if (control == 5) {
        startState = LOW;
        break;
      }

      timeStepMillis = timeStep[control] * 60000;                                           //converte il timeStep in millisecondi
      while (timeStepStart + timeStepMillis > millis()) {                                   //ciclo fino a quando il tempo di partenza + durata Step è maggiore di millis
        if (buttonStartState == HIGH && lastStartState == startState) {
          startState = LOW;
        }
        if (control == 0) {
          temperatureNow = temperatureIn;
        }
        else if (control == 1) {
          timeTemperature = timeStepNow * temperatureStep[control];                         //si esegue la formula tempo trscorso per temperatura impostata (a capo)
          temperatureNow = timeTemperature / timeStepMillis;                                //diviso la durata dello step (tempo trascorso x temperatura impostata)/durata Step
        }
        else {
          if (temperatureStep[control] < temperatureStep[control - 1]) {                    //si controlla prima qual'è lo step con temperatura maggiore
            temperatureStepDiff = temperatureStep[control - 1] - temperatureStep[control];  //si calcola la differenza di temperatura tra lo step precedente e quello attuale
            timeTemperature = timeStepNow * temperatureStepDiff;                            //tempo trascorso x differenza di temperatura
            temperatureNowStep = timeTemperature / timeStepMillis;                          //calcolo del valore da sottrarre allo step precedente
            temperatureNow = temperatureStep[control - 1] - temperatureNowStep;             //sottrazione di temperatura, perché più freddo, allo step precedente
          }
          else {
            temperatureStepDiff = temperatureStep[control] - temperatureStep[control - 1];  //si calcola la differenza di temperatura tra lo step attuale e quello precedente
            timeTemperature = timeStepNow * temperatureStepDiff;                            //tempo trascorso x differenza di temperatura
            temperatureNowStep = timeTemperature / timeStepMillis;                          //calcolo del valore da addizionare allo step precedente
            temperatureNow = temperatureStep[control] - temperatureNowStep;                 //addizione di temperatura allo step precedente perché più caldo
          }
        }

        timeStepNow = millis() - timeStepStart;                                             //Calcola il tempo trascorso dall'inizio dello step
        sensors.requestTemperatures();
        temperatureIn = sensors.getTempCByIndex(0);
        if (temperatureNow - 2 < temperatureIn) {                                        //se la temperatura al momento è minore di 2 gradi
          ;                                                                              //accende la resistenza
        }
        else if (temperatureNow + 2 > temperatureIn) {                                   //se la temperatura è maggiore di 3 gradi
          ;                                                                              //spegni la resistenza
        }
        hhFloat = (timeStepNow) / 60000; //DIVIDE I MILLISECONDI TRASCORSI PER 60000 E CALCOLO I MINUTI
        hh = (int (hhFloat) / 60);
        hhINT = hh * 60;
        mm = (int (hhFloat) - hhINT); // TRASFORMO I MINUTI DA DECIMALE A SESSADECIAMALE
        if (control == 0) {
          lcd.setCursor (0, 0);
          lcd.print (" PARTENZA RIT.");
          lcd.setCursor(0, 1);
          if (hh < 10) {
            lcd.print ("  Tempo 0");
            lcd.print (hh); //L' INTERO DELLA VARIABILE "H" SONO LE ORE
          }
          else {
            lcd.print ("  Tempo ");
            lcd.print(hh); //L' INTERO DELLA VARIABILE "H" SONO LE ORE
          }
          lcd.print (":");
          if (mm < 10) {
            lcd.print ("0");
            lcd.print (mm);
          }
          else {
            lcd.print(mm);//L'INTERO DELLA VARIABILE "M" CONTIENE I MINUTI
          }
        }                                                                                  //il tempo di partenza + durata Step raggiunge millis (scade il timeStep)
        else {
          lcd.setCursor (0, 0);
          lcd.print ("STEP");
          lcd.print (control);
          if (hh < 10) {
            lcd.print (" 0");
            lcd.print (hh); //L' INTERO DELLA VARIABILE "H" SONO LE ORE
          }
          else {
            lcd.print (" ");
            lcd.print(hh); //L' INTERO DELLA VARIABILE "H" SONO LE ORE
          }
          lcd.print (":");
          if (mm < 10) {
            lcd.print ("0");
            lcd.print (mm);
          }
          else {
            lcd.print(mm);//L'INTERO DELLA VARIABILE "M" CONTIENE I MINUTI
          }
          lcd.setCursor (0, 1);
          lcd.print (char(223));
          lcd.print ("C ");
          lcd.print (temperatureIn);
          lcd.print (" di ");
          lcd.print (temperatureStep[control]);
        }
      }
      lcd.clear();
      timeStepStart = millis();                                                          //resetta il valore a millis() per calcolare lo step successivo
    }                                                                                    //fine del ciclo for
  }
  //spegni la resistenza
  counterMenu = 0;                                                                       //esce dal ciclo while, startState è basso e torna al menu 0
}

Fabio_80:
ho provato a metterlo nel secondo while (dove resta per tutto il tempo del programma di solito 5 ore) ma non mi legge il tasto

.... scusa, ma non mi sembra di vedere nessun digitalRead() ::slight_smile:

Puoi evidenziare dove lo fai ?

Guglielmo

nel loop

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#include <DallasTemperature.h>
#include <Wire.h>
#define ONE_WIRE_BUS 14
OneWire ourWire(ONE_WIRE_BUS);
DallasTemperature sensors (&ourWire);

const int buttonUpPin =  10;                    //numero pin a cui è collegato il pulsante di UP
const int buttonDownPin = 9;                    //numero pin a cui è collegato il pulsnte di DOWN
const int buttonMenuPin = 8;                    //numero pin a cui è collegato il pulsnte Menu
const int buttonStartPin = 7;                   //numero pin a cui è collegato il pulsnte Start

int buttonUpState;                              //stato attuale del pulsante di UP
long UpDebounceTime;                            //Variabilie di appoggio per calcolare il tempo di cambio di stato del pulsante di UP
long buttonUpPressedTime;                       //tempo che indica da quanto è stato premuto il pulsante
boolean buttonUpPressed;                        //memoria che indica il passaggio da LOW a HIGH del pulsante di UP
boolean repeatUp;                               //memoria che indica il repeat del pulsante attivo
long repeatUpTime;                              //tempo che indica da quanto è attivo il repeat
long lastRepeatUpTime;                          //variabile di appoggio per calcolare repeatUpTime
int addUp;                                      //fattore per incrementare la variabile

int buttonDownState;                            //stato attuale del pulsante di Down
long DownDebounceTime;                          //Variabilie di appoggio per calcolare il tempo di cambio di stato del pulsante di Down
long buttonDownPressedTime;                     //tempo che indica da quanto è stato premuto il pulsante
boolean buttonDownPressed;                      //memoria che indica il passaggio da LOW a HIGH del pulsante di Down
boolean repeatDown;                             //memoria che indica il repeat del pulsante attivo
long repeatDownTime;                            //tempo che indica da quanto è attivo il repeat
long lastRepeatDownTime;                        //variabile di appoggio per calcolare repeatDownTime
int addDown;                                    //fattore per incrementare la variabile

int buttonMenuState;                            //stato attuale del pulsante Menu
long MenuDebounceTime;                          //Variabilie di appoggio per calcolare il tempo di cambio di stato del pulsante Menu
int counterMenu = 0;                            //Valore incrementato di 1 col pulsante Menu per gestire i settaggi
int lastCounterMenu;                            //Variabile di appoggio per il contatore per un solo incremento ad ogni pressione

int buttonStartState;                           //stato attuale del pulsante Start
long startDebounceTime;                         //Variabile per l'antirimbalzo del pulsante
int startState;                                 //memorizza lo stato di start acceso o spento
int lastStartState = LOW;                       //memorizza ultimo stato quando viene rilasciato il tasto start

long debounceDelay = 100;                       //Tempo di debounce per i pulsanti
long pressedDelay;                              //variabile per determinare l' attivazione del repeat e il tempo di repeat quando è attivo
long timeRepeatEnable = 500;                    //costante che determina il tempo minimo per cui deve rimanere premuto il pulsante prima di ripetere l'operazione
long timeRepeat = 250;                          //costante che determina il tempo di ripetizione di UP e di DOWN

const int numStep = 5;
int timeStep[numStep] = {0,60,60,120,60};
int timeStepMax[numStep] = {2880,300,300,300,300};
int timeStepMin = 0;
long timeStepStart;
int temperatureStep[numStep] = {0, 148, 371, 732, 595,};
int temperatureStepMin = 0;
int temperatureStepMax = 1000;
int temperatureIn;
int counterControl;

float hhFloat;
int hh; //VARIABILE UTILIZZATA PER LE ORE
int mm; //VARIABILE UTILIZZATA PER I MINUTI
int hhINT;

void setup() {
  Serial.begin(9600);
  sensors.begin();
  lcd.begin (16, 2);

  pinMode (buttonUpPin, INPUT);                  //impostazione buttonUpPin come ingresso
  pinMode (buttonDownPin, INPUT);                //impostazione buttonDownPin come ingresso
  pinMode (buttonMenuPin, INPUT);
  pinMode (buttonStartPin, INPUT);
}

void loop() {
  int readingUp = digitalRead(buttonUpPin);
  int readingDown = digitalRead(buttonDownPin);
  int readingMenu = digitalRead(buttonMenuPin);
  int readingStart = digitalRead(buttonStartPin);

  if (readingUp == HIGH) {
    if ((millis() - UpDebounceTime) > debounceDelay) {
      buttonUpState = HIGH;
    }
  } else {
    buttonUpState = LOW;
    UpDebounceTime = millis();
  }
  if (readingDown == HIGH) {
    if ((millis() - DownDebounceTime) > debounceDelay) {
      buttonDownState = HIGH;
    }
  } else {
    buttonDownState = LOW;
    DownDebounceTime = millis();
  }
  if (readingMenu == HIGH) {
    if ((millis() - MenuDebounceTime) > debounceDelay) {
      buttonMenuState = HIGH;
    }
  } else {
    buttonMenuState = LOW;
    lastCounterMenu = counterMenu;
    MenuDebounceTime = millis();
  }
  if (buttonMenuState == HIGH && lastCounterMenu == counterMenu) {
    if (counterMenu <= 9) {
      counterMenu++;
      lcd.clear();
    } else {
      counterMenu = 0;
      lcd.clear();
    }
  }
  if (readingStart == HIGH) {
    if ((millis() - startDebounceTime) > debounceDelay) {
      buttonStartState = HIGH;
    }
  } else {
    buttonStartState = LOW;
    startDebounceTime = millis();
    lastStartState = startState;
  }

  switch (counterMenu) {
    case 0:
      sensors.requestTemperatures();
      lcd.setCursor(0, 0);
      lcd.print ("TEMPERATURA INT");
      lcd.setCursor(4, 1);
      lcd.print (char(223));
      lcd.print ("C ");
      lcd.print (sensors.getTempCByIndex(0));
      break;
    case 1:
      timeSet (0);
      printTime (0);
      break;
    case 2:
      timeSet (1);
      printTime (1);
      break;
    case 3:
      temperatureSet (1);
      printTemperature (1);
      break;
    case 4:
      timeSet (2);
      printTime (2);
      break;
    case 5:
      temperatureSet (2);
      printTemperature (2);
      break;
    case 6:
      timeSet (3);
      printTime (3);
      break;
    case 7:
      temperatureSet (3);
      printTemperature (3);
      break;
    case 8:
      timeSet (4);
      printTime (4);
      break;
    case 9:
      temperatureSet (4);
      printTemperature (4);
      break;
    case 10:
      lcd.setCursor (0, 0);
      lcd.print ("AVVIO PROGRAMMA?");
      lcd.setCursor (0, 1);
      lcd.print ("START PER AVVIO");
      if (buttonStartState == HIGH && lastStartState == startState) {
        startState = !startState;
        lcd.clear();
        timeStepStart = millis();
        counterMenu++;
      }
      break;
      case 11:
      temperature();
      break;
  }
}

Fintantoché startState == HIGH, il loop principale non viene eseguito e quindi non legge lo stato del pulsante.
Vedo un tentativo di usare una macchina a stati basata su switch case, ora secondo me dovrebbe bastare eliminare il while da dentro la funzione temperature.

Se vuoi che alcune variabili locali alla funzione temperature mantengano il loro valore puoi anteporre alla dichiarazione il termine static.

Ciao.

Maurotec:
Fintantoché startState == HIGH, il loop principale non viene eseguito e quindi non legge lo stato del pulsante.
Vedo un tentativo di usare una macchina a stati basata su switch case, ora secondo me dovrebbe bastare eliminare il while da dentro la funzione temperature.

Se vuoi che alcune variabili locali alla funzione temperature mantengano il loro valore puoi anteporre alla dichiarazione il termine static.

Ciao.

Si è a stati finiti e c’è lo switch case che fa da menu ma il tentativo è riuscito, funziona tutto solo che non riesco a stoppare. Le variabili presenti in temperature devono cambiare non sono sempre le stesse.

Fabio_80:
nel loop
...

... appunto ...

Se vuoi che un pulsante venga letto all'interno di un while, non pensi che ci dovrebbe essere una digitalRead ANCHE all'interno di quel while ? ... e se dentro c'e' un'altro while, magari pure dentro quello ? ... :wink:

Etemenanki:
… appunto …

Se vuoi che un pulsante venga letto all’interno di un while, non pensi che ci dovrebbe essere una digitalRead ANCHE all’interno di quel while ? … e se dentro c’e’ un’altro while, magari pure dentro quello ? … :wink:

provo…
Lo stesso pulsante 2 digitalread. Ti faccio sapere

Risolto, grazie!!!

while (millis() - timeStepStart < timeStepMillis) {                                   //ciclo fino a quando il tempo di partenza + durata Step è maggiore di millis
        int readingStart = digitalRead(buttonStartPin);
        if (readingStart == HIGH) {
          if ((millis() - startDebounceTime) > debounceDelay) {
            buttonStartState = HIGH;
          }
        } else {
          buttonStartState = LOW;
          startDebounceTime = millis();
          lastStartState = startState;
        }
        if (buttonStartState == HIGH && lastStartState == startState) {
          timeStepMillis = 0;
          break;
          startState = LOW;

Ho messo il digitalRead all’interno del secondo while (nel primo non veniva considerato), ho modificato leggermente la condizione del while e nell’if ho dovuto rendere false entrambe le condizioni dei 2 while più un break.
Così facendo esce come volevo, karma per te

nid69ita:
Sono d'accordo con Orso, nel ciclo White NON rileggi mai il tasto

Boh, mi pare da 6 post te lo diciamo.

nid69ita:
Boh, mi pare da 6 post te lo diciamo.

hai ragione me lo avevi detto e avevo provato ma non avevo trovato la combinazione di rendere false con la pressione del tasto entrambe le condizioni dei while e che dovevo mettere tutto questo nel secondo. Meriti il karma anche tu!

Fabio_80:
... Lo stesso pulsante 2 digitalread ...

DigitalRead e' solo un comando con cui dici al micro di leggere un'ingresso ... se vuoi o se ti serve farlo, per ogni pulsante puoi usare tutti i digitalread che vuoi nelle varie parti dello sketch, non c'e' alcun errore formale in quello ...

Nel tuo caso, dato che quando sei dentro un while, tutto quello che c'e' fuori non viene eseguito finche' ci sei dentro, se vuoi poter leggere il pulsante o un qualsiasi altro ingressoda li dentro, devi per forza mettere un'altra read dentro il while ... nonche' dentro qualsiasi altro while in cui potrebbe servirti controllare lo stato di quel pulsante o di quell'ingresso ... :wink:

Grazie di tutto, è venuto fuori un bel programmino, tutto basato su millis() senza un delay e dato che è il mio primo progetto senza il vostro aiuto non sarei andato lontano.