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