MKR 1400 Watchdog?

Hey i just got my MKR 1400 and worte this code to receive sms compare the sms message and send new sms.
my problem is that the device seems to crash sometimes. I think thats the case because the Serialmonitor stops and i dont get any replies anymore. I then wanted to add a Watchdog but was unable to get anything working as the only one i used bevor was: #include <avr/wdt.h> and that dosnt work with the MKR.

Here is the code im trying to run:

// include the GSM library
#include <MKRGSM.h>


// initialize the library instances
GSM gsmAccess;


GSM_SMS sms;


GSMScanner scanner;


bool connected;
int LowConnectionCount;


// Array to hold the number a SMS is retreived from
char senderNumber[20];


//holding received SMS Parts;
char SMSBuffer[160];
int CharIndex;


//holding received SMS;
String message;


//Number GSM Ready is sent to at start
char DebugNumber[20] = "Phone Nummber";


int NumElements;


char IDS[][9] = //the length of the longest string + 1 ( for the '\0' at the end )
{
  "00007007",
  "00006006",
  "00005005"
};


char Numbers[][15] = //the length of the longest string + 1 ( for the '\0' at the end )
{
  "Phone Nummber",
  "Phone Nummber",
  "Phone Nummber"
};


void setup() 
{
  // initialize serial communications and wait for port to open:
  Serial.begin(9600);


  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.println("Starting");
  
  // connection state
  connected = false;
  
  // Start GSM connection
  while (!connected) 
  {
    if (gsmAccess.begin() == GSM_READY) 
    {
      connected = true;


      sms.beginSMS(DebugNumber);


      sms.print("GSM Ready");


      sms.endSMS();
    } 
    else 
    {
      Serial.println("Not connected");
      delay(1000);
    }
  }
  Serial.println("GSM initialized");


  Serial.println("Waiting for messages");


  NumElements = (sizeof(IDS)/sizeof(IDS[0]));
}


void loop() 
{    
  while(!connected)
  {
      if (gsmAccess.begin() == GSM_READY) 
      {
        Serial.println("Connected");
        connected = true;
        LowConnectionCount = 0;
      } 
      else 
      {
        Serial.println("Not connected");
        delay(1000);
        return;
      }
  }
  
  Serial.println(scanner.getSignalStrength());
  
  if(scanner.getSignalStrength().toInt() < 4)
  {
    Serial.println("Low Connection");
    LowConnectionCount++;


    if(LowConnectionCount > 5)
    {
      Serial.println("Restarting modem");
      gsmAccess.shutdown();


      delay(5000);
      connected = false; 
      return;
    }
  }
  else
  LowConnectionCount = 0;
  
  int c;
  String IDSString;


  // If there are any SMSs available()
  if (sms.available()) 
  {
    Serial.println("Message received from:");


    // Get remote number
    sms.remoteNumber(senderNumber, 20);
    Serial.println(senderNumber);




    // Read message bytes and print them
    while ((c = sms.read()) != -1) 
    {
      Serial.print((char)c);
      SMSBuffer[CharIndex] = (char)c;
      CharIndex++;
      SMSBuffer[CharIndex] = '\0';
    }


    Serial.println("");
    Serial.println(SMSBuffer);
    message = SMSBuffer;
    Serial.println(message);
    Serial.println(NumElements);


    //Reseting Message Buffer
    CharIndex = 0;
    SMSBuffer[0] = '\0';


    //Going through every IDS to check if it is in the message
    for(int i = 0; i < NumElements; i++)
    {
      IDSString = IDS[i];


      Serial.println(IDSString);
      
      if(message.indexOf(IDSString) != -1)
      {
        sms.beginSMS(Numbers[i]);


        sms.print("000001 Alarm");


        sms.endSMS();
      }
    } 
    Serial.println("\nEND OF MESSAGE");


    // Delete message from modem memory
    sms.flush();
    Serial.println("MESSAGE DELETED");
  }
  delay(1000);
}

Befor the crash everything works fine. It just seems to randomly give up.
Any Ideas would be great as i have been bashing my head trying to find something but it could that im just blind.

I also found this

but didnt get it working.

WDTZero library

1 Like

@cunibon

Your topic was Moved to it's current location / section as it is more suitable.

Could you also take a few moments to Learn How To Use The Forum.

Other general help and troubleshooting advice can be found here.
It will help you get the best out of the forum in the future.

Juraj:
WDTZero library

i saw that one too but it says
MKR1000 only
so i thought it wouldnt apply for my 1400

cunibon:
i saw that one too but it says
MKR1000 only
so i thought it wouldnt apply for my 1400

it is for SAMD21

Juraj:
it is for SAMD21

Hey i tried implementing the WDTZero library but im having some problems. I wanted to use Hardcycles as I think when the system actually crashes the softcycle wont work anymore as well. But when i run the code and it reaches the 10 sec delay it ironically just crashes and i cant reach it anymore. The same happens with the softcycle but there it reaches the void myshutdown() at the bottom of the code and then crashes. I just want this damn thing to restart when it crashes. Like with the Uno watchdog. The example of the WDT Zero library sadly dosnt showcase how to use the Hardcycles and im relativly new to arduino so maybe im just doing something wrong.

