AVR (AT90USB162) - Sleep Mode und PCINT

#7612704
Lesenswert?

Hallo,

ich habe hier einen AT90USB162 und möchte ihn nach dem Schlafenlegen mit einem Pin Change Interrupt an PB4 wieder aufwecken. Das soll mit einer LED an PB5 optisch angezeigt werden. Leider lässt sich der Contrller nicht mehr aufwecken, nachdem er im Power Down Modus ist.

Kann mir jemand vielleicht erlären woran das liegen kann?

1
/*
2
 *
3
 *  Program for sleep mode with pin change interrupt
4
 *  2024
5
 *
6
 */
7

8
#ifndef F_CPU        // Include guards
9
#define F_CPU 8000000UL    // AT90USB162 runs at 8 MHz clock speed - unsigned long
10
#endif            // Include guards
11

12
//#include <stdint.h>    // Integer variable
13
#include <avr/io.h>      // I/O ports
14
#include <util/delay.h>    // Delay function
15
#include <avr/sleep.h>    // Sleep mode
16
#include <avr/interrupt.h>  // Interrupt implemention
17
//#include <avr/wdt.h>    // Watchdog timer
18

19

20
/***************************************************
21
 *
22
 *  Description: Interrupt service routine
23
 *
24
 ***************************************************/
25
ISR(PCINT0_vect){      // Port B, PCINT0 - PCINT7
26
}
27

28

29
/***************************************************
30
 *
31
 *  Description: Main program
32
 *
33
 ***************************************************/
34
int main(void){
35
  
36
  DDRB &= ~(1 << PB4);  // PB4/Button as input
37
  DDRB |= (1 << PB5);    // PB5/LED as output
38
  
39
  cli();
40
  PCICR |= (1 << PB4);    // turn on port b
41
  PCMSK0 |= (1 << PB4);    // turn on pin PB4, which is PCINT4
42
  sei();
43
  
44
  PORTB |= (1<<PB5);    // PB5/LED on - LOW -> HIGH
45
  _delay_ms(500);      // Delay
46
  PORTB &= ~(1<<PB5);    // PB5/LED off - HIGH -> LOW
47
  _delay_ms(500);      // Delay
48

49

50
  // Sleep mode list
51
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
52
  //  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
53
  //  set_sleep_mode(SLEEP_MODE_STANDBY);
54
  //  set_sleep_mode(SLEEP_MODE_EXT_STANDBY);
55
  //  set_sleep_mode(SLEEP_MODE_IDLE);
56
  //  set_sleep_mode(SLEEP_MODE_ADC);
57
  //  sleep_bod_disable();
58

59
  sleep_mode();    // Start sleep mode
60
}
Angehängte Dateien:
#7612798
Lesenswert?

Mirko schrieb:

Kann mir jemand vielleicht erlären woran das liegen kann?

Forum: Projekte & Code

Hier könnt ihr Projekte, Schaltungen oder Codeschnipsel vorstellen. Projekte bitte nur mit Code oder Schaltplan posten (falls ihr nur Fotos vorstellen möchtet, bitte in "Zeigt her eure Kunstwerke"). Bitte hier keine Fragen posten.

Diese Formulierung ist offenbar zu komplizert.

#7613233
Lesenswert?

Hallo

Peter D. schrieb:

Mainloop vergessen. Er wacht auf und verläßt das Main.

Danke, eigentlicht logisch...

S. L. schrieb:

PCICR |= (1 << PB4); // turn on port b

Stimmt auch nicht, stattdessen: 'PCICR |= (1<<PCIE0);'

Vielen Dank, hätte es aber auch einfach im Datenblatt nachlesen können :D Manchmal sieht man den Wald vor lauter Bäumen nicht.

Vielen herzlichen Dank für euren Input. Es scheint jetzt soweit für mich zu funktionieren.

Nur noch eine kleine Bonusfrage: Bei mir reagiert der Controller nicht sofort nachdem er in den Schlaf geschickt wurde auf den PCINT. Benötigt der Controller eine Art "Einschlafzeit" bis er heruntergefahren ist? Bei mir braucht er etwa 3-4 Sekunden.

#7613876
Lesenswert?

Dietrich L. schrieb:

Mirko schrieb:

Da muss ich mich zu gegebener Zeit erst noch einlesen. Danke dazu!

Für meinen jetzigen Anwendungsfall als Alarm an einer Kühlschranktür funktioniert es soweit ersteinmal.

Wie ist der Eingang PB4 denn beschaltet? Wenn die Kühlschranktür einen einfachen Kontakt liefert brauchst du einen Ziehwiderstand - ja nach Verschaltung nach GND oder VCC.

Der PB4 hat einen 10kOhm Pullup Widerstand.

#7614374
Lesenswert?

Peter D. schrieb:

Mirko schrieb:

Bei mir reagiert der Controller nicht sofort nachdem er in den Schlaf geschickt wurde auf den PCINT.

Die Hauptfrage ist aber, wie stellst Du das fest?

Ich habe den Türkontakt mehrmals ausgelöst, direkt nachdem der Controller eingeschlafen ist. Eine LED zeigt mir, wann der MCU schläft oder wach ist.

