Arduino freezing but watchdog not activating?

I have a program that connects to a mysql database (db) to read setpoint changes and upload data. It reads the setpoint db every 5 seconds when off; every second when on. When running, it updates the data db every second. When it turns off, it updates both dbs. All of this functions perfectly.

Recently I have tried adding a delay start. When it reads a dly on the setpoint db it sets itself to delay mode, and waits for the time to run. Then it updates the setpoint db, stating it is on. At this point it hangs - and worse, the watchdog wont activate. Oddly, it updates the db just fine, and will run a serial print after the db update. However it will not run a second serial print just after the db update function in the checkDelay function.

I do not have this problem anywhere else in my code, and am very confused as to what is different here. All my code is below.

//Common Libraries
//#include <Time.h>
#include <TimeLib.h>
#include <SPI.h>
#include <WiFiNINA.h>
#include <MySQL_Connection.h>
#include <MySQL_Cursor.h>
#include "NTPClient.h"
#include <avr/dtostrf.h>
#include <WDTZero.h>
#include "secret.h"

//Node Libraries
#include <OneWire.h>
#include <DallasTemperature.h>


//Debugging

#define DEBUG

#ifdef DEBUG
#define DEBUGPRINT(x)  Serial.print (x)
#define DEBUGPRINTLN(x)  Serial.println (x)
#else
#define DEBUGPRINT(x)
#define DEBUGPRINTLN(x)
#endif

//Wifi
byte mac_addr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xAB }; //Do I need this?
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;
int status = WL_IDLE_STATUS;
int keyIndex = 0;
WiFiClient client;


//NTP Time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
time_t delayTime;
tmElements_t tm;


//MySQL
#define port 3306
IPAddress server_addr(192, 168, 1, 133);
char db[] = SECRET_MYSQL_DB;
char user[] = SECRET_MYSQL_USER;
char password[] = SECRET_MYSQL_PASS;
char query[150];
char tempStr[7], dataStr[50];
char INSERT_DATA[] = "INSERT INTO pasteurizer_data (%s) VALUES (%s);";
char INSERT_SP[] = "INSERT INTO pasteurizer_sp (%s) VALUES (%s);";
char SELECT[] = "SELECT * FROM pasteurizer_sp ORDER BY timestamp DESC LIMIT 1;";
byte dbCheckRate = 5;
uint32_t dbCheckTimer;
MySQL_Connection conn((Client *)&client);


//Watchdog
WDTZero watchDog;


//Node Specific
#define RELAYPIN 7
#define TEMPBUS  8
#define DEFAULT_STEAM_TEMP 90
#define DEFAULT_SUBSTRATE_TEMP 75
#define DEFAULT_THRESHOLD_TIME 15
boolean elementState, stage = 0;
byte state = 0;
byte steamTempSP = DEFAULT_STEAM_TEMP;
byte thresholdTempSP = DEFAULT_SUBSTRATE_TEMP;
byte thresholdTime = DEFAULT_THRESHOLD_TIME;
float steamTemp, substrateTemp = 0.00;
char delayStart[20];
uint32_t thresholdMilliCounter = 0;
OneWire oneWire(TEMPBUS);
DallasTemperature tempSensors(&oneWire);


void setup() {
  Serial.begin(9600);

  //Wifi
  wifiConn();

  //Time
  timeClient.begin();
  //setSyncProvider(timeProvider);
  //setSyncInterval(15); // sync every 15 seconds

  //Node Specific
  tempSensors.begin();
  pinMode(RELAYPIN, OUTPUT);
  digitalWrite(RELAYPIN, LOW);
  

  //Watchdog set function and set 8sec interval
  watchDog.attachShutdown(myshutdown);
  watchDog.setup(WDT_SOFTCYCLE8S);

  dbCheckTimer = millis() + 5000;
}

void loop() {
  watchDog.clear();
  switch (state) {
    case 0: {
        DEBUGPRINTLN("Loop Switch State is Off");
        break;
      }
    case 1: {
        checkDelay();
        break;
      }
    case 2: {
        pasteurize();
        break;
      }
    default: {
        DEBUGPRINT("Loop Switch Error - state: ");
        DEBUGPRINTLN(state);
        break;
      }
  }

  if (millis() - dbCheckTimer >= (dbCheckRate * 1000)) {

    if (conn.connect(server_addr, port, user, password, db)) {
      if (state == 2) {
        DEBUGPRINTLN("loop db update");
        dbUpdate();
      }

      DEBUGPRINTLN("loop sp check");
      spCheck();

      dbCheckTimer = millis();
    }
    else {
      DEBUGPRINTLN("Loop Conn Failed. Checking wifi");
      wifiConn();
    }
    conn.close();
  }


}

