Hallo, meine Anwendung währe so was in der Art: Da ist ein ATtiny25 ohne externen Takt. Er wird mit 3-4 AAA Batterien versorgt. Der µC ist im Tiefschlaf und wird einmal die Stunde vom Timer geweckt. Dann macht er ein paar Messungen und schaltet dann eventuel ein bistabiles Relais um, schaltet alle Port ab, stellt sich den Wecker wieder auf eine Stunde und schläft wieder ein. Wie kann ich so eine Routine machen die den Wecker auf eine Stunde stellt ihn schlafen legt und nach einer Stunde wieder aufweckt? Hat jemand ein einfaches Beispielprogramm?
Gokhlayeh schrieb: > Wie kann ich so eine Routine machen die den Wecker auf eine Stunde > stellt ihn schlafen legt und nach einer Stunde wieder aufweckt? > Hat jemand ein einfaches Beispielprogramm? geht nicht, es keinen Timer der so lange läuft. Du kannst aber ein paar sekunden lang schlafen, dann schauen wie "spät" es ist und wenn nichts zu tun ist dann gleich wieder schlafen. Alles was man dazubraucht steht im Datenblatt. Aber sehr genau wird es mit dem Internen Takt nicht.
Hi >geht nicht, es keinen Timer der so lange läuft. Du kannst aber ein paar >sekunden lang schlafen, dann schauen wie "spät" es ist und wenn nichts >zu tun ist dann gleich wieder schlafen. Beim ATTiny25 sollte man schon, wenn ich mich nicht verrechnet habe, auf einen Timeroverflow von 2,8 min kommen (6,4MHz, Clock Divider 256 und Timer-Prescaler 16364). Eine Stunde in einem Ritt ist mit einem Timer nicht möglich. Eine Möglichkeit wäre: http://www.atmel.com/dyn/resources/prod_documents/doc1268.pdf MfG Spess
Du kannst den Watchdoginterrupt nehmen und auf 8s setzen. Und dann ne Variable zählen, bis 1h rum ist. Du kannst den ATtiny25 aber auch langasm takten, um Strom zu sparen, z.B. mit nem 32kHz Quarz. Peter
Vielen Dank für die tollen Tip's :-) Leider fehlen mir die Basics wie Timerinterrupts aus dem Tiefschlaf etc. Vieleicht hat ja doch noch jemand ein einfaches (10-20 Zeilen) Beispielprogramm in C Den Artikel (Long Delay Generation Using the AVR Microcontroller) muss ich mal durcharbeiten. Peter Dannegger schrieb: > Du kannst den ATtiny25 aber auch langasm takten, um Strom zu sparen, > z.B. mit nem 32kHz Quarz. Leider keine Portleitung mehr frei. Würde CLKDIV8 helfen?
Peter Dannegger schrieb: > Du kannst den Watchdoginterrupt nehmen und auf 8s setzen. Und dann ne > Variable zählen, bis 1h rum ist. Geht aber nur, wenn die genannte Stunde auch mal eine Viertelstunde mehr oder weniger sein darf. Der ist zumindest dem Datasheet nach grässlich ungenau.
Gokhlayeh schrieb: > Leider keine Portleitung mehr frei. > Würde CLKDIV8 helfen? Gewissermassen, insbesondere mit dem Watchdog-Oszillator als Taktquelle. Wobei CLKDIV8 heute meist ein Speziallfall eines programmierbaren Registers ist. Voll ausgefahren kannst du dem AVR dann fast schon Befehl für Befehl live zusehen. ;-) Denk aber dran, dass ISP mit maximal 1/4 des Taktes arbeitet.
Ne, sowas mit Watchdogtimer ist weit über meinen Möglichkeiten. Was ich mir vorstellen kann, ist ein Timerinterrupt, der jede Sekunde aufwacht eine Variable hochzählt, bei 3600 ist dann eine Stunde rum und Action ;-) Hat jemand so ein Template für mich, das wär toll!
Gokhlayeh schrieb: > Hat jemand so ein Template für mich, das wär toll! NEIN - fang selber an zu Programmieren, wenn du nicht weiter kommst dann stellt konkrete Frage. Es gibt ausreichend Artikel http://www.mikrocontroller.net/articles/Hauptseite wo so alles drin steht was du brauchst.
Gokhlayeh schrieb: > sowas mit Watchdogtimer ist weit über meinen Möglichkeiten. D.h. Du hast Probleme, den entsprechenden Abschnitt im Datenblatt zu lesen? Gokhlayeh schrieb: > Was ich mir vorstellen kann, ist ein Timerinterrupt, Der Idle-Mode spart fast nix. Peter
Peter II schrieb: > NEIN - fang selber an zu Programmieren, wenn du nicht weiter kommst dann > stellt konkrete Frage. Ich habe jetzt dieses programmiert, leider erwacht der µC nach dem Schlafenschicken nicht mehr.
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <avr/sleep.h> |
4 | |
5 | |
6 | //Tabellen
|
7 | |
8 | |
9 | |
10 | |
11 | //***********************************************
|
12 | int main(void) |
13 | {
|
14 | TCCR1 = 0b00001111; // Prescaler = CK / 16384 |
15 | TIMSK |= (1 << TOIE1); // Timer1 Overflow Interrupt Enable |
16 | sei(); // Enable Interrrupt |
17 | while(1){} // tue nix und warte auf Timer-int |
18 | // 8MHz / 16384 / 256 = 1,9...Hz
|
19 | }
|
20 | //***********************************************
|
21 | ISR(TIMER1_OVF_vect) |
22 | {
|
23 | static unsigned char n; |
24 | DDRB = DDRB_tab[n]; |
25 | PORTB = PORTB_tab[n]; // LED-Blinky-Zauber |
26 | if(n++ >= 19) n=0; |
27 | |
28 | set_sleep_mode (SLEEP_MODE_PWR_DOWN); |
29 | sleep_mode (); |
30 | }
|
31 | //***********************************************
|
Was kann man tun?
Gokhlayeh schrieb: > Was kann man tun? man sollte das sleep nicht in der ISR aufrufen, das sollte in der main passieren. Ich habe jetzt die doku nicht im Kopf aber der Befehl zum schlafen war meines wissen sleep(); den sehe ich bei dir überhaupt nicht.
Gokhlayeh schrieb: > Was kann man tun? Sleep nicht in 'ner ISR ausführen, da sind Interrupts global disabelt. Müssen aber enabelt sein, damit der nächste Interrupt wieder auslösen kann.
Aus dem Power Down, wir er auch so nie wieder aufwachen, weil der Timmer nicht mehr läuft. vielleicht mal das Tutorial über Sleep Modi durch arbeiten. http://www.mikrocontroller.net/articles/Sleep_Mode Gruß Matthias
Stone schrieb: > Aus dem Power Down, wir er auch so nie wieder aufwachen, weil der Timmer > nicht mehr läuft. Stimmt. Für den Fall des Tiny25 ließe sich nur wie oben bereits vorgeschlagen der WDT-Interrupt missbrauchen. Unabhängig davon sägst Du mit einem Sleep in der ISR den eigenen Ast ab.
So, habe jetzt dieses:
1 | //***********************************************
|
2 | int main(void) |
3 | {
|
4 | TCCR1 = 0b00001111; // Prescaler = CK / 16384 |
5 | TIMSK |= (1 << TOIE1); // Timer1 Overflow Interrupt Enable |
6 | sei(); // Enable Interrrupt |
7 | while(1) |
8 | {
|
9 | set_sleep_mode (SLEEP_MODE_PWR_SAVE); |
10 | sleep_mode(); |
11 | }
|
12 | }
|
13 | /*
|
14 | SLEEP_MODE_IDLE 0
|
15 | SLEEP_MODE_PWR_DOWN 1 wacht nicht auf
|
16 | SLEEP_MODE_PWR_SAVE 2
|
17 | SLEEP_MODE_ADC 3 wacht nicht auf
|
18 | SLEEP_MODE_STANDBY 4 nicht bei ATtiny25
|
19 | SLEEP_MODE_EXT_STANDBY 5 nicht bei ATtiny25
|
20 | */
|
21 | //***********************************************
|
22 | ISR(TIMER1_OVF_vect) |
23 | {
|
24 | static unsigned char n; |
25 | DDRB = DDRB_tab[n]; |
26 | PORTB = PORTB_tab[n]; // LED-Blinky-Zauber |
27 | if(n++ >= 19) n=0; |
28 | }
|
29 | //***********************************************
|
Jetzt mal messen ob bei SLEEP_MODE_IDLE oder bei SLEEP_MODE_PWR_SAVE weniger Stromverbrauch.
Gokhlayeh schrieb: > Jetzt mal messen ob bei SLEEP_MODE_IDLE oder bei SLEEP_MODE_PWR_SAVE > weniger Stromverbrauch. geht auch ohne messen - steht sogar im Datenblatt. > set_sleep_mode (SLEEP_MODE_PWR_SAVE); das musst du nicht jedesmal machen, einmal beim init reicht.
Leider klappts mit dem Schlafen nicht so: Während des Schlafens nuckelt der ATtiny25 ca. 3mA aus der (5V) Batterie. Ich hatte eigentlich mit ein paar µA gerechnet
1 | int main(void) |
2 | {
|
3 | set_sleep_mode (SLEEP_MODE_IDLE); |
4 | TCCR1 = 0b00001111; // Prescaler = CK / 16384 |
5 | TIMSK |= (1 << TOIE1); // Timer1 Overflow Interrupt Enable |
6 | sei(); // Enable Interrrupt |
7 | while(1) |
8 | {
|
9 | //hier steht mein LED-Blinky-Zauber
|
10 | //13,5mA + 7mA Eigenverbrauch gemessen
|
11 | |
12 | DDRB = 0; |
13 | PORTB = 0; |
14 | unsigned char i=30; |
15 | while(i--) sleep_mode(); //leider hier 6mA gemessen |
16 | }
|
17 | }
|
18 | //***********************************************
|
19 | ISR(TIMER1_OVF_vect){TCNT1=14;} |
20 | //***********************************************
|
Vielleicht verwende ich dieses SLEEP_MODE_IDLE falsch? Welchen Sleep-Mode müsste ich denn nehmen, um den Stromverbrauch unter 10µA zu drücken?
Gokhlayeh schrieb: > Vielleicht verwende ich dieses SLEEP_MODE_IDLE falsch? Siehe: Peter Dannegger schrieb: > Der Idle-Mode spart fast nix. Gokhlayeh schrieb: > Welchen Sleep-Mode müsste ich denn nehmen, um den Stromverbrauch unter > 10µA zu drücken? Siehe: Peter Dannegger schrieb: > Du kannst den Watchdoginterrupt nehmen und auf 8s setzen. Und dann ne > Variable zählen, bis 1h rum ist. Peter
@ Gokhlayeh (Gast) >Vielleicht verwende ich dieses SLEEP_MODE_IDLE falsch? Ja. >Welchen Sleep-Mode müsste ich denn nehmen, um den Stromverbrauch unter >10µA zu drücken? PWR_SAVE, siehe Sleep Mode. MFG Falk
leider geht der SLEEP_MODE_PWR_SAVE bei mir irgendwie nicht, der µC schläft nicht ein. Bei SLEEP_MODE_IDLE schläft der µC ein, säuft allerdings noch 3mA. Was tun?
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.