Hi forum,
I've been searching the forum to solve a problem but couldn't find answer yet, so I'm asking for your help.
I have my custom board working, based on Arduino M0 pro (SAMD21G18A); I can get it into sleep mode for the time I need (tested with 1min/10 min/30 min/etc...) but I also want to insert a wake up from pin and back to sleep again. Wakeup from pin is also working but it resets my sleep time each time it wakes from pin. So if the order is to sleep for 10min, and after 5min it wakes up from PIN, it will go back to sleep but for 10 min, not for the remaining 5min...
here's simple code to count how many times it wakes up:
#define SLEEP_TIME 10
uint16_t wake_up_count=0;
void int_handle ()
{
wake_up_count++;
}
void setup()
{
SerialDEBUG.begin(115200);
delay(100);
pinMode(WAKE_UP_PIN, INPUT_PULLUP);
LowPower.attachInterruptWakeup(WAKE_UP_PIN, int_handle, CHANGE);
}
void loop()
{
// do stuff
LowPower.sleep(1000 * SLEEP_TIME); //go to sleep
delay(5000); // to allow manual connection to serial port
SerialDEBUG.print(" Wake UP count == "); SerialDEBUG.println(wake_up_count,DEC);
delay(100);
}
Wakeup from pin is also working but it resets my sleep time each time it wakes from pin.
You should be able to call the LowPower.sleep() function (without millis), after the microcontroller has been woken up by an interrupt. This will put microcontroller to sleep once more, but without affecting the RTC alarm.
By the way, in order for the wake_up_count variable to be used in both the loop() function and the int_handle() interrupt service routine, it needs to be made volatile:
Hi Martin.
Thanks for your reply!
I did try your suggestion to add "LowPower.sleep()" to the function handling the PIN interrupt but it did not work.
it seems it will sleep forever after a PIN interrupt detection. The idea was to continue the "count-down" from LowPower.sleep(1000 * SLEEP_TIME), at the point where it was at the moment of PIN interrupt.
// Arduino Low Power Library Test
#include <ArduinoLowPower.h>
#define SLEEP_TIME 10 // Sleep time in seconds
volatile boolean interrupt = false; // Interrupt flag
boolean toggle = false;
void setup()
{
pinMode(8, INPUT_PULLUP); // Configure the external interrupt and callback function on FALLING edge
LowPower.attachInterruptWakeup(8, extInterrupt, FALLING);
pinMode(LED_BUILTIN, OUTPUT); // Configure the LED output
}
void loop()
{
LowPower.sleep(SLEEP_TIME * 1000); // Put the microcontroller to sleep for 10 seconds, Zzzzz...
digitalWrite(LED_BUILTIN, toggle); // Toggle the LED
toggle = !toggle; // Flip the toggle
if (interrupt == true) // If an external interrupt has occured
{
interrupt = false; // Clear the interrupt flag
LowPower.sleep(); // Put the microcontroller to sleep once more
digitalWrite(LED_BUILTIN, toggle); // Toggle the LED
toggle = !toggle; // Flip the toggle
}
}
void extInterrupt()
{
interrupt = true; // Set the interrupt flag
}
Thanks again MartinL, and sorry for late reply.
Still have issues with this code... after external pin wake-up it goes to sleep, but always restart the sleep time count; so, it doesn't wake-up after the remaining time left, btu restart sleep timer.
Hare able to test it, to check if I'm doing something wrong here?
I finally managed to get it work, but with LowPower and RTCzero libs (using "epoch" option).
On external pin wake-up it reads epoch and thus I know how much more time it needs to sleep
Now I've added a watchdog to it... using WDTZero lib. The thing is I cannot have more than 8 minutes on watchdog timer. Is there a another lib I can use, that will manage WD in sleep mode?
The WDT is not really suited to counting over long durations and normally operates up to 16 seconds.
This is usually achieved using the Ultra Low Power 32.768kHz Oscillator (OSCULP32K) divided down to 1.024kHz and the WDT's timer set to trigger after 16384, (16384 / 1.024kHz = 16s).