Ciao a tutti, ho voluto realizzare un semplice contatore up\down con visualizzazione su lcd 16x2.
Il mio problema è il seguente, quando faccio il conteggio up parte da 0 e arriva a 100 e alla fine visualizzo cio:
CONTATORE:100
quando parte il conteggio down, non esegue 100,99,98...ecc ma, 100,990,980...ecc . (non elimina l'ultimo zero)
Sull'LCD se stampi 3 caratteri, tutti gli altri restano inalterati, quindi il consiglio di savoriano è di pulire prima di scrivere, oppure invece di stampare '99' stampi ' 99' cioè uno spazio in testa o in coda a seconda di come vuoi allineare i numeri. In testa sarebbe più naturale per l'utente. Cioè stampi sempre lo stesso numero di caratteri pulendo quelli che non ti servono.
Grazie a tutti per i consigli problema risolto!
p.s posso non utilizzare "delay(1000)" per eseguire il conteggio, per non bloccare il programma, in altro modo?
E' semplice, se non ti fai prendere dal panico, il concetto è di fare le cose solo se è passato un certo lasso di tempo dall'ultima volta.
Alla fine, una volta capito il meccanismo, risolvi con 2 righe di codice e una variabile
Credevo di averla risolta cosi, ma mi scrive solo lo "0" e stop.
Riporto il codice solo del conteggio crescente, che avviene tramite la pressione di un tasto.
Perchè il for da 0 a 100?
Chiaramente il for, al primo giro con i = 0 troverà che ((millis()-t)>dt e quindi eseguirà il contenuto, tra cui t=millis(), a i = 1, t è stato variato e quindi non sarà più vera la condizione ((millis()-t)>dt e quindi non eseguirà più nulla fino a 100.
Se vuoi stampare i 100 valori devi mettere il for dopo il test.
Poi non so cosa volevi fare con questo codice, ma in genere non serve nidificare due test diversi con millis.
if((millis())-lastDebounceTime>debounce){
e
if((millis()-t)>dt){
in genere con millis si gestiscono cose in parallelo,
quindi
#define SOGLIA_1 10000
#define SOGLIA_2 15000
void setup() {
unsigned long currMillis = millis();
unsigned long snapshot1 = currMillis;
unsigned long snapshot2 = currMillis;
}
void loop() {
unsigned long currMillis = millis();
if (currMillis - snapshot1 > SOGLIA_1) {
// Eseguo il compito con cadenza soglia1
...
snapshot1 = currMillis;
}
if (currMillis - snapshot2 > SOGLIA_2) {
// Eseguo il compito con cadenza soglia2
...
snapshot2 = currMillis;
}
}
In questo modo, i due compiti sono del tutto indipendenti tra di loro.
Io, gusto personale, preferisco salvarmi il valore di millis all'inizio del loop per testare tutto allo stesso istante.
Questo mi fa anche cadenzare le successive esecuzioni ad una distanza sempre uguale (o meglio non più vicine di quanto previsto), quindi ad es. un'operazione non la richiamo ogni 10 secondi ma distanziata di almeno 10 secondi dal termine dell'esecuzione precedente.
Per cose veloci cambia poco, per cose più lente può incidere, dipende sempre da quello che si deve fare.
Al momento prendilo come gusto personale, volevo solo spiegarti perchè ho fatto così nell'esempio.
usavo per il debounce del tasto. Mi sono accorto che nel codice ho scritto un delay(50) dopo la lettura del tasto , l'ho cancellato e sostituito con il codice sopra.
Allora ho sezionato lo sketch, utilizzando solo il conteggio up per utilizzare la funzione millis()
unsigned long t;
unsigned long dt;
int i=0;
void setup(){
t=millis();
}
void loop(){
dt=millis()-t;
if(dt>=1000){
t=millis();
lcd.setCursor(10,0);
lcd.print(i);
i++;
}
}
Ho fatto l'upload e funziona.
Adesso vorrei reintrodurre la pressione del tasto come in precedenza, per iniziare il conteggio.
Ma se riscrivo le righe di comando citate in precedenza, conteggio non parte.
Non capisco il xkè.
Come prima cosa potresti crearti una variabile booleana per dire se il conteggio è in corso o è fermo.
Poi, esternamente al codice che hai già fatto, vediamo di inserire il controllo della pressione del pulsante.
Diciamo che facciamo partire il conteggio quando il pulsante da basso va alto.
Dobbiamo iniziare con una variabile per indicare lo stato del pulsante che inizialmente sarà basso.
leggiamo il valore del pulsante con la digitalRead, se è cambiato inizializziamo il contatore per il debounce, in modo da non fare altre letture troppo ravvicinate e se passa da basso ad alto, attiviamo il contatore.
Ovviamente la digitalRead la facciamo solo se è scaduto il tempo di debounce, che se inizializziamo il riferimento a zero, finchè il pulsante non cambia stato sarà sempre scaduto facendoti leggere a raffica.
Quando il conteggio termina rimetti a false la variabile per spegnere il conteggio.
Dovrebbe bastare, se non mi sono dimenticato qualche pezzo.
#include <LiquidCrystal.h>
const int rs=12, en=11, d4=5, d5=4, d6=3, d7=2;
LiquidCrystal lcd(rs,en,d4,d5,d6,d7);
#define button1 8
bool statoButton1=LOW;
int i=0;
unsigned long lastDebounceTime=0;
unsigned long debounce=50;
unsigned long t;
unsigned long dt;
void setup() {
lcd.setCursor(0,0);
lcd.print("Contatore:");
pinMode(button1,INPUT);
t=millis();
}
void loop() {
statoButton1=digitalRead(8);
if(statoButton1==HIGH){
if((millis())-lastDebounceTime>debounce){
lastDebounceTime=millis();}
dt=millis()-t;
if(dt>=1000){
t=millis();
lcd.setCursor(10,0);
lcd.print(i);
i++;
}
}
Il problema è che il conteggio parte se tengo premuto il tasto, ma appena lo rilascio si ferma.
Io vorrei che fosse: pressione del tasto>
parte il conteggio>
rilascio il tasto>
continua il conteggio.
invece, questo if deve solo mettere a true una variabile booleana e tutto l'altro pezzo deve essere messo dentro un altro if che testi che questa variabile è a true.
Così che resti a true anche se rilasci il pulsante.
Ora, invece, se rilasci il pulsante non entra più sulla prima if
devi anche inizializzare il conteggio, cioè oltre a farlo partire devi anche inizializzarlo, es. riportarlo a 100 perchè possa di nuovo scorrere all'indietro.