Introduction

The Arduino boards provide an easy-to-use environment to control electrical components such as LEDs and motors. I have done this project with an Arduino Mega 2560 microcontroller board, but you can use nearly any official Arduino board.

To download and execute the source files attached to this article, you will need to have the following tools installed:

Background

I completely rewrote this article in fall 2013 and added several new examples, a better explanation and more background information.

What is a Serial Interface?

A serial interface is used for information exchange between computers and peripheral devices. When using a serial communication, the information is sent bit by bit (serial) over a cable. Modern serial interfaces are Ethernet, Firewire, USB, CAN-Bus or RS-485 even though they are not always called "a serial interface". The principle stays the same: Information is bit-by-bit transformed over short distances. Glenn Patton published a great article about the design patterns used by serial communication Ports - It is available on CodeProject.

Working Theory

To explain how a C# program and an Arduino Board may communicate, we are going to assume that the Arduino Board has a temperature sensor, collecting the environment temperatures three times a day: Once in the morning, once at noon and once in the evening. All these values are stored to the EEPROM on the Arduino board. The data is stored in the following format:

The raw data is formatted as [DATE TIME]=[temperature], and the temperature value is intended to be measured and stored in Celsius (C). The single sets of temperature data are separated by line breaks.

Now, in order to focus on the serial communication, I decided to leave out the EEPROM reading/writing and just define a set of dummy values which are sent whenever a request for the temperature data is coming to the Arduino board. I did a quick example of how a single set of data will look in the Arduino C++ code (I use Arduino's <a href="http://arduino.cc/de/Reference/StringObject" title="Arduino Reference - The String class">String</a> class):

Given the fact that a date-time (for example "11 21 2013 06:00", which stands for November 21st 2013 at 06:00 AM) can be at most 15 characters long, the temperature will cover everything from -275.00 to 1999.999 degrees and the separator ('=') is another character we come to a total length of 23 characters the singleSetOfData needs to take - Why is it in fact 24 characters long then?
Easy question, easy answer: The compiler adds a terminating character '\0' at the end which's space used need to be taken care of, too - 23 + 1 = 24.

I will not go into detail about the thermometer implementation since there are plenty of instruction sets on how to build one available on the internet - We are going to send dummy values anyways
However, the Arduino board may receive a serial command telling it to read the collected temperature data. I assigned every command a single command code, and defined it to be terminated by a '#' character. So for example, the command to tell the Arduino board has to send the stored temperature data would come like this over the serial interface of the Arduino board, issued by the .NET application which is going to display the temperature data:

1#

Simples. That's it. After the Arduino Board receives this command, it is going to send our previously defined dummy data up to the .NET application, using the serial port, too (Of course, this requires the .NET application to stop sending any command down to the Arduino board):

Every transmission starts with the code [STX] which is the official US ASCII code for the start of a transmission text (Code "2"). The transmission ends after sending the code [ETX] which is the official US ASCII code for the end of a transmission text (Code "3"). The single datasets are separated by a dollar ($) sign.

Using the Code

The code presented in this chapter was completely rewritten during fall 2013 to provide a more valuable learning resource, and match a less theoretical working theory.

The Arduino Source Code

Error, Warning and Status codes

I use various Error, Warning and Status codes within the Arduino source code to indicate whether method calls were successful or ended up causing a warning or an error.

/* WARNING, ERROR AND STATUS CODES *///STATUS#define MSG_METHOD_SUCCESS 0 //Code which is used when an operation terminated successfully
//WARNINGS#define WRG_NO_SERIAL_DATA_AVAILABLE 250 //Code indicates that no new data is available at the serial input buffer
//ERRORS#define ERR_SERIAL_IN_COMMAND_NOT_TERMINATED -1 //Code is used when a serial input commands' last char is not a '#'

Read a command from the Serial Input

I created a method which reads a command from the Arduino Board's serial input buffer and writes it into the pointer which points to an Arduino-String - returned is an integer value indicating an operation success or an operation fail / warning. It returns either one of the three following codes:

MSG_METHOD_SUCCESS

This code is returned if everything went fine and the command was written into the command pointer.

WRG_NO_SERIAL_DATA_AVAILABLE

This code is returned if the serial input buffer doesn't contain any data at the time the method is executed.

ERR_SERIAL_IN_COMMAND_NOT_TERMINATED

This code is returned if there is no data available in the serial input buffer before the end of a command was reached (which means it was not terminated by the '#' character)

Actually, this is the only method I left untouched in comparison to the article and source code in previous versions before I did the complete rewrite.

The code of this method is built up as follow:

The default return code operationStatus is MSG_METHOD_SUCCESS. If no data is available in the serial input buffer (checked by calling Serial.Available() which returns true if there is data in the serial input buffer), the said operationStatus has the code WRG_NO_SERIAL_DATA_AVAILABLE assigned.

What now happens is not a big deal and easy to explain. I declared the variable serialInByte in order to store a single byte which was read by the Serial.Read() method (which reads exactly one byte from the serial input buffer). I call the said Serial.Read() method, store the byte returned into serialInByte and append serialInByte to the command pointer - This goes on and on until no data is available in the serial input buffer, or the character "#" is showing up, indicating the end of a command.

The last if after the do-while-Loop checks whether the last read character was a "#" and sets the operationStatus to ERR_SERIAL_IN_COMMAND_NOT_TERMINATED if it wasn't because this would mean that a transmission error occurred.

Answer a Serial Command

As you may know, the Arduino source code has a loop() method which is executing the source code in a forever-loop. I placed the code to handle a command directly in this method:

As you can see, I call readSerialInputCommand to read the command string from the serial input buffer. The return code of the method call is stored in the integer variable serialResult, which is afterwards used to detect wether there was a command available to read:

Sure that this method call would need to be replaced in case you really want to send actual weather / any other data to the serial output, but it's fair enough for demonstration purposes.

The .NET Source Code

I implemented a small demo WPF application which shows you how serial data can be handled using the .NET Framework.

The WeatherDataContainer class

I have two classes which help me to organize the communication with the Arduino Board: WeatherDataItem and WeatherDataContainer. While the WeatherDataItem is a sole data-holding class (consisting of a property for the date and one for the temperature) WeatherDataContainer is (amongst a List of WeatherDataItems) encapsulating the communication with the Arduino Board, too.

Since the GUI is only calling methods which can be found in the WeatherDataContainer class, I'll focus on it rather than unrolling the boring GUI code.

The WeatherDataContainer has two field variables:

// Interface for the Serial Port at which an Arduino Board is connected.
SerialPort arduinoBoard = new SerialPort();
//Holds a List of WeatherData Items in order to store weather data received from an Arduino Board.
List<WeatherDataItem> weatherDataItems = new List<WeatherDataItem>();

It is important for you to keep these variables and the event in mind, since they'll be mentioned throughout the following code snippets.

Connect to an Arduino Board

The Serial communication capabilities for .NET are provided by the SerialPort class from the System.IO.Ports namespace. Before you can send or receive data with a SerialPort instance, you need to open the Port:

After this command is received by the Arduino Board, it will send back the weather data and trigger the DataReceived event of the Serial Port.

Receive and parse serial data

As soon as there is data available at the input buffer of the Serial Port, it will fire the DataReceived Event which is handled by the following event handler in the WeatherDataContainer class:

void arduinoBoard_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string data = arduinoBoard.ReadTo("\x03");//Read until the EOT code//Split into 'date=temperature' formatted text
string[] dataArray = data.Split(new string[]
{"\x02", "$" }, StringSplitOptions.RemoveEmptyEntries);
//Iterate through the split data and parse it into weather data items//and add them to the list of received weather data.foreach (string dataItem in dataArray.ToList())
{
WeatherDataItem weatherDataItem = new WeatherDataItem();
weatherDataItem.FromString(dataItem);
weatherDataItems.Add(weatherDataItem);
}
if(NewWeatherDataReceived != null)//If there is someone waiting for this event to be fired
{
NewWeatherDataReceived(this, new EventArgs()); //Fire the event, // indicating that new WeatherData was added to the list.
}
}

