Forum: Mikrocontroller und Digitale Elektronik Sleep Mode beim ATMega16


von Timo (Gast)


Lesenswert?

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

von johnny.m (Gast)


Lesenswert?

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.

von Björn W. (bwieck)


Lesenswert?

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

von Owz (Gast)


Lesenswert?

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

von johnny.m (Gast)


Lesenswert?

@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...

von gerd (Gast)


Lesenswert?

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=

von gerd (Gast)


Lesenswert?

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?

von rene (Gast)


Lesenswert?

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

von gerd (Gast)


Lesenswert?

zu teuer sorry.

gibt es noch eine andere Möglichkeit ausser int oder kompliziert den WDT 
zu verwenden ?

von Werner A. (homebrew)


Lesenswert?

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.

von gerd (Gast)


Lesenswert?

mh? wie funktioniert das dann?

ich initialisere mit HS das komplette Programm

von Werner A. (homebrew)


Lesenswert?

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
Noch kein Account? Hier anmelden.