.net core, arduino, IOT

Using .NET Core 2 to read serial data from an Arduino UNO over USB

If you’ve worked with an Arduino and used a Windows development machine, you’ll probably have used the Arduino IDE to deploy code, and used the IDE’s built in serial monitor to read messages back from the Arduino device. And if you want to use these messages in a .NET application, there’s already good support in the .NET Framework – but what about .NET Core?

In this post, I’ll look at how to use VSCode to create an Arduino simple project which writes to a serial port, and deploy this to an Arduino Uno using VSCode. Then I’ll write about how to use the preview NuGet package to read this data using .NET Core. I’ll finish up with some issues I’ve observed.

Note – this article about .NET Core targets Windows 10 32-bit/64-bit editions – this won’t work if you’re targeting ARM devices with Windows 10 IoT Core (i.e. win10-arm). I’ll cover targeting the ARM platform in a later post.

Also, you’ll obviously need an Arduino for this – I’ve found an Arduino UNO is ideal.

This post has two main sections – setting up a example project on an Arduino using VSCode to write data to a serial port, and then how to access this data using a .NET Core application.

Writing data to a serial port with an Arduino

Setting up VSCode for Arduino development

First of all, you’ll need VSCode on your development machine – you can download it from here. I’ll not describe this in detail – it’s pretty much a point and click installer.

You’ll also need the Arduino IDE installed on your machine so VSCode can access the necessary libraries – you can download it from here. Again this is a very straightforward installation.

Next, install the Arduino extension for VSCode. There are great instructions here – but in summary, from VSCode:

  • Hit ‘Ctrl + P’
  • Type:
ext install vscode-arduino

At this point, you’ll have the Arduino extension for VSCode, presently at version 0.2.4.

Create an Arduino project in VSCode which writes to the serial port

From VSCode, you can create a new Arduino project with the following steps:

  • Create a folder on your development machine to hold the Arduino project – I’ve called mine ArduinoSerialExample
  • Open this folder in VSCode.
  • In VSCode, hit ‘Ctrl + Shift + P’ to open the VSCode Command Palette.
  • Type: Arduino: Initialize – VSCode will offer to create a file with extension app.ino.

screenshot.1501514685

  • Rename this to ArduinoSerialExample.ino. It’s important that this file (also known as an Arduino sketch) has the same name as the parent directory.
  • At this point, VSCode will ask what Arduino device is being used – I’m using an Arduino UNO, so I selected this from the list.

screenshot.1501514840

Your VSCode workspace is now initialised for Arduino development.

  • Update the code in the ArduinoSerialExample.ino file to have the contents shown below.
int i = 0;
 
void setup(){
  Serial.begin(9600);
}
 
void loop(){
  Serial.print("Hello Pi ");
  Serial.println(i);
  delay(1000);
  i++;
}

Important tip – if you copy and paste into VSCode, make sure you don’t accidentally copy unexpected unicode characters, as these will cause compiler errors.

  • Now hit ‘Ctrl + Shift + R’ to compile (also known as Verify) the script – if everything works, you should see an output similar to the text below.
[Starting] Verify sketch - ArduinoSerialExample.ino
Loading configuration...
Initialising packages...
Preparing boards...
Verifying...

Sketch uses 1,868 bytes (5%) of program storage space. Maximum is 32,256 bytes.
Global variables use 198 bytes (9%) of dynamic memory, leaving 1,850 bytes for local variables. Maximum is 2,048 bytes.
[Done] Finished verify sketch - ArduinoSerialExample.ino

Test this project works with a real Arduino

There’s a couple of last steps – connecting the physical Arduino to your development machine, and choosing the serial port.

If you look at the bottom right corner of VSCode, you should see that there’s still a prompt to select the serial port (as shown below).

screenshot.1501515586

Once I plugged my Arduino UNO into a USB port on my machine, I was able to click on theprompt (highlighted in a red box in the image above), and VSCode prompts me to select a serial port, as shown below.

screenshot.1501518211

I selected COM4, and this updates VSCode to show the serial port in the bottom right corner of the screen, as shown below.

screenshot.1501278934

I’m now ready to rest the Arduino is writing to the serial port.

I can upload the sketch to the Arduino by hitting ‘Ctrl + Shift + U’ – this will re-compile the sketch and upload it to the Arduino.

