Hello everyone!
I'm using a SAMD51 board and currently trying to make it sleep to save some power. I'm using Adafruit_SleepyDog library to make it sleep and wakeup, with a basic code. The Built in LED is blinking like it should, meaning that the board is sleeping and waking it up. However, I can't access the USB after it wakes up.
// just to make sure that this isn't the problem
#define __SAMD51__
#define ARDUINO_ARCH_SAMD
#include <Adafruit_SleepyDog.h>
int times = 0;
int sleepMS = 0;
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); // Show we're awake
Serial.begin(115200);
while(!Serial); // wait for Arduino Serial Monitor (native USB boards)
Serial.println("Adafruit Watchdog Library Sleep Demo!");
Serial.println();
}
void loop() {
Serial.println("Going to sleep in one second...");
delay(3000);
// Serial.println("USBDevice.detach");
// USBDevice.detach();
digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
sleepMS = Watchdog.sleep(4000);
digitalWrite(LED_BUILTIN, HIGH); // Show we're awake again
// Try to reattach USB connection on "native USB" boards (connection is
// lost on sleep). Host will also need to reattach to the Serial monitor.
// Seems not entirely reliable, hence the LED indicator fallback.
// USBDevice.init();
// USBDevice.attach();
Serial.print("I'm awake now! I slept for ");
Serial.print(sleepMS, DEC);
Serial.println(" milliseconds.");
Serial.println();
times += 0;
}
I added some comments in the SleepyDog function to know where the USB problem happens. The USB connection happens after the __WFI(), that is when the board goes to sleep, and I do agree that this should happen. The problem is that the USB doesn't come back after it.
sleep: int WatchdogSAMD::sleep(int maxPeriodMS)
enable: int WatchdogSAMD::enable(int maxPeriodMS, bool isForSleep)
_initialize_wdt: Before USB->DEVICE.CTRLA.bit.ENABLE = 0;
_initialize_wdt: After USB->DEVICE.CTRLA.bit.ENABLE = 1;
enable: #if defined(__SAMD51__)
enable: After maxPeriodMS and cycles
enable: #if defined(__SAMD51__)
enable: if (isForSleep)
sleep: #if defined(__SAMD51__)
sleep: before __DSB() and __WFI()
The next step was to add USBDevice.detach() before the board goes to sleep and USBDevice.init(); USBDevice.attach(); after it awakes. The only difference is that after the board awakes, the stop running and never sleeps again.
Serial.println("USBDevice.detach");
USBDevice.detach();
digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
sleepMS = Watchdog.sleep(4000);
digitalWrite(LED_BUILTIN, HIGH); // Show we're awake again
// Try to reattach USB connection on "native USB" boards (connection is
// lost on sleep). Host will also need to reattach to the Serial monitor.
// Seems not entirely reliable, hence the LED indicator fallback.
USBDevice.init();
USBDevice.attach();
To make sure that the problem isn't with the USBDevice, I removed the Watchdog and used a simple delay and it worked, the USB "goes out", wait for the delay and them "comes back" and print in the Serial Monitor.
Serial.println("Going to sleep in three second...");
delay(2500);
digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
USBDevice.detach();
delay(2500);
digitalWrite(LED_BUILTIN, HIGH); // Show we're awake again
USBDevice.init();
USBDevice.attach();
delay(5000);
Serial.print("I'm awake now! I slept for ");
Serial.print(sleepMS, DEC);
Serial.println(" milliseconds.");
Serial.println();
times += 0;
