Scusate, da un pò di giorni cerco, leggento i vari post di capire se mi conviene o no utilizzare la funzione millis in un programma che sto scrivendo. A differenza di quanto richiesto da valvale io mi trovo nella situazione di compiere una semplice operazione (visualizzare su LCD il valore che ho in un ingresso analogico) con frequenza regolare X. Ora questa X non ho ancora capito se mi convenga calcolarla con millis o basarmi sul mio RTC. Voi cosa consigliate?
In parole povere ogni X millisecondi leggi il valore di AnalogIn 0, esegui un calcolo e sparalo a LCD.
Volevo evitare di usare delay perchè nel programma ho previsto la possibilità di interrupt (pressione pulsanti e datalogging ciclico) e mi pare di aver capito che delay bloccando il programma per X secondi possa sfalsare questi eventi. Sbaglio?
Volevo evitare di usare delay perchè nel programma ho previsto la possibilità di interrupt (pressione pulsanti e datalogging ciclico) e mi pare di aver capito che delay bloccando il programma per X secondi
non sbagli, evita il delay. Il delay(5000) dice testuali parole, "ferma tutto, ignora qualsiasi cosa succeda per 5 secondi", se prevedi di fare altre cose nel frattempo usa il millis o rtc, il millis ti permette precisione al millesimo, l'rtc al secondo anche se poi chi pilota un RTC chi è? ....... un millis. vedi tu
ciao
pablos:
se prevedi di fare altre cose nel frattempo usa il millis o rtc, il millis ti permette precisione al millesimo, l'rtc al secondo anche se poi chi pilota un RTC chi è? ....... un millis. vedi tu
ciao
Non capisco. Pensavo che il RTC funzionasse con un quarzo.
Ciao Uwe
E' vero funziona con un quarzo, ho fatto sbadatamente riferimento all'swRTC che utilizza il millis() per proseguire dopo un aggiornamento, visto che io non ho un vero e proprio RTC, intendevo comunque sottolineare che tanto vale utilizzi un riferimento derivante dal clock dell'MCU piuttosto che complicarsi la vita con l'orologio esterno
ciao
ma gli RTC danno valori in millis()? io sapevo che l'unità base è il secondo ![]()
ce ne sono di vari modelli, l'uscita ad onda quadra su alcuni e' settabile e si puo' decidere se avere una frequenza di 1Hz o piu'.
x 9six4: usa millis, e' piu' comodo che usare l'rtc. e cmq potresti usare il codice anche su altri progetti che non lo prevedono. L'orologio e' piu' indicato se devi settare un allarme ad un orario del giorno, ma per cose da fare ogni 10secondi ad esempio e' meglio millis secondo me.
domanda: ma il delay non blocca gli interrupt esterni giusto ?, quindi usando un tasto su un pin di interrupt, che va a stampare millis, anche se il loop e' in delay, il dato millis viene stampato.
OT: ecco un altro caso dove usare millisTLL
![]()
pablos:
E' vero funziona con un quarzo, ho fatto sbadatamente riferimento all'swRTC che utilizza il millis() per proseguire dopo un aggiornamento, visto che io non ho un vero e proprio RTC, intendevo comunque sottolineare che tanto vale utilizzi un riferimento derivante dal clock dell'MCU piuttosto che complicarsi la vita con l'orologio esternociao
La swRTC non usa millis. Usa un timer interno del micro per aggiornare un contatore che funziona in maniera simile a millis, ossia che viene aggiornato ogni millisecondo. Ma le similitudini finiscono qui perché poi la swRTC mantiene al suo interno un vero e proprio RTC, con registri per secondi, minuti, ore, giorni, mesi ed anni nonché una funzione per poter correggere lo scostamento dell'ora interna dall'ora reale.
lesto:
ma gli RTC danno valori in millis()? io sapevo che l'unità base è il secondo
+1
Non confondiamo le funzionalità di orologio di un RTC hardware con quelle di generatore di un segnale. Se interrogo l'RTC ricevo un tempo la cui unità di misura base è il secondo (per modelli generici tipo il DS1307 o il PCF8563): non posso leggere un tempo inferiore. Poi se attivo l'interrupt sul pin esterno posso ottenere un'onda quadra con una frequenza X, ma non ho una "misura" del tempo trascorso ma solo un segnale alto/basso.
domanda: ma il delay non blocca gli interrupt esterni giusto ?, quindi usando un tasto su un pin di interrupt, che va a stampare millis, anche se il loop e' in delay, il dato millis viene stampato.
Il dato millis non saprei ma io ad esempio do la possibilità, premendo dei pulsanti, di accedere ad un menù. Se metto il programma in "pausa" con delay succede quanto segue: quando si preme non succede nulla, ma appena termina il delay aggiorna lo stato del programma in maniera corrispondente a quante volte si è premuto il tasto. In poche parole è come se lui memorizzasse gli interrupts e li eseguisse di seguito appena terminato il delay. Il problema è che ho la necessita di visualizzare un dato a LCD e variando il dato molto rapidamente se non gli do un delay di almeno mezzo secondo, i cristalli liquidi mi sfarfallano a display, però purtroppo non posso permettermi di bloccare tutto il programma.
Avete qualche trucchetto da insegnarmi con millis per fare in modo che la visualizzazione del dato avvenga una volta al secondo e non interferisca col resto del programma?
Grazie!
uhmm la millis non dovrebbe bloccare gli interrupt. è probabile che tu abbia l'interrupt che setta da qualche parte il fatto che è scoccato, e poi il loop se ne occupa. Una soluzione è di usare al posto di delay un while con millis e una variabile, se scatta l'interrupt poni la variabile = a millis così da uscire dal loop di delay.
Secondo me stiamo entrando in polemiche inutili "tu hai detto questo" e "io ho detto quest'altro". Comunque che l'RTC usa un quarzo, che usa un millis, che usa un timer, secondo me avendone usati diversi nello stesso loop la soluzione migliore è millis().
Leo hai realizzato una nuova lib timer, non la conosco, ma potrebbe fare al caso suo?
ciao
lesto:
uhmm la millis non dovrebbe bloccare gli interrupt. è probabile che tu abbia l'interrupt che setta da qualche parte il fatto che è scoccato, e poi il loop se ne occupa. Una soluzione è di usare al posto di delay un while con millis e una variabile, se scatta l'interrupt poni la variabile = a millis così da uscire dal loop di delay.
Millis ferma appena un istante gli interrupt, il tempo necessario a leggere il valore del contatore, per evitare che una lettura effettuata durante un aggiornamento del contatore stesso porti ad un valore incongruente.
9six4:
Il dato millis non saprei ma io ad esempio do la possibilità, premendo dei pulsanti, di accedere ad un menù. Se metto il programma in "pausa" con delay succede quanto segue: quando si preme non succede nulla, ma appena termina il delay aggiorna lo stato del programma in maniera corrispondente a quante volte si è premuto il tasto. In poche parole è come se lui memorizzasse gli interrupts e li eseguisse di seguito appena terminato il delay. Il problema è che ho la necessita di visualizzare un dato a LCD e variando il dato molto rapidamente se non gli do un delay di almeno mezzo secondo, i cristalli liquidi mi sfarfallano a display, però purtroppo non posso permettermi di bloccare tutto il programma.
Avete qualche trucchetto da insegnarmi con millis per fare in modo che la visualizzazione del dato avvenga una volta al secondo e non interferisca col resto del programma?
Grazie!
Senza vedere il codice è difficile sapere come gestisci questi segnali. Dove li intercetti?
void loop()
{
letturaph(); //analogread su A0, semplice operazione e visualizzazione su LCD
readButtons(); //Legge ed interpresta la pressione dei pulsanti
navigateMenus(); //Naviga attraverso il menù
if(abilitazioneLog != 0)
{
lastSaveLoop (); //Funzione di Logging: determina l'intervallo con cui memorizzare su SD
}
} //loop()...
Questo è il mio loop. Cosi pianto tutto perchè il display inizia a sfarfallare (credo sia dovuto al lcd.clear troppo veloce) e non mi prende la pressione dei pulsanti con la giusta tempistica. Vorrei inserire la funzione letturaph dentro un ciclo che faccia si che la stampa su LCD avvenga una volta al secondo e che però, interagisca fluidamente col resto del programma.
pablos:
Secondo me stiamo entrando in polemiche inutili "tu hai detto questo" e "io ho detto quest'altro". Comunque che l'RTC usa un quarzo, che usa un millis, che usa un timer, secondo me avendone usati diversi nello stesso loop la soluzione migliore è millis().
Leo hai realizzato una nuova lib timer, non la conosco, ma potrebbe fare al caso suo?ciao
Da parte mia nessuna polemica, preferisco sempre precisare bene le cose. Sono prolisso e pedante, scusa se passo da arrogante per questo. ![]()
Considero lo spiegare bene come funziona una porzione di codice al pari di come voi più esperti di elettronica spiegate sempre con dovizia di particolari come si usa questo o quel componente. Tutto qui.
9six4:
void loop()
{
letturaph(); //analogread su A0, semplice operazione e visualizzazione su LCD
readButtons(); //Legge ed interpresta la pressione dei pulsanti
navigateMenus(); //Naviga attraverso il menù
if(abilitazioneLog != 0)
{
lastSaveLoop (); //Funzione di Logging: determina l'intervallo con cui memorizzare su SD
}
} //loop()...
Questo è il mio loop. Cosi pianto tutto perchè il display inizia a sfarfallare (credo sia dovuto al lcd.clear troppo veloce) e non mi prende la pressione dei pulsanti con la giusta tempistica. Vorrei inserire la funzione letturaph dentro un ciclo che faccia si che la stampa su LCD avvenga una volta al secondo e che però, interagisca fluidamente col resto del programma.
Questo è un estratto di 5 righe di codice ![]()
se non vediamo cosa c'e' nelle funzioni è come non postare nulla
quelli sono solo dei richiami,
in ogni caso questo pezzo (esempio) usa due timer aggiorna il display ogni secondo senza interrompere altre funzioni ed eviti lo sfarfallio e fa lampeggiare un led ogni mezzo secondo
#include <LiquidCrystal.h>
#include <swRTC.h>
swRTC rtc;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
unsigned long previousMillis_a = 0; //contatore millisecondi display
unsigned long previousMillis_b = 0; //contatore millisecondi led
long interval_a = 1000;
long interval_b = 500;
byte led = 40; // pin led
byte ledState = LOW;
void setup()
{
//delay(200); //delay to let the user opens the serial monitor
pinMode(led, OUTPUT);
rtc.stopRTC(); //stop the RTC
rtc.setTime(12,43,00); //set the time here
rtc.setDate(13,2,2012); //set the date here
rtc.startRTC(); //start the RTC
}
void loop()
{
unsigned long currentMillis_a = millis();
if(currentMillis_a - previousMillis_a > interval_a)
{
previousMillis_a = currentMillis_a;
lcd.begin(16, 2);
lcd.print("Data: ");
lcd.print(rtc.getDay(), DEC);
lcd.print("/");
lcd.print(rtc.getMonth(), DEC);
lcd.print("/");
lcd.print(rtc.getYear(), DEC);
lcd.setCursor(0, 1);
lcd.print("Ora: ");
lcd.print(rtc.getHours(), DEC);
lcd.print(":");
lcd.print(rtc.getMinutes(), DEC);
lcd.print(":");
lcd.print(rtc.getSeconds(), DEC);
}
unsigned long currentMillis_b = millis();
if(currentMillis_b - previousMillis_b > interval_b)
{
previousMillis_b = currentMillis_b;
if (ledState == LOW)
ledState = HIGH;
else
ledState = LOW;
digitalWrite(led, ledState);
}
//...
//...
// qui metti il resto delle cose che vuoi fare
//...
//..
}
ciao
Lcd.clear e' il problema.
Toglilo del tutto, lcd ha un buffer se sovrascrivi sempre tutte le posizioni non serve ripulire.
Se invece non riempi tutti i caratteri, ti serve.Lo metti in scrittura une volta al secondo. Prendi spunto da blink without delay.
Testato:
Lcd.clear e' il problema.Toglilo del tutto, lcd ha un buffer se sovrascrivi sempre tutte le posizioni non serve ripulire.
Se invece non riempi tutti i caratteri, ti serve.Lo metti in scrittura une volta al secondo. Prendi spunto da blink without delay.
Questo è vero.
Questo è un estratto di 5 righe di codice
Purtroppo mi dice che l'intero codice è troppo grande :~ Come posso fare?
Lcd.clear e' il problema.
Toglilo del tutto, lcd ha un buffer se sovrascrivi sempre tutte le posizioni non serve ripulire.
Se invece non riempi tutti i caratteri, ti serve.Lo metti in scrittura une volta al secondo. Prendi spunto da blink without delay.
Provato, il dato cambia spesso, soprattutto i centesimi, e quindi purtroppo sfarfalla lo stesso ![]()
puoi se vuoi allegare il file con l'opzione Additional Options... sotto il box del reply
Fatto, spero vada. Se avete voglia di darci una letta mi farebbero molto piacere suggerimenti, non sono un gran programmatore, anzi, diciamo che mi limito a fare dei collage ![]()
inlavorazione.ino (20 KB)