1
\$\begingroup\$

I am trying to reduce the current consumption of my Atmega328 -Arduino- by using the sleep modes. In my code, I want to wake-up every 10ms, read the value from ADC, and go to the sleep mode again.

There are some useful instructions (here and here), but most of them are either based on Watch Dog Timre or external interrupt from pins.

Here is the simplified code of mine, but doesn't work (it doesn't go to the interrupt handler function):

In the setup, I take care of the Timer and its handler:

void setup() {
 Serial.begin(19200);
 Timer1.initialize(10000); //10ms sampling rate
 Timer1.attachInterrupt(ReadMyADC,10000);
 power_spi_disable(); // SPI
 power_timer0_disable();// Timer 0
}

The rest of the code including loop() is as follows:

void ReadMyADC(){
 sleep_disable();
 PRR = PRR & 0b00000000;
 Serial.print("sth");
 power_adc_enable(); // ebable ADC converter
 //Read ADC
 power_adc_disable();
}
void loop() {
 // ----------------low power ---------------
 PRR = PRR | 0b00100000;
 sleep_enable();
 set_sleep_mode(SLEEP_MODE_STANDBY);
 EIMSK |= _BV(INT0); //enable INT0
 ADCSRA = 0; //disable ADC
 cli();
 mcucr1 = MCUCR | _BV(BODS) | _BV(BODSE); //turn off the brown-out detector
 mcucr2 = mcucr1 & ~_BV(BODSE);
 MCUCR = mcucr1;
 MCUCR = mcucr2;
 sei(); //ensure interrupts enabled so we can wake up again
 sleep_cpu(); //go to sleep
 sleep_disable(); //wake up here
 Serial.print("Wake\n");
}

Apparently, Timer1 is not able to exit the cpu from sleep mode. Do you have any idea how to manage that, or where the problem is?

asked Mar 18, 2017 at 13:45
\$\endgroup\$
1
  • \$\begingroup\$ Look at the data sheet for the Atmega. You'll find that for all deeper sleep modes than idle and adc noise reduction mode only the wdt, an external interrupt, or an asynchronous timer (external 32kHz quartz) can wake up the CPU. \$\endgroup\$ Commented Mar 18, 2017 at 14:39

2 Answers 2

3
\$\begingroup\$

Deeper sleep modes turn off more of the chip to reduce current consumption.

The deeper modes turns off the timer counters since they consume quite a bit of current.

Use the watchdog timer in interrupt mode instead, or for max power down, use a micro driven external RC decay to interrupt the micro after a short period.

answered Mar 18, 2017 at 16:08
\$\endgroup\$
1
  • \$\begingroup\$ the watchdog timer does not support interrupts with higher frequency than 64Hz. So, it seems that for a frequency of 100Hz, I need to use Timer1 at SLEEP_MODE_IDLE with unnecessary peripherals shut down. \$\endgroup\$ Commented Mar 19, 2017 at 11:10
1
\$\begingroup\$

Sleep_Mode_Standby does not allow Timer1 to run since the clock domain is turned off. You can only use Timer1 in Sleep_Mode_Idle, your code should work if you use that mode.

Use the WDT since it has it's own clock at 128 kHz that is enabled whenever it is on.

Code such as this may work for you:

#include <avr/sleep.h>
#include <avr/wdt.h>
void setup () { }
const byte LED = 13; //Nano LED
void flashLED ()
{
 pinMode (LED, OUTPUT);
 // Flash the LED 
 for (byte i = 0; i < 10; i++)
 {
 digitalWrite (LED, HIGH);
 delay (50);
 digitalWrite (LED, LOW);
 delay (50);
 }
 } 
// Watchdog ISR routine
ISR (WDT_vect) 
{
 wdt_disable(); // disable watchdog
 // Return from ISR
} 
void loop () 
{
 flashLED ();
 // disable ADC
 ADCSRA = 0; 
 // clear all MCUSR flags
 MCUSR = 0; 
 // allow changes, disable reset pin
 WDTCSR = bit (WDCE) | bit (WDE);
 // set interrupt mode and an interval 
 WDTCSR = bit (WDIE) | bit (WDP2) | bit (WDP1) | bit (WDP0); // set WDIE, and 2 second WDT delay
 wdt_reset(); // Start the timer
 set_sleep_mode (SLEEP_MODE_PWR_DOWN); 
 noInterrupts (); // timed sequence follows
 sleep_enable();
 // turn off brown-out detector
 MCUCR = bit (BODS) | bit (BODSE);
 MCUCR = bit (BODS); 
 interrupts ();
 sleep_cpu (); 
 // Sleep here in powerdown state
 // Return here after WDT return from ISR 
 // disable sleep
 sleep_disable();
 // Do your thing here
 }
answered Mar 18, 2017 at 23:11
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.