Hi,
I have created an industrial controller that communicates with a PC to turn on and off large loads and read inputs/ analog to digital/ set pwm, etc. The controllers are crashing - just freezing up, and I am having a hard time catching the issue, because it might take hours of use before it happens.
The controller is based on the Panda II.
The program’s main loop just flashes the onboard LED to show that it is alive and working. It checks an ‘isData’ flag to see if serial data is present:
while (true)
{
// Check to see if there is data available, then process
if (isData)
{
ProcessData();
}
// If 500 ms have passed, blink LED
if (i > 50)
{
LED.Write(!LED.Read());
i = 0;
}
Thread.Sleep(10);
i++;
}
The serial data interrupt:
/// <summary>
/// Handles Data Received by COM1
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void COM1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
// Set data flag
isData = true;
}
catch (Exception)
{
return;
}
}
If there is data, it is processed as a string to determine what action the PC wants:
/// <summary>
/// Processes incomming serial data
/// </summary>
static void ProcessData()
{
try
{
// Wait for full string
Thread.Sleep(50);
// set write buffer
bufferString = String.Empty;
byte[] bufferWrite = null;
// Set read buffer
byte[] buffer = new byte[COM1.BytesToRead];
COM1.Read(buffer, 0, COM1.BytesToRead);
char[] read = System.Text.Encoding.UTF8.GetChars(buffer);
string readString = new string(read);
string valueString = new string(new char[3] { read[3], read[4], read[5] });
// determine command value
int value = Convert.ToInt16(valueString);
// determine what action to take...
// Check for proper start character
if (read[0] == '$')
{
// Check for analog
if (read[1] == 'A' || read[1] == 'a')
{
// Check for input
if (read[2] == 'I' || read[2] == 'i')
{
// Read and print input
bufferString = ReadADC(Convert.ToInt16(read[3].ToString()), Convert.ToInt16(read[5].ToString()));
}
}
// Check for digital
else if (read[1] == 'D' || read[1] == 'd')
{
// Check for input
if (read[2] == 'I' || read[2] == 'i')
{
// Read inputs
bufferString = ReadDigitalInputs();
}
// Check for output
else if (read[2] == 'O' || read[2] == 'o')
{
// Write outputs
bufferString = WriteDigitalOutputs(value);
}
// Check for read outputs
else if (read[2] == 'R' || read[2] == 'r')
{
// Read Outputs
bufferString = ReadDigitalOutputs();
}
}
// Check for I/O expansion
else if (read[1] == 'X' || read[1] == 'x')
{
// Check for output
if (read[2] == 'O' || read[2] == 'o')
{
ExpansionSetOutput(read[4], read[5], read[6]);
}
// Check for set
if (read[2] == 'S' || read[2] =='s')
{
string outputValue = new string(new char[5] { read[4], read[5], read[6], read[7], read[8] });
ExpansionSetOutputs(read[3], Convert.ToInt16(outputValue));
}
// Check for input
else if (read[2] == 'I' || read[2] == 'i')
{
ExpansionReadInputs(read[3]);
}
// Check for read outputs
else if (read[2] == 'R' || read[2] == 'r')
{
ExpansionReadOutputs(read[3]);
}
}
// Check for PWM control
else if (read[1] == 'P' || read[1] == 'p')
{
// Check for PWM Set
if (read[2] == 'S' || read[2] == 's')
{
// Determine frequency
string dutyString = new string(new char[2] { read[4], read[5] });
// determine command value
int duty = Convert.ToInt16(dutyString);
// Set PWM
if (read[3] == '1')
{
if (duty == 0)
{
PWM1.Set(false);
}
else
{
PWM1.Set(1000, (byte)duty);
}
}
if (read[3] == '2')
{
if (duty == 0)
{
PWM2.Set(false);
}
else
{
PWM2.Set(1000, (byte)duty);
}
}
bufferString = "PWM Set";
}
}
// Create buffer string
bufferWrite = System.Text.Encoding.UTF8.GetBytes(bufferString + "\n");
// Return values
COM1.Write(bufferWrite, 0, bufferWrite.Length);
}
}
catch (Exception)
{
return;
}
finally
{
// Reset Data Flag
isData = false;
// Reset buffer string
bufferString = String.Empty;
}
}
I have a number of machines on my production floor with this problem, and it is getting to be a major issue. Any help that can be offered is very much appreciated.
Thank you,
Tom