Serial Port Polling and Data handling

this is not a good way to do it, it far better to work on the DataReceived event.

basically with serial ports there’s a 3 stage process that works well.

  • Receiving the Data from the serial port
  • Waiting till you have a relevant chunk of data
  • Interpreting the data

so something like

class DataCollector
{
    private readonly Action<List<byte>> _processMeasurement;
    private readonly string _port;
    private SerialPort _serialPort;
    private const int SizeOfMeasurement = 4;
    List<byte> Data = new List<byte>();

    public DataCollector(string port, Action<List<byte>> processMeasurement)
    {
        _processMeasurement = processMeasurement;
        _serialPort = new SerialPort(port);
        _serialPort.DataReceived +=SerialPortDataReceived;
    }

    private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        while(_serialPort.BytesToRead > 0)
        {
           var count = _serialPort.BytesToRead;
           var bytes = new byte[count];
           _serialPort.Read(bytes, 0, count);
           AddBytes(bytes);
        }
    }

    private void AddBytes(byte[] bytes)
    {
        Data.AddRange(bytes);
        while(Data.Count > SizeOfMeasurement)            
        {
            var measurementData = Data.GetRange(0, SizeOfMeasurement);
            Data.RemoveRange(0, SizeOfMeasurement);
            if (_processMeasurement != null) _processMeasurement(measurementData);
        }

    }
}

Note: Add Bytes keeps collecting data till you have enough to count as a measurement, or if you get a burst of data, splits it up into seperate measurements…. so you can get 1 byte one time, 2 the next, and 1 more the next, and it will then take that an turn it into a measurement. Most of the time if your micro sends it in a burst, it will come in as one, but sometimes it will get split into 2.

then somewhere you can do

var collector = new DataCollector("COM1", ProcessMeasurement);

and

  private void ProcessMeasurement(List<byte> bytes)
            {
                // this will get called for every measurement, so then
                // put stuff into a text box.... or do whatever
            }

Leave a Comment