//---------------------------------------Node Functions-----------------------------------
void pasteurize() {
  watchDog.clear();
  tempUpdate();

  if (!stage) {
    if (steamTemp < steamTempSP) {
      digitalWrite(RELAYPIN, HIGH);
      elementState = 1;
    }
    else {
      digitalWrite(RELAYPIN, LOW);
      elementState = 0;
    }
  }
  else {
    if (steamTemp < (thresholdTempSP + 5)) {
      digitalWrite(RELAYPIN, HIGH);
      elementState = 1;
    }
    else {
      digitalWrite(RELAYPIN, LOW);
      elementState = 0;
    }
  }

  if (stage && substrateTemp < thresholdTempSP) stage = 0;
  else if (stage && millis() - thresholdMilliCounter >= 60000 * thresholdTime) {
    if (conn.connect(server_addr, port, user, password, db)) {
      DEBUGPRINTLN("Pasteurizer Off");
      state = 0;
      resetPasteurizer();
      spUpdate();
      dbUpdate();
      conn.close();
    }
    else {
      DEBUGPRINTLN("Loop Conn Failed. Checking wifi");
      wifiConn();
    }
    
  }
  else if (!stage && substrateTemp >= thresholdTempSP) {
    thresholdMilliCounter = millis();
    stage = 1;
  }
}

void checkDelay() {
  timeClient.update();
  
  DEBUGPRINT("checkDelay - Current Time: ");
  DEBUGPRINT(timeClient.getFormattedTime());
  DEBUGPRINT(", In epoch time: ");
  DEBUGPRINT(timeClient.getEpochTime());
  DEBUGPRINT(", Delay Time: ");
  DEBUGPRINTLN(delayTime);

  if (timeClient.getEpochTime() >= delayTime) {
    if (conn.connect(server_addr, port, user, password, db)) {
      DEBUGPRINTLN("Pasteurizer On");
      state = 2;
      resetPasteurizer();
      spUpdate();
      DEBUGPRINTLN("Why no print me?");//<-------------This Println will not activate--------------
      conn.close();
    }
    else {
      DEBUGPRINTLN("CheckDelay Conn Failed. Checking wifi");
      wifiConn();
    }
    
  }
}


void tempUpdate() {
  tempSensors.requestTemperatures();
  substrateTemp = tempSensors.getTempCByIndex(0);
  steamTemp = tempSensors.getTempCByIndex(1);

  DEBUGPRINT("Substrate Temp: ");
  DEBUGPRINT(substrateTemp);
  DEBUGPRINT(", Steamp Temp: ");
  DEBUGPRINT(steamTemp);
}


void resetPasteurizer() {
  digitalWrite(RELAYPIN, LOW);
  elementState = 0;
  stage = 0;
  if (state == 2) dbCheckRate = 1;
  else dbCheckRate = 5;
}

//------------------------------------MySql Functions--------------------------------------
bool spCheck() {
  watchDog.clear();
  DEBUGPRINT("Start spCheck. ");
  char tempState[4];
  byte newState = 0;
  MySQL_Cursor *cur = new MySQL_Cursor(&conn);
  row_values *row = NULL;

  cur->execute(SELECT);
  cur->get_columns();
  do {
    row = cur->get_next_row();
    if (row != NULL) {
      strcpy(tempState, row->values[2]);
      strcpy(delayStart, row->values[3]);
      steamTempSP = atol(row->values[4]);
      thresholdTempSP = atol(row->values[5]);
      thresholdTime = atol(row->values[6]);
    }
  } while (row != NULL);
  delete cur;

  DEBUGPRINT("Db State is: ");
  DEBUGPRINT(tempState);
  DEBUGPRINT(", DelayStart is: ");
  DEBUGPRINTLN(delayStart);

  if (strcmp(tempState, "off") == 0)newState = 0;
  else if (strcmp(tempState, "dly") == 0) {
    createTime(delayStart);
    newState = 1;
  }
  else if (strcmp(tempState, "on") == 0)newState = 2;
  else newState = 3;

  if (newState != state) {
    state = newState;
    resetPasteurizer();
    dbUpdate();
  }
}

