Data not uploaded to internet when using watchdog interrupts

Hi, I have SODAQ Autonomo with GBRSBee (rev. 6b), it uploads data to the internet if I don’t enable the watchdog, but when watchdog is enabled to upload data periodically e.g. every half an hour, it doesn’t work out, I am enabling watchdog with this line sodaq_wdt_enable(WDT_PERIOD_8X); in the void setup() and then I am calling the takedata() function in the void loop() this way: -
sodaq_wdt_reset();

sodaq_wdt_reset();

if (hz_flag) {
      takedata();
    }

Would any one help me on how I should make watchdog work and upload data to the internet?.
Thanks

Hi Roman,

The purpose of the Watch Dog Timer (WDT) is to prevent the microcontroller from getting stuck. It achieves this by using a timer which must be reset regularly, if the timer is allowed to elapse the Watch Dog resets the microcontroller.

The implementation on the Autonomo uses a early warning interrupt which fires when the WDT is at half the reset time. Using:sodaq_wdt_enable(WDT_PERIOD_8X) you are specifying an early warning interrupt after 8 seconds, and Watch Dog Reset after 16 seconds.

It is possible to use the early warning interrupt to wake the board from sleep and then run scheduled tasks. However, while this is fine, it is not the main purpose of the WDT.

In this case, if you fail to call sodaq_wdt_reset() at least once every 16 seconds, your board will reset. This is very likely the cause of why you are not seeing uploads after enabling the WDT, the board is likely getting reset before the upload occurs.

I would check to see if you are using delay(x) at all in your code, as this is usually the culprit. There is a method sodaq_wdt_safe_delay(x) which is safe to use for any length of delay as it calls sodaq_wdt_reset() for you. However, this method has a fair bit of overhead and is quite inaccurate (delay length wise) with longer delays (10s of seconds).

1 Like

Hi Gabriel,

Thank you so much for the help.

I have tried to call sodaq_wdt_reset() frequently and eliminated delay(x) from my code but still nothing is uploaded and it is saving to SD card, and without WDT it uploads, I get so confused!.

Here is my program sketch, it is for recording water level using ultrasonic sound sensor

   ///////  NEED to fix sleep code so that it wakes up every minute to check time.  
#include "Sodaq_wdt.h"
#include <SPI.h>
#include <SD.h>
#include <RTCZero.h>
#include "GPRSbee.h"

//Cellular Network
#define APN "internet"
#define APN_USERNAME ""
#define APN_PASSWORD ""

//Internet Time Service Defines
#define TIME_URL "time.sodaq.net"
#define TIME_ZONE 3
#define TIME_ZONE_SEC (TIME_ZONEВ * 3600)

//SpeakThings constants
#define URL "api.thingspeak.com/update"
#define WRITE_API_KEY "xxxxxxxxxxxxxxxxxx" //this is my channel's key

RTCZero rtc;

File dataFile;

bool hz_flag;

int arraysize = 9;  //quantity of values to find the median (sample size). Needs to be an odd number
int rangevalue[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};    //declare an array to store the samples. not necessary to zero the array values here, it just makes the code clearer

void setup()
{

  delay(15000);  // wait 15seconds before starting up
    
  Serial.begin(57600);
  
  SerialUSB.print("Initializing SD card...");

  if (!SD.begin(SS_2)) {
    SerialUSB.println("initialization failed!");
    return;
  }
  SerialUSB.println("initialization done.");

  rtc.begin(); // start the clock

  // Set the alarm at the 12 second mark
  rtc.setAlarmMinutes(12);

  // Match only seconds (Periodic alarm every minute)
  rtc.enableAlarm(RTCZero::MATCH_MMSS);

  // Attach ISR
  rtc.attachInterrupt(RTC_ISR);

  //Open Serial1 for the GPRSbee
  Serial1.begin(57600);

  //Switch on the VCC for the Bee socket
  digitalWrite(BEE_VCC, HIGH);
  gprsbee.initAutonomoSIM800(Serial1, BEEDTR, BEE_VCC, BEECTS);
  gprsbee.setDiag(SerialUSB);

    // Set sleep mode
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

  pinMode(LED_BUILTIN, OUTPUT);

    //Sync time
  syncRTCwithServer();

  //Adjust for time change
  int hourtime = rtc.getHours();
  int TanzaniaTime = hourtime + 3;
  rtc.setHours(TanzaniaTime);

  sodaq_wdt_enable(WDT_PERIOD_8X);
 }

void loop()
{
      sodaq_wdt_reset();
      
      digitalWrite(LED_BUILTIN, HIGH);
      delay(50);
      digitalWrite(LED_BUILTIN, LOW);
      delay(50);
      digitalWrite(LED_BUILTIN, HIGH);
      delay(50);
      digitalWrite(LED_BUILTIN, LOW);
  
    sodaq_wdt_reset();
  
    if (hz_flag) {
      takedata();
    }
    
  // Disable USB
  USB->DEVICE.CTRLA.reg &= ~USB_CTRLA_ENABLE;
 
  //Enter sleep mode
  __WFI();
  
  // Sleeping
  
  // Enable USB and wait for resume if attached
  USB->DEVICE.CTRLB.bit.UPRSM = 0x01u;

  // Awake
}

void RTC_ISR()
{
    hz_flag = true;
}

