Timer ohne Überlauf
Arduino-Bastelprojekt: Lange Laufzeiten mit millis() ohne Überlauf-Probleme.
Bei Arduino-Projekten wird oft millis() für zeitgesteuerte Aktionen genutzt. Nach etwa 49 Tagen läuft der 32-Bit-Zähler über – eine naive Abfrage wie if (millis() - lastTime > interval) kann dann fehlschlagen. Diese Timer-Klasse umgeht das Problem, indem sie die vergangene Zeit kumuliert statt mit dem aktuellen millis()-Wert zu vergleichen.
Materialien
- Arduino (beliebig)
- Keine zusätzliche Hardware nötig – reine Software-Bibliothek
Verwendung
Timer updateLCD(1 * TIMER_SECONDS); // alle 1 Sekunde
Timer storeValue(15 * TIMER_SECONDS); // alle 15 Sekunden
void loop() {
if (updateLCD.check()) {
// wird jede Sekunde ausgeführt
}
if (storeValue.check()) {
// wird alle 15 Sekunden ausgeführt
}
}
Der Trick: Statt ul_PreviousMillis = millis() wird ul_PreviousMillis += ul_Interval gesetzt. So bleibt die Zeitlogik auch nach einem Überlauf von millis() korrekt. Optional kann der Timer aus dem EEPROM geladen und gespeichert werden – nützlich für Geräte, die über lange Zeit laufen.
#include "./Timer.h" // initiate Timer::Timer(){ // just create object setInterval(0); } Timer::Timer(void* ee){ // load value from eeprom (4 bytes) int ee_int = (int)ee; ee_addr = (ee_int>=0 && ee_int<EEPROM.length()) ? ee_int : -1; unsigned long value = 0; if(ee_addr>=0) EEPROM_readAnything(ee_addr, value); setInterval(value); } Timer::Timer(unsigned long value){ // set value setInterval(value); } void Timer::setInterval(unsigned long value){ ul_Interval = value; if(ee_addr>=0) EEPROM_writeAnything(ee_addr, ul_Interval); } unsigned long Timer::getInterval(void){ return ul_Interval; } boolean Timer::check(){ if(millis()-ul_PreviousMillis <= ul_Interval) return false; ul_PreviousMillis += ul_Interval; return true; }
#ifndef TIMER_H #define TIMER_H #include "Arduino.h" #include <EEPROM.h> // required for EEPROMAnything.h #include "./EEPROMAnything.h" #define TIMER_SECONDS 1000 #define TIMER_MINUTES TIMER_SECONDS*60 #define TIMER_HOURS TIMER_MINUTES*60 class Timer{ public: Timer(void); // just create object Timer(void* ee); // load timer from eeprom addr. Timer(unsigned long value); // initiate and set value (without eeprom) void setInterval(unsigned long value); // in Milliseconds unsigned long getInterval(void); // in Milliseconds boolean check(void); // TODO: void restart(void); // TODO: void pause(void); // TODO: void continue(void); // TODO: unsigned long remaining(void); // in Milliseconds private: unsigned long ul_PreviousMillis; unsigned long ul_Interval; int ee_addr = -1; }; #endif
Weitere Artikel
Gefällt dir die Webseite? Unterstütz die werbefreie Seite mit einer Spende.





Kommentare