void spUpdate() {
  watchDog.clear();
  DEBUGPRINT("Start spUpdate. ");
  char columnStr[40] = {"status"}, dataStr[20], tempStr[5];
  MySQL_Cursor *cur = new MySQL_Cursor(&conn);

  switch (state) {
    case 0: {
        strcpy(dataStr, "\'off\'");
        break;
      }
    case 1: {
        //this should never be called, but keep it for safety
        strcpy(dataStr, "\'dly\'");
        break;
      }
    case 2: {
        strcat(columnStr, ",mediaTemp,thresholdTemp,thresholdTime");
        strcpy(dataStr, "\'on\',");
        itoa(steamTempSP, tempStr, 10);
        strcat(dataStr, tempStr);
        strcat(dataStr, ",");
        itoa(thresholdTempSP, tempStr, 10);
        strcat(dataStr, tempStr);
        strcat(dataStr, ",");
        itoa(thresholdTime, tempStr, 10);
        strcat(dataStr, tempStr);
        break;
      }
    default: {
        strcpy(dataStr, "\'err\'");
        break;
      }
  }

  sprintf(query, INSERT_SP, columnStr, dataStr);
  DEBUGPRINTLN(query);
  cur->execute(query);
  delete cur;
  DEBUGPRINTLN("Last Serial that prints");   //<-------Last Serial update before hang--------------
}


bool dbUpdate() {
  watchDog.clear();
  DEBUGPRINT("Start dbUpdate. ");
  char columnStr[45] = {"status"}, dataStr[20];
  MySQL_Cursor *cur = new MySQL_Cursor(&conn);

  switch (state) {
    case 0: {
        strcpy(dataStr, "\'off\'");
        break;
      }
    case 1: {
        strcpy(dataStr, "\'dly\'");
        break;
      }
    case 2: {
        strcat(columnStr, ",elementState,stage");

        strcpy(dataStr, "\'on\',");
        dataStr[5] = elementState + 48;
        strcat(dataStr, ",");
        dataStr[7] = stage + 48;

        tempUpdate();

        if (substrateTemp != -127) {
          strcat(columnStr, ",steamTemp");
          dtostrf(substrateTemp, 5, 2, tempStr);
          strcat(dataStr, ",");
          strcat(dataStr, tempStr);
        }

        if (steamTemp != -127) {
          strcat(columnStr, ",substrateTemp");
          dtostrf(steamTemp, 5, 2, tempStr);
          strcat(dataStr, ",");
          strcat(dataStr, tempStr);
        }
        break;
      }
    default: {
        strcpy(dataStr, "\'err\'");
        break;
      }
  }

  sprintf(query, INSERT_DATA, columnStr, dataStr);
  DEBUGPRINTLN(query);
  cur->execute(query);
  delete cur;
}

//Standard functions
void myshutdown() {
  DEBUGPRINTLN("watchdog shutdown");
}


void wifiConn() {
  while (status != WL_CONNECTED) {
    Serial.println("Batman reporting in");
    digitalWrite(LED_BUILTIN, HIGH);
    delay(100);
    status = WiFi.begin(ssid, pass);
  }
  digitalWrite(LED_BUILTIN, LOW);
}


void createTime(const char *str) {
  int Year, Month, Day, Hour, Minute, Second;

  sscanf(str, "%d-%d-%d %d:%d:%d", &Year, &Month, &Day, &Hour, &Minute, &Second);
  tm.Year = CalendarYrToTm(Year);
  tm.Month = Month;
  tm.Day = Day;
  tm.Hour = Hour;
  tm.Minute = Minute;
  tm.Second = Second;

  delayTime = makeTime(tm);
}

You seem to have a fair coverage with you debugprintln thing, nevertheless it looks like you need moreā€¦

If the watchdog isn't working, it must be getting service that keeps it from firing off.

At a glance it appears there may be conditions in which you are actually running, just outside of any printed indications that you are.

I would start with printing something unique at each point where you "kick the dog" and see if you've really gone tots south, or just entered a blind spot to your coverage.

Have you tried using the watchdog from an exaplme sketch, or a small one you wrote yourself just to give some confidence that the mechanism is operating the way you think?

Also, I can't tell if you mean to rely on the watchdog in normal operating circumstances - if so, that should really be handled better with straight ahead code that recognizes and recovers from whatever you were using the watchdog for.

I just have to mention this article for you or anyone, good stuff all over this guy's website:

Not much direct help, just good thought food.

a7

Hey, thanks for the link, I'll check it out!

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