Go Down

Topic: Arduino Micro sleep modes + watchdog wakeup (Read 350 times) previous topic - next topic

svebert

Jul 05, 2020, 09:31 pm Last Edit: Jul 05, 2020, 09:33 pm by svebert
Hi everyone!

I am using an Arduino MICRO in my project. My goal is it to power the Arduino with a LiPo about 2 weeks. Which does not seem unrealistically...
The same LiPo will also power a small sensor and a SIM 800L Module.
It is all working and I could run the system well over 14h. In this test I did not use any sleep modes, just delay() for idle time. I have read that delay is a "busy waiting" and does need the same amount of power like any other computation on the Arduino.


Now I try to implement the sleep modes, but I fail with the wake up.


This is my code, which is working

Code: [Select]

#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/power.h>

const int ledPin = 13;
const int resetPin = 12;
int cycles = 0;
volatile int i_am_in_sleep = 0;

void setup()
{
  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin,LOW);
  digitalWrite(resetPin, HIGH);
  pinMode(resetPin,OUTPUT);
  i_am_in_sleep = 0;
  watchdogSetup();
}

void watchdogSetup(void){
  cli(); // disable all interrupts
  wdt_reset();
  WDTCSR |= (1<<WDCE) | (1<<WDE);
  WDTCSR = (1<<WDIE) | (0<<WDE) | (1<<WDP3); // 4s / no interrupt, system reset
  sei();
}

void loop()
{
  delay(500);
  digitalWrite(ledPin,HIGH);
  delay(100);
  digitalWrite(ledPin,LOW);
  delay(2000); //after blink you have 2secs to for upload
  digitalWrite(ledPin,HIGH);
  delay(100);
  digitalWrite(ledPin,LOW);
  i_am_in_sleep = 1;
  delay(500);
  while(i_am_in_sleep > 0)
  {
    enter_sleep();
  }
  i_am_in_sleep = 0;
}

void enter_sleep(void)
  /* Arduino schlafen legen */
  {
    sleep_enable();
    set_sleep_mode(SLEEP_MODE_IDLE);
    sleep_cpu();
  }

void hardwarereset()
{
    digitalWrite(resetPin, LOW);
    delay(300);
    digitalWrite(resetPin, HIGH);
    delay(300);
}

ISR(WDT_vect)
{
  cycles += 1;
  Serial.println("wake up?");
  if(i_am_in_sleep> 0)
  {
    if(cycles>3)
    {
      Serial.println("yess! And reset");
      delay(500);
      cycles = 0;
      hardwarereset();
    }
    else
    {
      Serial.println("not yet...");
      delay(500);
    }
  }
  else
  {
        Serial.println("not sleeping...");
  }

}


I have PIN 12 (digital i/o) connected with 1kOhm to Reset-Pin (RS).
Also a LED is connected at PIN 13 and it blinks two times shortly, when the board is awake.
After the two blinks the board goes into  SLEEP_MODE_IDLE.
From the watchdog I get a interrupt every 4secs and when I get the fourth interrupt I do a hardreset via PIN 13. This is all fine.

My problem:
Whatever other SLEEP_MODE I use, the wake up fails.
I want to use
SLEEP_MODE_PWR_DOWN
but I get no interrupt from the watchdog.

All info about sleep modes I find is with Arduino UNO, but I have a MICRO, which has a different ATMega processor. Maybe that is the problem?

1) Did anyone have luck with the Arduino MICRO and other sleep modes than IDLE?

2) I read about external Real Time Clocks to trigger a reset of the Arduino. Are there any cheap and simple solutions to achieve about 10min to 2h wake-up cycles?

3) Should I pick a different Arduino? Which one would offer the deeper sleep modes? I am very happy with the size of the micro. The Uno is too large. But what about the Mini or ProMini? Unfortunatly Mini and Pro Mini do not have a USB connection for programming. I have a FTDI 232 adapter but never used it... i hope its not complicated...

m_k_akash

refer this. you could use this function
Code: [Select]
LowPower.deepSleep(milliseconds);
You asked me and I am here

PaulRB

#2
Jul 06, 2020, 10:24 am Last Edit: Jul 06, 2020, 10:40 am by PaulRB
Quote
I have read that delay is a "busy waiting" and does need the same amount of power like any other computation on the Arduino.
That's not true, it uses just the same power.

refer this. you could use this function
Code: [Select]
LowPower.deepSleep(milliseconds);
That library is for Arduino based on SAMD21 chips, like Zero, MKR1000 etc. Micro uses an atmega32u4.

There is a version of the low power library for atmega328, I'm not certain if it also supports atmega32u4.

EDIT: here is a low power library compatible with atmega32u4.

hzrnbgy

If your goal is to maximize power, I would rewrite your code a little bit to make it simpler


Attached pseudo-code below


Basically, the WDT ISR wakes up the MCU, set a flag (wdtFlag) and increment a counter (wdtCounter)


On the main loop, every time it wakes up, it checks the wdtFlag (which will be true at this point because the interrupt set it), enters the if statement, reset the wdtFlag, and check the wdtCounter. The following if statement determines how often you want to execute your main application code. In my example, if your WDT interrupt triggers every 4 second, your main code is executed every 44 seconds since wdtCounter must be 11 for this to be true. After all is said in done, the MCU goes back to sleep again.

So basically, the Arduino wakes up every 4 seconds, check two variables (wdtFlag and wdtCounter) and depending on the value of wdtCounter, the MCU may or may not execute your main application code. Assuming your main application code takes about 10ms to complete, your Arduino would be asleep 99.75% of the time. If you change the WDT interrupt to do 8 sec instead, the sleep time would be 99.875%. Assuming your main task is code optimized and only takes 1 ms to complete, your power-saving goes all the way to 99.9875%

hzrnbgy

#4
Jul 06, 2020, 11:08 pm Last Edit: Jul 06, 2020, 11:13 pm by hzrnbgy
Going back to your question, looks like WDT interrupt can't wake up the CPU from Power-down mode


From the datasheet:

When the SM2..0 bits are written to 010, the SLEEP instruction makes the MCU enter Power-down mode. In
this mode, the external Oscillator is stopped, while the external interrupts, the 2-wire Serial Interface, and the
Watchdog continue operating (if enabled). Only an External Reset, a Watchdog Reset, a Brown-out Reset, 2-
wire Serial Interface ad
dress match, an external level interrupt on INT6, an external interrupt on INT3:0, a pin
change interrupt or an asynchronous USB interrupt sources (VBUSTI, WAKEUPI), can wake up the MCU.

It doesn't mention WDT interrupt as a wake-up source


edit:

The table on page 44 of the datasheet do show WDT interrupt as a wakeup source in Power-down mode...

Go Up