EmbDev.net

Forum: µC & Digital Electronics Atmega328PU wake up with a long button press


von Maurice W. (iciwi)


Rate this post
useful
not useful
Hello there,

I'm working on a new project. One important topic is to save power in 
standalone Atmega 328PU. The microcontroller is into a deep sleep mode 
and should only wake up after the button was pressed for over 3 seconds. 
I wrote the following two codes.


1
#define LED_PIN 13
2
void setup() {
3
// put your setup code here, to run once:
4
pinMode(LED_PIN, OUTPUT);
5
//Save Power by writing all Digital I0 LOW 
6
for(int i=0; i<20; i++){
7
  if(i != 2)//just because the button is hooked up to digital pin 2
8
    pinMode(i, OUTPUT);
9
  }
10
11
  attachInterrupt(0, digitalInterrupt, FALLING); //interrupt for waking up
12
}
13
14
void loop() {
15
  // put your main code here, to run repeatedly:
16
digitalWrite(LED_PIN, HIGH);
17
delay(1000);
18
digitalWrite(LED_PIN, LOW);
19
20
//DISABLE ADC
21
ADCSRA &= ~(1<<7);
22
//ENABLE SLEEP
23
SMCR |= (1<<2); //power down mode
24
SMCR |= 1; //enable sleep
25
26
//BOD DISABLE
27
MCUCR |=(3 << 5); //set both BODS and BODSE at the same time
28
MCUCR = (MCUCR & ~(1 << 5)) | (1<< 6); //then set the BODS bit and clear the BODS bit at the same time
29
__asm__ __volatile__("sleep");
30
}
31
32
void digitalInterrupt(){
33
  //needed for the digital input interrupt
34
}



1
int inPin = 2;  // the pin number for input (for me a push button)
2
int ledPin = 13; 
3
4
int current;         // Current state of the button
5
                     // (LOW is pressed b/c i'm using the pullup resistors)
6
long millis_held;    // How long the button was held (milliseconds)
7
long secs_held;      // How long the button was held (seconds)
8
byte previous = HIGH;
9
unsigned long firstTime; // how long since the button was first pressed 
10
11
12
void setup() {
13
  pinMode(ledPin, OUTPUT);
14
  digitalWrite(inPin, HIGH);  // Turn on 20k pullup resistors to simplify switch input
15
}
16
17
void loop() {
18
  current = digitalRead(inPin);
19
20
  // if the button state changes to pressed, remember the start time 
21
  if (current == LOW && previous == HIGH) {
22
    firstTime = millis();
23
  }
24
25
  millis_held = (millis() - firstTime);
26
  secs_held = millis_held / 1000;
27
28
    if (current == LOW && previous == LOW) {
29
30
      // If the button was held for more then 3 seconds blink LED 1 time
31
      if (secs_held >= 3) {
32
        ledblink(1,4000,ledPin); 
33
      }
34
35
    }
36
  
37
38
  previous = current;
39
40
}
41
42
// Just a simple helper function to blink an led in various patterns
43
void ledblink(int times, int lengthms, int pinnum){
44
  for (int x=0; x<times;x++) {
45
    digitalWrite(pinnum, HIGH);
46
    delay (lengthms);
47
    digitalWrite(pinnum, LOW);
48
    delay(lengthms);
49
  }
50
}


The first code is for the deep sleep mode and wakes the Atmega 328PU up 
after an external interrupt.
The second code is a normal code (without any power saving option) and 
reads the digital input and sets a timer if the button was pressed. If 
the timer is over 3 seconds and the button is still pressed something 
will happen (for example a LED will flash).

So now my question is how to combine them? Is there any way to do that?
I hope somebody can help me :) I'm looking forward to your replies.

Best regards

Maurice W.

: Moved by Moderator
von Stefan Us (Guest)


Rate this post
useful
not useful
You have to wake up immediately when the button interrupt comes in. Then 
you can measure how long it is pressed and go back to sleep when the 
time was too short.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.