UART BytesToRead

I have a problem with the uart BytesToRead function.

I have a sensor that is streaming data into a SCM20260D Dev board. The sensor output is RS422
connected to a RS485 Click.

The SCM20260D/Click does not transmit only ever receives and is forced to receive mode.

BaudRate = 921600 8N1

The relavent part of the program is below with the full simple program at the end of the post

Timer serial_poll_tmr = new Timer(serial_poll_tmr_callback, true, 500, 500);

      void serial_poll_tmr_callback(object data)
      {
       int bytes_in_buffer = 0;
        bytes_in_buffer = serial_1.BytesToRead;
        Debug.WriteLine("Bytes in buffer - " + bytes_in_buffer.ToString());
        serial_1.ClearReadBuffer();         
      }

If I set the timer to 10 mS everything works as I would expect the debug output looks like:
Bytes in buffer - 60
Bytes in buffer - 60
Bytes in buffer - 60
Bytes in buffer - 57
…

Similarly if I set the timer to 20 mS everything still looks ok:
Bytes in buffer - 120
Bytes in buffer - 120
Bytes in buffer - 119
Bytes in buffer - 119
…

If I stretch the timer to 1000 mS allowing the uart buffer to fill I get the following debug output.
Bytes in buffer - 750
Bytes in buffer - 0
Bytes in buffer - 750
Bytes in buffer - 0
Bytes in buffer - 750
Bytes in buffer - 0
…

The two questions I cant resolve are:

  1. Why the buffer only reports 75% of size when full
    (I have set the buffer size to 1000 bytes if I change the buffer size to 500 it reports 375) .

  2. Why every second poll does it report 0?

Any thoughts would be greatly appreciated.

I have searched the forum posts but haven’t found anything relavent. If I have missed something I apologize.

As an aside if I actually read the data every 20 mS it is as it should be. The data value I
extract does not need to be updated more than once a second and I am reluctant to use
system resources where unnecessary.

VS2019
All assemblies are 2.1.0.0
SCM20260D Dev Firmware 2.1.0.6400

The complete “simple” program is:

using System;
using System.Collections;
using System.Diagnostics;
using System.Text;
using System.Threading;
using GHIElectronics.TinyCLR.Devices.Gpio;
using GHIElectronics.TinyCLR.Devices.Uart;
using GHIElectronics.TinyCLR.Pins;

namespace Serial_Port_Test
{
  class Program
  {
    static void Main()
    {

      //Force serial port to receive mode *********************************
      var gpioController = GpioController.GetDefault();
      GpioPin read_control_output = gpioController.OpenPin(SC20260.GpioPin.PI0);
      read_control_output.SetDriveMode(GpioPinDriveMode.Output);
      read_control_output.Write(GpioPinValue.Low);
      //*******************************************************************************


      //*******************************************************************************
      //Configure Serial Port
      var serial_1 = UartController.FromName(SC20260.UartPort.Uart8);
      var uartSetting = new UartSetting()
      {
        BaudRate = 921600,
        DataBits = 8,
        Parity = UartParity.None,
        StopBits = UartStopBitCount.One,
        Handshaking = UartHandshake.None,
      };

      serial_1.SetActiveSettings(uartSetting);
      serial_1.ReadBufferSize = 1000;
      serial_1.Enable();
      //*******************************************************************************
      
      Timer serial_poll_tmr = new Timer(serial_poll_tmr_callback, true, 1000, 1000);

      void serial_poll_tmr_callback(object data)
      {
       int bytes_in_buffer = 0;
        bytes_in_buffer = serial_1.BytesToRead;
        Debug.WriteLine("Bytes in buffer - " + bytes_in_buffer.ToString());
        serial_1.ClearReadBuffer();         
      }

      while (true)
      {
        Thread.Sleep(5000);
      }

    }
  }
}

Serial is hard. In my opinion, and it’s only an opinion, you are much better off NOT using a timer and just use a thread. The thread has to just move the bytes that are available in the UART into a managed buffer. Then you can read from the buffer as much as you like from another thread.

Also, this is pointless. Just do a timeout.infinite sleep and stop asking for a context switch.

  1. There is threshold that will raise event error full one reach to 3/4 of buffer, let users know before buffer is full completely.
    That explains why you see 75% of buffer.
    It should still receive data to 100% buffer but looks like not. We will check.
    Make buffer larger for now.

UART thresold · Issue #1132 · ghi-electronics/TinyCLR-Libraries (github.com)

  1. Probably (1) effect to this so 750 bytes is max.

Thanks @Dat_Tran .

1 Like

I have to agree with Brett on this. I’ve only ever used threads to read serial data and never had an issue with receiving and decoding it, even at higher baud rates and multiple serial ports.

2 Likes

I agree @Dave_McLaughlin - the production software uses threads to read the data and does this without issue. The code I supplied was the simplest version I could come up with to demonstrate what I could not understand with respect to bytestoread function.

  1. Why bytestoread only ever reported a maximum of 75% of the buffer size when I know the buffer was full

  2. why it would sometimes report 0 bytes to read when I know the buffer is full

With the particular instrument I am using I . I don’t need to read all the data it sends - it is sending a continuous stream - 3 bytes constitute 1 “reading”. If I clear the read buffer delay check there is more than 3 bytes in the buffer I know that I have a current and valid data set ready to read.

If I use the following process

[clear read buffer] [delay 1 sec] [read bytestoread]
[clear read buffer] [delay 1 sec] [read bytestoread]
[clear read buffer] [delay 1 sec] [read bytestoread]
[clear read buffer] [delay 1 sec] [read bytestoread]

The first and third bytestoread returns 75% of the buffer size whe the should be full

The second and fourth bytestoread returns 0 when the buffer should actually be full.

If the delay is in the order of 10 ms then it all works perfectly. I just don’t want to use the resources to read it that often. Hope that makes sense.

This is fixed in v2.2.0-preview2. Can you please confirm when have time? thks

Thanks @Dat_Tran . I do not have access to this system now but will try and put together a simulation to test. Will le tyou know th result.