SAMD51 Thing Plus - Sleep Mode

Hello everyone,

I am setting the board to sleep after doing some basic tasks. Both, the sleeping and the tasks are working. However, The max sleep time that I managed to get is 16 seconds.

Inside Sleepy Dogs library, it is possible to find this explanation:

// Watchdog timer on SAMD is a slightly different animal than on AVR.
  // On AVR, the WTD timeout is configured in one register and then an
  // interrupt can optionally be enabled to handle the timeout in code
  // (as in waking from sleep) vs resetting the chip.  Easy.
  // On SAMD, when the WDT fires, that's it, the chip's getting reset.
  // Instead, it has an "early warning interrupt" with a different set
  // interval prior to the reset.  For equivalent behavior to the AVR
  // library, this requires a slightly different configuration depending
  // whether we're coming from the sleep() function (which needs the
  // interrupt), or just enable() (no interrupt, we want the chip reset
  // unless the WDT is cleared first).  In the sleep case, 'windowed'
  // mode is used in order to allow access to the longest available
  // sleep interval (about 16 sec); the WDT 'period' (when a reset
  // occurs) follows this and is always just set to the max, since the
  // interrupt will trigger first.  In the enable case, windowed mode
  // is not used, the WDT period is set and that's that.
  // The 'isForSleep' argument determines which behavior is used;
  // this isn't present in the AVR code, just here.  It defaults to
  // 'false' so existing Arduino code works as normal, while the sleep()
  // function (later in this file) explicitly passes 'true' to get the
  // alternate behavior.

So, I just want to be sure, is it possible to sleep for more than 16 seconds or the only way to do this is to set a while together with the sleep function?

I don’t mind if you guys suggests using another library or code.

You might ask what code I’m using, so here it is (https://github.com/adafruit/Adafruit_Sl … /Sleep.ino).

// Adafruit Watchdog Library Sleep Example
//
// Simple example of how to do low power sleep with the watchdog timer.
//
// Author: Tony DiCola

#include <Adafruit_SleepyDog.h>

void setup() {
  // For boards with "native" USB support (e.g. not using an FTDI chip or
  // similar serial bridge), Serial connection may be lost on sleep/wake,
  // and you might not see the "I'm awake" messages. Use the onboard LED
  // as an alternate indicator -- the code turns it on when awake, off
  // before going to sleep.
  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(1000);
 
  // To enter low power sleep mode call Watchdog.sleep() like below
  // and the watchdog will allow low power sleep for as long as possible.
  // The actual amount of time spent in sleep will be returned (in
  // milliseconds).
  digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
  int sleepMS = Watchdog.sleep();

  // Alternatively you can provide a millisecond value to specify
  // how long you'd like the chip to sleep, but the hardware only
  // supports a limited range of values so the actual sleep time might
  // be smaller.  The time spent in sleep will be returned (in
  // milliseconds).
  // int sleepMS = Watchdog.sleep(1000);  // Sleep for up to 1 second.

  // Code resumes here on wake.

  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.
#if defined(USBCON) && !defined(USE_TINYUSB)
  USBDevice.attach();
#endif

  Serial.print("I'm awake now! I slept for ");
  Serial.print(sleepMS, DEC);
  Serial.println(" milliseconds.");
  Serial.println();
}

Tags to make the post easier to find:

#SleepyDog #Watchdog #SAMD51 #ThingPlus #PowerSaver

I’m testing it with a SparkFun Thing Plus - SAMD51.

With this code, even though I can still see the USB, I can’t print anything. However the code is still working, except for the Serial, the LED keep blinking in the correct time.

  digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
  sleepMS = Watchdog.sleep(4000);
  digitalWrite(LED_BUILTIN, HIGH); // Show we're awake again
  USBDevice.attach();
  delay(2500);

With USBDevice parts it doesn’t work a second time. The led goes on, then off when sleeping, on again when it awakes than nothing more, it gets stuck somewhere.

  USBDevice.detach();
  digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
  sleepMS = Watchdog.sleep(4000);
  digitalWrite(LED_BUILTIN, HIGH); // Show we're awake again
  USBDevice.init();
  USBDevice.attach();

If I use the Watchdog.enable() to make it reset, the USB comes back, but this is far from a good solution.

Full code:

#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);

  USBDevice.detach();
  digitalWrite(LED_BUILTIN, LOW); // Show we're asleep
  sleepMS = Watchdog.sleep(4000);
  digitalWrite(LED_BUILTIN, HIGH); // Show we're awake again
  USBDevice.init();
  USBDevice.attach();

  Serial.print("I'm awake now! I slept for ");
  Serial.print(sleepMS, DEC);
  Serial.println(" milliseconds.");
  Serial.println();
  times += 0;
}

This seems to be a question for Adafruit if you’re using their software.

Hello Kansas, although it is their code, it is sparkfun’s board, so it suit both.

I commented some parts of the code and also removed the USBDevice.dettach() so I could see the logs.

Going to sleep in one second...
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()

We can see [in the line 247](https://github.com/adafruit/Adafruit_Sl … D.cpp#L247) that the USB is disabled and than enabled (don’t know why it does it just after disabling it).

So I tried to move the line [251 to 253](https://github.com/adafruit/Adafruit_Sl … D.cpp#L251) to just after the [__WFI();](https://github.com/adafruit/Adafruit_Sl … D.cpp#L215) command

__WFI(); // Wait for interrupt (places device in sleep mode)
  Serial.println("after: before __DSB() and __WFI()");
  
  USB->DEVICE.CTRLA.bit.ENABLE = 1;   // Enable the USB peripheral
  Serial.println("sleep: After USB->DEVICE.CTRLA.bit.ENABLE = 1;");
  while (USB->DEVICE.SYNCBUSY.bit.ENABLE)
    ; // Wait for synchronization

But the only thing that changed was that I lost the usb connection earlier than before…

Hello everyone, any news on that?

I could solve the problem. So far my ThingPlus USB doesn’t work after sleeping.

[This topic made me realize that I should try to run it on Windows, maybe it would “work” (opening and closing the serial) as with my MacOS even opening and closing didn`t work. And guess what? This method “worked”. Although this is not the best solution, neither the good, at least it kind of works so its better than before.

BTW, i tried [Bryon program and it helped a lot.

Also, BryonMiller and danhalbert suggested to use Tera Term to have better results.](https://forums.adafruit.com/viewtopic.php?f=52&t=137543)](https://forums.adafruit.com/viewtopic.php?f=57&t=137520&hilit=+serial#p680578)