Hallo, Ich möchte mein Projekt (ATMega 16 + Beschaltung) in den "Schlaf" versetzen, da ich die Schaltung mit einer Batterie versorgen möchte. Folgendes soll geschehen: Wenn ich 60 Sekunden 'nichts' tue ... also keine Taster drücke (das bekomme ich alles hin mit Tastern und so), dann soll der Controller schlafen. Laut Tutorial habe ich die Wahl zwischen verschiedenen Arten ... also Power-Down, Standby und so weiter ... Welche Art würdet ihr mir raten ? Da ist nun von einem Aufweck - Interrup die Rede ... wie Realisiere ich soetwas ? Aus dem Datenblatt wird ersichtlich, dass ich bestimmte Pins am Controller beschalten muss ?! IN0 - IN2 ... Geht es nicht auch so, dass der Controller wieder aufgeweckt wird, wenn man irgendeinen Taster betätig, sprich eine Aktion ausführt ? Möchte IN0 - IN2 nicht unnötig beschalten. Danke Timo
Je nachdem, welchen Sleep-Mode Du benutzt, bleibt Dir keine andere Wahl, als das Aufwecken mit einem externen Interrupt zu realisieren. Je mehr Komponenten des Controllers abgeschaltet werden, um Strom zu sparen, desto weniger Möglichkeiten zum Aufwecken gibt es. Aus dem Power-Down-Modus, in dem auch der Hauptoszillator deaktiviert ist, geht das nur über einen Level(!)-Interrupt, da für die Flankendetektierung der CPU-Takt benötigt würde. Behelfen kann man sich z.B., indem man alle Taster, die den µC aufwecken sollen, über ein UND-Gatter an einen der externen Interrupt-Pins legt und den Interrupt vor dem Schlafenlegen als Level-Interrupt freigibt. Das wäre die stromsparendste Lösung.
johnny.m wrote: > der CPU-Takt benötigt würde. Behelfen kann man sich z.B., indem man alle > Taster, die den µC aufwecken sollen, über ein UND-Gatter an einen der > externen Interrupt-Pins legt und den Interrupt vor dem Schlafenlegen als > Level-Interrupt freigibt. Das wäre die stromsparendste Lösung. Dann doch lieber ein ODER Gatter oder ? ;) Grüße Björn
Hallo! Kommt drauf an wieviel Ansprech zeit du zulassen wills! Ich hab mir schon mal so beholfen dass ich den Controller alle 50ms per Timer interrupt hab wecken lassen, die Tasten abgefragt hab und in dann wieder hab einschlafen lassen. Die paar µs die der dafür braucht fallen meist nicht ins Gewicht! MfG Owz
@Björn: > Dann doch lieber ein ODER Gatter oder ? ;) Nö. Taster werden bei den AVRs aufgrund der integrierten Pull-Ups eigentlich sinnvollerweise immer Low-aktiv angeschlossen. Wenn man die Taster an ein UND-Gatter hängt und ein Taster gedrückt wird, so dass die UND-Bedingung nicht mehr erfüllt ist, dann gibt das Gatter am Ausgang einen Low-Pegel aus. Und das ist genau das, was der Interrupt-Eingang braucht...
wenn mein Pic schläft wie wecke ich Ihn wieder auf ohne Flanke am INT sondern anch einer bestimmten Zeit. ich führe einfach nur Sleep(); aus aber wie zähle ich jetzt mit ? wenn der Timer aus ist=
Ich verwende einen externen Quarz für den Pic, wenn ich den Timer1 verwende möchte kann ich diesen quarz nicht mehr verwenden weil sich der Pic im schlaf befindet. Muss ich jetzt nochmal einen Quarz verwenden und an das RC1 Pin hängen für den Timer1?
Es gibt die Moeglichkeit eines externen RTC, zB eines DS1306. Man kann auch einen 32K Quarz anhaengen und den die Zeit machen lassen. Eine Seite : http://www.ibrtses.com/embedded/avrpowersave.html
zu teuer sorry. gibt es noch eine andere Möglichkeit ausser int oder kompliziert den WDT zu verwenden ?
ich habe bei einem mega168 den internen 32 khz oszi aktiviert und lass ihn darüber wieder aufwachen. Dann wird quasi alles schlafen gelegt, nur der timer2 läuft weiter.
mh? wie funktioniert das dann? ich initialisere mit HS das komplette Programm
Da laut Datenblatt im SLEEP_MODE_PWR_SAVE der Timer2 weiterläuft setzt man einfach den nächsten Weckwert und der Prozessor wird zum Zeitpunkt wieder aufgeweckt. Interrupt ausführen und dann im Main direkt zurück in den sleep. So z.B.
1 | /* weckt den Prozessor alle x ms auf und generiert einen kurzen Impuls auf Ausgang PB0
|
2 | * hier wird mit einem Transistor ein Trafo sekundärseitig angetrieben
|
3 | *
|
4 | */
|
5 | |
6 | |
7 | #include <avr/io.h> |
8 | #include <avr/interrupt.h> |
9 | #include <avr/sleep.h> |
10 | |
11 | |
12 | #define Set2Output(DataDirection, Pin) DataDirection |= (1<<Pin)
|
13 | #define Set2Hiz(DataDirection, Pin) DataDirection &= ~(1<<Pin)
|
14 | |
15 | #define Tog_Bit(Port, Pin) Port ^= _BV(Pin) //Toggeld Charbit
|
16 | #define Set_Bit(Port, Pin) Port |= _BV(Pin) //set Bit
|
17 | #define Clr_Bit(Port, Pin) Port &= ~_BV(Pin) //clear Bit
|
18 | |
19 | //show system_state with dual led between PB2 and PB3
|
20 | #define Show_Status (IO == System_State) ? (Set_Bit(PORTC, PC0)) : (Set_Bit(PORTC, PC1))
|
21 | |
22 | //check if trafo works. If voltage comes back to PIN1 everything is OK
|
23 | #define Check_Output (bit_is_set(PINC,PIN5)) ? (System_State = IO) : (System_State = NIO)
|
24 | |
25 | //exchange if output is active high/low
|
26 | #define time_off 125//125
|
27 | #define time_on 1// 3
|
28 | |
29 | typedef unsigned char u8; |
30 | |
31 | typedef enum { |
32 | IO, |
33 | NIO
|
34 | } state_t; |
35 | volatile state_t System_State; |
36 | |
37 | |
38 | //timer 2 used in CTC Mode
|
39 | void init_timer2(void){ |
40 | TCCR2A = (1<<WGM21); //mode 2, CTC Mode |
41 | TCCR2B = (1<<CS22) | (1<<CS21) | (1<<CS20); |
42 | //prescaler 1024, 8 bit count, 1 count = 8ms, 125 count = 1000ms
|
43 | OCR2A = time_off; //interrupt every second |
44 | TIMSK2 = (1<<OCIE2A); // enable compare interupt |
45 | }
|
46 | |
47 | ISR(TIMER2_COMPA_vect) |
48 | {
|
49 | //Tog_Bit(DDRB,PB1);
|
50 | if (OCR2A == time_off) // lange geschlafen, jetzt ausgang aktivieren |
51 | {
|
52 | Set_Bit(PORTB,PB0); |
53 | Show_Status; |
54 | OCR2A = time_on; // Einschaltdauer einstellen |
55 | }
|
56 | else
|
57 | {
|
58 | Check_Output; // Überprüfen, ob Ausgangsspannung Trafo |
59 | // _delay_ms(1);
|
60 | Clr_Bit(PORTB, PB0); // Ausgang wieder aus |
61 | Clr_Bit(PORTC, PC0); |
62 | Clr_Bit(PORTC, PC1); |
63 | OCR2A = time_off; // Wecker stellen |
64 | }
|
65 | }
|
66 | |
67 | void init_io(void){ |
68 | // init Outputs
|
69 | Set2Output(DDRB, PB0); // Transistor für Trafo |
70 | |
71 | Set2Output(DDRC, PC0); // DualLED nach PB2, |
72 | Set2Output(DDRC, PC1); // PC1 = 1 & PC2 = 0 -> grün |
73 | // PC1 = 0 & PC2 = 1 -> rot
|
74 | Clr_Bit(PORTB, PB0); // Ausgang wieder aus |
75 | Clr_Bit(PORTC, PC0); |
76 | Clr_Bit(PORTC, PC1); |
77 | |
78 | System_State = IO; |
79 | }
|
80 | |
81 | void init_sleepmode(void){ |
82 | set_sleep_mode(SLEEP_MODE_PWR_SAVE); |
83 | }
|
84 | |
85 | /*****************************************************************************/
|
86 | int main(void) |
87 | {
|
88 | init_timer2(); |
89 | init_io(); |
90 | init_sleepmode(); |
91 | |
92 | sei(); |
93 | |
94 | while(1){ |
95 | sleep_mode(); |
96 | }
|
97 | |
98 | return 0; |
99 | |
100 | |
101 | };
|
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.