Home > Blockchain >  Serial Port receiving "old" data
Serial Port receiving "old" data

Time:02-15

Currently using the standard .NET serial port systems to interact with serial (COM) port barcode scanners. The code is reasonably straight forward (combined into one block for ease of reading below). This code works 100% of the time with the 3 or 4 test scanners and PC's I have but seams to cause one or both of the below issues with some users with no discernible hardware or software patterns between affected users.

The application either:

  • Receives the data from the previous scan a second time, e.g. physically scan "barcode1" app receives "barcode1", physically scan "barcode2" app receives "barcode1" again !
  • or the entire scanner/application appears to be out of sync by one scan e.g. physically scan "barcode1" receive "barcode0", scan "barcode2" receive "barcode1" etc

The return character matches the scanners setup (expecting "\r" for reading and receiving 0d from the scanner port) and the other settings should be correct as other than occasional occurrences of the above the application and scanner interact correctly.

// setup the port class
_serialPort = new SerialPort(Settings.PortName, Settings.Scanner_BaudRate, Parity.None, Settings.Scanner_dataBits, StopBits.One); 
_serialPort.Handshake = Handshake.None;
_serialPort.ReadTimeout = Settings.Scanner_Timeout; 
_serialPort.WriteTimeout = Settings.Scanner_Timeout; 
_serialPort.NewLine = "\r";

// once ready open the port (this gets called each time we attach/detach the scanner)
_serialPort.Open();

// if successful attach the receiving method
_serialPort.DataReceived  = new SerialDataReceivedEventHandler(DataIn);

// inside the receiver (DataIn)
SerialPort p = (SerialPort)sender;
string data = "###NOSCANN##";
data = _serialPort.ReadLine();
// data string is then sent on to processing

CodePudding user response:

Try using

_serialPort.NewLine = "\r\n";

CodePudding user response:

You should definitely try clearing the read buffer after reading the response in the DataIn method. Try something like _serialPort.DiscardInBuffer();

Besides that, I would be careful on synchronizing the command transmission and response receival. Before attempting to read the response, you should be sure that there is one available.

  public class SerialPortConnection
    {
        private readonly SerialPort serialPort;
        private readonly ManualResetEvent mre = new ManualResetEvent(false);
        private readonly object mutex = new object();

        public SerialPortConnection(string port, int baudRate, Parity parity, int dataBits,StopBits stopBits, int timeOut)
        {
            serialPort = new SerialPort(port, baudRate, parity, dataBits, stopBits)
            {
                Handshake = Handshake.None,
                ReadTimeout = timeOut,
                WriteTimeout = timeOut,
                NewLine = "\r\n"
            };
            serialPort.DataReceived  = SerialPort_DataReceived;
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            mre.Set();
        }

        public void OpenPort()
        {
            serialPort.Open();
        }

        public string SendCommand(string command)
        {
            lock (mutex)
            {
                serialPort.DiscardOutBuffer();
                serialPort.Write(command);
                mre.WaitOne();
                string response = serialPort.ReadLine();
                serialPort.DiscardInBuffer();
                return response;
            }
        }

For ensuring that only one command is sent and a response is received before being able to send a new command, I would use a lock statement. Next, for making sure that a response is available to be read before doing so, I would use an instance of the ManualResetEvent. After sending the command, I am blocking the execution by using the WaitOne() method. When a response is received, the DataReceived event is invoked, whose event handler calls the Set() method which sets the signaling to true, thus allowing further execution of the code in the SendCommand() method.

Please also notice that before writing any data on the transmit buffer I perform a DiscardOutBuffer(). Also, after reading the data from the receive buffer I clean it by calling DiscardInBuffer()

  • Related