Closing a SerialPort

It is highly recommended to close a SerialPort after it isn't in use anymore. This happens by calling the Close() method on a SerialPort object:

arduinoBoard.Close();

The GUI

I chose two ways of displaying the weather data: As DataGrid, and as 3D Cylinder Chart. Either one of them has its advantages, even though I prefer the Chart since it looks a bit fancier.

Displaying the Data in a Data Grid

Displaying the weather data in a data grid has an advantage if you want to display a lot of data in a reasonable way - If you only have ten or less data items displaying the weather data as a Cylinder graph is rather reasonable.

In the End, a Chart looking somewhat like the Chart shown in the picture below is drawn onto the Canvas:

Points of Interest

Arduino provides a huge amount of possibilities on working with hardware and connection to a computer. Last but not least, at the official Arduino homepage is a large community support available. It is very interesting which possibilities are available when you use a serial interface: You can send a pretty huge amount of data and it is not even really complicated.

The best part (for me) was that I was able to do a basic bit of WPF. I played around with various methods of databinding and invoking before I got the .NET app to run.

It depends on the communication protocol. Most, but not every serial communication protocol relies on EOT as the End of Transmission Block. I've seen some who determined the End of the Transmission by their length, or defined '\0' as EOT. There is really anything possible...

I will never again mention that Dalek Dave was the poster of the One Millionth Lounge Post, nor that it was complete drivel.

The Link looks interesting, even though I am not surprised to see that there are Arduino clones available on the market since the Arduino platform and its construction plans for the boards are fully open source.

I haven't had the patience to search and write down the details of how a COM Port works, apart from that these facts wouldn't be directly applicable on the USB-based COM Port communication - It was just easier for me to refer to your article .

Hi,
The article is really informative, thank you for it.
Since I am a beginner I got a bit confused, so I would like to ask for help, if possible.
The so called "commands" I send from the computer to the Arduino board are simple strings which will be printed to the Serial Monitor but they won't be executed or anything like that, will they?

So no matter what I send to the board nothing will change in its behaviour, right?

Yes that's right, you send it you need to write a handler to take the string check it (compare it) to a list if() it is on the do something. When it is compared (using a switch() case statement) it will give the chance to act on things like turn an LED on! If you want the boards behaviour to change you are in control, practice the evil laugh now

Hello,
i really like the article and i appreciate your effort. Pls, i would like to get the schematics for this design and also to know if the usb port on the Arduino board could be used for serial communication.
Thanks.