Meinem TonUINO-Aufbau habe ich ein 4x20 I2C LC-Display spendiert.
Dieses soll im Einschaltmoment (=Strom anschließen) für x Sekunden eine Art Willkommenstext anzeigen. Anschließend sollen alle Zeichen verschwinden und die Hintergrundbeleuchtung abgeschaltet werden.
Erst mit Vorhalten einer neuen/bekannten RFID-Karte soll es erneut erleuchten. Wieder für x Sekunden, ehe es wieder gelöscht und seine Hintergrundbeleuchtung abgeschaltet wird.
Nun hab ich es mit dem Interrupt Timer1 versucht und obwohl der Interrupt sekündlich ausgelöst wird, funktioniert das Löschen und Abschalten nicht.
Bisher komm ich nicht dahinter, was ich an den wenigen Zeilen Code wohl verkehrt gemacht habe und erbitte daher Hilfe
Vielen Dank!!
Hier meine Interrupt Service Routine:
//Interrupt service routine of timer1
ISR(TIMER1_OVF_vect) {
TCNT1 = 3036;
if (timer_10sec >= lcd_timeout) {
//Clear LCD and turn of its backlight
lcd.clear();
lcd.noBacklight();
timer_10sec = 1;
}
else
{
timer_10sec++;
}
}
Für den gesamten Programm-Code habe ich die Timer1-relevanten Variablen wie folgt angelegt:
Hm, das hat leider nicht genügt. Weder nach Programmstart, noch nach Auflegen einer RFID-Karte erlischt das Display.
„Schlimmer“ noch: Nach exakt 10 Sekunden geht auf dem Arduino-Board die rote L-LED aus und mein TonUINO reagiert auf keine neuen Karten. Es scheint als würde sich der Arduino aufhängen…
Implementiere das ganze doch mal ohne Timer und ISR. Sprich ne Funktion die du im Loop kontinuierlich aufrufst und die dann mit millis() merken und Differenz ausrechen guckt ob 10s um sind. ISRs haben sehr viele Eigenheiten die normale Funktionen nicht haben. Vielleicht läufst du da in irgend eine Falle.
i2c ist nicht gerade das schnellste protokoll. wenn du das in der isr machst, blockierst du dir damit den ganzen controller während der ausführung. eigentlich setzt man in der isr nur statusvariablen und macht die zeitfressenden sachen (z.b. displayansteuerung) dann in der mainloop.
ISRs are special kinds of functions that have some unique limitations most other functions do not have. An ISR cannot have any parameters, and they shouldn’t return anything.
Generally, an ISR should be as short and fast as possible. If your sketch uses multiple ISRs, only one can run at a time, other interrupts will be executed after the current one finishes in an order that depends on the priority they have. millis() relies on interrupts to count, so it will never increment inside an ISR. Since delay() requires interrupts to work, it will not work if called inside an ISR. micros() works initially but will start behaving erratically after 1-2 ms. delayMicroseconds() does not use any counter, so it will work as normal.
Typically global variables are used to pass data between an ISR and the main program. To make sure variables shared between an ISR and the main program are updated correctly, declare them as volatile .
Tatsächlich hatte ich in der ISR zunächst keine direkte Ansteuerung des I2C-Displays, sondern nur eine Status-Boolean gesetzt und die Auswertung in der Main-Loop vorgenommen. Leider ohne Erfolg, weil die If-Abfrage in der ISR einfach nicht so funktionieren wollte, wie ich es benötige. Der oben angeführte Code war mein letzter Stand.
Ich bin letztlich dem Ratschlag millis() einzusetzen gefolgt und nun funktioniert alles wie gewünscht. Danke.
nur durch nutzung von millis() statt der isr / delay kann es ja nicht auf einmal funktionieren. da muss dann ja schon irgendwo ein anderer logikfehler gewesen sein.
der timer overflow kam auch wirklich jedes mal? woher weißt du das? ich toggle da dann immer gern einen pin und hänge mein oszi dran. dann hab ich auch gleich die frequenz.
Hallo,
ich nutze folgenden Abschaltmechanismus:
zu Beginn führe ich eine Variable zum Zeitspeichern ein:
unsigned long timestore; // Variable Speicher für Systemzeit.
nach jedem Oled.print (oder sonsiger Display ausgabe) wird die aktuelle Zeit gespeichert
timestore = millis(); //Die aktuelle Systemzeit wird in den TimeStore gebracht
Ganz am Ende in der voidloop prüfe ich, ob seit dem letzten Speichern (also auch Anzeigen auf dem Display) schon X millisekunden vergangen sind. Falls ja, cleare ich das display.
void loop() {
do {
//Display
if (millis() - timestore> 3000) // ...wenn die aktuelle Zeit minus die Gespeicherte Zeit > 3 sek sind...
{
oled.clear(); // wird display gecleared
}
//Display Ende