Next, hit open the command palette again (by hitting ‘Ctrl + Shift + P’, and type ‘Arduino Open Serial Monitor’, and select the option to open the Serial Monitor from the dropdown list.

screenshot.1501519010

The serial monitor opens, and I’m able to see output being logged to the console from the Arduino through the serial port COM4, as shown below.

screenshot.1501518933

Accessing the serial port data on a PC using .NET Core

TL:DR; I’ve uploaded the project to GitHub here.

First set up the .NET Core 2 solution – a console project and a .NET Standard 2.0 class library

Create a new project to hold your .NET solution. I like to manage solutions using the command line – I create a solution using the command:

dotnet new sln -n ReadSerialDataFromArduino

Inside this solution folder, create a new .NET Core console project – I do this using the command:

dotnet new console -n ReadFromArduino

Also create a new .NET Standard 2.0 library project inside the solution folder – again, I do this using the command:

dotnet new classlib -n ReadSerialInputFromUSB

Now we can add these two projects to the solution using the commands below

dotnet sln add .\ReadFromArduino\ReadFromArduino.csproj
dotnet sln add .\ReadSerialInputFromUSB\ReadSerialInputFromUSB.csproj

And we can see the projects in the solution using the command below:

dotnet sln list

And this command presents the expected output of:

Project reference(s)
--------------------
ReadFromArduino\ReadFromArduino.csproj
ReadSerialInputFromUSB\ReadSerialInputFromUSB.csproj

Finally for this section, I want to add the library as a reference to my console application with the command:

dotnet add .\ReadFromArduino\ReadFromArduino.csproj reference .\ReadSerialInputFromUSB\ReadSerialInputFromUSB.csproj

Add the .NET Core System.IO.Ports preview package

The System.IO.Ports package (available here on nuget.org) allows access to the serial port through a .NET Core application. I can add this to my .NET Standard 2.0 class library by navigating into the ReadSerialInputFromUSB directory, and run the command below:

dotnet add package System.IO.Ports --version 4.4.0-preview2-25405-01

So now the project structure is is place – we can add the bits of code that actually do things.

Let’s use C# to list what serial ports are available to us. I’ve created a class in the ReadSerialInputFromUSB project named SerialInformation, and added a static method called GetPorts().

using System;
using System.IO.Ports;
 
namespace ReadSerialInputFromUSB
{
    public class SerialInformation
    {
        public static void GetPorts()
        {
            Console.WriteLine("Serial ports available:");
            Console.WriteLine("-----------------------");
            foreach(var portName in SerialPort.GetPortNames())
            {
                Console.WriteLine(portName);
            }
        }
    }
}

And we can access this through the main method in the ReadFromArduino project:

using ReadSerialInputFromUSB;
 
namespace ReadFromArduino
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialInformation.GetPorts();
        }
    }
}

If we build this and run the project (using dotnet build and dotnet run) the output is:

Serial ports available:
-----------------------
COM4

This is exactly what we’d expect from earlier, where VSCode identified COM4 as the port being used by the Arduino.

And if we can get the data from the Arduino into a variable and write to the console, we can do that by using the DataReceived event and using the ReadExisting() method on the serial port object, as shown below:

public void ReadFromPort()
{
    // Initialise the serial port on COM4.
    // obviously we would normally parameterise this, but
    // this is for demonstration purposes only.
    this.SerialPort = new SerialPort("COM4")
    {
        BaudRate = 9600,
        Parity = Parity.None,
        StopBits = StopBits.One,
        DataBits = 8,
        Handshake = Handshake.None
    };
 
    // Subscribe to the DataReceived event.
    this.SerialPort.DataReceived += SerialPortDataReceived;
 
    // Now open the port.
    this.SerialPort.Open();
}
 
private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
    var serialPort = (SerialPort)sender;
 
    // Read the data that's in the serial buffer.
    var serialdata = serialPort.ReadExisting();
 
    // Write to debug output.
    Debug.Write(serialdata);
}

I can call this in my console project’s main method using the code below:

static void Main(string[] args)
{
    SerialInformation.GetPorts();
 
    var serialInformation = new SerialInformation();
 
    serialInformation.ReadFromPort();
 
    Console.ReadKey();
 
    serialInformation.SerialPort.Close();
}

So when I run this console application, the COM4 serial port is opened, and writes whatever it receives to the debug output.

You can see the source code for the Serial.IO.Ports library on GitHub in the CoreFX library, and there’s access to the nightly builds on myget.org.

This library is great for connecting to (and reading from) serial ports using a .NET Core application running on a Windows x32/x64 machine. However, one issue is this library doesn’t work with ARM – either for Windows 10 IoT Core or for Linux.

Wrapping up

Using the Serial.IO.Ports preview library available on NuGet, it’s possible to read from serial ports using a .NET Core 2 application on a Windows 32-bit/64-bit machine, and I’ve a very simple example of how to do this available on GitHub here. So far there’s not an implementation in the Serial.IO.Ports library which works for ARM architectures, but I’ll look at options for closing this gap in future posts.


About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

One thought on “Using .NET Core 2 to read serial data from an Arduino UNO over USB

Comments are closed.