I am trying to read data from the serial port. The data comes off of a scale. I first send a command to start reading the scale.
_serialPort.Write("P");
then after waiting for some time I am trying to read using
temp2 = _serialPort.ReadLine();
The application hangs at this line of code. I have also tried the Read function but am getting the same result. ReadExisting() function returns an empty string.
As the ReadLine() is not timing out or throwing any exceptions I am unable to debug this issue as I have no further information. The port cannot be defective as WriteLine() and ReadExisting() are working.
Any help would be appreciated.
Thanks
Try this behind your recieve button:
string msg = serialObj.ReadExisting();
MessageBox.Show(msg);
With comms, start with a terminal program. That is a program that lets you type commands that are sent out of the serial port to your device, and displays any text that comes back from the device. This will allow you to try out the protocol you've described and see what the device sends back. Once you get the correct response, you know:
The device is working
The serial cable is correctly wired and working
You are using the correct port settings (baud rate, stop bits, parity, etc)
You understand what the protocol is (do you send a "P" or a "P" followed by a newline?)
Then you can run your code in the knowledge that if it doesn't work, it's something in your code that is wrong, not any other factors muddying the waters.
Once you send the initial command, you can read the serial port immediately for the response - the call you are using will simply wait until some data is received. If no data is received, it will wait forever (hence your program hang). Any of the above things being incorrect will cause the same symptom of not receiving any data. And changing the way you read the data (e.g. async reads etc) will not change the fact that there is no data being received.
The other thing to be careful of is port settings. Generally, start with the default settings for most things (as RS232 is used in a pretty standard way by most devices) - a typical beginner mistake is to explicitly set options like the Handshaking approach, but if you get it wrong it'll break the comms. Usually you'd specify a baud rate and 8N1 (8 bits, no parity, 1 stop bit) and leave the other settings alone until you find they need to be set to get anything wto work, or you know (as in their manual states it in black and white) that your device requires something different.
Change your Write function to WriteLine. That may help. In addition, take a look at the sample of this link at MSDN. It is helpful.
Check that the SerialPort.NewLine property is set correctly. If you receive a CR character only, and the ReadLine expect eg. CRLF, your application will hung.
Does the scale respond to each "P" sent to it, or is "P" a command that tells it to begin sending a continuous stream of data? To use a terminal program, set its baud rate and protocol to the same as the scale (and your program), and use it to send a "P" to the scale in place of doing that with your program. Any response from the scale should appear in the terminal window. I prefer termie or termite (both downloadable) hyperterminal is pretty bad.
you can use that part to send a data to serial port from c#:
int MyInt3 = Convert.ToInt32(textBox3.Text);
byte[] p = BitConverter.GetBytes(MyInt3);
serialPort1.Write(p, 0, 1);
And after that you can use Read() method.
Related
I'm new to c# and try to control a device over tcp/ip. The device behaves as the server so what i have done so far is that my client program initiates the connection and successfully connects to the device.
But that's all i have. Once the connection is established the device starts sending all these hex strings that i somehow need to parse. I have the protocol manual for the device so i know how to read them but i have absolutely no idea how i would implement this in c#.
What i think that needs to be done is that i constantly need to listen for the device to send data.
Then i somehow need to find complete hex command strings. I know every string starts with "0x10, 0x02" and ends with the hex chars "0x10, 0x03".
The device dictates that i also need to send some sort of acknowledge message every time i receive a string. "0x10, 0x06" (ack) So there has to be some sort of two way communication.
Any help or guidance would be very much appreciated.
Thanks
You've got to keep the incoming data in a buffer and keep looking for that end character. When you find both start and end characters, you can run your custom "parse" method to extract the information and clear the buffer.
Here's a good starting point:
https://learn.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-client-socket-example
In the server part you can find an example of looking for the end character:
https://learn.microsoft.com/en-us/dotnet/framework/network-programming/asynchronous-server-socket-example
I'm totally confused and stunned about my problem. I wrote a multi client server using sockets.
I created a first GUI that receives clients and display them in a gridview, in the click gridview event it opens a new GUI with the socket between the clicked client and the server. So everything about the connection between server and the clients go well and fast
But my problems are :
the send information between them like sending full process it sometimes shown full and it sometimes less result .
send files management for example when the server request full folders/files in a directory sometimes it shows them all and sometimes less result .
But the command such open a window open an url, send a message , commands like those works so perfectly and instantly .
I am so confused right now what's the problem
Notice 1 : I used the extern IP for connection between server/client.
Notice 2 : internet connection is perfect (definitely not slow)
I tried to use different buffer sizes, but what I'm really confused about is that sometimes the result comes full with a specific buffer size and sometimes not with the same buffer size .
Thank you for your time !
I would also recommend you use wireshark so that you are able to get the full information and transactions that are really going on in the network.
This will help you to rule out where the issue is coming from.
To determine the packet size see the image
Here I am not talking about how the TCP handshaking protocol works as I assume it is working. However do note that in the transmission if you see something like RST then maybe somebody issued a reset command implying that some error occurred in the transmission. Such as something due to checksum for example. Although it is generally a problem for someone working directly on TCP/IP protocol
This should help you confirm that you sent and recieved the correct length.
I'm writting a small application that automatically connects to the correct serial port by sending a list of commands, and then waiting for a response back from the serial device (RF Transmitter). The serial port objects sends certain commands in decimal format, a reset, login and then a query command.
When the query command is sent, the device then replies back with a response - when this response is received I know I have the correct serial port connection.
All of this works fine, but sometimes I receive an error back from the device - Error 130: TX Queue Overflow. This error can be resolved by simply restarted the device (RF Transmitter), but the frequency of this error is just silly.
Am I correct in thinking that a TX Overflow error would be caused when the buffer on the hardware becomes full? I thought a simple DiscardInBuffer just after opening a connection to the device would fix this - but it doesn't.
When should I use the DiscardInBuffer, am I using it in the correct context?
-- Edit
After some more comments and thoughts, I've come to the conclusion that the SerialPort.DiscardInBuffer won't do anything for my current situation, rather I need to discard the buffer on the actual RF Device - Hence why inplugging it works.
You've sent too much data to the device, and its output queue has overflowed, meaning it is not able to forward the data as fast as you're providing it.
There's no method you can call on the SerialPort class to fix this, these are two completely different buffers we're talking about. Calling SerialPort.DiscardOutBuffer will only discard the output data pending for your serial port, not the device.
To temporarily fix the issue, the manual indicates that you can:
Use the command “reset txqueue” to clear the queue.
The better solution, however, is to prevent the issue and not flood the device with data. The exact way to do this will depend on your hardware.
One way might be to introduce some sort of CommandQueue class which has an associated SerialPort object to push the commands to the hardware. In this class, you could queue up commands to be sent, and send them out a configurable maximum rate. You would use a timer, and only send commands out if one hasn't been sent in the last X msec.
Another way would be to implement some sort of software flow control. It appears that your device supports querying the queue length with the "?STATE" command (page 13). It will respond with:
STATE x1/x2 x3 x4
x1: Number of datapackets in TX queue
x2: Size of TX queue
x3: Status byte (8 bit hexadecimal)
Normal state: status byte = 0
Bit 0 = 1: Error in transceiver
Bit 1 = 1: Error in EEPROM
x4: Current value of the dataset counter (number of last received and saved datapacket)
You could query this before attempting to send a data packet, and simply sleep while the queue is full.
Having written a lot of code to interface with finicky hardware (Serial, Ethernet, etc.) in C#, I can offer the following advice:
Implement an abstract class TN9000DeviceBase which has abstract methods for all of the commands supported by the device.
Derive a class TN9000SerialDevice : TN9000DeviceBase which executes the command using serial port.
This will allow you to come back and implement it via Ethernet when requirements change.
I need to detect when someone is connected to my computer. I have an incoming connection enabled, and need to know when a user is connected. Preferably from a script in CSharp
Generally, regardless of language, the approach is to open a serial port to talk to the modem. For .NET, you might want to refer to System.IO.Ports.SerialPort. The connection parameters (baud rate, data bits, stop bits, parity, flow control) depends on the device in question. Try 57600 or the fastest speed of your serial port, 8 databits, 1 stop bit, no parity and hardware flow control; that's what's typically used.
Hayes compatible modems spend "RING" notifications (plan text) over a serial port when someone is dialling. You'd send an "AT A" to the modem to anwer the call (or the modem may be configured for auto answer). When a connection is established, a "CONNECT XXX" is sent from the modem, where XXX is the connection details. For a summary of Hayes commands, see this Wikipedia link. (It also describes details such as command/data mode that you'll probably need to go into, if you want to program communications over a modem connection.)
Attach a DataReceived event to the serial port you have opened
Look at the SerialPort documentation on how to open the port and attach handlers. you need to know the port speed and stop, start bits, parity, etc. Try speed of 9600 (bps), parity.none, no handshaking, 1 stop and start bits... best thing to do is leave everything at the default and just do new SerialPort("COM5") or whatever your com port is so you leave things at their default values.
Keep putting the received data into a buffer and keep scanning that buffer for "RING".
your serial port will literally receive the word "ring" when your modem is ringing. so you've gotta keep scanning for it.
Also, the reason why I say put your data in a buffer is because sometimes it arrives out of sequence. or you might want to do a readLine so it reads till the /r (carriage return) that indicates one complete response
i have a program that send ASCII commands to a device via a serial port. The program is a demo and doesn't do what i want.
I am just trying to get the device to respond in c# and I'm not getting anything back.
all the serial port settings are correct.
I am sending exactly the same message as the demo software.
//e.g message <STX>ABC<EOT>
byte[] msg = new byte[5];
msg[0] = 0x02;
msg[1] = 0x41;
msg[2] = 0x42;
msg[3] = 0x43;
msg[4] = 0x04;
comport.write(msg, 0,msg.length)
the device is a monitor. The code was only an example. there isn't a heartbeat just a response for a correct message sent or a error message. the settings are standard 9600-8-N-1. "paperclip between pins 2 and 3 (TX and RX)." yeah i know the cable works because its the same one used with the product software that works. and im getting back what i send. I have used a virtual com program and everything seems alright. "6 bytes but initializing only the first 5. " sorry typo.
the SerialPort.DtrEnable and RtsEnable properties to true. are on by default in c#. i have tried the hyper terminal and am not getting a response with that either. I have sent \r and \n with no luck.
This C# Tutorial on Serial Port Communication should be able to help. I'm not sure if there is an appropriatei intrinsic caste between Hex and Byte through assignment in C#. That may be the source of your problem.
Device Heartbeat
Does the device send a DC2 or DLE response (heartbeat)? If so, try opening a COM port in Hyperterminal using basic 9600-8-N-1 settings and see if you get anything. Is there any STX, SYN, ETX commands sent back when you try to send a command? I'm not sure on the command-set implementation for the hardware you are trying to communicate with.
Checking COM Port Operation
Have you checked if your COM port is working properly? You can create a loopback by inserting a paperclip between pins 2 and 3 (TX and RX). This will loopback your COM port and in Hyper terminal you can open that COM port and type. The characters will echo back.
You can also use a piece of software called com0com to create virtual COM ports to test what you are sending before you actually send it.
It provides pairs of virtual COM ports that are linked via a nullmodem connetion. You can then use your favorite terminal application or whatever you like to send data to one COM port and recieve from the other one
Without anymore specific information, we'll be grasping at straws.
You're allocating and sending 6 bytes but initializing only the first 5.
Also, according to what you write, you're doing everything correctly, exactly as the demo program. Right? Then I can see only one solution: The device is pulling your leg!
Seriously: If one program works and your doesn't, there MUST be some difference.
By far the most common mistake is forgetting to turn on the hardware handshake signals. The device won't send anything if it thinks the host is turned off. Make sure you set the SerialPort.DtrEnable and RtsEnable properties to true.
As mentioned before, fix the array size. Although it probably won't help, the STX character ensures that junk is thrown away.
Check if basic hardware is okay with the Windows Hyperterminal applet. You can send the message you are trying to transmit by typing Ctrl+B, ABC, Ctrl+D
As others have suggested, it is good idea to check what is being sent and received with some kind of terminal software. I have had success with "realterm"-- it has nice displays of ascii or binary/hex views.
Since you are working with ASCII, another issue might be that you are not sending the correct line-terminating character. Some devices expect \r and others \n. Make sure you are setting that correctly.
the device is a monitor. The code was only an example.
there isn't a heartbeat just a response for a correct message sent or a error message.
the settings are standard 9600-8-N-1.
"paperclip between pins 2 and 3 (TX and RX)." yeah i know the cable works because its the same one used with the product software that works. and im getting back what i send. I have used a virtual com program and everything seems alright.
"6 bytes but initializing only the first 5. " sorry typo.
the SerialPort.DtrEnable and RtsEnable properties to true. are on by default in c#.
i have tried the hyper terminal and am not getting a response with that either.
I have sent \r and \n with no luck.