Forum: Mikrocontroller und Digitale Elektronik Atmega328p wacht nicht auf, wo steckt der Fehler?


von David (Gast)


Lesenswert?

Hallo,
ich möchte meinen MCU alle 2 Sekunden wecken, um ein Sensor kurz zu 
überprüfen und dann wieder schlafen legen lassen. Zusätzlich habe ich in 
der ISR eine Countdown Schaltung programmiert. Mit dem Flag zeige ich an 
wann der MCU alarmieren soll. Leider glaube ich das der MCU gar nicht 
aus dem Schlafmodus aufwacht, denn der Sensor reagiert nicht mehr und 
der Stromverbrauch ist konstant bei 42µA.

1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <avr/interrupt.h>
4
#include <avr/sleep.h>
5
#include <util/delay.h>
6
7
#define F_CPU 8000000L 
8
9
volatile uint8_t flag;
10
11
int main(void)
12
{
13
14
 
15
16
 
17
 DDRC |= (1<<PC5) | (1<<PC4); 
18
 DDRC &= ~(1<<PC3);
19
 
20
 
21
 GTCCR |= (1<<TSM) | (1<<PSRASY);
22
 ASSR |= (1<<AS2); 
23
 TCCR2A |= (1<<WGM21); 
24
 TCCR2B |= (1<<CS22) | (1<<CS21); 
25
 OCR2A = 256-1; 
26
 TIMSK2 |= (1<<OCIE2A); 
27
 GTCCR &= ~(1<<TSM); 
28
 
29
30
 
31
 sei(); 
32
 
33
 
34
 
35
 while(1)
36
    {
37
38
   
39
   set_sleep_mode(SLEEP_MODE_PWR_SAVE);
40
   sleep_mode();
41
 
42
 
43
   
44
   
45
   
46
   PORTC |= (1<<PC4); 
47
   _delay_ms(1); 
48
   
49
   while(!(PINC &= (1<<PINC3)))
50
   {
51
   PORTC |= (1<<PC5); 
52
   }
53
   
54
   PORTC &= ~(1<<PC5); 
55
   PORTC &= ~(1<<PC4); 
56
   
57
   
58
     
59
   while(flag==1)
60
   {
61
   PORTC|= (1<<PC5); 
62
   }
63
   
64
    }
65
 return (0);
66
}
67
68
69
70
71
ISR(TIMER2_COMPA_vect)
72
{
73
 static uint8_t zweitesekunde;
74
 static uint8_t minute=0;
75
 static uint8_t stunde=0;
76
 static uint8_t tag=0;
77
 
78
 zweitesekunde++;
79
 if(zweitesekunde==30)
80
 {
81
 zweitesekunde=0;
82
 minute++;
83
 }
84
    if(minute == 60)
85
    {
86
    stunde++;
87
    minute = 0;
88
    }
89
    if(stunde == 24)
90
    {
91
    stunde = 0;
92
 tag++;
93
 flag=1; 
94
    }
95
 
96
}

von Daniel V. (danvet)


Lesenswert?

David schrieb:
>
1
> 
2
> ....
3
>    while(!(PINC &= (1<<PINC3)))
4
>    {
5
>    PORTC |= (1<<PC5);
6
>    }
7
> 
8
> .....
9
>
10
>    while(flag==1)
11
>    {
12
>    PORTC|= (1<<PC5);
13
>    }
14
> ....
15
>

Deine "while()s" würde ich nochmal überdenken.
Sollte vielleicht "if()" heißen?

von David (Gast)


Lesenswert?

Das erste würde ich so lassen, weil ich solange der Input PINC3 ungleich 
high ist , die LED einschalten möchte und sie auch solange eingeschaltet 
bleiben soll bis der Input wieder zurück auf HIGH geht.

Beim zweiten hast du recht, da die Zeit überschritten wurde und dort die 
LED nur durch resetten zurückgesetzt werden kann.

von Stefan S. (sschultewolter)


Lesenswert?

Solange eines der beiden Abfragen 1 ist, wird dort nichts in den 
Schlafmodus gehen.