void takedata()
{

    digitalWrite(LED_BUILTIN, HIGH);

    String url;
  
     for(int i = 0; i < arraysize; i++)
   {                                                    //array pointers go from 0 to 4
     rangevalue[i] = analogRead(A2);
     delay(100);  
     sodaq_wdt_reset();
    }  
  
    int midpoint = arraysize/2;   
      
    int depthvalue = 400 - rangevalue[midpoint];    // enter in the total possible channel height here

//   int depthvalue = rangevalue[midpoint];  // raw distance

   sodaq_wdt_reset();
   
   dataFile = SD.open("datalog.txt", FILE_WRITE);

  // Print date...
   dataFile.print(rtc.getMonth());
   dataFile.print("/");
   dataFile.print(rtc.getDay());
   dataFile.print("/");
   dataFile.print(rtc.getYear());
   dataFile.print(", ");
  
  // ...and time
   dataFile.print(rtc.getHours());
   dataFile.print(":");
   dataFile.print(rtc.getMinutes());
   dataFile.print(":");
   dataFile.print(rtc.getSeconds());
   
   dataFile.print(", ");
   dataFile.println(depthvalue); 

   //SerialUSB.print(depthvalue);
   sodaq_wdt_reset();

   delay(100);

   dataFile.flush();

   sodaq_wdt_reset();
    
   OneSecondDelay();
  sodaq_wdt_reset();

  gprsbee.on();
  TwoSecondDelay();
  url += String("api.thingspeak.com/update");
  url += String("?key=");
  url += String(WRITE_API_KEY);
  url += String("&field1=");
  url += String(depthvalue);
  
  sodaq_wdt_reset();
  char buffer[512];
  
  memset(buffer, '\0', sizeof(buffer));
  OneSecondDelay();
  bool retval = gprsbee.doHTTPGET(APN, APN_USERNAME, APN_PASSWORD, url.c_str(), buffer, sizeof(buffer));
  SerialUSB.println(retval);
  SerialUSB.println("GET result: ");
  sodaq_wdt_reset();
  //Lets be safe in case result length > 247
  for (int i=0; i<strlen(buffer); i++) {
    SerialUSB.print(buffer[i]);
  }
  TwoSecondDelay();
  sodaq_wdt_reset();
  gprsbee.off();

  sodaq_wdt_reset();

  hz_flag = false;

  sodaq_wdt_reset();

  digitalWrite(LED_BUILTIN, LOW);

}

void HalfSecondDelay()
{
  sodaq_wdt_reset();
  delay(500);
  sodaq_wdt_reset();
}

void OneSecondDelay()
{
  sodaq_wdt_reset();
  delay(500);
  sodaq_wdt_reset();
  delay(500);
  sodaq_wdt_reset();
}

void TwoSecondDelay()
{
  sodaq_wdt_reset();
  delay(500);
  sodaq_wdt_reset();
  delay(500);
  sodaq_wdt_reset();
  delay(500);
  sodaq_wdt_reset();
  delay(500);
  sodaq_wdt_reset();
}

void syncRTCwithServer()
{
    char buffer[20];
   
    if (gprsbee.doHTTPGET(APN, APN_USERNAME, APN_PASSWORD, TIME_URL, buffer, sizeof(buffer)))
    {
        sodaq_wdt_reset();
     
        SerialUSB.println("HTTP GET: " + String(buffer)); 
         
        //Convert the time stamp to unsigned long
        char *ptr;
        uint32_t newTs = strtoul(buffer, &ptr, 0);
 
        rtc.setEpoch(newTs);    
    }
}

I would appreciate any help please, I have stuck here for a while.
Thanks.

There are a few possibilities here. First the WDT timer could be resetting the board, preventing it from completing the sequences which uploads the data (you could start with removing the 15s delay at the start, or use safe delay for that). Atlernatively, there could be some issue with RTC alarm which generates the flag which starts the upload sequence.

You will need to debug this. One thing to note, when the board enters sleep mode or is reset, the output will stop in SerialMontior. There are a few work arounds, first you could send the output to Serial (on pins 0/1) and then route that output through a USARTbee or similar to your PC. Alternatively, I believe the VisualMicro extension for Visual Studio has a tool which will automatically reconnect to a COM port.

I would recommend trying increasing the frequency of the uploads in order to test this. You could start with an every minute alarm (match only seconds), instead of the every hour alarm (match minutes and seconds) which you are currently using. Also you may want to consider disabling the sleep instructions while testing.

Hi Gabriel,

Thanks for help.

I have debugged a lot and I have recognized that WDT timer is preventing uploads, I have tested with a SimpleRTCAlarm.ino file it is working fine, which means RTC Alarm is OK. And also increased the frequency of uploads to every minute alarm as you suggested with no success.

But one-thing to note it might be helpful, This problem has started after changing my PC, the same project have been working from my old PC and I was using the same sketch, I copied all the files from my old PC to the new one, this is where the problem begun, nothing have been uploaded since then when using WDT timer.

I checked libraries updates, and they are all updated, I guess a certain library has to be installed.

I appreciate for the help, thank you.

Hi Gabriel,

I got back my old PC and re-installed arduino IDE and made all configurations to test if it could work out but still can not upload data when the board is in an interrupted mode (sodaq WDT enabled and use hz_flag). Could you have an other suggestions please?

Thanks.

Hi Roman,

All I can really suggest is that you check for any differences between any libraries you might be using (maybe use a diff tool), to ensure that isn’t the cause.

Also you should try some more debugging. You need to see what operations the sketch is carrying out and what it might be skipping. Is the hz_flag ever being set (perhaps switch on an LED when it is asserted)? Is the upload process ever started? If so is there an issue there (you can turn on debugging of the GPRSbee)?

Hi Gabriel,

Finally it uploaded, I had a suggestion from one of my friend Mr. Chris Dutton, to leave a unit under battery power (without connecting to USB on computer), then I found uploaded. What could be the reason behind that?.

Thank you so much for your help, I have learnt so much.
Cheers.

The GPRSbee requires a battery to be connected in order to operate correctly. A standard USB connection is limited to 500mAs, the GPRSbee can draw higher currents at times.

You should find that it also works correctly if both a battery and the USB are connected.