1

I have a C# code which communicates with three different COM ports. The COM ports are actually three serial port to USB converters.

The code each time switches 'off' and 'on' the devices to which it is communicating, then initializes the three com ports, tries to send and read data and then closes the com port. This keeps continuing for a pre-defined number of loops. My problem is that after about 8 or 9 iterations, the COM port communication stops working. Sometime it throws an error saying the port is closed, sometime it does not throw any exception but it is actually not reading or writing anything from the com port. Some point it was only writing but not reading back the data.

What might be the reason and any tips to debug this problem?

EDIT:

The port abruptly closes or stops working even in the middle of the program as shown below:

SerialPort.Write("ss");
SerialPort.Read("ss"); // FAILS!!

Some part of the code I am using

public string Read(string readCommand)
        {
            string str = "";
            _port.WriteLine("\r");
            _port.WriteLine(readCommand + "\r");
            Thread.Sleep(0x3e8);
            str = _port.ReadExisting();
            return str;
        }

public void Write(string command)
        {
            _port.WriteLine(command + "\r");
            Thread.Sleep(100);
            if (_port.ReadExisting() == string.Empty)
            {
                throw new IOException("Error writing to COM");
            }
        }

    public void Initialize()
    {
        if (_port == null)
        {
            _port = new SerialPort(this.PortName.ToString(), this.BaudRate, this.Parity, this.DataBits, this.StopBits);
            _port.Handshake = this.Handshake;
        }
        try
        {
            if (!_port.IsOpen)
            {
                _port.Open();
                if (Read("") == string.Empty)
                {
                    throw new IOException("Device not connected or powered on");
                }

            }
        }
        catch (Exception)
        {
            this.Close();
        }
    }

Thanks...

Manoj
  • 5,011
  • 12
  • 52
  • 76
  • 3
    Is it possible for you to keep the ports open for the duration of your application instead of opening and closing them so often? – Justin Oct 01 '10 at 13:48
  • 1
    I tried that also, but the same thing was happening. – Manoj Oct 01 '10 at 13:53
  • 1
    Some code will help understand your problem...(and +1 to @Justin's advise) – Hemant Oct 01 '10 at 13:53
  • Whose USB to serial converters are you using? It actually may make a difference; different chips and drivers behave differently, and we're currently chasing driver issues with the ones we use that are so painful we're contemplating a move to different hardware entirely. – twon33 Oct 01 '10 at 13:54
  • There is no manufacturers name! Even the driver CD does not have a manufacturers name...! – Manoj Oct 01 '10 at 14:05
  • :) yeah that's 1000 ms delay... – Manoj Oct 01 '10 at 14:21
  • You may want to check out this other question for USB-serial open/close weirdness: http://stackoverflow.com/questions/2948428/reopening-serial-port-fails-if-not-closed-properly-with-closehandle – twon33 Oct 01 '10 at 14:32
  • You can identify the manufacturer by selecting the converter device in Device Manager and finding the USB vendor string. Note that you may need to select the parent of the COMn USB Serial Port object and not the serial port itself. – Ben Voigt Oct 01 '10 at 15:18
  • @Ben Voigt - Yeah that helped...It was "Prolific". – Manoj Oct 04 '10 at 06:40
  • @Manoj: Now that you know the manufacturer, did you install the latest drivers and do you still have the problem? – Ben Voigt Oct 04 '10 at 14:01
  • @Ben Voigt: I tried updating the device driver. It still does not help. Sometime it is failing to read but is able to write. Sometime the code just hangs.When I break from debug menu, a green arrow comes up saying "This is the next statement to execute when the function returns from the current thread". Not sure which thread it is in at that point. I think I should change the USB to serial converter. – Manoj Oct 05 '10 at 12:27

3 Answers3

2
        _port.WriteLine(command + "\r");
        Thread.Sleep(100);
        if (_port.ReadExisting() == string.Empty)
        {
            throw new IOException("Error writing to COM");
        }

That's evil code and bound to throw sooner or later. Windows cannot provide a service guarantee like that. Or for that matter the device itself, especially when you power it on and off. Use SerialPort.ReadTimeout, set it to at least 2 seconds. And make a blocking call, like ReadLine().

    catch (Exception)
    {
        this.Close();
    }

That's tops the previous snippet. You have no idea what's going wrong when that runs. And your code will try to use a closed port. Just delete the statements, it does nothing but harm.

Do not close the ports until your program ends. SerialPort uses a background thread to watch for events on the port, that thread needs to shutdown after the Close() call before you can open the port again. How long it takes to shutdown is unpredictable, it could be seconds worst case. There's no point in closing the port, it isn't going to be useful to anything else.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
1

You need to use SetCommTimeouts (not sure what the .NET wrapper is, I gave up on the .NET serial classes long ago and call the Win32 API directly) to force the USB/serial converter to send the data back to your program.

By default it may try to collect a block equal in size to a USB transfer block, for efficiency.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • The relevant properties are probably ReadBufferSize and ReadTimeout, which default to 4096 and InfiniteTimeout respectively. (Though if ReadTimeout were the problem, it should block rather than return with an error.) – twon33 Oct 01 '10 at 14:18
  • @twon33: Not so for `ReadExisting`, that'll just return whatever is in the kernel buffer without blocking. – Ben Voigt Oct 01 '10 at 14:23
  • If that's what ReadExisting does, does SetCommTimeouts actually affect anything? I guess it would affect writes; if he's expecting a response to a command after a certain amount of time but it never made it, that would produce this. Maybe WriteTimeout is really what the issue is. – twon33 Oct 01 '10 at 14:31
  • @twon33: Delayed writes could definitely be a problem, but I'm thinking mostly of the case where the data is buffered in the USB device, not the kernel buffer. So `ReadExisting` would return nothing, it isn't allowed to wait for any reason, so it specifically won't wait for a USB transfer to take place. – Ben Voigt Oct 01 '10 at 15:16
0

Its tough to tell exactly what the problem might be without see some of the code. My guess would be that you are not waiting long enough for the COM port to close after reopening it. Note from the SerialPort.Close page, that:

The best practice for any application is to wait for some amount of time after calling the Close method before attempting to call the Open method, as the port may not be closed instantly.

Can you just open the COM ports and leave them open until you are done? For example from this post:

using (SerialPort serialPort = new SerialPort("COM1", 9600))
{
    serialPort.Open();
    while (true)
    {
        Thread.Sleep(1000);
        // serialPort.Write();
        Thread.Sleep(1000);
        // serialPort.Read();
        // break at some point to end
    }
    serialPort.Close();
}
Community
  • 1
  • 1
SwDevMan81
  • 48,814
  • 22
  • 151
  • 184
  • I had tried leaving the com port open for the entire application. Still I saw the same behavior. Actually what happens is it stops even when I am writing continuously. Please see the edit. – Manoj Oct 01 '10 at 13:54
  • Sounds like it might be a hardware or driver issue. How are you 'switching on and off' the device in code? – SwDevMan81 Oct 01 '10 at 13:56
  • I have a serial port controlled power switch which can be used to power on and off the device from the code. – Manoj Oct 01 '10 at 14:01
  • Does the device not close communications when it's switched off? – Captain Kenpachi May 27 '15 at 08:51