Warum dauerhaft die Ports setzen?
1
  while(!(PINC &= (1<<PINC3)))
2
   {
3
   PORTC |= (1<<PC5); 
4
   }
5
   
6
   PORTC &= ~(1<<PC5); 
7
   PORTC &= ~(1<<PC4); 
8
   
9
   
10
     
11
   while(flag==1)
12
   {
13
   PORTC|= (1<<PC5); 
14
   }

von Daniel V. (danvet)


Lesenswert?

David schrieb:
> Das erste würde ich so lassen, weil ich solange der Input PINC3 ungleich
> high ist , die LED einschalten möchte und sie auch solange eingeschaltet
> bleiben soll bis der Input wieder zurück auf HIGH geht.
>
> Beim zweiten hast du recht, da die Zeit überschritten wurde und dort die
> LED nur durch resetten zurückgesetzt werden kann.

Deine Timing-Vorstellungen verstehe ich nicht.
Erst schläfst du 2 Sekunden, dann willst sofort und gleich auf ein 
Eingangssignal reagieren.
Was wenn das Signal innerhalb des 2 Sekundenschlafs kommt?

Funktioniert denn dein Programm ohne Sleep?

Edit:
hier schon geschaut?:
http://www.mikrocontroller.net/articles/Sleep_Mode

: Bearbeitet durch User
von Thomas E. (thomase)


Lesenswert?

David schrieb:
> Zusätzlich habe ich in der ISR eine Countdown Schaltung programmiert.

Sehe ich nicht.

> Mit dem Flag zeige ich an wann der MCU alarmieren soll.

Nach 24 Stunden um 0.00h?

mfg.

von Joachim B. (jar)


Lesenswert?

David schrieb:
> set_sleep_mode(SLEEP_MODE_PWR_SAVE);

womit soll er denn geweckt werden?

möglich wäre:
Timer 2
ext. Interrupts
TWI
Watchdog

wenn er schläft läuft er nicht mehr....

von David (Gast)


Lesenswert?

Ja das Programm funktioniert ohne Sleep funktion wunderbar es geht mir 
eigentlich auch nur um die Sleep Funktion.
Ich habe das Programm jetzt einfach mal vereinfacht, damit es um das 
wesentliche geht, das aufwachen:
1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
#include <avr/sleep.h>
6
7
#define F_CPU 8000000L
8
9
volatile uint8_t flag;
10
11
12
int main(void)
13
{
14
15
  
16
  //konfigurieren der PINS:
17
18
  
19
  DDRC |= (1<<PC5) | (1<<PC4); //Pin pc5 und pc4 als ausgang definieren
20
  //DDRC &= ~(1<<PC3); //Pin pc3 als eingang definieren
21
  
22
  
23
  //Start der Initalisierung des Timer 2:
24
  GTCCR |= (1<<TSM) | (1<<PSRASY); //Timer anhalten, Prescaler Resetten, um die Einschwingzeit des Oszillators zu überbrücken (Einschwingzeit 100ms-1000ms
25
  ASSR |= (1<<AS2); //Timer Asynchron-Mode einschalten 32768 RTC hängt an XTAL1+XTAL2
26
  TCCR2A |= (1<<WGM21); // Versetze in Compare Mode
27
  TCCR2B |= (1<<CS22) | (1<<CS21); //Prescaler auf 256
28
  OCR2A = 256-1; //(=OCR2A Compare Register) Berechnung der Aufwachzeit (32768/256)^-1*256= Aufwachzeit alle 2 Sekunden wird der MCU aufgeweckt
29
  TIMSK2 |= (1<<OCIE2A); //Timer 2 Interrupt Enable
30
  GTCCR &= ~(1<<TSM); //"Timer anhalten Bit" löschen
31
  
32
33
  
34
  sei(); // Global Interrupt Mode aktiviert
35
  
36
  
37
  
38
  while(1)
39
  {
40
    
41
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
42
    sleep_mode();
43
    
44
    
45
    // Hier wird aufgewacht
46
    
47
    if(flag==1)
48
    {
49
      PORTC |= (1<<PC5); //LED anschalten
50
      _delay_ms(100);
51
      PORTC &= ~(1<<PC5); //LED abschalten
52
      flag=0;
53
    }
54
    
55
56
    
57
  }
58
  return (0);
59
}
60
61
62
63
64
ISR(TIMER2_COMPA_vect)
65
{  
66
  flag=1;
67
}

