Free Information Technology Magazines and eBooks

Friday, April 24, 2009

C#: Serial Port Communication

Serial Port Communication on C#Next week, we are to migrate our existing Truckscale system that was developed in Visual Basic 6.0. The system talks to a Weight Indicator hardware unit that transmit Weight information from the Weigh bridge. Aside from the Truck weight, the system also accepts some other information like the plate number, driver and etc. But the only challenge we are facing here is the migration of the serial port com module. Luckily for us Serial Port integration with .NET 2.0 is easier than we expect because it has SerialPort Class that represents a serial port resource. Today, I will share the solution with you. So without further ado, here is how to implement serial port communication using C#:


To reference SerialPort class on your project, we need the following "Using" directives:


using System.IO;
using System.IO.Ports;


Before we can communicate with a serial port, first we need to initialize it. Here's how:

Instantiate the Serial Port Class

//create an Serial Port object
SerialPort sp = new SerialPort();
//Error handling
SerialError spErr;


Initialize the Serial Port

private void InitializeComPort()
{
try
{
sp = new SerialPort();
//set the parameters
sp.PortName = Settings.Default.PortName;
sp.BaudRate = Settings.Default.BaudRate;
sp.Parity = Settings.Default.Parity;
sp.StopBits = Settings.Default.StopBits;
sp.DataBits = Settings.Default.DataBits;
sp.Handshake = Settings.Default.HandShake;

//open the COM port
sp.Open();

this.Text = "Truck Scale Entry (Connected)";

}
catch (IOException ioex)
{
MessageBox.Show("Error opening device:" + ioex.Message, "Warning");
}
catch (Exception ex)
{
MessageBox.Show("Error initializing device:" + ex.Message, "Warning");
}
finally
{
//Bind the events on the following event handler
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
sp.ErrorReceived += new SerialErrorReceivedEventHandler(sp_ErrorReceived);

}
}


Then to handle data being sent we need to put the data parsing code in sp_DataReceived event while for error handling use the sp_ErrorReceived event. To give you an idea, take a look on the actual code we have on our system:



//Serial Port Error Event Handler
private void sp_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
spErr = e.EventType;
}

//Serial Port DataReceived Handler
private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// This method will be called when there is data waiting in the port's buffer

// Determine which mode (string or binary) the user is in
if (Settings.Default.DataMode == DataMode.Text)
{
// Read all the data waiting in the buffer
try
{
string rawdata = sp.ReadLine();

//check if rawdata is empty
if (rawdata.Length > 0)
{
//perform data format, strip non-numeric char starting from weigh unit
string data = Convert.ToInt32(StripNonNumeric(rawdata.Substring(0, rawdata.IndexOf(Settings.Default.WeightUnit)))).ToString("##,##0") + Settings.Default.WeightUnit.ToLower();
if (data.Length > 0)
{
string preformat = data.Replace(",", "");
string weigh = preformat.Substring(0, preformat.IndexOf(Settings.Default.WeightUnit.ToLower()));
//store weigh as string and int
wd = new Weighdata(weigh, Convert.ToInt32(weigh));
// Display the text to the user in the terminal
Log(data); //this just display the capture wieght on a textbox
}
}


}
catch (Exception ex)
{
statusmsg("2- Error reading from device:" + ioex.Message);

}
}
else
{
// Obtain the number of bytes waiting in the port's buffer
int bytes = sp.BytesToRead;

// Create a byte array buffer to hold the incoming data
byte[] buffer = new byte[bytes];

// Read the data from the port and store it in our buffer
sp.Read(buffer, 0, bytes);

// Show the user the incoming data in hex format
Log(ByteArrayToHexString(buffer));
}
}



Usually Weigh Indicator units are set to continuous data transmission so we need a Timer Control to capture the data being sent every second. Add a timer control and on its Tick event, paste the following codes:


private void tmrCheckDevice_Tick(object sender, EventArgs e)
{
//check if serial port is already open, if not initialize it.
if (sp.IsOpen == false)
{

//reconnect
this.Text = "Truck Scale Entry (Disconnected from the device...)";
InitializeComPort();

}
else { this.Text = "Truck Scale Entry (Connected)"; }

switch (spErr)
{
case SerialError.Frame:
statusmsg("The hardware detected a framing error.");
break;
case SerialError.Overrun:
statusmsg("A character-buffer overrun has occurred. The next character is lost.");
break;
case SerialError.RXOver:
statusmsg("An input buffer overflow has occurred. There is either no room in the input buffer...");
break;
case SerialError.RXParity:
statusmsg("The hardware detected a parity error.");
break;
case SerialError.TXFull:
statusmsg("The application tried to transmit a character, but the output buffer was full.");
break;
}
}


Simple huh?. You just need to remove or change the code to fit your needs. Thank you for reading and have a nice day!


4 comments:

Naresh Kumar said...

Nice article. very very useful for me.

Can you provide complete source code for this demo

Ashraf said...

Hi, I need help for my final year project. I'm designing a carpark sensor system my display interface will be receiving data from the micro-controller and showing it on the display interface using visual studio 2008 C#. I need help in interfacing the data. For an example, updating number of lots available and showing pictures of cars at designated car park lots. Please get back to me as soon as possible. thanks.

Manoj said...

Hello
I am from Salunkhe Weigh Bridge ..My problem weight is not transfer from computer...so weigh bridge softwear is not running in auto mode ..please call me 9766364604

Anonymous said...

hello sir can you give me source code please.my email is ranagulzar009@yahoo.com