Serial port does not receive data - c#

first of all sorry for my english :)
I have a PCI serial ports card with 2 COM ports. I am using it to receive data from another computer via serial cables. (That other computer will be named as "Sender" subsequently)
The problem is, when cables are plugged in to my computer and i reboot (Windows 7),(Sender is still running...), then my PC does not receive any data. But when i reboot and after that I connect the cables in my PC it starts to receive. I temporary solved it by firstly starting my PC and then the Sender PC, but it's really a terrible solution...
I tried to connect my PC with a different computer (different sender), and it works good.
So I think that the problem can be with my main Sender. Maybe it is waiting for some signal from my computer that the ports are ready? Or Windows 7 can block my serial ports card (standard COM1 which is not on that card works fine) during reboot? Maybe I have to manually send some signal to Sender that I'm ready? By the way, I cannot, in any way, make adjustments to the Sender PC; only turn it on or off.
I do not have any expertise on serial ports so I really don't know what to do, or what I'm currently doing wrong.
Any ideas? (my receiver application is programmed in C#)
UPDATE: I forgot to mention that when the cables are connected... reboot... then ports can't be even opened.

This is a problem caused by the handshake signals. The Sender's DSR (Data Set Ready) is wired to your DTR (Data Terminal Ready). It will see the signal turn off when you reboot, now it gets sulky about sending anything because it thinks that you are no longer connected. You can exacerbate this problem by not setting the SerialPort.DtrEnable to true in your program, that's very commonly overlooked.
Same story with the RTS and CTS signals, if you set the SerialPort.Handshake property to anything else than Handshake.RequestToSend (the recommended value) then it now becomes your job to control the signal. You must set the RtsEnable property to true explicitly in your code.
It tends to work by accident, you're apt to use another program to test the connection. Like HyperTerminal or Putty, they'll turn the signals on for you and your program will now operate correctly.
This kind of bug could of course also exist in Sender. If you can't fix that code then all you can do is rewire the cable. Connect RTS to DSR and CTS on the Sender side to it will always see the signals turned on.

Problem was in card... I changed for new one and now its working correctly. Looks like the card was too old for Windows 7.

Related

Getting error only first time I communicate with my SerialPort later on its working fine

I have a USB device (e.g. barcode scanner etc.)
I communicate with it using SerialPort (which is found nicely from toolbox of VS2008)
My problem is:
After starting my PC when starting my application for the first time it is hanging up or stuck up or going into not responding mode when it tries to sending a string to the serial port.
To come out of it I just remove the USB cable from the USB port of my PC.
As soon as I remove the cable I getting below error message:
If I press the Continue button plug the removed USB cable back in my application working fine.
Note: I am getting this error only when I start my app first time after starting or restarting my PC. Afterwards it's working fine as I wanted.
Note: Another thing to consider is that if I put my code in try and catch
I catch the exception only when I remove the USB cable from my PC.
Edit:
After restarting my PC, if I do
plug out and then plug in the USB cable from the USB Port of the PC, and then
I start my App then it's working fine
It seems to me that the control is going inside an infinite loop when i try sending a string to the serial port at the very first time after starting of the PC.
See the details of my code over here
The 90% odds here are that you are trying to work around a common deadlock scenario with SerialPort. It is common to get triggered when you use Invoke() in your DataReceived event handler. If you then use Close() in your main thread while the port is busy receiving data then a deadlock is common. Close cannot complete until the DataReceived event handler completed running, Invoke() cannot complete because the main thread is stuck in the Close call. Jerking out the connector works because the ThreadExceptionDialog pumps messages, allowing the Invoke to complete.
A simple workaround is to use BeginInvoke() instead. Just not calling Close is fine too, Windows takes care of it when your program terminates. Some sort of controlled shutdown of your app so that you don't lose anything sent by the serialport device is best.
You must close the serial port in the FormClose event. Because, port is once open your application and close the port on the application end

Simulate Socket Hard Disconnect

I have a C# app where a server and some clients communicate from different machines using sockets.
Most of the time, the server detects a dis-connect correctly when it receives 0 bytes in the sock.Receive(...) call. But when there is a hardware issue (say a network cable is unplugged), there is a problem. One server thread continues to block on sock.Receive(...) because it doesn't know the connection is lost. I was going to add a heartbeat message to detect this, but I wanted to test it in dev.
But I'm not sure how I can test this case without an actual hardware issue. Even when I just kill the client process, the socket somehow manages to dis-connect gracefully (that is, the server does a read of 0 bytes). It's only when I physically unplug the client machine from the network that I see this issue.
Is there any way that I can simulate this issue in dev?
You need to explicitly inform WinSock that you don't want it to clean up for you after closing the socket. This is done by setting LingerState as such:
socket.LingerState = new LingerOption(true, 0);
socket.Close();
LingerState is a bit confusing, because if you disable the linger, WinSock will actually linger but just not block your program. You have to enable the linger and set the linger timeout to zero in order to force WinSock to drop the connection.
P.S. If you want some info about keepalive packets (heartbeats), I've written a blog entry on the subject.
Update:
I re-read your question (and comment), and my answer is wrong...
The code above will simulate an abortive close, not a half-open situation. There isn't a way to simulate a half-open situation in software; you need to unplug an Ethernet cable that is not attached to either computer in order to test this (e.g., yank the cable between the two switches in this configuration: computer A <-> switch <-> switch <-> computer B).

SerialPort.GetPortNames() behavior

In my C# 2008 application, I use the SerialPort.GetPortNames() function to retrieve the list of currently available ports. What I have noticed is, when ever I plug in a USB device, it's port number i s shown in the list on my Application and when I unplug it and refresh the list, the port number is no longer there.
One phase of the application involves reading/writing data from/to the device continuously. Now, my expectation is, If I unplug the device during the operation and get the current Port list using SerialPort.GetPortNames(), the Port Name will not be there and I can use that to make the decision that the device has been unplugged.
To my surprise, the Port name is still found despite having it removed
Why is the program behaving like this? The port name isn't listed when in no-communication mode. Does it have something to do with the device being removed when it's communicating?
You have to be talking about SerialPort.GetPortNames(), "GetPortList" doesn't make sense. The function iterates values in the registry, written there by your USB emulator device driver. You can have a look-see with Regedit.exe, navigate to HKLM\Hardware\DeviceMap\SerialComm. Unplug it, press F5, if the COM port is still there then SerialPort doesn't know any better than the port still being present.
There is no prescribed behavior as to how a serial port device driver should behave when the port suddenly vanishes. Serial ports are very primitive, they date back to an era where "bug" meant a moth gumming up the teletype. There is no hardware support at all for Plug and Play, removing a port with the power turned on is equivalent to unplugging the disk drive while Windows is swapping to the paging file.
Most device drivers return an error code, it generates an uncatchable exception that crashes your program. The subject of this feedback article. Apparently your device driver doesn't do that, which ought to be preferable over bombing your program. Encouraging btw, most USB emulator device drivers are utter junk.
The ultimate workaround is simple: put a little tag on the plug "don't disconnect while in use!" It's kinda of a problem with USB, most people look at it and go "hmm, what can I do with it?". And arrive at the only answer and unplug it. After a couple of kabooms, they'll learn to not do that anymore.
I'm assuming you mean System.IO.Ports.SerialPort.GetPortNames(), because i could not find a GetPortList() function anywhere. MSDN says: "If the registry contains stale or otherwise incorrect data then the GetPortNames method will return incorrect data", so that's probably where the problem lies. I guess Windows doesn't update the registry if the port is still being 'used', just like you can't delete a file when a program has a handle on it.
If you want to test if the device is removed, you can do so with a Window API call (http://www.pinvoke.net/default.aspx/user32/RegisterDeviceNotification.html). Hope that helps!
It is correct that GetPortNames() reads the ports from the Registry key
HKLM\Hardware\DeviceMap\SerialComm
This is automagically updated by Windows every time a port is opened or closed.
But nevertheless it has happened to me that there is a non-existent Port listed in the Registry, and also returned from GetPortNames(). When I try to open this port I get "The Port XYZ does not exist".
What is that ???
I now found out the reason:
This happens always after using PortMon from www.sysinternals.com.
This tool is buggy and lets the dead port hanging around in the Registry if the port is closed while it is monitored.
In this case the only remedy is to reboot the computer.
As others have mentioned, it's very driver-specific. There does not appear to be a way to check with the .Net API whether a port returned by GetPortNames() actually exists and is valid.
As for why the ports behave like this, I have found that some USB-to-serial drivers cause the application to crash when the port is unplugged suddenly.
Other drivers, often those that do not crash, will keep the port in the list until your application closes it, then it disappears. Trying to read from or write to the stale port will (usually) cause timeouts or errors. Presumably, in order not to crash the application, the driver needs to keep the stale port around while it is still open in the application.
If you plug in the port again, some drivers are even be able to reconnect it to your application, others will not recognize the port until your application closes the stale port. This reconnecting behaviour can be somewhat dangerous if the port disappeared because the device rebooted, because then it will suddenly be in a different state than your application expects without an obvious indication that it has reset. At least if you get errors from the port you know that something happened.
I've also found that if I forget to close the port, it won't disappear from the list until the garbage collector gets around to disposing the SerialPort object.

How to properly timeout when communicating with a serial-port device?

I am using a serial port communication C# windows application. I wrote a program to get the data from the port, to manipulate it and write through the serial port.
My question is in case the unit is not powered on, the power supply is disconnected, or the unit is not responding to commands for a long time, how will I know? In my program, I have written for normal flow of execution. But in case there is no response for long time, the program keeps on waiting for a long time. I used a timer but it doesn't work properly.
Can anyone help me please?
If you are using the "SerialPort" object in C#, then you can use the ReadTimeOut and WriteTimeOut Properties.
You've got two options:
If you have a device which should be generating data you can listen on the serial port for data from and if nothing is received for a set period you can assume it is offline,
Periodically send data to your device over the serial port and if you get an exception then you will know your device is offline.
One thing that might help is if the cable you are using is wired with DTR / DSR crossed, meaning that when your program starts you raise DTR and the other device see's DSR go high, and in turn raises it's DTR, which raises your DSR.
If you are using unknown cables and communicating with devices you don't have control over, then you will have to use .Timeout.

create a dialtone from 56k modem

Ok, everybody get in your wayback machine. I need to have a phone dial into my computer's 56k modem. I need my computer to have the modem "on" and have an active dialtone.
Here is why:
I have a sump pump alarm that will call me on a pump failure. It only works with a landline. I want to stop paying for my landline to save money and just have my cell. My idea is to intercept the outbound caLL from my sump alarm on my pc's 56k v90 modem. Then I can text message, email,etc... for free.
Does anybody know how to get started? I have found plenty of stuff on how to make outbound calls from my pc, but I want a phone (device) to dial my pc. I think the sump alarm will not dial unless it hears a dialtone.
I prefer a C# or vb6 program, but willing to go with anything. I have some experience working with serial comm devices so I just need to be pointed in the right direction.
Thanks!!!
You're going to need more than a modem in your PC to accomplish what you've described. Both the sump pump and your PC have modems, which are the subscriber end of a telephone "loop". The CO end (Central office in telephony terms) provides functions that you're telephone and both the modems mentioned above.
A big one is the generation of a ring ... this is a relatively high voltage AC signal that actually rang the bell in the old style telephones, but is simply detected in newer phones and your modems. In order for your sump pump's call to be recognized, this ring voltage has to be received at your PC's modem, but the sump pump won't actually generate this tone.
The other ideas presented here (the use of a PABX SOHO switch or connecting the detected signal from the sump pump directly to a I/O port on your PC), I can think of one other option. Somewhere inside the sump pump is a UART chip that does the serial communications to the included modem. If you disconnect the modem from the UART, you have the basics of a serial port, which can be connected to the serial port on a PC (though you may need an interface chip to get the levels right ... see the ICs provided by Maxim).
Good luck!
The easy way: Take a simple PABX (small SOHO kind) to let your alarm call your PC. You can use your PC's modem to wait for a RING from your modem. (Use the System.IO.Ports.SerialPort class to accoumplish this.) You'll need to program your alarm system to call the internal number of your PC.
Once you get a ring, you let your software do the rest.
Another option is a pySerial script written in Python.
You can write a small listener that listens for phone calls from your pump modem. You will need to know some AT commands, which you can look up anywhere online.
import pySerial
ser=serial.Serial('COM4',2400,timeout=1) #replace 2400 with your baudrate
ser.open()
ser.write("ATS0=1\r\n") #picks up after one ring
while(1):
line = ser.readline() #listen in a loop
I used to have a "Telephone Line Simulator" that allowed me to test modem configurations by letting one modem call another through a little black box that simulated the phone company's part of the bargain. Something like that should be easy to find, and would be an easy solution to your problem.
Do you need the sump pump to actually dial?
Can you not just intercept the sump pump's check for the dialtone?
Or better,
maybe there is an electronics friend you have who can wire up a simple device that plugs into the sump pump and checks for a voltage edge that occurs when the pump fails. This is an event preceding or concurrent with the pump actually trying to dial. When this little device detects the edge, it can then trigger something on your PC appropriately. The device might even be able to detect the V change on the telephone line - on the RJ11.
I don't know how familiar you are with electronics, but I almost wonder if your solution could be handled with a mix of software and hardware.
My first thought was to have something like an Arduino hooked up to either the circuit that does the pump failure detection or the phone line and watches for whatever signal the pump sends out. Arduinos are usually hooked up to your computer via serial/usb, and then you can have a piece of software that emails you, tweets at you, or whatever you want.
You could possibly have your modem watch for the pump trying to dial out, but I have no idea how you could do that.
I'd probably keep the two programs separate.
I'd have HyperTerminal (assuming you're on a Windows machine) running against your modem, with ATA or something similar, upon activity, I'd have it write a file.
I'd have another program running as an automated task (like every 30 minutes), looking to see if that file has been changed, and have that trigger a SMS message to your phone.
I'd imagine this would be a simple enough setup that it'd be easy to maintain, yet reliable enough to prevent your house from becoming a pool...

Categories

Resources