von David (Gast)


Lesenswert?

Joachim B. schrieb:
> David schrieb:
>> set_sleep_mode(SLEEP_MODE_PWR_SAVE);
>
> womit soll er denn geweckt werden?
>
> möglich wäre:
> Timer 2
> ext. Interrupts
> TWI
> Watchdog
>
> wenn er schläft läuft er nicht mehr....

Deswegen habe ich eigentlich den Timer2 in Compare-Mode programmiert, im 
Power Save Mode sollte dann nur Timer 2 mit einem 32,768khz Quarz laufen 
sobald die 2 Sekunden um sind sollte der Interrupt erfolgen und ihn 
aufwecken, der dann das Hauptorogramm weiter ausführt.

von Joachim B. (jar)


Lesenswert?

David schrieb:
> es geht mir
> eigentlich auch nur um die Sleep Funktion.

verstehe ich, nur wenn er schläft schläft er, ich schrieb ja schon die 
Aufwachmöglichkeiten, externer Uhrenquarz am Timer2 32kHz, watchdog, 
oder externer Interrupt.

Ich weiss immer noch nicht wie du den aufwecken willst wenn kein 
watchdaog programmiert ist, kein externer Uhrenquarz dranhängt und kein 
externer Interrupt ausgelöst wird.

von Thomas E. (thomase)


Lesenswert?

Joachim B. schrieb:
> kein externer Uhrenquarz dranhängt

???

mfg.

von David (Gast)


Lesenswert?

Uhrenquarz hängt dran. Fehlt da jetzt was in der Programmierung? :D 
Sorry ich verstehe dich nicht ganz.

von Thomas E. (thomase)


Lesenswert?

David schrieb:
> Uhrenquarz hängt dran. Fehlt da jetzt was in der Programmierung?

Mach mal so:
1
ISR(TIMER2_COMPA_vect)
2
{  
3
  PINC |= (1<<PC5); 
4
}

Wenn die LED jetzt nicht blinkt, läuft der Timer nicht.

mfg.

von Joachim B. (jar)


Lesenswert?

Thomas Eckmann schrieb:
> ???

so ähnlich bei mir auch

also mit sleepmodi hatte ich schon mal das Vergnügen, nur noch nicht mit 
der allgemein beliebten Timer Variante mit dem 32kHz Quarz am extra 
Eingang, nicht dem Systemquarz. Ich las immer davon das der den AVR 
aufwecken kann um alle Skunde die SoftUhr einen weiterlaufen zu lassen. 
Ich bevorzugte die RTC DS3231 die mit ihrem Alarmregister und /INT 
Ausgang am AVR per PCINT weckt, da muss der arme AVR nicht alle Sekunde 
gewckt werden, kann fröhlich pennen bis er wirklich dran ist.

von David (Gast)


Lesenswert?

Leider kein blinken :/
Heißt das, das der Uhrenquarz kaputt ist?

von Thomas E. (thomase)


Lesenswert?

David schrieb:
> Leider kein blinken :/
> Heißt das, das der Uhrenquarz kaputt ist?

Die Konfiguration des Timers ist OK.

Kontrollier erstmal deine Lötstellen auf Verbindung und Kurzschluss, 
bevor du den Quarz abschreibst. Was für Kondensatoren hast du dran?

mfg.

: Bearbeitet durch User
von David (Gast)


Lesenswert?

Das ganze ist auf Breadbord,
die Kondensatoren sind 2 x 27 pF, da ich damals keine 22 pF 
Kondensatoren zur Hand hatte - diese habe ich jetzt aber wieder besorgt, 
soll ich diese mal anbringen?