Ich kann es aber auch noch gerne nachmessen...

Hmm.. könnte es ein Fehler im Code sein??

1
/*
2
 *
3
 *  Program for a door watch with sleep mode and pin change interrupt wake up
4
 *  2024
5
 *
6
 */
7

8

9
#include <stdint.h>      // Integer variable
10
#include <avr/io.h>      // I/O ports
11
#include <util/delay.h>    // Delay function
12
#include <avr/sleep.h>    // Sleep mode
13
#include <avr/interrupt.h>  // Interrupt implemention
14
#include <avr/wdt.h>    // Watchdog timer
15

16
#ifndef F_CPU        // Include guards
17
#define F_CPU 8000000UL    // AT90USB162 runs at 8 MHz clock speed - unsigned long
18
#endif            // Include guards
19

20

21
/***************************************************
22
 *  Name:        ISR(PCINT0_vect)
23
 *
24
 *  Returns:     Nothing.
25
 *
26
 *  Parameters:  None.
27
 *
28
 *  Description: Interrupt service routine
29
 *
30
 ***************************************************/
31
ISR(PCINT0_vect){      // Port B, PCINT0 - PCINT7
32
}
33

34

35
/***************************************************
36
 *  Name:        status
37
 *
38
 *  Returns:     Nothing.
39
 *
40
 *  Parameters:  None.
41
 *
42
 *  Description: Status indication.
43
 *
44
 ***************************************************/
45
void status (){
46
  PORTB |= (1 << PB5);
47
  _delay_ms (1000);
48
  PORTB &= ~(1 << PB5);
49
  _delay_ms (1000);
50
}
51

52

53
/***************************************************
54
 *  Name:        open
55
 *
56
 *  Returns:     Nothing.
57
 *
58
 *  Parameters:  None.
59
 *
60
 *  Description: Indication for door is open.
61
 *
62
 ***************************************************/
63
void open (){
64
  PORTB |= (1 << PB6);
65
  _delay_ms (1000);
66
  PORTB &= ~(1 << PB6);
67
  _delay_ms (1000);
68
}
69

70

71
/***************************************************
72
 *  Name:        alarm
73
 *
74
 *  Returns:     Nothing.
75
 *
76
 *  Parameters:  None.
77
 *
78
 *  Description: Alarm.
79
 *
80
 ***************************************************/
81
void alarm (){
82
  PORTB |= (1 << PB5);
83
  PORTB |= (1 << PB6);
84
  _delay_ms (1000);
85
  PORTB &= ~(1 << PB5);
86
  PORTB &= ~(1 << PB6);
87
  _delay_ms (1000);
88
}
89

90

91
/***************************************************
92
 *  Name:        main(void)
93
 *
94
 *  Returns:     Nothing.
95
 *
96
 *  Parameters:  None.
97
 *
98
 *  Description: Main program
99
 *
100
 ***************************************************/
101
int main(void){
102

103
    // I/O Pin setup
104
    DDRB &= ~(1 << PB4);    // Pin PB4 as input - Button
105
    DDRB |= (1 << PB5);      // Pin PB5 as output - green LED
106
    DDRB |= (1 << PB6);      // Pin PB6 as output - Buzzer/ red LED
107

108
    // Variables
109
    uint8_t counter = 0;    // Variable for counting the clock cycles how long the door was open
110

111
  // Main loop
112
  while (1){
113

114
    status();                      // Status blink
115

116
    if (PINB & (1 << PB4) && (counter < 2)){      // If button PB4 pressed = door open (HIGH -> LOW)
117
      for (uint8_t i = 0; i <= 2; i++){        // Loop until it checks input again (2 times)
118
        open();                    // Door open indication
119
      }
120
      counter += 1;                  // Counts up for how many times is input "door open" checked
121
    }
122

123
    if (PINB & (1 << PB4) && (counter == 2)){      // If button PB4 still pressed = door still open (HIGH -> LOW)
124
      for (uint8_t i = 0; i <= 2; i++){        // Loop until it checks input again (2 times)
125
        alarm();                  // Door to long open -> alarm
126
      }
127
    }
128

129
    if ((!(PINB & (1 << PB4))) && (counter <= 2)){    // If button PB4 released = door closed and wasn't open before or closed for a while (LOW -> HIGH)
130
      counter = 0;                  // Reset counter
131
      
132
      // Pin change interrupt setup
133
      cli();                      // Disable interrupt for programming
134
      PCICR |= (1<<PCIE0);              // Turn on port b
135
      PCMSK0 |= (1 << PB4);              // Turn on pin PB4, which is PCINT4
136
      sei();                      // Enable interrupt
137

138
      // Sleep mode list
139
      set_sleep_mode(SLEEP_MODE_PWR_DOWN);
140
//      set_sleep_mode(SLEEP_MODE_PWR_SAVE);
141
//      set_sleep_mode(SLEEP_MODE_STANDBY);
142
//      set_sleep_mode(SLEEP_MODE_EXT_STANDBY);
143
//      set_sleep_mode(SLEEP_MODE_IDLE);
144
//      set_sleep_mode(SLEEP_MODE_ADC);
145

146
      sleep_mode();                  // Start sleep mode
147
    }
148
  }
149
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren