Reputation: 19
I am using the Serial Port functionality in C# to communicate with a piece of hardware. Everything writes fine to the serial port, and the serial port is always connected.
For some reason the Serial Port Data Received Handler doesn't always read data coming up (every 1 out of 8 times it fails to read anything or call the event function itself). Everything is fine on the other side. I am only receiving one letter from the serial port which is 1, 2, 3, etc
Here is my code:
Serial Setup:
//Create new serial port
SerialPort SerPort = new SerialPort("COM4");
private void SetupSerial()
{
SerPort.BaudRate = 9600;
SerPort.Parity = Parity.None;
SerPort.StopBits = StopBits.One;
SerPort.DataBits = 8;
SerPort.Handshake = Handshake.None;
SerPort.ReadTimeout = 4000;
SerPort.WriteTimeout = 6000;
SerPort.Open();
SerPort.DataReceived += new SerialDataReceivedEventHandler(HandleSerialData);
lblStatus.Text = "Successfully connected to COM port with no errors!";
}
My Write to Serial function:
private void WriteToSerial( string data )
{
byte[] MyMessage = Encoding.UTF8.GetBytes(data);
SerPort.Write(MyMessage, 0, MyMessage.Length);
string time = "[" + DateTime.Now.ToString("HH:mm") + "]";
bool debug = chkDebug.Checked;
if (debug ) f.DebugText = time + " Wrote bytes to serial: " + data;
}
My Recieve event function:
//Called everytime serial data is recieved
private void HandleSerialData(object sender, SerialDataReceivedEventArgs e)
{
try
{
//Store recieved data in variable
SerialPort sp = (SerialPort)sender;
string data = sp.ReadExisting().ToString();
bool debug = chkDebug.Checked;
string time = "[" + DateTime.Now.ToString("HH:mm") + "]";
if( debug ) f.DebugText = time + " Recieved serial data: " + data;
switch ( data )
{
case "1":
//If Battery is already on
if( Battery1[0] == "ON")
{
Battery1[0] = "OFF"; //ON or OFF
Battery1[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("1");
lblST1.Text = "n/a";
lblET1.Text = "n/a";
if (debug) f.DebugText = time + " Battery 1 testing switched OFF.";
}
else
{
Battery1[0] = "ON"; //ON or OFF
Battery1[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery1[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST1.Text = Battery1[1];
if (debug) f.DebugText = time + " Battery 1 testing switched ON.";
}
break;
case "2":
//If Battery is already on
if (Battery2[0] == "ON")
{
Battery2[0] = "OFF";
Battery2[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("2");
lblST2.Text = "n/a";
lblET2.Text = "n/a";
if (debug) f.DebugText = time + " Battery 2 testing switched OFF.";
}
else
{
Battery2[0] = "ON"; //ON or OFF
Battery2[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery2[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST2.Text = Battery2[1];
if (debug) f.DebugText = time + " Battery 2 testing switched ON.";
}
break;
case "3":
//If Battery is already on
if (Battery3[0] == "ON")
{
Battery3[0] = "OFF"; //ON or OFF
Battery3[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("3");
lblST3.Text = "n/a";
lblET3.Text = "n/a";
if (debug) f.DebugText = time + " Battery 3 testing switched OFF.";
}
else
{
Battery3[0] = "ON"; //ON or OFF
Battery3[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery3[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST3.Text = Battery3[1];
if (debug) f.DebugText = time + " Battery 3 testing switched ON.";
}
break;
case "4":
//If Battery is already on
if (Battery4[0] == "ON")
{
Battery4[0] = "OFF"; //ON or OFF
Battery4[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("4");
lblST4.Text = "n/a";
lblET4.Text = "n/a";
if (debug) f.DebugText = time + " Battery 4 testing switched OFF.";
}
else
{
Battery4[0] = "ON"; //ON or OFF
Battery4[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery4[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST4.Text = Battery4[1];
if (debug) f.DebugText = time + " Battery 4 testing switched ON.";
}
break;
case "5":
//If Battery is already on
if (Battery5[0] == "ON")
{
Battery5[0] = "OFF"; //ON or OFF
Battery5[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("5");
lblST5.Text = "n/a";
lblET5.Text = "n/a";
if (debug) f.DebugText = time + " Battery 5 testing switched OFF.";
}
else
{
Battery5[0] = "ON"; //ON or OFF
Battery5[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery5[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST5.Text = Battery5[1];
if (debug) f.DebugText = time + " Battery 5 testing switched ON.";
}
break;
case "6":
//If Battery is already on
if (Battery6[0] == "ON")
{
Battery6[0] = "OFF"; //ON or OFF
Battery6[2] = DateTime.Now.ToString("h:mm tt"); //End time
WriteLogFile("6");
lblST6.Text = "n/a";
lblET6.Text = "n/a";
if (debug) f.DebugText = time + " Battery 6 testing switched OFF.";
}
else
{
Battery6[0] = "ON"; //ON or OFF
Battery6[1] = DateTime.Now.ToString("h:mm tt"); //Start time
Battery6[5] = DateTime.Now.ToString("d/MM/yyyy"); //Start date
plcRespond = true;
lblST6.Text = Battery6[1];
if (debug) f.DebugText = time + " Battery 6 testing switched ON.";
}
break;
}
SerPort.DiscardInBuffer();
SerPort.DiscardOutBuffer();
}
catch (Exception ex)
{
MessageBox.Show("Error recieving COM data! " + ex.Message);
}
}
Is there a better way of reading serial data not using the ReadExisting? Or using a more reliable function?
Upvotes: 0
Views: 1317
Reputation: 1974
I have had problem in the past with ReadExisting
. I don't know what happens in ReadExisting if more data arrives while the buffer is being read.
In serial port even handlers I use the following code. Because it determines the length to read first, new data arriving will be read during the next function call so the buffer can be emptied at the rate data is sent.
private void HandleSerialData(object sender, SerialDataReceivedEventArgs e)
{
int lengthToRead = sp.BytesToRead;
byte[] rxBytes = new byte[lengthToRead];
sp.Read(rxBytes, 0, lengthToRead);
functionThatInterpratesData(rxBytes);
}
This also has the benefit of being re-usable because you convert the byte array to a string or however you have encoded it separately.
I would create a function to convert you byte array to a string (lots of examples on SO) and another one to handle the case statement.
Upvotes: 2