LelloGi:
Il dubbio che il while non funziona nel Setup è venuto anche a me.
Aspetta, non ho detto che un while() nella setup() non funzioni, è che “in genere” nella setup() non servono dei while() perché i cicli li gestisci nel loop().
Lo sketch che ho in mente di fare deve eseguire due cose:
Per primo devo modificare la variabile “correttore” incrementandola o diminuendola all’inizio del mio programma.
Se non premo tasti, dopo 10 secondi vado a eseguire il programma principale.
Nel “Loop” invece testo una funzione che mi spegne il display del LCD dopo 15 secondi.
Se voglio fare riaccendere il display per altri 15 secondi, premo il tasto “statoSu”.
Ok, ora riesco a capire meglio. Vorrei però, più che farti piccole correzioni al codice o ai collegamenti (ad esempio il debounce che ha citato poco fa fabpolli), darti qualche indicazione generale che penso ti possano essere utili non solo ora ma anche nel futuro.
Quindi, oltre a consigliarti caldamente di indentare sempre il codice (per info vedi il regolamento del forum, punto 17.2) ci sono anche altre cose che ti conviene applicare e mantenere, come le costanti da distinguere con nomi tutti in maiuscolo, affiancare le parentesi al nome della funzione, eccetera.
Poi quando ti accorgi che un programma non è “lineare”, ossia c’è una specifica sequenza di comportamenti, conviene pensarlo come una cosiddetta “macchina a stati finiti”, concetto che ti consiglio di apprendere ed approfondire un poco perché in questo campo (ossia microcontrollori) ti sarà sicuramente utile non solo per evitare di “perderti” nei meandri delle condzizioni, ma anche per impostare correttamente alcune cose, e creare programmi molto più “flessibili” per eventuali future modifiche. E’ diciamo una forma mentale, più che un metodo di implementazione, perché puoi realizzarla in più modi.
Per fare un “micro-bignamino” delle macchine a stati finiti, puoi iniziare elencando gli stati e per ognuno di questi le condizioni che, se verificate (quindi con delle condizioni “se”) fanno “qualcosa” ed a quale stato passare (con un “allora”) che può anche essere lo stesso. Ossia uno schema analogo alle “if”:
Se (condizione) allora (azione) e vai allo stato (stato)
Una o più di queste parti possono essere omesse.
Quindi nel tuo caso direi che, ad esempio, hai una macchina a stati finiti descrivibile così:
Stati: INIZIO, VALORI e RUN
Stato iniziale: INIZIO
INIZIO:
(attiva timer, accendi display) e vai allo stato (VALORI)
VALORI:
Se (il timer è >= 10 secondi) allora (ripristina timer) e vai allo stato (RUN)
Se (il tasto Su è premuto) allora (incrementa valore, ripristina timer) e vai allo stato (VALORI)
Se (il tasto Giù è premuto) allora (decrementavalore, ripristina timer) e vai allo stato (VALORI)
RUN:
Se (il timer è >= 15 secondi e lo schermo è acceso) allora (spegni display) e vai allo stato (RUN)
Se (il tasto Su è premuto) allora (accendi display, ripristina timer) e vai allo stato (RUN)
Lo stato INIZIO puoi implementarlo nella setup() visto che è solo una inizializzazione, poi il resto lo gestisci nel loop(), ad esempio uno schemino generico potrebbe essere questo, vedi come ti ho riconfigurato tutto lo sketch:
#include <PCF8574_HD44780_I2C.h>
// Definizione dei pin
#define P_SU 7 // pulsante Su
#define P_GIU 6 // pulsante Giu
// Stati: INIZIO, VALORI e RUN
#define S_INIZIO 0
#define S_VALORI 1
#define S_RUN 2
byte stato;
// Flag che indica se lo schermo è spento
bool schermo = false;
// Variabili globali
int statosu = 0;
int statogiu = 0;
int correttore = 2500;
unsigned long tmr = 0;
byte stato = 0;
PCF8574_HD44780_I2C lcd(0x27, 16, 2);
void setup() {
pinMode(P_SU, INPUT);
pinMode(P_GIU, INPUT);
lcd.init();
Serial.begin(9600);
// Stato iniziale: INIZIO
stato = S_INIZIO;
// Per debug:
Serial.println("INIZIO");
}
void loop() {
// Gestione degli stati
switch (stato) {
case S_INIZIO: // INIZIO:
// (attiva timer, accendi display) e vai allo stato (VALORI)
tmr = millis();
lcd.setBacklight(1);
schermo = true;
mostraCorr();
stato = S_VALORI;
// Per debug:
Serial.println("VALORI");
break;
case S_VALORI: // VALORI:
// Se (il timer è >= 10 secondi) allora (ripristina timer) e vai allo stato (RUN)
if ( millis() - tmr >= 10000 ) {
tmr = millis();
stato = S_RUN;
// Per debug:
Serial.println("RUN");
break;
}
// Se (il tasto Su è premuto) allora (incrementa valore, ripristina timer) e vai allo stato (VALORI)
if ( digitalRead(P_SU) ) {
correttore = correttore + 100; // aumenta di 100
mostraCorr();
debounce();
// Per debug:
Serial.println(correttore);
break;
}
// Se (il tasto Giù è premuto) allora (decrementavalore, ripristina timer) e vai allo stato (VALORI)
if ( digitalRead(P_GIU) ) {
correttore = correttore - 100; // diminuisci di 100
mostraCorr();
debounce();
// Per debug:
Serial.println(correttore);
break;
}
case S_RUN: // RUN:
// Se (il timer è >= 15 secondi e lo schermo è acceso) allora (spegni display)
if ( millis() - tmr >= 15000 && schermo ) {
lcd.setBacklight(0);
schermo = false;
// Per debug:
Serial.println("Spengo lo schermo");
}
// Se (il tasto Su è premuto) allora (accendi display, ripristina timer)
if ( digitalRead(P_SU) ) {
lcd.setBacklight(1);
schermo = true;
tmr = millis();
debounce();
// Per debug:
Serial.println("ACCENDO lo schermo");
break;
}
}
}
void debounce() {
// Un minimo di debounce e ritardo, per evitare di far
// "correre" il valore (da rivedere in seguito...)
delay(500);
}
void mostracorr() {
lcd.setCursor(0, 0);
lcd.print("Corr.: ");
lcd.setCursor(0, 7);
lcd.print(correttore);
}
PS: il codice NON l’ho provato, sia perché non ho quella libreria, sia perché è meglio se verifichi tu (so già che qualche errore c’è…), così fai anche pratica a fare debug… 