PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Arduino/Atmega328PU wake up with a long button press



iciwi
04.08.2016, 09:49
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.



#define LED_PIN 13
void setup() {
// put your setup code here, to run once:
pinMode(LED_PIN, OUTPUT);
//Save Power by writing all Digital I0 LOW
for(int i=0; i<20; i++){
if(i != 2)//just because the button is hooked up to digital pin 2
pinMode(i, OUTPUT);
}

attachInterrupt(0, digitalInterrupt, FALLING); //interrupt for waking up
}

void loop() {
// put your main code here, to run repeatedly:
digitalWrite(LED_PIN, HIGH);
delay(1000);
digitalWrite(LED_PIN, LOW);

//DISABLE ADC
ADCSRA &= ~(1<<7);
//ENABLE SLEEP
SMCR |= (1<<2); //power down mode
SMCR |= 1; //enable sleep

//BOD DISABLE
MCUCR |=(3 << 5); //set both BODS and BODSE at the same time
MCUCR = (MCUCR & ~(1 << 5)) | (1<< 6); //then set the BODS bit and clear the BODS bit at the same time
__asm__ __volatile__("sleep");
}

void digitalInterrupt(){
//needed for the digital input interrupt
}






int inPin = 2; // the pin number for input (for me a push button)
int ledPin = 13;

int current; // Current state of the button
// (LOW is pressed b/c i'm using the pullup resistors)
long millis_held; // How long the button was held (milliseconds)
long secs_held; // How long the button was held (seconds)
byte previous = HIGH;
unsigned long firstTime; // how long since the button was first pressed


void setup() {
pinMode(ledPin, OUTPUT);
digitalWrite(inPin, HIGH); // Turn on 20k pullup resistors to simplify switch input
}

void loop() {
current = digitalRead(inPin);

// if the button state changes to pressed, remember the start time
if (current == LOW && previous == HIGH) {
firstTime = millis();
}

millis_held = (millis() - firstTime);
secs_held = millis_held / 1000;

if (current == LOW && previous == LOW) {

// If the button was held for more then 3 seconds blink LED 1 time
if (secs_held >= 3) {
ledblink(1,4000,ledPin);
}

}


previous = current;

}

// Just a simple helper function to blink an led in various patterns
void ledblink(int times, int lengthms, int pinnum){
for (int x=0; x<times;x++) {
digitalWrite(pinnum, HIGH);
delay (lengthms);
digitalWrite(pinnum, LOW);
delay(lengthms);
}
}



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.

Ceos
04.08.2016, 10:44
your main problem here is, making the timer in software makes your sleep mode useless, the moment the interrupt is called, the controller leaves it's sleep mode immediately to execute your Interrupt Service Routine (ISR)

you need to make it a bit more complicated to achive this with maximum efficiency


loop_code(){
if(buttonisreleased())
prepare_deep_sleep();
sleeping = TRUE;
//enter sleep, store the sleep status to some variable like sleeping = TRUE (important!!!)
while(sleeping){
execute_sleep();
}
}
}
ISR(external_interrupt)
{
if(buttonhasbeenpressed()){
start_timer();
prepare_low_power_sleep_with_timer();
else if(buttonhasbeenreleased()){
stop_timer();
prepare_deep_sleep();
sleeping = TRUE;
}
}
ISR{timer_reached_3s)
{
sleeping = FALSE;
}


when the button is not pressed, the cpui enters deep sleep until you press the button

whenever an ISR is returning, it re-enters the normal execution, the call after your sleep(), so when the button is pressed but sleep remains true(because your time dod not run out yet), you automatically returns to lo power mode, waiting for either the timer to execute an interrupt or the button to be released

when you release the button too early, the timer is stopped and deep sleep is re-entered
when the timer runs up, the sleeping variable is set to false and the sleep loop is left until you again release the button!

HeXPloreR
04.08.2016, 16:57
Mein lieber (Funk-)freund,

was stimmt mit Dir nicht?

Nein, du bist hier nicht richtig! Findest du es nicht ziemlich unhöflich in diese Unterhaltung hereinzuplatzen??

Bitte kann ein Moderator, oder höher, den Thread selbstständig machen. Dieser Beitrag hier darf/kann/soll dann bitte entfernt werden.

Viele Grüße
Jörg

Ceos
05.08.2016, 06:38
@HeXPloreR unter dem Beitrag, links neben "Blog-Eintrag" kannst du auf dieses Dreieck mit Ausrufezeichen klicken und den Post melden (hab ich auch gerade gemacht). Ich mag solche Dreistigkeit ebenfalls überhaupt nicht!