Hallo, ich habe bei einem Projekt ein recht eigenartiges Verhalten von
verschiedenen AtMega328P's. Bei Atmega A funktioniert der Beispiel
Sketch von unten wie geplant und ohne Probleme. Jedoch funktioniert das
Programm bei einem anderen nicht bzw. nur sehr sporadisch. z.B. Watchdog
löst nach 3x loop aus (mal mehr, mal weniger), nach dem in Power Down
(genauer in sleep_cpu) wahrscheinlich nicht mehr in die Interrupt
Funktion gewechselt wird und der wdt nicht mehr resetted wird.
Prinzipiell sollte es so funktionieren:
1. WDT aktivieren um nach uC zu resetten wenn er durch irgendwas
blockiert wird
2. Jedoch sollte zwischen den Messungen immer kurz in den sleep Modus
gewechselt werden
3. WDT wieder auf 8s setzen um zu resetten wenn nötig
Schritt 2 macht mir teilweise bei manchen AtMega328P's Probleme.
Verwende für den Sleep Modus die LowPower Library
https://github.com/rocketscream/Low-Power
1
#include<Arduino.h>
2
#include"LowPower.h"
3
#include<avr/wdt.h>
4
5
6
voidsetup(){
7
bool_WDRF=((1<<WDRF)&MCUSR);// Watchdog Reset
8
9
if(_WDRF){
10
cli();
11
MCUSR&=~(1<<WDRF);
12
WDTCSR|=(1<<WDCE)|(1<<WDE);
13
WDTCSR=0;
14
sei();
15
}
16
17
bool_BORF=((1<<BORF)&MCUSR);// BrownOut Reset
18
bool_EXTRF=((1<<EXTRF)&MCUSR);// External Reset
19
bool_PORF=((1<<PORF)&MCUSR);// Power-Off Reset
20
MCUSR=0;
21
22
23
Serial.begin(4800);
24
25
if(_WDRF)
26
Serial.println("WDT Triggered");
27
Serial.println(F("Start Setup"));
28
29
30
WDTCSR|=(1<<WDIE)|(1<<WDE);//Watchdog Mode = Interrupt Mode && System Reset Mode
Mathias schrieb:> wahrscheinlich nicht mehr in die Interrupt> Funktion gewechselt wird
Überprüfe das. Du könntest dazu in der Interrupt-Funktion einen Ausgang
toggeln.
Warum rufst du innerhalb der loop wdt_enable() auf? Das scheint mir
unnötig.
Bist du sicher, dass die Brown-Out Schwelle 4,3V OK ist? Bei USB kann
man durchaus mal darunter fallen, das müssen USB Geräte tolerieren.
Offenbar soll der ADC den Mikrocontroller aufwecken, aber ich sehe keine
Code dazu. Die Interrupt-Funktion hast du auch nicht gezeigt. Mit so
wenig Infos kann man dir kaum helfen.
Die LowPower-Bibliothek, die du verwendest, scheint auch was mit dem
Watchdog zu machen, und hat mehrere Stellen, die den umkonfigurieren.
Hab jetzt nicht im Detail geprüft, ob das mit deiner eigenen
WDT-Verwendung kollidiert, könnte aber sehr gut sein.
Insbesondere wird dort der Watchdog zum Aufwachen aus dem Sleep
verwendet, was mit deiner Intention, den µC per Watchdog zu resetten,
nicht ganz kompatibel ist.
Den Sleep mode "zu Fuß" selber zu implementieren ist vmtl. einfacher als
zu versuchen deinen Code mit dieser Low-Power-Library in Einklang zu
bringen.
Steve schrieb:> Warum rufst du innerhalb der loop wdt_enable() auf? Das scheint mir> unnötig.
Weil die Library folgendes enthält:
1
ISR(WDT_vect)
2
{
3
// WDIE & WDIF is cleared in hardware upon entering this ISR
4
wdt_disable();
5
}
d.H. der Watchdog schaltet sich damit immer selber aus...
Εrnst B. schrieb:> Den Sleep mode "zu Fuß" selber zu implementieren ist vmtl. einfacher als> zu versuchen deinen Code mit dieser Low-Power-Library in Einklang zu> bringen.
Ja, dann wird auch transparenter, was der Code eigentlich tut.
Um sleep zu benutzen, brauchst Du einen Interrupt, der die CPU wieder
aufweckt. Der fehlt aber.
Die Reihenfolge ist falsch. MCUSR muß gelöscht werden, bevor man den
Wachhund disabled.
wdt_enable(WDTO_8S); gehört nicht in die Loop. Einmal im Init reicht
völlig, die CPU ist ja nicht vergeßlich.
Ebenso ist des doppelte sei() im Macro überflüssig, einmal reicht.
Peter D. schrieb:> Um sleep zu benutzen, brauchst Du einen Interrupt, der die CPU wieder> aufweckt. Der fehlt aber.
Läuft bei Arduino nicht sowieso immer ein Timer mit, um die millis()
hochzuzählen?
Ansonsten wärs der Watchdog-Irq...
Peter D. schrieb:> wdt_enable(WDTO_8S); gehört nicht in die Loop. Einmal im Init reicht> völlig, die CPU ist ja nicht vergeßlich.
Dafür sorgt die Rundum-Glücklich-Lowpower-Library :)
@ribisl:
tl;dr:
Entweder du kontrollierst den Watchdog in deinem Code, oder
rocketscream/Low-Power tut es. Dann lässt du aber auch die Finger davon.
Εrnst B. schrieb:> Dafür sorgt die Rundum-Glücklich-Lowpower-Library :)
Mit Sicherheit macht sie das Programm extrem undurchschaubar. Ich hab da
keine Lust mich durchzukämpfen. Sie scheint mir nicht gerade foolproof
zu sein.
Εrnst B. schrieb:> Entweder du kontrollierst den Watchdog in deinem Code, oder> rocketscream/Low-Power tut es. Dann lässt du aber auch die Finger davon.
So wirds sein. Ich sehe auch keinen rechten Nutzen in der Lib.
Ich würde sie komplett in die Tonne treten und alles selber ordentlich
machen. Sleepmode ist nämlich recht tricky und enthält einige
Race-Conditions.
Daß ich sleep_disable(); für Bullshit halte, hab ich ja schon mehrfach
gesagt.
Ohne das sleep_disable(); reicht es völlig, das sleep_enable(); nur im
Init zu machen und dann ist man schonmal eine Race-Condition los.
Steve schrieb:> Warum rufst du innerhalb der loop wdt_enable() auf? Das scheint mir> unnötig.
Nach dem Sleep Modus soll der Watchdog wieder auf 8s gesetzt werden,
damit er nicht nach 250ms wieder resetted.
Steve schrieb:> Bist du sicher, dass die Brown-Out Schwelle 4,3V OK ist? Bei USB kann> man durchaus mal darunter fallen, das müssen USB Geräte tolerieren.
Ja, AtMega läuft auf 3.3V und BrownOut wird nie ausgelöst
Steve schrieb:> Offenbar soll der ADC den Mikrocontroller aufwecken, aber ich sehe keine> Code dazu.
Verstehe nicht ganz wie du drauf kommst, dass der ADC den uC aufweckt?
Steve schrieb:> Die Interrupt-Funktion hast du auch nicht gezeigt.
1
ISR(WDT_vect)
2
{
3
// WDIE & WDIF is cleared in hardware upon entering this ISR
4
wdt_disable();
5
}
Das eigenartige ist halt, dass bei einigen ATMegas alles ohne Probleme
funktioniert, und bei manchen nach wenigen loops resetted wird.
Werde jetzt mal versuchen den sleep Teil selbst zu machen.
Peter D. schrieb:> Daß ich sleep_disable(); für Bullshit halte, hab ich ja schon mehrfach> gesagt.
Könntest du es kurz nocheinmal erklären? :)
In dieser Sequenz ist sleep_disable(); vollkommen überflüssig, da ja vor
jedem Sleep das sleep_enable(); ausgeführt wird.
Daher reicht sleep_enable(); einmal im Init und sleep_disable(); fällt
ersatzlos weg.
Übrig bleibt in der Loop nur das:
sleep_cpu();
Eine Race-Condition wäre möglich wenn im Interrupt das SMCR angefaßt
wird.
Der Interrupt ändert aber das WDTCSR. Ob dadurch auch eine
Race-Condition möglich ist, müßte man bei jeder Funktion prüfen, die im
Main das WDTCSR ändert. Am besten vorsorglich alle diese Funktionen
atomar kapseln.
Mathias schrieb:> Verstehe nicht ganz wie du drauf kommst, dass der ADC den uC aufweckt?
Weil du geschrieben hast, dass der µC zwischen den Messungen schlafen
soll. Habe ich wohl missverstanden.
Mathias schrieb:> Das eigenartige ist halt, dass bei einigen ATMegas alles ohne Probleme> funktioniert, und bei manchen nach wenigen loops resetted wird.
Das ist das Fiese an so Race-Conditions, besonders wenn sie von zwei
voneinander unabhängigen Clock-Sources abhängen...
Die Watchdog-Clock ist sehr ungenau, temperaturabhängig, und streut
stark mit den Exemplaren. Da kann es schon sein, dass ein Chip bei
Raumtemperatur lange problemlos läuft, und der nächste praktisch ständig
ins Fettnäpfchen tritt.
Kannst ja mal probieren, deine Crash-Kandidaten etwas zu erwärmen oder
zu kühlen, oder anderweitig das Timing beeinflussen, z.B. durch ein paar
extra delay() in der loop().
Aber: das ist natürlich keine Lösung, nur ein evtl. interessantes
Experiment, falls du der Sache auf den Grund gehen möchtest.
Εrnst B. schrieb:> Das ist das Fiese an so Race-Conditions, besonders wenn sie von zwei> voneinander unabhängigen Clock-Sources abhängen...
Hmm... dachte Race Condidtions können nur bei mehreren Threads
auftreten. Und wie kann ich diese in meinem Fall am besten verhindern?
Peter D. schrieb:> Eine Race-Condition wäre möglich wenn im Interrupt das SMCR angefaßt> wird.
Sollte das nicht gemacht werden? Wenn der WDT Triggered soll ja der
Sleep Modus deaktiviert werden, ich dachte das macht man jetzt mit
Mathias schrieb:> Funktioniert schon etwas besser aber immer noch nicht prefekt
Kannst Du das mal übersetzen.
Was soll das ganze Konstrukt eigentlich bewirken.
Peter D. schrieb:> Was soll das ganze Konstrukt eigentlich bewirken.
Es sollte eine Messung durchgeführt werden und periodisch auch etwas auf
eine SD Karte geschrieben werden. Nach der Messung sollte für 500ms
geschlafen werden. Nun kam es manchmal dazu, dass der uC komplett
blockiert wurde und nichts mehr ging. Deshalb wollte ich den WDT so
umkonfigurieren, dass wenn der blockierte Fall eintritt nach 8s resetted
wird.
1
voidloop(){
2
wdt_reset();
3
4
// Messung oder SD Karte beschreiben, könnte blockieren
Mathias schrieb:> ich dachte das macht man jetzt mit> ISR(WDT_vect)> {> SMCR = 0; // stop sleeping> }
Nö, das stoppt nichts.
Es ändert nur die Funktion eines folgenden sleep_cpu();.
Mathias schrieb:> void loop()> {> ...> delay(500);
Da krempeln sich einem die Fußnägel hoch. Laß den Unsinn.
Mathias schrieb:> Deshalb wollte ich den WDT so> umkonfigurieren, dass wenn der blockierte Fall eintritt nach 8s resetted> wird.
Was nicht funktioniert hat, weil das "LowPower-Sleep" den Watchdog zum
Aufwachen nach den 500ms umkonfiguriert hat, also auf kürzeren Timeout
und auf Interrupt statt Reset.
=> wenn der Watchdog zuverlässig immer zuschlagen können soll, darf
dein sleep den nicht mal zwischendurch zum Wiederaufwachen verwenden.
Also: andere Aufwach-Zeitquelle verwenden, auch wenn dann der
Schlafmodus nicht ganz so stromsparend ausfallen kann.
Timer2 im Async-Mode mit 32kHz Uhrenquarz wäre eine Möglichkeit, der
läuft im Power-Save Modus weiter, und kann die CPU wieder aufwecken.
Stomverbrauch müsstest du nachmessen.
Peter D. schrieb:> Da krempeln sich einem die Fußnägel hoch. Laß den Unsinn.
Das war nur um es Testweise etwas weiter zu verzögern und hat auch
nichts mit meinem Problem zu tun...
Εrnst B. schrieb:> Was nicht funktioniert hat, weil das "LowPower-Sleep" den Watchdog zum> Aufwachen nach den 500ms umkonfiguriert hat, also auf kürzeren Timeout> und auf Interrupt statt Reset.
Hab jetzt die LowPower Library rausgeschmissen und was anderes probiert.
Εrnst B. schrieb:> wenn der Watchdog zuverlässig immer zuschlagen können soll, darf> dein sleep den nicht mal zwischendurch zum Wiederaufwachen verwenden.
Verstehe nicht ganz warum das nicht geht soll? WDT umkonfigurieren um
nach 500ms sleep aufzuwachen, nach dem Aufwachen wieder so
umkonfigurieren damit er nach 8s keinem wdt_reset() den uC resetted.
Klingt für mich nicht ganz unlogisch aber ich kann mich auch irren.
Mathias schrieb:> Verstehe nicht ganz warum das nicht geht soll?
Es geht schon wenn es korrekt umgesetzt ist, und nicht wenn, wie in
deinem Original-Code, der "Absturz" genau an der Stelle passiert an der
der Watchdog gerade Pause macht.
Εrnst B. schrieb:> Es geht schon wenn es korrekt umgesetzt ist, und nicht wenn, wie in> deinem Original-Code, der "Absturz" genau an der Stelle passiert an der> der Watchdog gerade Pause macht.
Und wie würde es richtig gehen? :) Bzw warum passiert der Absturz genau
an der Stelle?
Mathias schrieb:> dachte Race Condidtions können nur bei mehreren Threads> auftreten
main() und alle Interrupt-Routinen sind Threads. Also hast du alleine
deswegen schon mindestens zwei Threads. Alles worauf diese gemeinsam
zugreifen bedarf besonderer Vorsicht.
Mathias schrieb:> Bzw warum passiert der Absturz genau> an der Stelle?
ich hab keine große Freude daran, diese LowPower-Bibliothek zu debuggen.
Das darf gerne jemand anderes machen.
Auf den ersten Blick: an den beiden markierten Stellen könnte die
Watchdog-ISR ausgeführt werden, und ein "wdt_disable()" reinmogeln.
Führt das zum Absturz? Zum sleep ohne wakeup? Keine Ahnung. Möglich.
Mathias schrieb:> Ich hab weiter oben eine Version ohne LowPower gemacht;)
die hat schonmal den Vorteil, dass du den Watchdog-counter zurücksetzt,
bevor du den interrupt-mode aktivierst.
der LowPower Code hat das nicht gemacht, was durchaus der Grund dafür
sein könnte, dass die ISR unerwartet früh ausgeführt wird.
Ich finde es nicht so schlau, den Watchdog Timer wechselweise als
Watchdog und zum Aufwachen zu benutzen. Immer wenn der Mikrocontroller
schläft, ist der Watchdog deaktiviert. Wenn er sich dabei aufhängt,
bleibt er für immer hängen.
Εrnst B. schrieb:> Also: andere Aufwach-Zeitquelle verwenden, auch wenn dann der> Schlafmodus nicht ganz so stromsparend ausfallen kann.
Εrnst B. schrieb:> Watchdog-ISR ausgeführt werden, und ein "wdt_disable()" reinmogeln.
wenn ich hier ein wdt_disable() einbauen würde, dann würde ja nie mehr
aufgewacht werden oder?
Steve schrieb:> Immer wenn der Mikrocontroller> schläft, ist der Watchdog deaktiviert.
sollte er eigentlich nicht sein, wenn der uC schläft ist der WDT auf
500ms und Interrupt eingestellt?
Mathias schrieb:> Εrnst B. schrieb:>> Watchdog-ISR ausgeführt werden, und ein "wdt_disable()" reinmogeln.>> wenn ich hier ein wdt_disable() einbauen würde, dann würde ja nie mehr> aufgewacht werden oder?
Genau das könnte bei deinen Abstürzen passiert sein. Nur dass das
"wdt_disable()" natürlich nicht direkt an der Stelle steht, sondern in
der ISR (WDT_vect)
Das ist exakt eine der Sachen, die man beachten muss, und die die
Autoren der LowPower-Lib vermasselt haben:
ISRs können den Programmfluss immer unterbrechen, solange nicht per CLI
verboten, und dann an den ungünstigsten Stellen ausgeführt werden.
Mathias schrieb:>> Immer wenn der Mikrocontroller>> schläft, ist der Watchdog deaktiviert.> sollte er eigentlich nicht sein,
Aber im Sleep macht der Watchdog nur einen Interrupt, keinen Reset. Wenn
der µC hängt, führt er den Interrupt mit einer gewissen
Wahrscheinlichkeit auch nicht mehr aus.
Εrnst B. schrieb:> Genau das könnte bei deinen Abstürzen passiert sein. Nur dass das> "wdt_disable()" natürlich nicht direkt an der Stelle steht, sondern in> der ISR (WDT_vect)
hab jetzt mal versucht, das ist mein Ergebnis:
1
#include<Arduino.h>
2
#include<avr/sleep.h>
3
#include<avr/wdt.h>
4
5
inlinevoidsleep()
6
{
7
cli();
8
wdt_reset();
9
WDTCSR|=(1<<WDCE)|(1<<WDE);
10
WDTCSR=(1<<WDIE)|(1<<WDP2)|(1<<WDP0)|(0<<WDE);// Interrupt and 0.5s
11
wdt_reset();
12
13
Serial.println("1");
14
Serial.flush();
15
16
SMCR&=~0x0e;
17
SMCR|=0x01|0x04;// SE + SM1 (power-down)
18
sei();
19
sleep_cpu();
20
21
Serial.println("2");
22
Serial.flush();
23
24
cli();
25
wdt_reset();
26
WDTCSR|=(1<<WDCE)|(1<<WDIE)|(1<<WDE);// Watchdog Mode = Interrupt Mode && System Reset Mode // do not put this in ISR
27
WDTCSR=(1<<WDE)|(1<<WDP3)|(1<<WDP0);// Interrupt and 8s
28
sei();
29
}
30
31
ISR(WDT_vect)
32
{
33
wdt_disable();
34
Serial.println("ISR");
35
Serial.flush();
36
}
37
38
voidsetup()
39
{
40
bool_WDRF=((1<<WDRF)&MCUSR);// Watchdog Reset
41
if(_WDRF)
42
{
43
cli();
44
MCUSR&=~(1<<WDRF);
45
WDTCSR|=(1<<WDCE)|(1<<WDE);
46
WDTCSR=0;
47
sei();
48
}
49
bool_BORF=((1<<BORF)&MCUSR);// BrownOut Reset
50
bool_EXTRF=((1<<EXTRF)&MCUSR);// External Reset
51
bool_PORF=((1<<PORF)&MCUSR);// Power-Off Reset
52
MCUSR=0;
53
54
pinMode(6,OUTPUT);
55
56
Serial.begin(4800);
57
if(_WDRF)
58
Serial.println("WDT Triggered");
59
Serial.println(F("Start Setup"));
60
delay(3000);
61
62
cli();
63
WDTCSR|=(1<<WDIE)|(1<<WDE);// Watchdog Mode = Interrupt Mode && System Reset Mode
64
wdt_enable(WDTO_8S);
65
wdt_reset();
66
sei();
67
}
68
voidloop()
69
{
70
staticintx=0;
71
wdt_reset();
72
digitalWrite(6,x++%2==0);
73
sleep();
74
}
Mit der seriellen Ausgabe hab ich herausgefunden, dass er nach "1"
manchmal in den Setup wechselt.
Was auch relativ eigenartig ist, dass er fast sofort in nach "1"
wechselt, also ohne die 8s abzuwarten
1
15:27:47.970>ISR
2
15:27:47.980>2
3
15:27:47.988>1
4
15:27:48.527>StartSetup
5
15:27:49.018>ISR
PS das selbe Verhalten ist auch ohne Seriellen Monitor sichtbar. Und es
kommt auch die WDT Triggered Nachricht nicht!
> Serial.println("ISR");
Das funktioniert nur mit Glück. Wenn der Sendepuffer gerade voll ist,
hängt sich der µC auf. Denn dann wartet println() für immer, dass der
Puffer frei wird, wird er aber nie.
Und zwar deswegen nicht, weil der AVR nicht gleichzeitig die ISR vom
seriellen port ausführen kann, welche den Puffer senden und somit Platz
schaffen würde.
Steve schrieb:> Wenn der Sendepuffer gerade voll ist,> hängt sich der µC auf.
sollte hier aber nicht der Fall sein oder? Ohne serielle Schnittstelle
passiert ja dasselbe.
Bin jetzt gerade auch drauf gekommen, dass alle Reset Reasons 0 sind,
vielleicht hilft das ja auch was.
Mathias schrieb:> Und es> kommt auch die WDT Triggered Nachricht nicht!
Das Auslesen von MCUSR in der setup() zum herausfinden der Reset-Quelle
muss nicht klappen. Da läuft vorher noch der Bootloader und
Arduino-code, die das Register u.U. schon gelöscht haben.
Hab ich nicht geprüft --> selber nachschauen.
Warum verwendest du nicht die sleep_enable() und
set_sleep_mode(SLEEP_MODE_PWR_DOWN)
aus der avr/sleep.h?
und welchen Sinn siehst du im wdt_disable() in deiner ISR?
Steve schrieb:> Ich finde es nicht so schlau, den Watchdog Timer wechselweise als> Watchdog und zum Aufwachen zu benutzen.
Es sollte schon gehen.
Einfach vor dem sleep_cpu(); den Watchdog auf 500ms, Interrupt setzen.
Und danach, also wenn er aufgewacht ist, den Watchdog auf 8s, Reset
setzen. Der Interrupt bleibt leer:
EMPTY_INTERRUPT(WDT_vect);
Zum Testen kann man per Pinabfrage die Loop irgendwo anhalten d.h. in
eine Endlosschleife gehen. Nur dann darf ein Reset erfolgen (nach 8,5s).
Ein wdt_disable(); darf nirgends stehen!
Und Sleepmode einstellen erfolgt nur einmalig im Setup, d.h. da dreht
man nicht mehr ständig dran rum. Bzw. nur, wenn man definitiv nicht mehr
schlafen will.
Εrnst B. schrieb:> Das Auslesen von MCUSR in der setup() zum herausfinden der Reset-Quelle> muss nicht klappen. Da läuft vorher noch der Bootloader und> Arduino-code, die das Register u.U. schon gelöscht haben.> Hab ich nicht geprüft --> selber nachschauen.
ist nicht der Fall, wenn ich im LOOP ein +8s delay hineingebe, erscheint
die wdt triggered Nachricht und der Reset Modus wird auch angezeigt.
Εrnst B. schrieb:> Warum verwendest du nicht die sleep_enable() und> set_sleep_mode(SLEEP_MODE_PWR_DOWN)> aus der avr/sleep.h?
Weil es keinen Unterschied macht.
Εrnst B. schrieb:> und welchen Sinn siehst du im wdt_disable() in deiner ISR?
Ich dachte mir da ich den WDT eh danach wieder direkt aktiviere kann ich
ihn hier deaktivieren. Sollte die ISR leer bleiben?
Mathias schrieb:> Und es> kommt auch die WDT Triggered Nachricht nicht!
Im Power-Down macht die UART ja auch nichts.
Alle Hardwaren außer Watchdog, Pin-Change und async T2 schlafen tief und
fest.
Willst Du noch was machen, darfst Du maximal in Idle gehen.
Peter D. schrieb:> Es sollte schon gehen.> Einfach vor dem sleep_cpu(); den Watchdog auf 500ms, Interrupt setzen.> Und danach, also wenn er aufgewacht ist, den Watchdog auf 8s, Reset> setzen. Der Interrupt bleibt leer:> EMPTY_INTERRUPT(WDT_vect);
Sollte dann so ja prinzipiell stimmen oder?
1
inlinevoidsleep()
2
{
3
cli();
4
wdt_reset();
5
WDTCSR|=(1<<WDCE)|(1<<WDE);
6
WDTCSR=(1<<WDIE)|(1<<WDP2)|(1<<WDP0)|(0<<WDE);// Interrupt and 0.5s
7
wdt_reset();
8
9
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
10
sleep_enable();
11
sei();
12
sleep_cpu();
13
14
cli();
15
wdt_reset();
16
WDTCSR|=(1<<WDCE)|(1<<WDIE)|(1<<WDE);// Watchdog Mode = Interrupt Mode && System Reset Mode // do not put this in ISR
17
WDTCSR=(1<<WDE)|(1<<WDP3)|(1<<WDP0);// Interrupt and 8s
18
sei();
19
}
20
21
EMPTY_INTERRUPT(WDT_vect);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
*sollten nur im setup sein()
Peter D. schrieb:> Mathias schrieb:>> Und es>> kommt auch die WDT Triggered Nachricht nicht!>> Im Power-Down macht die UART ja auch nichts.
Die WDT Triggered Nachricht kommt ja auch erst wieder im Setup nach dem
das WDRF Bit gesetzt wurde
S. Landolt schrieb:> Ist bekannt, dass der ATmega328P im Modus Power-save mit einem 32> KiHz-Quarz so um ein uA herum, je nach Ucc, benötigt?
Ja ist bekannt aber nicht möglich da 32kHz zu langsam sind und ich es
gerne auf die Weise schaffen möchte.
> da 32kHz zu langsam
Der Controller läuft dann natürlich mit dem internen RC-Oszillator, also
z.B. mit 8 MHz. Die 32 KiHz sind nur für den asynchronen Timer2.
> gerne auf die Weise schaffen möchte
Okay - ich lese interessiert mit.
Ist denn überhaupt Batteriebetrieb vorgesehen?
Bei Netzberieb laß den MC einfach durchlaufen, der wird nicht heiß.
Schon der 7805 im Netzteil zieht allein bis zu 8mA, da ist es Unsinn, um
µA zu feilschen.
Mathias schrieb:> Sollte dann so ja prinzipiell stimmen oder?
Sieht erstmal nicht schlecht aus.
Nun ist auch klar, wo das Watchdog-Reset herkommt. Dein UART-Puffer
läuft voll und die CPU wartet, bis sie senden darf, darf sie aber im
Power-Down nie. Setz mal auf Idle, dann sollte es klappen.
S. Landolt schrieb:> Ist bekannt, dass der ATmega328P im Modus Power-save mit einem 32> KiHz-Quarz so um ein uA herum, je nach Ucc, benötigt?
Hast du das Nachgemessen? Im Datenblatt hab ich nur Angaben zum WDT
gefunden, der den Stromverbrauch je nach VCC um so 6µA hochtreibt.
Εrnst B. schrieb:> Timer2 im Async-Mode mit 32kHz Uhrenquarz wäre eine Möglichkeit, der> läuft im Power-Save Modus weiter, und kann die CPU wieder aufwecken.> Stomverbrauch müsstest du nachmessen.
Damit wäre ja für Low-Power/Batterie-Anwendungen ein Betrieb ohne WDT
aber mit Uhrenquarz besser.
Peter D. schrieb:> Ist denn überhaupt Batteriebetrieb vorgesehen?
Ja Batteriebetrieb ist vorgesehen!
Habe jetzt auch herausgefunden, dass wenn ich den Mikrocontroller etwas
erhitze das ganze sehr stabil läuft. Läuft jetzt seit einer Stunde ohne
einen einzigen Reset.
Natürlich könnte es jetzt ein anderes Hardware Problem sein, deshalb
habe ich mal einen "problematischen" uC mit einem neuen augetauscht und
es läuft mit dem neuen auch ohne Probleme.