Hallo, Ich habe ein funktionierendes Programm welches ich um eine zusätzliche Funktionalität erweitern möchte. Ich möchte alle 8 Sekunden (über einen Watchdog Interrupt gesteuert) die Spannung der angeschlossenen Akkus überprüfen. Sollte die Spannung unter 2V (zwei NIMH in Reihe) liegen solle sich der Controller, ein Atmega88pa, schlafen legen. Alle 8 Sekunden soll er wieder aufwachen, die Spannung überprüfen und solange diese nicht über 2,4V liegt weiter schlafen. Wie gehe ich das am besten an?
Ein Timer-Interupt hilft Dir weiter, nicht der Watchdog. Gruß Jobst
Hmm, aber wenn der Controller dann schläft kann ich ja nicht mehr wecken. Außer mit dem Watchdog.
Dann schau Dir nochmal die Schafmodi und deren Weckmöglichkeiten im Datenblatt an. Der WDT resetet Deinen Prozessor. Gruß Jobst
Es gibt zwei Schalf-Modi. Einer kann durch interrupts unterbrochen werden, der andere nur durch eine Reset.
Also hätte jetzt an sowas gedacht: .include "m88padef.inc" .org 0x006 rjmp Stromsparen rcall init main: . . . rjmp main init: ldi r16,(1<<wdce) sts WDTCSR,r16 ldi r16,(1<<WDIE)|(1<<WDP3)|(1<<WDP0) ;Watchdog mit 8s in Interrupt Mode ret Stromsparen: push r16 ;r16 und sreg sichern in r16,sreg push r16 rcall Adceinlesen ;liefert Batteriespannung cpi r16, 103 brlo schlafen pop r16 out sreg, r16 pop r16 reti schlafen: ldi r16,(1<<SM2)|(1<<SM1)|(1<<SE) pop r16 out sreg, r16 pop r16 sleep [/avrasm] @Jobst: schau doch lieber selber nochmal nach. Bei den etwas neueren AVRs kann der Watchdog beides.
1 | .include "m88padef.inc" |
2 | .org 0x006 |
3 | rjmp Stromsparen |
4 | |
5 | rcall init |
6 | main: |
7 | . |
8 | . |
9 | . |
10 | rjmp main |
11 | |
12 | init: |
13 | ldi r16,(1<<wdce) |
14 | sts WDTCSR,r16 |
15 | ldi r16,(1<<WDIE)|(1<<WDP3)|(1<<WDP0) ;Watchdog mit 8s in Interrupt Mode |
16 | ret |
17 | |
18 | Stromsparen: |
19 | push r16 ;r16 und sreg sichern |
20 | in r16,sreg |
21 | push r16 |
22 | rcall Adceinlesen ;liefert Batteriespannung |
23 | cpi r16, 103 |
24 | brlo schlafen |
25 | pop r16 |
26 | out sreg, r16 |
27 | pop r16 |
28 | reti |
29 | |
30 | |
31 | |
32 | |
33 | schlafen: |
34 | ldi r16,(1<<SM2)|(1<<SM1)|(1<<SE) |
35 | pop r16 |
36 | out sreg, r16 |
37 | pop r16 |
38 | sleep |
nochmal in Farbe.
Jobst M. schrieb: > Dann schau Dir nochmal die Schafmodi und deren Weckmöglichkeiten im > Datenblatt an. Der WDT resetet Deinen Prozessor. Kommt drauf an. Bei manchen (neueren?) AVRs kann man den Watchdog auch so konfigurieren, daß er beim ersten Ablaufen nur einen Interrupt generiert und erst beim zweiten einen Reset, oder auch daß er nur den Interrupt generiert. Tatsächlich habe ich bei meiner erste blinkende LED mit einem AVR das Blinken über den Watchdog-Timer der Tiny13 gesteuert, statt über einen normalen Timer, weil ich halt beim Lesen des Datenblatts erst dort vorbeigekommen bin ;-)
Okay. Stimmt. "In Interrupt mode, the WDT gives an interrupt when the timer expires. This interrupt can be used to wake the device from sleep-modes, and also as a general system timer." Der Interupt-Mode ist mir neu. Dann ist er aber quasi zum Timer degradiert. Zum Programm: Bei zu geringer Batteriespannung wird der Prozessor schlafen gelegt, bevor der WDT initialisiert wird. Gruß Jobst
Nicht degradiert, erweitert ;) Er kann das ja noch zusätlich. Das feine darin ist, dass man den Controller aus jedem schlaf wecken kann. Zum Programm: eigentlich dürfte nichts passieren, kein sei weit und breit. Das gehört noch ans Ende von init.
derHorst schrieb: > kein sei weit und breit. Dein Programm springt auch ohne IRQ erst mal zu 'Stromsparen'. Gruß Jobst
Hab nochmal in einer Appnote von Atmel nachgelesen (AVR132) jetzt klappt alles.
Ich brauche leider doch nochmal ein bisschen Hilfe. Der Stand ist: Programm läuft, Interrupt wird aufgerufen ADC Wert eingelesen und dementsprechend weitergemacht oder geschlafen. Das Problem ist: Ist der Controller einmal eingeschlafen wacht er nicht mehr auf. Hier das entscheidende Codestück:
1 | schlafen: |
2 | ldi r16,0b00001111 |
3 | out SMCR,r16 ;sleep einschalten, extended Standby |
4 | pop r16 ;sreg und r16 wieder herstellen |
5 | out sreg, r16 |
6 | pop r16 |
7 | sleep ;schlafen |
8 | reti |
ich bin mir nicht wirklich sicher, ob ich den Controller in einer ISR schlafen schicken kann. Und ob das so funktioniert wie ich es geschrieben habe. Danke für eure Hilfe.
Hi >ich bin mir nicht wirklich sicher, ob ich den Controller in einer ISR >schlafen schicken kann. Und ob das so funktioniert wie ich es >geschrieben habe. Da das ganze vor dem RETI passiert dürften weitere Interrupts gesperrt sein. MfG Sspess
Wenn man Strom sparen will muss man vieles beachten. Eine Uebersicht : http://www.ibrtses.com/embedded/avrpowersave.html
Vielen dank an Spess, das reti wird ja nicht mehr ausgeführt. Und auch vielen Dank für den Link!
Jobst M. schrieb: > Der Interupt-Mode ist mir neu. > Dann ist er aber quasi zum Timer degradiert. Die andere Perspektive ist: Toll, ein Timer mit zusätzlicher Watch dog - Funktionalität ;-) Auf den kleinen MSP430 gibt es nur einen normalen Timer. Dessen Interrupts helfen allerdings nichts im "low power mode 3", da dort dessen Clock aus ist. Dort bleibt gar nichts anderes übrig als den Watch dog - Timer zu nehmen, dessen Clock auch in diesem Modus noch an ist.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.