this is my code now:

#include <WDTZero.h>
WDTZero MyWatchDoggy; // Define WDT
// include the GSM library
#include <MKRGSM.h>
// initialize the library instances
GSM gsmAccess;
GSM_SMS sms;
GSMScanner scanner;
bool connected;
int LowConnectionCount;
// Array to hold the number a SMS is retreived from
char senderNumber[20];
//holding received SMS Parts;
char SMSBuffer[160];
int CharIndex;
//holding received SMS;
String message;
//Number GSM Ready is sent to at start
char DebugNumber[20] = "TelefonNummber";
int NumElements;
char IDS[][9] = //the length of the longest string + 1 ( for the '\0' at the end )
{
  "00007007",
  "00006006",
  "00005005"
};
char Numbers[][15] = //the length of the longest string + 1 ( for the '\0' at the end )
{
  "+TelefonNummber",
  "+TelefonNummber",
  "+TelefonNummber"
};
void setup() 
{
  // initialize serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial)
  {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("Starting");
  
  // connection state
  connected = false;
  
  // Start GSM connection
  while (!connected) 
  {
    if (gsmAccess.begin() == GSM_READY) 
    {
      connected = true;
      sms.beginSMS(DebugNumber);
      sms.print("GSM Ready");
      sms.endSMS();
    } 
    else 
    {
      Serial.println("Not connected");
      delay(1000);
    }
  }
  Serial.println("GSM initialized");
  Serial.println("Waiting for messages");
  NumElements = (sizeof(IDS)/sizeof(IDS[0]));
 Serial.print("\nWDTZero-Demo : Setup Hard Watchdog at 8S interval"); 
 MyWatchDoggy.attachShutdown(myshutdown);
 MyWatchDoggy.setup(WDT_HARDCYCLE8S);  // initialize WDT
}
void loop() 
{    
  MyWatchDoggy.clear();
  
  while(!connected)
  {
      if (gsmAccess.begin() == GSM_READY) 
      {
        Serial.println("Connected");
        connected = true;
        LowConnectionCount = 0;
      } 
      else 
      {
        Serial.println("Not connected");
        delay(1000);
        return;
      }
  }
  
  Serial.println(scanner.getSignalStrength());
  
  if(scanner.getSignalStrength().toInt() < 4)
  {
    Serial.println("Low Connection");
    LowConnectionCount++;
    if(LowConnectionCount > 5)
    {
      Serial.println("Restarting modem");
      gsmAccess.shutdown();
      delay(5000);
      connected = false; 
      return;
    }
  }
  else
  LowConnectionCount = 0;
  
  int c;
  String IDSString;
  // If there are any SMSs available()
  if (sms.available()) 
  {
    Serial.println("Message received from:");
    // Get remote number
    sms.remoteNumber(senderNumber, 20);
    Serial.println(senderNumber);
    // Read message bytes and print them
    while ((c = sms.read()) != -1) 
    {
      Serial.print((char)c);
      SMSBuffer[CharIndex] = (char)c;
      CharIndex++;
      SMSBuffer[CharIndex] = '\0';
    }
    Serial.println("");
    Serial.println(SMSBuffer);
    message = SMSBuffer;
    Serial.println(message);
    Serial.println(NumElements);
    //Reseting Message Buffer
    CharIndex = 0;
    SMSBuffer[0] = '\0';
    //Going through every IDS to check if it is in the message
    for(int i = 0; i < NumElements; i++)
    {
      MyWatchDoggy.clear();
          
      IDSString = IDS[i];
      Serial.println(IDSString);
      
      if(message.indexOf(IDSString) != -1)
      {
        sms.beginSMS(Numbers[i]);
        sms.print("000001 Alarm");
        sms.endSMS();
      }
    } 
    Serial.println("\nEND OF MESSAGE");
    // Delete message from modem memory
    sms.flush();
    Serial.println("MESSAGE DELETED");
    delay(10000);
  }
  delay(1000);
}
void myshutdown()
{
Serial.print("\nWe gonna shut down ! ..."); 
}

Relax. Everything is gonna be alright. I think WDTZero is doing it’s job properly but you misunderstand the behaviour.

You can:
WDT_HARDCYCLE62m
WDT_HARDCYCLE250m
WDT_HARDCYCLE1SS
WDT_HARDCYCLE2S
WDT_HARDCYCLE4S
WDT_HARDCYCLE8S
WDT_HARDCYCLE16S

So max 16S. This will reset (you name it crash) without execute myshutdown().

Or:
WDT_SOFTCYCLE8S
WDT_SOFTCYCLE16S
WDT_SOFTCYCLE32S
WDT_SOFTCYCLE1M
WDT_SOFTCYCLE2M
WDT_SOFTCYCLE4M
WDT_SOFTCYCLE8M
WDT_SOFTCYCLE16M

With execute the shutdown procedure.
I do a proper modem shutdown in this procedure. The Ublox modems can be sensitive to hard power cuts.

// Proper Modem Shutdown
  MODEM.sendf("AT+CFUN=15");
  MODEM.waitForResponse(10000);

Don’t take the Minutes and Seconds (eg WDT_SOFTCYCLE2M = 2 minutes ) too precise, the lib controls the independent internal timers of the SAMD21 and was written for a specific cpu. Now the clockspeed times blablabla equals another time on another cpu, so try it out if you need specific time. I always take 16S for hardcycle and 2M for softcycle. You can not choose free, 16S is the longest possible for hardcycle for example.
You can initialize WDT before the gsm attach precedure to include it in the watch.

I finaly found my problem it was this part of my code.

the arduino wasnt able to reconnect to the serial after restarting and thus it would seemed to me as if it had crashed.

thanks for all the replies. In the end it seems like im just dumb :smiley:

LOL...you're fresh! Every arduino coder stumbles somewhen over a while..

I'm also looking at how to add a watchdog timer; however, my application currently takes 15-20s to connect to GPRS:

if ((gsmAccess.begin(PINNUMBER) == GSM_READY) &&
    (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {

Arguably I could split them and add a WDT reset between the begin and the attach, but even then it gets very close to the WDT timeout of 16s.

Likewise the connect to the HTTP server is taking 9-10s:

if (!client.connect(server, port)) {

I have considered disabling the WDT for those sections of code which I know usually take a long time, but i also know that where I've had hanging issues (fixed now I think - related to interrupts from other aspects of the system) they've occurred during the connect cycles...

Before I starting digging in to the MKRGSM code to add wdt resets into it is there a less hacky way to use a WDT with MKRGSM libraries?

I'm a experienced fighter with the modems on the mkr 1400 & 1500... :confounded:
You're on the wrong path, i'll tell you why: the modem is a computer of it's own, an openbsd os with a AT console which is the communication port to the arduino, thus your code and the mkrgsm lib.
So every command to the modem (AT+whatever) can take 9 or 90 seconds, it's dependent of the signal strenght, the previous AT commands and so on.. i was bug hunting like you on extern interupts etc. The result was the unpredictable behaviour of the modem.
THE MODEM IS NOT UNDER YOUR CONTROL. You can please the modem to do something, one day it obey like a trained dog, next day it does not even start.
And you don't see all the AT commands when you set access(true) which makes the debuging a dive in dark waters at night.
ERGO: At the moment it takes 15 to 20 s and 9 to 10 but you can't rely on this.
It's useless to add wdt resets in the MKRGSM, the library is NOT the problem, these AT commands are correct, the modem reacts differently.

Ah, possibly you've misunderstood what I'm trying to achieve (or I've misunderstood your response)... The application communicates with another device over SPI and has a library (that I've written) which has a fairly large set of structures in memory and does quite a bit with memcpy and various other 'risky' pointer accesses - occasionally (every few hours of running currently) I encounter a bug that hangs the Arduino; so far these have been down either to my library or interrupt handling and not the MKRGSM library.

At some point I'm going to need to leave the device unattended and its possible (probable even) that my library will still have one or more bugs that will eventually cause the Arduino to hang; therefore I'd like to add a watchdog timer in order to ensure that if this does occur then the device restarts and carries on.

My problem is that if I set a 16s WDT then I need to call 'clear_wdt()' (or equivalent) at least every 15 seconds to ensure it doesn't reset when it shouldn't - for the most part this is fine. However, something like the GSM begin or GPRS attach could, perfectly legitimately, take that long and are one command i.e. gprs.attachGPRS(...) and thus would end up with a reset while attaching.

Having used the modem debug mode to check other aspects it looks like the MKRGSM library sends an AT command to start a process and in most (all?) cases of long running commands e.g. a connect, then issues AT commands every few hundred ms to check the status (as you say the modem is a separate MCU doing its own thing); so my 'hack' would be to add a 'clear_wdt()' to whichever bit of the MKRGSM library is issuing an AT command - since these get repeated every few hundred ms and would prevent the Arduino from resetting while waiting for the modem to connect.

Does that make more sense? And back to the original question; is there a less hacky way of doing it than modifying the MKRGSM library?

I think i do understand you. You don't understand me. I think we're chating over different issues.

whichever bit of the MKRGSM library is issuing an AT command - since these get repeated every few hundred ms and would prevent the Arduino from resetting while waiting for the modem to connect.

You can't rely on this. What if the AT console is blocked by the modem? Or the socket dies? The MKRGSM lib expects a AT answer and will (wait) hang until the watchdog resets the board.
In good conditions (strong signal) and the modem is answering as expected, it might work, you can easy add a "clear_wdt()" on the AT+CREG? loop in the MKRGSM while connecting, that's not a hack - i did it also - with no remedy for my problems.. Anyway i had to switch to the mkr1500 because UMTS is over here in Europa - but i'm still fighting with the new R410 modem... Good luck!

OK - I see exactly what you mean; I think we are trying to solve different issues - so far the modem side has been ok for me (once I stuck a different battery on the 1410 and a big cap across Vin and GND) . The watchdog timer is to deal with any potential issues from the rest of the code, but without resetting while we're waiting for legitimate connection delays.

Anyway, I'll go with my originally planned route of adding clear_wdt into the connection loops in the MKRGSM lib

Thanks!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.