0
votes

I am writing a solution in VS2017 made of two UWP projects that require using a UHF RFID Reader. One is a x64 system and the other is an ARM (for Raspberry Pi 3 - Windows 10 IoT Core).

The parts I am using for both projects are:

I am thinking on using the same code on both applications (being both UWP) to Read and Write commands to my UHF Reader.

My UHF Reader (which has an RS-232 Female port) connects directly to one of my laptop's USB ports (using an RS-232 - USB cable). The same UHF Reader connects first to the CP2102 USB - TTL controller (Reader_GND <-> TTL_GND, Reader_Tx <-> TTL_Rx, Reader_Rx <-> TTL_Tx) which connects to one of my Pi 3's USB 2.0 ports.

The following code runs on both applications and identifies the respective device:

// ...
aqs = SerialDevice.GetDeviceSelector(); 
DeviceInformationCollection dis = await 
DeviceInformation.FindAllAsync(aqs);
// ...

The code on the UWP x64 application (running on my laptop) finds a device name "USB-SERIAL CH340" while the same code on the ARM application (running on the Pi 3) finds "CP2102 USB to UART Bridge Controller". So far so good.

Following the developer's protocol manual for my UHF Reader, I was able to construct the methods that send commands to Get Reader Firmware Version, Start Reader, Stop Reader, Get Parameters, Set Parameters and Scan a Card (Tag ID). All these methods work well on the UWP x64 app (laptop); however, when I run the same Stop Reader method on my UWP ARM app (Pi 3), it executes the Write command and then after, it hangs on the line of code DataReader.LoadAsync().

These are the lines of code it goes through before it hangs:

// ...
private SerialDevice _serialRFPort = null;
...

public RfidCardReader(SerialDevice device) //SerialDevice device
{
    //configures the serial settings for interfacing with the RFID-Reader board

    _serialRFPort = device;
    _serialRFPort.WriteTimeout = TimeSpan.FromMilliseconds(1000);
    _serialRFPort.ReadTimeout = TimeSpan.FromMilliseconds(1000);
    _serialRFPort.BaudRate = 9600;
    _serialRFPort.Parity = SerialParity.None;
    _serialRFPort.StopBits = SerialStopBitCount.One;
    _serialRFPort.DataBits = 8;
    _serialRFPort.Handshake = SerialHandshake.None;

    // Create cancellation token object to close I/O operations when closing the device
    ReadCancellationTokenSource = new CancellationTokenSource();
}
...

private async Task<byte[]> SendCommand(byte[] command)
{
   var writeResult = await Write(command); 
   if (writeResult.IsSuccessful)
   {
      //get response from the RFID-Reader
      var readResult = await Read(ReadCancellationTokenSource.Token);
...

private async Task<RfidReaderResult> Write(byte[] writeBytes)
{
    var dataWriter = new DataWriter(_serialRFPort.OutputStream);
...

private async Task<RfidReaderResult> Read(CancellationToken cancellationToken)
{
   DataReader dataReader = new DataReader(_serialRFPort.InputStream);
   ...
        loadAsyncTask = dataReader.LoadAsync(1024).AsTask(childCancellationTokenSource.Token);
        uint numBytesRecvd = await loadAsyncTask;  // <-- HANGS HERE FOREVER! .... :'(
...
// ...

The UWP x64 application code processes loadAsyncTask returning a an array of 6 bytes (with values of "0") to variable numBytesRecvd while the UWP ARM application hangs forever awaiting loadAsyncTask (which is really executing DataReader.LoadAsync()).

I thought the issue was probably related to the Pi 3 not having the driver for the "CP2102 USB to UART Bridge Controller" but I ran the following PowerShell script on the Pi 3 and I presume it lists the driver (unless I am wrong):

// ---------------------------------
> devcon.exe driverfiles *
...
USB\VID_10C4&PID_EA60\0001
    Name: Silicon Labs CP210x USB to UART Bridge
...
// ---------------------------------

Do any of you have any idea on what causes DataReader.LoadAsync() to hang on my UWP ARM app (Pi 3) while it and does not hang on my UWP x64 app (laptop)? Any suggestions on how to resolve this issue? ... :(

1

1 Answers

0
votes

I have a class for managing serial bus in UWP ARM based project, You can see that below:

class SerialDataBus : IDisposable
{
    private DataReader dataReader;
    private DataWriter dataWriter;

    public SerialDataBus(SerialDevice serialDevice)
    {
        dataReader = new DataReader(serialDevice.InputStream);
        dataWriter = new DataWriter(serialDevice.OutputStream);
        dataReader.InputStreamOptions = InputStreamOptions.Partial;
    }

    public DataReaderLoadOperation LoadAsync(uint count)
    {
        return dataReader.LoadAsync(count);
    }

    public DataWriterStoreOperation StoreAsync()
    {
        return dataWriter.StoreAsync();
    }

    public void ReadBytes(byte[] value)
    {
        dataReader.ReadBytes(value);
    }

    public void Dispose()
    {
        if (dataReader != null)
        {
            dataReader.DetachStream();
            dataReader.Dispose();
        }

        if (dataWriter != null)
        {
            dataWriter.DetachStream();
            dataWriter.Dispose();
        }
    }

    public void WriteBytes(byte[] value)
    {
        dataWriter.WriteBytes(value);
    }
}

And I use SerialDataBus for read from modules and write to modules in this way :

  using (SerialDataBus dataBus = new SerialDataBus(serialDevice))
  {
       //If you want write command to module or reader
       dataBus.WriteBytes('Your Command in Byte[] format');
       await dataBus.StoreAsync().AsTask();

       //Read data from module
       uint readByteLenght = await dataBus.LoadAsync(1024).AsTask();
       byte[] buffer = new byte[readByteLenght];
       dataBus.ReadBytes(buffer);
  }