Hi all,
This is my first post so please excuse me if I'm in the wrong board or my formatting's a little weird. I'm working on a relatively simple project that I can't get to run right because of what I believe is a software issue. My Arduino Uno board will sometimes run my sketch for hours without an issue and then randomly reset. Sometimes it won't make a few loop iterations. I've rebuilt my circuit onto a perfboard shield to ensure it isn't a connection issue and have supplied the Arduino with it's own 12V supply so the regulator can keep it running independent of the system and it's noise. Here's a simple circuit diagram.
(I couldn't find a good representation of the arduino plug input and the resistor value bands are incorrect as well, they are 10KΩ pulldown resistors.)
The basic operating procedure is this:
- The system is powered on and the Arduino initializes the SD reader.
- The SD card is cleared of the previous log file ("Output.csv") and a fresh one is created.
- The system closes the first relay, waits 100 ms for the mechanical system on the other end to actuate.
- The Arduino reads the switches of the Unit Under Test (one is engaged at the beginning of travel while the other is actuated at the bottom) and stores the states using digital read.
- The data is logged to the SD card
- The relay is opened and the system waits another 100 ms.
- Repeat from 3 until 1,000,000 loop iterations have been cleared without triggering any failure conditions.
The failure conditions are if the UUT fails to register either switch three times consecutively or if the same step fails three times in a row.
I believe that the reason the unit keeps restarting is because of something I'm doing wrong in my code but I have no idea what it could be. I know the Arduino will fail if the RAM gets overloaded but I've gone through and tried to trim the fat and make sure I have some headroom for the system to work. However, since I'm using an Uno there isn't a ton of memory to work with and I'm hoping that's the issue. The Arduino IDE reports ~830 bytes are open in dynamic memory.
Below is my code in full.
#include <SD.h>
const unsigned char fs = 7; //footswitch enable input
const unsigned char fsb = 2; //footswitch boost input
const unsigned char rly_1 = 3;//relay 1
const unsigned char rly_2 = 4;//relay 2
const unsigned char rly_3 = 5;//relay 3
const unsigned char rly_4 = 6;//relay 4
const char* errordecode[4] = {"No error", "No enable", "No boost", "Both failed"};
const unsigned char steppause = 100;//pause between step
unsigned char fsstate = 0;//footswitch enabled
unsigned char fsbstate = 0;//boost enabled
unsigned long loopcount = 1;//current step
unsigned char step = 1;//4 side of footpedal per step counter
unsigned long errorarray[9][3];//counts errors for analysis
unsigned char currerrcode = 0;//0=none;1=no enable;2=no boost;3=both fail
File outputtxt;
void setup()
{
//Serial.begin(115200);0
pinMode(fs, INPUT);
pinMode(fsb, INPUT);
pinMode(rly_1, OUTPUT);
pinMode(rly_2, OUTPUT);
pinMode(rly_3, OUTPUT);
pinMode(rly_4, OUTPUT);
digitalWrite(rly_1, HIGH);
digitalWrite(rly_2, HIGH);
digitalWrite(rly_3, HIGH);
digitalWrite(rly_4, HIGH);
if (!SD.begin(10))
{
while (1)
{
//will not procceed without SD card
}
}
delay(100);
outputtxt = SD.open("Output.csv", FILE_WRITE);
if (outputtxt)
{}
else
{
while (1);
{}
}
outputtxt.println("Count,Step,Code");
outputtxt.close();
}
void loop()
{
switch (step)
{
case 1://1st Press
digitalWrite(rly_1, LOW);
delay(steppause);
fsstate = digitalRead(fs);
fsbstate = digitalRead(fsb);
if (fsstate == 0 || fsbstate == 0)
{
goto error;
}
else
{
currerrcode = 0;
digitalWrite(rly_1, HIGH);
step = 2;
delay(steppause);
break;
}
case 2://2nd Press
digitalWrite(rly_2, LOW);
delay(steppause);
fsstate = digitalRead(fs);
fsbstate = digitalRead(fsb);
if (fsstate == 0 || fsbstate == 0)
{
goto error;
}
else
{
currerrcode = 0;
digitalWrite(rly_2, HIGH);
step = 3;
delay(steppause);
break;
}
case 3://3rd Press
digitalWrite(rly_3, LOW);
delay(steppause);
fsstate = digitalRead(fs);
fsbstate = digitalRead(fsb);
if (fsstate == 0 || fsbstate == 0)
{
goto error;
}
else
{
currerrcode = 0;
digitalWrite(rly_3, HIGH);
step = 4;
delay(steppause);
break;
}
case 4://4th Press
digitalWrite(rly_4, LOW);
delay(steppause);
fsstate = digitalRead(fs);
fsbstate = digitalRead(fsb);
if (fsstate == 0 || fsbstate == 0)
{
goto error;
}
else
{
currerrcode = 0;
digitalWrite(rly_4, HIGH);
step = 1;
delay(steppause);
break;
}
error:
digitalWrite(rly_1, HIGH);//disable all relays
digitalWrite(rly_2, HIGH);
digitalWrite(rly_3, HIGH);
digitalWrite(rly_4, HIGH);
if (fsstate == 0)
{
currerrcode = 1;
}
else if (fsbstate == 0)
{
currerrcode = 2;
}
else if (fsbstate == 0 && fsstate == 0)
{
currerrcode = 3;
}
delay(1000);
if (step <= 3)//after 1 sec continue to next step
{
step++;
}
else
{
step = 1 ;
}
break;
}
//Log errors
for (int i = 0; i < 9; i++)
{
if (i < 8)
{
errorarray[i][0] = errorarray[i + 1][0];
errorarray[i][1] = errorarray[i + 1][1];
errorarray[i][2] = errorarray[i + 1][2];
}
else
{
errorarray[8][0] = loopcount;
errorarray[8][1] = step;
errorarray[8][2] = currerrcode;
}
}
if (errorarray[6][2] != 0 && errorarray[7][2] != 0 && errorarray[8][2] != 0)
{
outputtxt = SD.open("Output.csv", FILE_WRITE);
outputtxt.print(loopcount); outputtxt.print(","); outputtxt.print(step); outputtxt.print(","); outputtxt.println(currerrcode);
outputtxt.print("3 Consecutive failure shutdown - Past 9");
outputtxt.close();
while (1)
{}//3 Consecutive failure shutdown - Past 9
}
if (errorarray[0][2] != 0 && errorarray[4][2] != 0 && errorarray[8][2] != 0)
{
outputtxt = SD.open("Output.csv", FILE_WRITE);
outputtxt.print(loopcount); outputtxt.print(","); outputtxt.print(step); outputtxt.print(","); outputtxt.println(currerrcode);
outputtxt.print("3 Sequential Step failure - Past 9");
outputtxt.close();
while (1)
{}//3 Sequential Step failure - Past 9
}
}
outputtxt = SD.open("Output.csv", FILE_WRITE);
if (!outputtxt)
{
while (1)
{}// Detects if SD card is removed
}
if (step > 1)
{
outputtxt.print(loopcount); outputtxt.print(", "); outputtxt.print(step - 1); outputtxt.print(", "); outputtxt.println(errordecode[currerrcode]);
}
else
{
outputtxt.print(loopcount); outputtxt.print(", 4, "); outputtxt.println(errordecode[currerrcode]);
}
outputtxt.close();
loopcount++;
if (step >= 1000000 - 70000) //Success State
{
outputtxt = SD.open("Output.csv", FILE_WRITE);
outputtxt.println("END");
outputtxt.close();
while (1)
{}//Victory Condition
}
}
and before you yell at me yes I know goto is the devil, but I couldn't think of a cleaner way to do it. Suggestions on how to make that more concise would be appreciated. Also removed some serial debugging things I had in the comments to make my post shorter.