I am running 4 linear actuators, a CO2 sensor and a solenoid valve from a Teensy 4.0. the teensy is always connected to the PC from which a C# program is sending simple text commands to control the linear actuators and solenoid valve and read the CO2 sensor. In a similar project I had issues with the teensy crashing, likely caused by buffer overflow, so I programmed in a watchdog to reset the teensy whenever it gets overwhelmed. The watchdog works when I intentionally send long nonsensical strings to the teensy and the C# program can reopen the port and continue communication. Somehow, the Teensy still crashes once in a while ( ~ once every 12 hours, but irregular) in a way that the watchdog cannot reset it. Besides requesting CO2 sensor data, no communication is usually happening at the moment of the crash, and the only way to recover the connection to the teensy is by unplugging and plugging it back in. As I am using this in a system that needs to run continuously for >5 days, I need to resolve this crashing problem. Clearly, the teensy can crash in ways the watchdog cannot recover, but how?
This is my code:
This is my code:
Code:
#define HWSERIAL Serial5
#include "Watchdog_t4.h"
WDT_T4<WDT1> wdt; // watchdogtimer
char c = ' '; //initializes to a space
char cmdBuffer[9] = "";
int Current = 0;
int AIN2[4] = {1,5,8,11};
int AIN1[4] = {2,4,9,10};
int PWM[4] = {0,6,7,12};
int STBY = 3;
int Solenoid = 18;
elapsedMillis AliveTime; //timer for checking PC connection
long TimeOn = 0; // tracks time CO2
void setup()
{
Serial.begin(115200);
Serial.println("Teensy is ready");
Serial.println("Serial started at 115200");
HWSERIAL.begin(9600); // Serial port declaration for communication with CO2 sensor
for ( int k = 0; k <= 3; k++) { // sets mode of all channels
pinMode(AIN2[k], OUTPUT);
pinMode(AIN1[k], OUTPUT);
pinMode(PWM[k], OUTPUT);
analogWriteFrequency(PWM[k], 20);
analogWrite(PWM[k], 30);
}
pinMode(STBY, OUTPUT);
pinMode(Solenoid, OUTPUT);
analogWriteResolution(8);
digitalWrite(STBY, HIGH);
// watchdog config block
WDT_timings_t config;
config.trigger = 5;
config.timeout = 10;
// config.callback = myCallback;
wdt.begin(config);
// end watchdog config blcok
}
void loop()
{
wdt.feed();
if (HWSERIAL.available()) // pass through data from CO2 sensor to PC
{
c = HWSERIAL.read();
Serial.write(c);
}
if (Serial.available()) // respond to commands send from PC.
{
while (Serial.available())
{
c = Serial.read(); // read by character
cmdBuffer[Current] = c;
Current++;
if (c == '\n') // jump to action when end of line is detected, otherwise keep reading
{
else if (cmdBuffer[0] == 'Z' ) // CO2 data request.
{
for (int i = 0; i <= 2; i++) {
HWSERIAL.write(cmdBuffer[i]);
delay(10);
}
}
else if (cmdBuffer[0] == 'I') // linear actuator control
{
if (Current == 7) /
{ // command format: "I" +"0" (bathnumber) + "000" (pump speed) +"U" or "D" or "S" (direction) + "/n"
String Temp = "";
Temp = cmdBuffer[1];
int Pump = Temp.toInt();
Temp = "";
Temp += cmdBuffer[2];
Temp += cmdBuffer[3];
int PumpSpeed = Temp.toInt();
String Direction = cmdBuffer[4];
if (Pump >= 0 && Pump <= 3 && PumpSpeed > 0 && PumpSpeed <= 100 && (Direction == "U" || Direction == "D" || Direction == "S"))
{
if (Direction == "D")
{
digitalWrite(AIN1[Pump], HIGH);
digitalWrite(AIN2[Pump], LOW);
analogWrite(PWM[Pump], PumpSpeed);
}
else if (Direction == "U")
{
digitalWrite(AIN1[Pump], LOW);
digitalWrite(AIN2[Pump], HIGH);
analogWrite(PWM[Pump], PumpSpeed);
}
else
{
digitalWrite(AIN1[Pump], LOW);
digitalWrite(AIN2[Pump], HIGH);
analogWrite(PWM[Pump], 0);
}
}
}
}
else if (cmdBuffer[0] == 'S') // CO2 solenoid control. command format: "S" + "0000" (time solenoid stays in open position in milliseconds)
{
String Temp = "";
Temp += cmdBuffer[1];
Temp += cmdBuffer[2];
Temp += cmdBuffer[3];
Temp += cmdBuffer[4];
TimeOn = millis() + (Temp.toInt());
digitalWrite(Solenoid, HIGH);
}
else if (cmdBuffer[0] == 'A') // signals live connection
{
AliveTime = 0;
}
cmdBuffer[0] = 0;
Current = 0;
}
delay(55);
}
}
if (millis() > TimeOn) // turns solenoid closed when time is up.
{
digitalWrite(Solenoid, LOW);
}
if (AliveTime > 10000) // Means connection to PC lost, so shut down all actuators
{
digitalWrite(Solenoid, LOW);
analogWrite(PWM[0], 0);
analogWrite(PWM[1], 0);
analogWrite(PWM[2], 0);
analogWrite(PWM[3], 0);
Serial.println("6. External Dead");
delay(500);
}
}