Quantcast
Channel: xanthium enterprises - robotics and embedded system for all
Viewing all articles
Browse latest Browse all 134

Cross platform Serial Programming using C# on Linux and Windows

$
0
0

serial programming tutorial on windows /linux using CSharp (C#) and dot net framework and net core

In this tutorial we are going to learn How to program the serial port on a Windows/Linux PC using C# .

The main goals of the tutorial are

  • Develop a cross platform serial communication App using C# and .NET Core(3.1)/.Net 5 to communicate with a USB device over Virtual COM port.
  • Develop a serial communication App using C# and Dotnet Framework 4.5+ to communicate with a USB device over Virtual COM port.
  • How to control the RTS and DTR pins of Serial Port using C# and .Net Core(3.1)/.Net 5 /Dotnet Framework 4.5+.

All the codes listed here are designed to run on command line and is intended to highlight the core serial programming concepts.

 

If you are looking for a GUI based serial programming tutorial check the link below.

 

Sourcecodes

link to xanthium enterprises repo on Github containing code for serial communication using CSharp and Dot net Framework 

 

Compilers and IDE's used 
 

C# code is written and compiled using

  1. Visual Studio Community Edition  on Windows 10
  2. Visual Studio code on Linux (Ubuntu)

 

Hardware Used 

Buy USB to RS485 converter online from here   Buy USB to RS485 converter online from here (made in India )

USB2SERIAL - Any easy to use multi protocol converter that can convert from USB to RS485/RS232/Serial.The Board comes with selectable voltage levels for interfacing with 5V and 3.3V logic families.

Selecting the COM port
To find out the COM number corresponding to your serial port, 

  • In Windows7, Open Device Manager by right clicking on My Computer icon and selecting "Manage → Device Manager".Under Ports(COM & LPT) you can see the parallel and serial ports (COM) detected by your system.
  • In Windows 10, Type "Device Manager"on the serach box in the Taskbar.

 

serial ports (COM) detected by your system

If your PC has any hardware ports, it will be shown either as COM1 or COM2 under the Ports Section.

I am using a FTDI based USB to Serial Converter (USB2SERIAL) which is recognized as COM46.

If you double click on COM46,you can see the details of the corresponding port.

 

Displaying the available serial ports using C#

String[] PortNames = SerialPort.GetPortNames();

Console.WriteLine("Available Ports:");
foreach (string s in
PortNames)
{
    Console.WriteLine("   {0}", s);
}

SerialPort.GetPortNames() is a static method which can be used to get all the available Serial ports in your System.

It is a part of the System.IO.Ports namespace,so you have to include it.

It returns an array of available serial ports(COMxx in Windows and ttyUSBx in Linux).

 

Opening a serial port in C# (C Sharp)

Serial port communication is accomplished using the SerialPort Class provided by the Dotnet Framework.The namespace is also available in .Net Core 3.0 and up  

The class is present in the System.IO.Ports namespace .In order to access the SerialPort class you have to include the System.IO.Ports namespace  in your source file.

In Visual studio if everything is properly configured the auto complete feature will show the namespace while typing. 

System.IO.Ports namespace  imported into program.cs for serial programming

 

Writing into Serial Port using C# (C Sharp)

Now lets write a small program that will open a connection to serial port and configure BaudRate,Stop bits ,Parity etc and send a character to Microcontroller board connected to it.

The microcontroller and PC are interfaced using null modem cable and is shown at the bottom of this page. 

usingSystem.IO.Ports; //namespace containing SerialPort Class
using System;          
                             

namespace SerialPort_Tutorial
{
    classProgram
    {
        staticvoid Main(string[] args)
        {
            SerialPort MyCOMPort = new SerialPort(); // Create a new SerialPort Object
            
            //COM port settings to 8N1 mode 
            MyCOMPort.PortName = "COM46";            // Name of the COM port 
            MyCOMPort.BaudRate = 9600;               // Baudrate = 9600bps
            MyCOMPort.Parity  = Parity.None;        // Parity bits = none 
            MyCOMPort.DataBits = 8;                  // No of Data bits = 8
            MyCOMPort.StopBits = StopBits.One;       // No of Stop bits = 1

            try
            { 
              MyCOMPort.Open();   // Open the port
            }
            Catch(Exception Ex)
            {
 
            }

            MyCOMPort.Write("A");                    // Write an ascii "A"
            MyCOMPort.Close();                       // Close port
        }
    }
}

After you have typed/copied  the code into the Visual Studio IDE.

Compile and Run it by pressing F5.the code will open a connection to the serial port ("COM46") ,write an ASCII " A " character and close the port.

If you are using the USB2SERIAL converter brought from this site, TX_RX_LED (D1) will blink signifying that a character is transmitted.

Please note that "COM46" is the serial port number assigned by my computer,the COM number will be different in your system.Please check the device manager and find out COM number assigned to your serial port or USB to serial converter.

If you have entered an invalid COM port number that do not exist in your computer (I have used COM4 to show that),Visual Studio will generate an exception.

 exception generated by visual studio on writing into invalid serial port

In the above code we are creating a SerialPort object of the name MyCOMPort

SerialPort MyCOMPort = new SerialPort();

which is then use to configure the parameters and communicate with the serial port.After the SerialPort object MyCOMPort is created,We assign the name of the serial port to be opened to it. 

MyCOMPort.PortName = "COM46";

then baud rate Parity bits and number of start stop bits are assigned .

 

Setting Parity,Stop/Start bits for Serial Port in C#

Parity can be selected as Even,Odd or None using Parity.Even , Parity.Odd ,Parity.None.

The good thing about the intellisense feature in Visual studio is that it will show all the available options when you type.

MyCOMPort.Parity   = Parity.None;

Intellisense showing parity options

 

You can see the options of Stop bits also in the same way.In the above program we are using one stop bit.

MyCOMPort.StopBits = StopBits.One;

Intellisense showing stop bit options

 

Opening a SerialPort in C#

After the settings are configured we open the serial port usingMyCOMPort.Open();

Opening  a serial port is a critical operation and may generate exceptions.It is our duty as the programmer to catch and handle these exceptions.

We should enclose the statement  MyCOMPort.Open(); within a try catch() block and handle any exceptions that may arise.

You can make do with a single try catch block or use multiple blocks as shown below.This one helps to pinpoint the cause of the exception and makes it easy to debug the application.

try
{
     MyCOMPort.Open();     // Open the port
}
catch (UnauthorizedAccessException Ex)
{
   //Access is denied to the port
}
catch(ArgumentOutOfRangeException Ex)
{
   //Parity, DataBits,Baudrate are not valid values
}
catch (ArgumentException Ex)
{
    //The port name does not begin with \"COM\
}
catch (IOException Ex)
{
   //The port is in an invalid state
}
catch (InvalidOperationException Ex)
{
   //Port on the current instance of the SerialPort is already open
}

 

After you have successfully opened the Serialport ,write a character or string using MyCOMPort.Write("A");

After the communication is over we close the port using MyCOMPort.Close();

Here is the screenshot of Program running on Windows 7 transmitting a ASCII character 'A' to the microcontroller.Here COM81 is the name of my COM port.

serial port programming using C Sharp and Dot net framework writing a charater

 

Reading from Serial Port using C# (C Sharp)

One problem with reading from Serial Port is that you need some data coming from the outside world through the serial port which you can read.

One way to solve is to use another computer and connect its serial port with your's using a NULL Modem cable.

Another way is to use a microcontroller board like Arduino,MSP430 Launchpad etc to transmit a string to your computers serial port.In this example i am going to use the later method,where a MSP430 Launchpad/ATmega328P will transmit a string of characters toward my PC using its UART which is then read by C# program running on the PC. 

One thing to note is that Legacy PC's may have hardware based DB9 RS232 serial ports (quite rare now a days),When you are connecting your microcontroller board with PC make sure that it(microcontroller board) has an RS232 decoder circuit (usually based on MAX232).Connecting the outputs of a DB9 serial port directly to microcontroller pins will damage it.

PC to Microcontroller Serial Communication setup

In this example I am using a MSP430 launchpad which is connected to a laptop using a USB to Serial Converter (USB2SERIAL).USB2SERIAL provides access to the TTL outputs of FT232 (RXD and TXD ) through berg strip connectors which can then be directly connected to the UART of MSP430.

It also has selectable TTL voltage levels(3V and 5V) so that it can be directly connected to 3.3V microcontrollers like MSP430. The TXD(TTL) of MSP430 is connected to RXD (TTL) of USB2SERIAL and vice versa .Whatever the MSP430 microcontroller transmits is received by the PC through USB2SERIAL.

You can use any USB to Serial converter of your choice for this.

 

null modem serial connection 

Here is a picture of the connection between the MSP430 and USB2SERIAL (USB to Serial/RS485 converter).Connections are similar for ATmega328P also.

 picture of the connection between the MSP430 and USB2SERIAL (USB to Serial/RS485 converter) 

Reading from the serial port is similar to writing to serial port.Most of the code remains same ,

instead of using MyCOMPort.Write() we use MyCOMPort.ReadLine().

We also set Read/Write Timeouts to keep the C# code from waiting for ever.After a set time has elapsed the ReadLine() function returns irrespective of whether it has received any data.Time is specified in Milliseconds.

// Set the read/write timeouts
MyCOMPort.ReadTimeout  = 500;     
MyCOMPort.WriteTimeout = 500;

The data received in the PC serial port is read using MyCOMPort.ReadLine() and then printed on the screen.Here is the code for reading from serial port.

using System;
usingSystem.IO.Ports;

namespace SerialPort_Tutorial
{
    class SerialPort_Read
    {
        static void Main(string[] args)
        {
            StringRxedData;                         // String to store received data
            SerialPort MyCOMPort = new SerialPort(); // Create a new SerialPort Object

            //COM port settings to 8N1 mode 
            MyCOMPort.PortName = "COM46";            // Name of the COM port 
            MyCOMPort.BaudRate = 9600;               // Baudrate = 9600bps
            MyCOMPort.Parity = Parity.None;          // Parity bits = none  
            MyCOMPort.DataBits = 8;                  // No of Data bits = 8
            MyCOMPort.StopBits = StopBits.One;       // No of Stop bits = 1

           

            try
            {
               MyCOMPort.Open();      // Open the port
            }
            catch(Exception Ex)
            {
               //Deal with Exception here
            }

 

            try
            {
                RxedData = MyCOMPort.ReadLine(); // Wait for data reception
            }
           catch(TimeoutException Ex)//Catch Time out Exception
            {
               MyCOMPort.Close();
               Environment.Exit(0);
            }
           

            Console.WriteLine(RxedData);             // Write the data to console
            Console.Read();                          // Press any key to exit

            MyCOMPort.Close();                       // Close port
        }
    }
}

If you  compile and run this program,the program will execute and wait for the string to be transmitted by the MSP430 microcontroller.

 

One thing to note that, is Console.ReadLine() will return only after encountering the end of line character "\n".

Please make sure that the microcontroller sends the "\n" character otherwise the Console.ReadLine() will never return and program will hang.

 

C sharp program waiting for data to be transmitted by MSP430

Press the reset button on the Launchpad board so that MSP430 will transmit the string "Hello from MSP430" .When the string is received by PC ,it is displayed on the screen using Console.WriteLine(). 

showing the received data

 

Code running on Windows 10 ,

Reading a string from ATmega328P

Serialport reading data on Windows 10 using dot net core

Read Time out occuring in Windows 10

C# Serial port programming tutorial read time out  occuring

Please note that i have modified the earlier program to be more informative by adding a few extra lines of code.In the last two examples (reading and writing to serial port code  ),I have hard coded  the COM port number in the program itself like this MyCOMPort.PortName = "COM46"; .In the new one,i have made the COM port selection interactive by  adding the following lines

StringCOM_PortName;

Console.Write("Enter the COM Port Number [eg COM32] ->");
COM_PortName = Console.ReadLine();

COM_PortName = COM_PortName.Trim();
COM_PortName = COM_PortName.ToUpper();

MyCOMPort.PortName = COM_PortName;  

Console.ReadLine() function is used to read the COM port number in the format "COM32".

The extra spaces present in the input value is trimmed by using

COM_PortName = COM_PortName.Trim(); .

Then the whole string is converted to upper case by using

 COM_PortName = COM_PortName.ToUpper(); .

Finally the port name is assigned to

MyCOMPort.PortName = COM_PortName; 

and then the port is opened. The full code is available in the zip file.

Controlling the RTS and DTR pins of Serial Port using C#

After reading and writing to the serial port,its time to play with the other pins of a serial port like DTR and RTS .

In Some USB to Serial Converters DTR and RTS pins are not available,only the RXD,TXD and Ground pins  are available outside.

In USB2SERIAL all 9 pins are brought outside to berg strips which you can easily access.

 

One use of RTS and DTR pins is used to control the RS485 chips during a USB to RS485 conversion.

When you have to control some thing over several 100's of meters ,RS232 or USB will not be suitable.In such cases we have to use RS485 protocol, one problem with RS485 is that most PC's / Laptops will not have an RS485 port.You can solve that problem by using USB to RS485 converters like USB2SERIAL .

 

In USB2SERIAL RTS pin is used to put the RS485 chip in receive mode and DTR pin is used to put theRS485 chip in transmit mode.

Please note that in FT232 based USB to Serial converters (like USB2SERIAL) the RTS and DTR pins are inverted internally so setting the pins high will make then low and vice versa

The SerialPort Class in .NET Framework have two properties called RtsEnable​ and DtrEnable enable to control the RTS and DTR pins respectively.

The code shown below will show you how to control the pins.

using System;
usingSystem.IO.Ports;

namespace SerialPort_Tutorial
{
    class SerialPort_Write
    {
        static void Main(string[] args)
        {
            SerialPort MyCOMPort = new SerialPort(); // Create a new SerialPort Object

            MyCOMPort.PortName = "COM46"; // Assign the name of the serial port to be opened
            MyCOMPort.Open();             // Open the port

            MyCOMPort.RtsEnable = true;   // RTS pin = 1 ,~RTS = 0
            Console.Read();               // Press any key
            MyCOMPort.RtsEnable = false;  // RTS pin = 0 ,~RTS = 1
            Console.Read();              

            MyCOMPort.DtrEnable = true;   // DTR pin = 1, ~DTR = 0
            Console.Read();
            MyCOMPort.DtrEnable = false;   // DTR pin = 0, ~DTR = 1
            Console.Read();

            MyCOMPort.Close();             // Close port

        }//end of Main
    }//end of class
}//end of namespace

The RTS pin is set high usingMyCOMPort.RtsEnable = true; and it is set low usingMyCOMPort.RtsEnable = false;  .

Since the pins are inverted internally (in FT232)

Setting the RTS pinMyCOMPort.RtsEnable = truewill make the pin LOW and 

Clearing the pin usingMyCOMPort.RtsEnable = false;  will make it HIGH,same goes for DTR pin also.

Here is a picture of RTS and DTR lines of USB2SERIAL connected to LED's .

CSharp ode for controlling the RTS and DTR pins of FT232 serial port,C# Robotics

Please note that the USB2SERIAL also has onboard LED's near the RS485 section to display the status of RTS and DTR lines used to control the RS485 chip.

Screenshot of the program executing on windows

Program for controlling the RTS and DTR pins executing on a windows 7 PC

 

Creating a Dotnet framework Project in Windows 10

For compiling the serial programming codes you have to create a C# .Net Framework Console project as shown below. Here our App runs on top of .Net Framework  in Windows.

creating a serial communication program using c# and dot net core framework

The System.IO.Ports reference will be automatically added to your project file.

All the codes in the tutorials are available as Visual Studio Project files (.sln) in the repo.

Creating a .NET Core Serial Comm Project in Windows 10

Here we are going to create a serial communication project for the .NET Core runtime on windows 10.

We will use the same source files .CS from our github repo.

We will use Visual Studio Community Edition to create the .NET Core Project.

Create a Console App which target the .NET Core runtime as shown below.

serial port programming using net core 3.1 on windows and linux mac osx

Please note that System.IO.Ports is not available in the NET Core Project by default .

If you compile a .cs file that use the System.IO.Ports classes like SerialPort,you will get an error stating that references are missing or "type name SerialPort cannot be found in the namespace System.io.Ports".

serial port error visual studio in net core runtime

 

You have to install System.IO.Ports  using the Nuget package manager.

 

In VS Community Ed, 

Goto "Tools" → "Nuget Package Manager"→ "Manage Nuget Packages for Solution" as shown below.

install system.io.Ports uding Nuget package manager in Visual studio Community

Then type "System.IO.Ports" into  search box and install it as shown below.

how to install system io ports using nuget for c# serial communication

installing serial port class in net core sdk using nuget

After the installation is complete ,Your code will compile without any issues.

Here is the output of the program running in Windows 10 on top of NET Core 3.1 runtime.

compiling and running c# serial programming tutorial on windows 10 on net core 3.1.9

 

 

If you are interested,there is a small tutorial on how to control a robot using RS485 network from your PC .

You can also check out our RS485 Communication tutorial here 

 

 

 

 

 

 


Viewing all articles
Browse latest Browse all 134

Trending Articles