Connect Arduino to Raspberry via USB to read serial data

Okay, first of all, this thing has been made way too complicated in the official samples, where they require you to get USB to TTL cables or similar, when all you really need is the product id and vendor id, which you can easily check and hard code on your project.

So, if you are doing some cool IOT project, and have Arduino reading sensors and writing to serial port the results, this is what you need on the Raspberry side to make the magic work:

You need to include two namespaces

using Windows.Devices.SerialCommunication;
using Windows.Devices.Enumeration;

What I did next was based on hint from article by Bereket Godebo, INTERFACING ARDUINO IN THE UNIVERSAL WINDOWS PLATFORM , which is in C++/CX, but I found out that when you connect the Arduino first to normal PC, go to the device manager and from the ports section you open Arduino, go to Details -section, select Hardware Id from the Property combo, and there you have a string which looks something like USB\\VID_2341&PID_0043… where you take the vid and pid and input them as hexa values to the following code:

var aqs = SerialDevice.GetDeviceSelectorFromUsbVidPid(0x2341, 0x0043);
var devices = await DeviceInformation.FindAllAsync(aqs);

First parameter is the vendor id, second is product id. The ids used above are for Arduino Uno, so if you have one, that code should work as it is.

Now the rest of the code needed to read the serial is only as follows:

// member variables
private SerialDevice serialPort;
private DataReader reader;
private CancellationTokenSource ReadCancellationTokenSource;

Put this in your method, where you want to do the reading, as it will find the the arduino, and create serial connection to it, and create loop to call for reading the input:

var aqs = SerialDevice.GetDeviceSelectorFromUsbVidPid(0x2341, 0x0043);
var devices = await DeviceInformation.FindAllAsync(aqs);
            
if (devices.Count > 0)
{
    Debug.WriteLine("Serial devices found...");
    DeviceInformation deviceInfo = devices[0];
    serialPort = await SerialDevice.FromIdAsync(deviceInfo.Id);
    serialPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
    serialPort.BaudRate = 9600;
    serialPort.Parity = SerialParity.None;
    serialPort.DataBits = 8;
    serialPort.StopBits = SerialStopBitCount.One;

    try
    {
        if (serialPort != null)
        {
            reader = new DataReader(serialPort.InputStream);
            Debug.WriteLine("Reading serial port COM");

            // Read the serial input in loop
            while (true)
            {
                await ReadAsync(ReadCancellationTokenSource.Token);
            }
        }
    }
    catch (TaskCanceledException tex)
    {
        Debug.WriteLine("Reading was cancelled");

        serialPort.Dispose();
    }
    catch (Exception ex)
    {
        Debug.WriteLine(ex.Message);
    }
    finally
    {
        if (reader != null)
        {
            reader.DetachStream();
            reader = null;
        }
    }
}

The actual reading of the serial port happens in this method:

private async Task ReadAsync(CancellationToken cancellationToken)
{
    Task<UInt32> loadAsyncTask;
    uint ReadBufferLength = 1024;

    // Cancel in case it was requested 
    cancellationToken.ThrowIfCancellationRequested();
    reader.InputStreamOptions = InputStreamOptions.Partial;
    loadAsyncTask = reader.LoadAsync(ReadBufferLength).AsTask(cancellationToken);

    // Launch the task and wait 
    UInt32 bytesRead = await loadAsyncTask;
    if (bytesRead > 0)
    {
        string txt = reader.ReadString(bytesRead);
        Debug.WriteLine(txt);
    }
} 

That’s all needed to connect Raspberry to read Arduino through normal USB cable plugged into Arduino, connected to Raspberry.

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *