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.