Forum: Mikrocontroller und Digitale Elektronik Arduino WDT Counter zurücksetzen


von Robin H. (robin_h)


Lesenswert?

Hallo zusammen,

ich arbeite derzeit mit dem Yakindu Statechart Tool und soll ein 
Programm auf einem Arduino umsetzen.

Innerhalb des Programms soll ich den WDT nutzen um alle X Sekunden ein 
Interrupt auszulösen, solange keine andere Transition innerhalb des 
Statecharts aktiviert wird.

Dabei habe ich folgendes Problem:

Wenn Event XY kommt rufe ich eine Funktion auf reset_WDT(). Innerhalb 
dieser Funktion möchte ich nur den Wert innerhalb des WDTs zurücksetzen. 
Er soll ganz normal weiterlaufen.
Also:
1. Funktion wird aufgerufen
2. WDT wird angehalten
3. WDT wird zurückgesetzt
4. WDT wieder im Interrupt Mode mit einer Zeit von 8s starten

Der Code sieht derzeit so aus:
1
 
2
#include "Arduino.h"
3
#include <avr/wdt.h>
4
5
void resetWatchdog(){
6
  WDTCSR |= (1<<WDCE) | (1<<WDE); // Configuration Mode
7
  WDTCSR = (0<<WDIE)
8
        | (0<<WDE)    // Stop WDT
9
        | (1<<WDP3)
10
        | (0<<WDP2)
11
        | (0<<WDP1)
12
        | (1<<WDP0);  // Einstellung der Zeit sind hier egal
13
  
14
   wdt_reset(); // Reset des WDT?
15
   
16
   WDTCSR |= (1<<WDCE) | (1<<WDE); // Configuration Mode
17
   WDTCSR = (1<<WDIE)
18
        | (0<<WDE)    // Interrupt Mode (WDIE = 1, WDE = 0)
19
        | (1<<WDP3)
20
        | (0<<WDP2)
21
        | (0<<WDP1)
22
        | (1<<WDP0);  // Interrupt every 8 seconds*/
23
}

Das funktioniert leider nicht...
Gibt es eine Möglichkeit den Wert innerhalb des WDT Registers zu 
manipulieren/ändern? Oder generell auszulesen? Ich habe in der Register 
Summary des Atmegas 328p auch kein Register gefunden, in dem der Wert 
gespeichert wird (muss er aber ja irgendwo...)... Ich habe das nur für 
die normalen Timer gefunden.

Hat einer eine Idee?

Viele Grüße,
Robin

von Forist (Gast)


Lesenswert?

Robin H. schrieb:
> (muss er aber ja irgendwo...)

Schon mal was von nachtriggerbarem Monoflop gehört?

Stell dir vor, soetwas kann ohne einen Controller und Großrechner 
funktionieren - so einfach mit Widerstand und Kondensator, RC-Glied 
eben.

... aber nicht im ATmega.
Die genaue Beschreibung dafür mit Code Beispielen steht auf sieben 
Seiten im Datenblatt in den Abschnitten 11.8 Watchdog Timer und 11.9 
Register Description.

von Robin H. (robin_h)


Lesenswert?

Hallo Forist

Forist schrieb:
> Seiten im Datenblatt in den Abschnitten 11.8 Watchdog Timer und 11.9
> Register Description.

Die habe ich mir auch schon durchgelesen, nur leider findet man dort nur 
zwei Register beschrieben:
11.9.1 MCUSR – MCU Status Register
11.9.2 WDTCSR – Watchdog Timer Control Register

Mehr nicht, daher habe ich in der Register Summary (Kapitel 36) 
nachgeschaut. Auch hier taucht, bis auf die beiden genannten Register 
keines auf, in dem der tatsächliche Timer Wert gespeichert wird.

Das auslösen des Interrupts nach 8s funktioniert. Nach dem Verlassen der 
ISR startet der  WDT von vorn. Mein Problem ist, dass ich den WDT 
stoppen und den Counter auf 0 zurücksetzen will. Dafür ist leider kein 
Code Beispiel vorhanden.

Mit dem Register aus 11.9.1 kann ich mir nur anzeigen lassen, welcher 
Interrupt ausgelöst worden ist und mit dem WDTCSR kann ich nur den 
Prescaler einstellen und festlegen, wie sich der WDT bei einem Überlauf 
verhalten soll.

Das bringt mir (glaube ich) nichts für mein beschriebenes Problem.

Hat sonst noch wer eine Idee, oder schon mal ein ähnliches Problem 
gehabt?
Alternativ würde ich einfach einen normalen Timer nutzen...

Viele Grüße,
Robin

von Karl M. (Gast)


Lesenswert?

Hallo,

du meinst sicherlich anstatt "X Sekunden ein Interrupt ", alle "X 
Sekunden ein Event".
Die Interruptfrequenz wird entprechend der kleinsten Auflösung per 
Software "verlängert".

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Robin H. schrieb:
> Das auslösen des Interrupts nach 8s funktioniert. Nach dem Verlassen der
> ISR startet der  WDT von vorn. Mein Problem ist, dass ich den WDT
> stoppen und den Counter auf 0 zurücksetzen will. Dafür ist leider kein
> Code Beispiel vorhanden.

 Von welchem Counter redest du überhaupt ?
 Mit wdr oder wdt_reset() geht der WD-Counter auf Null.

 WDT kann man auch jederzeit stoppen.
 Eine andere WDT-Zeit kann man auch ohne Probleme einschreiben.

 Wo ist dein Problem ?

von Hanswurst (Gast)


Lesenswert?

@ Robin

Wenn ich Dein Problem recht verstehe, dann ist es völlig hinreichend, 
den Watchdog mit der WDR-Maschinenanweisung zurückzusetzen. Es nicht 
notwendig den Zähler anzuhalten.

Reicht Dir das als Hilfe? Falls nicht, wäre ich interessiert zu 
erfahren, was Dich annehmen lässt, Du müsstest den Zähler anhalten. Auch 
würde mich die genaue Aufgabenformulierung interessieren.

von Robin H. (robin_h)


Lesenswert?

Hallo Hanswurst,

ich habe den Fehler gefunden.
Ja der reset Befehl ist ausreichend. Das Problem war, dass die Funktion 
gar nicht aufgerufen worden ist und dadurch der Reset nicht ausgeführt 
worden ist.

Zu der Aufgabenstellung: Ich soll einen Tresor auf einem Arduino Uno 
mithilfe des Yakindu Statechart Tools umsetzen.

Das Problem war, dass ich ein halbfertiges Modell bekommen habe und das 
Erweitern sollte. Der State, in dem die Funktion aufgerufen werden 
sollte, war schon vorgegeben. An der Stelle gab es in dem Modell aber 
noch einen Fehler. Den habe ich jetzt nach ca. 3 Stunden gefunden...

Ich hatte nur in einem eigenem kleinen Programm den WDT getestet und mir 
die Interrupts im Serial Monitor anzeigen lassen. Die Funktion mit dem 
Reset habe ich dort nicht getestet. Hätte mir wahrscheinlich einiges an 
Zeit gespart.. Naja... Was solls...

Entschuldigung für die Verwirrung an der Stelle. Bin davon ausgegangen, 
dass der fertige Teil des Modells funktioniert.

Viele Grüße,
Robin

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Robin H. schrieb:
> Gibt es eine Möglichkeit den Wert innerhalb des WDT Registers zu
> manipulieren/ändern? Oder generell auszulesen? Ich habe in der Register
> Summary des Atmegas 328p auch kein Register gefunden, in dem der Wert
> gespeichert wird (muss er aber ja irgendwo...)...

 Nein, gibt es nicht weil ganz einfach kein WDT Register in dem
 Sinne vorhanden ist.

 128KHz Takt geht auf den WDT-Prescaler dessen Wert durch WDP0-WDP3
 bestimmt wird.
 Wenn der voreingestellte Wert erreicht ist, wird ganz einfach ein
 Impuls ausgelöst der WDT-ISR oder RESET auslöst.

 WDP0-WDP3 = 1001 = 1024*1024 = 1,048,576
 128KHz = 7.8125us
 7.8125us * 1,048,576 = 8,192,000us = 8.192s

 Mit wdr wird der Prescaler auf Null gesetzt, das ist alles.

 So etwas gibt es als TTL-Counter schon lange.
 Google mal nach 74HC590 oder nach TTL Counter...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.