0

I have a Magellan scanner/scale. It is connected to my pc through rs232. When i send the command "S11" on ComTestSerial programm, i receive the weight. However, with my vb.net code i cannot receive a response. As a result i get a TimeoutException.

The file that sends the command:

Dim yy() As Byte = System.Text.Encoding.ASCII.GetBytes("S11" & vbLf)
Me.Port.Send(yy)
Dim input = Me.Port.Receive
Return Me.ExtractMeasurement(input)

The file that writes and reads from serialport:

public void Send(byte b)
    {
        byte[] bytes = new byte[1] { b };
        this.Send(bytes);
    }

    public void Send(byte[] bytes)
    {
        this.Send(bytes, 0, bytes.Length);
    }

    public void Send(byte[] bytes, int offset, int count)
    {
        this._port.Write(bytes, offset, count);
    }

    public byte[] Receive()
    {
        int attempts = 1;
        Boolean dataReceived;

        try
        {
            while (!this.DataReceived && this._port.BytesToRead == 0 && attempts < 15)
            {
                System.Threading.Thread.Sleep(100);
                attempts++;
            }
        }
        finally
        {
            dataReceived = this.DataReceived;
            this.DataReceived = false;
        }

        if (!dataReceived && this._port.BytesToRead == 0) throw new TimeoutException();

        byte[] bytes = new byte[this._port.BytesToRead];
        this._port.Read(bytes, 0, bytes.Length);

        return bytes;
    }

I can't understand why BytesToRead and BytesToWrite stays 0 after this._port.Write(bytes, offset, count);

Here is the serialportconfig.xml file

<PortName>COM3:</PortName>
<BaudRate>Baud_9600</BaudRate>
<DataBits>Eight</DataBits>
<Parity>None</Parity>
<StopBits>One</StopBits>
<FlowCtrl>CtsRts</FlowCtrl>

Update: i figure out that if i send vbCr instead of vbLf i sometimes get the right response back. But the problem is SOMETIMES. I sometimes get a TimeoutException and sometimes get the response. I am using an adaptor from RS232 to usb. Could this be the problem?

Here is all the code related to the serial:

public class SerialPortAdapter
{
    #region Private Members

    private System.IO.Ports.SerialPort _port;

    private Object _dataReceivedLock = new Object();
    private Boolean _dataReceived;

    #endregion

    #region Constructor/Destructor

    public SerialPortAdapter(SerialCnfg config)
    {
        if (string.IsNullOrEmpty(config.PortName))
        {
            this._port = new System.IO.Ports.SerialPort();
        }
        else
        {
            string portName = config.PortName.TrimEnd(':');
            this._port = new System.IO.Ports.SerialPort(portName);
        }

        this._port.WriteTimeout = 2000;
        this._port.ReadTimeout = 2000;
        this._port.SetBaudRate(config.BaudRate);
        this._port.SetDataBits(config.DataBits);
        this._port.SetStopBits(config.StopBits);
        this._port.SetHandshake(config.FlowCtrl);
        this._port.SetParity(config.Parity);
    }

    ~SerialPortAdapter()
    {
        this.Close();
        this._port = null;
    }

    #endregion

    #region Public Properties

    public Boolean IsOpen
    {
        get { return this._port.IsOpen; }
    }

    public System.Text.Encoding Encoding
    {
        get { return this._port.Encoding; }
        set { this._port.Encoding = value; }
    }

    #endregion

    #region Public Methods

    public void Open()
    {
        if (this.IsOpen) return;

        this.DataReceived = false;
        this.AttachPortHandlers();
        this._port.Open();
    }

    public void Close()
    {
        if (!this.IsOpen) return;

        this._port.Close();
        this.DetachPortHandlers();
        this.DataReceived = false;
    }

    public void Send(byte b)
    {
        byte[] bytes = new byte[1] { b };
        this.Send(bytes);
    }

    public void Send(byte[] bytes)
    {
        this.Send(bytes, 0, bytes.Length);
    }

    public void Send(byte[] bytes, int offset, int count)
    {
        this._port.Write(bytes, offset, count);
    }

    public byte[] Receive()
    {
        int attempts = 1;
        Boolean dataReceived;

        try
        {
            while (!this.DataReceived && this._port.BytesToRead == 0 && attempts < 15)
            {
                System.Threading.Thread.Sleep(100);
                attempts++;
            }
        }
        finally
        {
            dataReceived = this.DataReceived;
            this.DataReceived = false;
        }

        if (!dataReceived && this._port.BytesToRead == 0) throw new TimeoutException();

        byte[] bytes = new byte[this._port.BytesToRead];
        this._port.Read(bytes, 0, bytes.Length);

        return bytes;
    }

    #endregion

    #region Private Properties

    private Boolean DataReceived
    {
        get
        {
            lock (this._dataReceivedLock)
            {
                return this._dataReceived;
            }
        }
        set
        {
            lock (this._dataReceivedLock)
            {
                this._dataReceived = value;
            }
        }
    }

    #endregion

    #region Initialization/Finalization

    private void AttachPortHandlers()
    {
        this._port.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.OnDataReceived);
    }

    private void DetachPortHandlers()
    {
        this._port.DataReceived -= new System.IO.Ports.SerialDataReceivedEventHandler(this.OnDataReceived);
    }

    #endregion

    #region Event Handlers

    private void OnDataReceived(Object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
    {
        this.DataReceived = true;
    }

    #endregion
}
  • Can you show all relevant code for your serial class? It could be a number of things, such as is the port even open, but it is difficult to diagnose without seeing the code. – tval Dec 23 '20 at 16:19
  • Just posted the code related to the serial. I do open the port and close it when needed. – Stavros Karagiannidis Dec 28 '20 at 09:56

2 Answers2

0

Based on the code you posted, you are attempting to handle your own timeout exception. SerialPort class has its own built in timeout (ie, ReadTimeout, WriteTimeout) which you set in the constructor. Therefore you do not need the other methods to handle the timeout as it would be redundant. Moreover, stay away from the System.Threading.Sleep method as it can be a huge waste of resources Why is Thread.Sleep so harmful.

I suggest that you refactor your code a bit to get rid of the self imposed Throw TimeoutException.

Here is just a suggestion:

public byte[] Receive()
{
    
    try
    {
        byte[] bytes = new byte[]{};

        while(_port.BytesToRead > 0)
        {
            bytes = new byte[this._port.BytesToRead];
            this._port.Read(bytes, 0, bytes.Length);
        }
    }
    catch (TimeoutException ex)
    {
       Console.WriteLine(ex.Message);
    }
    finally
    {
        this.DataReceived = false;
    }

    return bytes;
}
tval
  • 412
  • 3
  • 17
0

It appears that Magellan can work if you resend the command to request the weight(S11). So the solution for me was whenever i have _port.bytesToRead=0 after this._port.Write(bytes, offset, count) , then i resend the command S11. Eventually, it will response the right result.