von Joachim B. (jar)


Lesenswert?

David schrieb:
> sollte dann nur Timer 2 mit einem 32,768khz Quarz

hatte ich überlesen

Thomas Eckmann schrieb:
> ???
>
> mfg.

und wurde im Eröffnungbeitrag auch nicht geschrieben ;-)

von Chris (Gast)


Lesenswert?

Hast du den Quarz zwischen TOSC 1 und TOSC 2?
Sonst klappt es nicht. Da benötigtst du auch keine extra Kondensatoren.

http://www.atmel.com/Images/Atmel-1259-Real-Time-Clock-RTC-Using-the-Asynchronous-Timer_AP-Note_AVR134.pdf

von Thomas E. (thomase)


Lesenswert?

Chris schrieb:
> Hast du den Quarz zwischen TOSC 1 und TOSC 2?
> Sonst klappt es nicht. Da benötigtst du auch keine extra Kondensatoren.

Ja, lass die Kondensatoren ganz weg.
22pF ist sowieso zu gross und 27pF viel zu gross.

mfg.

von David (Gast)


Lesenswert?

Chris schrieb:
> Hast du den Quarz zwischen TOSC 1 und TOSC 2?
> Sonst klappt es nicht. Da benötigtst du auch keine extra Kondensatoren.

Ja hab ich.

Der Timer scheint jetzt zu funktionieren. Aber anstatt alle 2 Sekunden 
zu blinken braucht er jetzt fast 10 sekunden?

1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <util/delay.h>
4
#include <avr/interrupt.h>
5
#include <avr/sleep.h>
6
7
#define F_CPU 8000000L
8
9
volatile uint8_t flag;
10
11
12
int main(void)
13
{
14
15
  
16
  //konfigurieren der PINS:
17
18
  
19
  DDRC |= (1<<PC5) | (1<<PC4); //Pin pc5 und pc4 als ausgang definieren
20
  //DDRC &= ~(1<<PC3); //Pin pc3 als eingang definieren
21
  
22
  
23
  //Start der Initalisierung des Timer 2:
24
  GTCCR |= (1<<TSM) | (1<<PSRASY); //Timer anhalten, Prescaler Resetten, um die Einschwingzeit des Oszillators zu überbrücken (Einschwingzeit 100ms-1000ms
25
  ASSR |= (1<<AS2); //Timer Asynchron-Mode einschalten 32768 RTC hängt an XTAL1+XTAL2
26
  TCCR2A |= (1<<WGM21); // Versetze in Compare Mode
27
  TCCR2B |= (1<<CS22) | (1<<CS21); //Prescaler auf 256
28
  OCR2A = 256-1; //(=OCR2A Compare Register) Berechnung der Aufwachzeit (32768/256)^-1*256= Aufwachzeit alle 2 Sekunden wird der MCU aufgeweckt
29
  TIMSK2 |= (1<<OCIE2A); //Timer 2 Interrupt Enable
30
  GTCCR &= ~(1<<TSM); //"Timer anhalten Bit" löschen
31
  
32
33
  
34
  sei(); // Global Interrupt Mode aktiviert
35
  
36
  
37
  
38
  while(1)
39
  {
40
    _delay_ms(500);
41
    PORTC &= ~(1<<PC5); //LED abschalten
42
43
    
44
    set_sleep_mode(SLEEP_MODE_PWR_SAVE);
45
    sleep_mode();
46
    
47
    
48
    // Hier wird aufgewacht
49
    
50
51
    
52
  }
53
  return (0);
54
}
55
56
57
58
59
ISR(TIMER2_COMPA_vect)
60
{  
61
          PORTC |= (1<<PC5); //LED anschalten
62
}

von David (Gast)


Lesenswert?

Danke es lag tatsächlich an den Kondensatoren!

von Thomas E. (thomase)


Lesenswert?

David schrieb:
> Danke es lag tatsächlich an den Kondensatoren!

Eine Stolperfalle hast du noch drin:

http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR#Wenn_er_die_Minute_in_20s_schafft

mfg.

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.