adafruit / Adafruit_SleepyDog

Arduino library to use the watchdog timer for system reset and low power sleep.
MIT License
232 stars 63 forks source link

When trying to connect to GSM with arduino GSM1400. Watchdog timer resets the board #22

Open dimilio81 opened 4 years ago

dimilio81 commented 4 years ago

I am trying to use the sleepydog library in a project that i am building that uses the GSM1400 arduino Board. The library works fine always until you try to connect with the arduino library to GSM network. If you disable the watchdog, the GSM connection is successful and works normally. And when i say it resets the board, the reset is immediate, it does not occur after the time that the watchdog is setup passes. Any ideas?

SWoto commented 3 years ago

I've a problem like yours.

The code runs smoothly if I remove the line uint32_t sleepMS = sleepForSeconds(SLEEP_TIME);, and spams my XCTU with messages. However, after sleeping the SAMD51, I can't get it to work. I even tried checking Serial2.avaiable(), but it didn't work either. Even though it doesn't uses the USB Serial, I've also tried USBDevice.attach().

Basic Code:

#include <XBee.h>
XBee objXBee = XBee();
XBeeAddress64 addr64 = XBeeAddress64(0x00000000, 0x0000ffff);
ZBTxStatusResponse txStatus = ZBTxStatusResponse();

void setup() {
  // set up the LCD
  lcd.begin();
  lcd.setContrast(30);

  Serial2.begin(115200);
  objXBee.setSerial(Serial2);

  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {

  BaterryMeasument(); //measure and send xbee frame

  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(messageRow1);
  lcd.setCursor(0,1);
  lcd.print(messageRow2);

  delay(2000);

  digitalWrite(LED_BUILTIN, LOW);
  USBDevice.detach();
  uint32_t sleepMS = sleepForSeconds(SLEEP_TIME);
  USBDevice.attach();
  SLEEP_TIME += SLEEP_TIME/4;

  digitalWrite(LED_BUILTIN, HIGH);

  while(!Serial2.available() || !Serial2){
    digitalWrite(LED_BUILTIN, LOW);
    delay(500);
    digitalWrite(LED_BUILTIN, HIGH);
    delay(500);
  }

  sleepMS1 = sleepMS2;
  sleepMS2 = sleepMS;

  writeLCD();

}

uint32_t sleepForSeconds(uint16_t secs){             // sleep for seconds  (maximum is 65535 seconds = 18.2 hours) 43200 = 12 hours.
  uint32_t sleepMS = 0;
  while(secs != 0) {
    int _sleepMS = Watchdog.sleep(secs*1000);
    sleepMS += _sleepMS;
    secs += -_sleepMS/1000;
  }
  return sleepMS;
}
Rock-N-RollaMann commented 3 years ago

Hi, I think it’s better to use the RTC Zero library. I use it instead of the sleepy dog library and works much better.

SWoto commented 3 years ago

I've tested using an LCD to display (because the USB doesn't work after waking it up) that uses SPI communication and it worked.

SWoto commented 3 years ago

@MartinL1, did u managed to make the USB/Serials work after waking the board up?

Rock-N-RollaMann commented 3 years ago

@SWoto I don't know who MartinL1 is in this thread, but this code works for me:

USBDevice.detach(); //Reinitialize USB for debugging USBDevice.init(); USBDevice.attach(); `

SWoto commented 3 years ago

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.

USB_PORTS_ARDUINO
  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();
Screen Shot 2020-07-29 at 15 24 40

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

SWoto commented 3 years ago

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

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;
}
Rock-N-RollaMann commented 3 years ago

Try commenting out this line: while(!Serial); // wait for Arduino Serial Monitor (native USB boards)

It should look like this: //while(!Serial); // wait for Arduino Serial Monitor (native USB boards)

SWoto commented 3 years ago

@Rock-N-RollaMann, thanks for your fast reply.

The board would only get stuck there if the board had, somehow, reseted itself. Otherwise it shouldn't go back to the setup... Anyway, I tried commenting this line and the problem persist. The code is locked somewhere...

SWoto commented 3 years ago

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 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 to just after the __WFI(); 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...

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;
mdelain commented 2 years ago

Coming back to the inital issue:

I am trying to use the sleepydog library in a project that i am building that uses the GSM1400 arduino Board. The library works fine always until you try to connect with the arduino library to GSM network. If you disable the watchdog, the GSM connection is successful and works normally. And when i say it resets the board, the reset is immediate, it does not occur after the time that the watchdog is setup passes. Any ideas?

I also have the same annoying behavior - this library seems to be just incompatible with MKR GSM 1400 as soon as you try to open the GSM connection, and even without putting the board asleep! Or does anyone has a workaround to make it work?

CptHolzschnauz commented 5 months ago

The issue is IMHO that when the SAMD is interupted by the watchdog, it doesn't read the serial AT console and some bytes get lost. Can lead to a freeze but it's flaky behaviour. The modem is full computer and doesn't know that the SAMD is not listening.