I'm trying to write a simple c# console application to read/write from a serial port that communicates to an Arduino that I have hooked up. The problem that I'm running into is that I can write to the Arduino no problem, but I am unable to receive any data back. My serial port's SerialDataReceivedEventHandler isn't ever being fired either, but I'm guessing those two issues are related.
I know it isn't my Arduino that is causing the problem because when using the Arduino IDE I am able to receive data without any problems. Here is what I've got code wise for now:
SerialPort sPort = new SerialPort();
sPort.PortName = SerialPort.GetPortNames()[0];
sPort.BaudRate = 9600;
sPort.Parity = Parity.None;
sPort.DataBits = 8;
sPort.StopBits = StopBits.One;
sPort.RtsEnable = false;
sPort.Handshake = Handshake.None;
sPort.DataReceived += new SerialDataReceivedEventHandler(sPort_dataReceived);
sPort.ErrorReceived += new SerialErrorReceivedEventHandler(sPort_ErrorReceived);
sPort.Open();
Console.Read();
sPort.Write("tt_calib");
while (true)
{
if (sPort.ReadExisting() != string.Empty)
Console.WriteLine(sPort.ReadExisting());
}
I am aware that I don't close the port in this code, that is not the issue as I am able to rerun and open it every time. This code is also not in its final form, I'm attempting to get the read event working so that I can react to various messages differently. I've read what seems like every question but no solution I've found seems to do the trick.
This is a C# .NET 4.5 console application running on Windows 8.1
It ended up being a stupid simple issue. Instead of sPort.RtsEnable = false; it should be true. All events now trigger and I am able to read.
With C# in VS2019 available cross-platform, I ran into the same issue on my VM (Parallels+Windows10) and my host machine (MacOS).
Setting DTR to true did the trick
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
private static void DataReceivedHandler(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
}
I had the exact same issue and finally realized that my hardware flow control setting is bios configurable and my setting was DISABLED! doh
Related
I am trying to read data from a device connected via USB.
For creating the trigger the code looks like:
private SerialPort realTimePort;
realTimePort = new SerialPort();
realTimePort.BaudRate = 9600;
realTimePort.PortName = "COM4";
realTimePort.ReadTimeout = 5000;
realTimePort.ReadBufferSize = 32768;
realTimePort.ReceivedBytesThreshold = 1;
realTimePort.BaudRate = 9600;
realTimePort.ReadBufferSize = 4096;
realTimePort.ParityReplace = 63;
realTimePort.Parity = Parity.None;
realTimePort.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(realTimePort_DataReceived);
realTimePort.Open();
To read the data, which was sent, the code looks like:
public void realTimePort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
// Do something with the data
}
With one version of the device everything works fine and the trigger starts, when data was sent, but with a newer software-version of the device realTimePort_DataReceived is never triggered.
At first i thought, that the problem might be, that the device never sends data, but then i tried to read the data with "Tera Term" and there i can see exactly, what i am expecting. I also compared the data with "Tera Term", which was sent of the devices with the different software-versions, but it is exactly the same string.
Do you have any ideas, why the event is triggered with the older software-version and not with the newer one?
An employee of the manufacturer of the device already gave me the specification of the SerialPort, because i had this problem, but it didn't help me.
It is hard to reproduce the issue as i am not aware what type of device you are using and what type of data is sends here are some tips you can evaluate a quick check list to ensure the correct data receiving.
1. Play with RTS or DTR port flags for new version device
Basically some new versions of hardware uses flags of SerialPort e.g. DTR (Data Terminal Ready) indicates that your code is ready to receive, and RTS (Request to Send) a request to device to actually send data. for older hardware types it was not mandatory to use these flags although in modern devices its still not but just a standard practice so you should experiment & try enabling these by your code e.g.
realTimePort.RtsEnable = true; //enable this mode
realTimePort.DtrEnable = true; //and also this one
2. Try to read device error stream
It is possible that your new version hardware is sendind data over error stream, the tool you was using utilizes both streams for data read so you can subscrive to error event like.
realTimePort.ErrorReceived += new SerialErrorReceivedEventHandler(sPort_ErrorReceived);
private static void sPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{
//process your error, it will give you further hint about why part of your question.
}
I have been struggling with commincations speeds with some code.
So i want to increase the baud rate for both the code & Arduino. But if i leave the 9600 baud rate, the data stops sending & reciving properly.
So i set up a simple test program.
Arduino Code:
void setup()
{
Serial.begin(9600);
Serial.setTimeout(10);
}
void loop()
{
if (Serial.available())
{
String Data = Serial.readStringUntil('#');
if (Data == "Test")
{
Serial.println("Recived");
}
}
delay(1);
}
c# Code:
SerialPort Port = new SerialPort("COM4", 9600);
Port.Open();
if (Port.IsOpen)
{
Port.Write("Test#");
System.Threading.Thread.Sleep(1000);
String Read = Port.ReadExisting();
Port.Close();
}
So running that String Read comes back with "Recived\r\n".
Change the baud rate to 19200 and it comes back with "".
Any ideas why this is occuring?
Edit: If I use the Arduino IDE's Serial Monitor Program, this works just fine regardless of baudrate used. Its as soon as i use c# that it that this issue occurs. Which rules out hardware issues I believe.
Try sending a character at a time from the PC and use Serial.read() to read a character into a buffer in the arduino. Sometimes sending the whole text from PC at high baud rate is too much for the arduino to handle.
Thankyou for you inputs.
Think i have found a solution, although not to clear about why.
I think it was due to the Serial.Avalible() Command. Appears i needed to send though some data first to make it register the port is open.
So modifying my C# code to this: Works
SerialPort Port = new SerialPort("COM4", 9600);
Port.Open();
if (Port.IsOpen)
{
Port.Write("#");
Port.Write("Test#");
System.Threading.Thread.Sleep(1000);
String Read = Port.ReadExisting();
Port.Close();
}
Thanks a lot
Background: we are developing an application (or windows service) that will listen for communications from various devices connected via virtual serial ports. Each device's information will be captured manually, so I know device 1 will be on COM5, Device 2 is on COM6, etc. Any time a device transmits data, I need to capture it and write in somewhere else (basically a log file).
With that in mind, is it possible to monitor more than one serial port on a single thread, or should I spawn a new thread for each port (keep in mind that I know exactly which ports to monitor)?
Or what would you guys think is a good approach?
My working prototype code looks like this (only reads one port though):
class Program
{
public static void Main()
{
SerialPort mySerialPort = new SerialPort("COM5");
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
mySerialPort.Open();
Console.WriteLine("Press any key to continue...");
Console.WriteLine();
Console.ReadKey();
mySerialPort.Close();
}
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine(indata);
Debug.Print("Data Received:");
Debug.Print(indata);
}
}
I'm basically wondering if I should create a class for each port that contains the code in the console application, or if I should go old-school and write a giant procedural app that monitors all of them at once.
If the COM port devices are all similar, one class to handle retrieving their data with an instance for each device seems like the way to go. If separate functionality is needed you can always inherit from a base class. If you go down the rout of 'writing a giant procedural app' it will be much more difficult to maintain and modify in future.
As for multiple threads, the event handler you are using should allow multiple ports to be read without affecting other operations in your program. They can be considered their own thread, operations between them need to be handled as cross thread operations (such as changing form properties).
The DataReceived events tend to occur on a background thread created by SerialPort anyway.
This means:
a. You don't need to create multiple threads yourself to monitor multiple ports
b. You need to be careful what you do in the event handler, because you're probably not on your app's main thread, which can be a problem if, for example, you interact directly with a window. Your console stuff will be fine, however.
I need to connect to a sensor through a serial port and read some data off it. I connect to it and send the command, but nothing is returned from the device, instead a Timeout exception is thrown. Similar questions here on stackoverflow use the OnDataReceived event, i tried that and it did not work. The parameters i used to initialize and the command i send work as expected on Putty.
-- what am i missing here
void Read()
{
SerialPort serialPort = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
try
{
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Encoding = new ASCIIEncoding();
serialPort.ReadTimeout = 1000;
serialPort.WriteTimeout = 900;
serialPort.Open();
serialPort.WriteLine("TEMP");
MessageBox.Show("Reading");
MessageBox.Show(serialPort.ReadLine());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
serialPort.Close();
}
}
Thank you
serialPort.Handshake = Handshake.XOnXOff;
Maybe that's correct, it is pretty unusual. But real devices almost always pay attention to the hardware handshake signals, in addition to an Xon/Xoff flow control protocol. The DTR (Data Terminal Ready) and RTS (Ready To Send) signals have to be turned on before the device is convinced that it is connected to a real computer. A program like Putty will always turn them on, your program does not.
Add these two required lines:
serialPort.RtsEnable = true;
serialPort.DtrEnable = true;
And ensure that the serialPort.NewLine property correctly matches the end-of-message character used by the device. Temporarily use ReadExisting() instead to avoid getting bitten by that detail, don't leave it that way.
I would suggest that the problem is with the encoding you're using. To check if that's the problem use a sniffer of your choice to see that the bytes transferred on your application are the same as on putty.
Only be sure that you're actually trying to read the bytes when using a sniffer because if you don't they won't be shown on the output.
If that doesn't show you anything you can try to change your ReadLine() method to ReadByte() to ensure that there's no problem with the reading type that you're using.
Serial port sniffers
http://www.serialmon.com/
virtual-serial-port.org/products/serialmonitor/?gclid=CInI2ZPL_bsCFaxr7Aod8S4A8w
www.hhdsoftware.com/device-monitoring-studio
I working on an application handling serial port communication. It's a WPF, multithreaded application. Everything went fine until I sent only small packages through the COM port with communication.
No I reached a phase, where I have to listen for data sent to my application on COM port. For this big chunk of data I go into trouble. I have only one DataReceived event fired, which reads part of the data I need. But after that there is no DataReceived event fired anymore for the rest of the data.
If I monitor the COM port I saw that the bytes are there, the monitoring software states, that there are 2067 bytes in the in queue, but the event do not fire.
I searched Google for similar problems, but I was unable to find relevant answers for this. Have you got any idea where to start searching the roots of the problem.
Thanks in advance.
Here is the code of the DataReceived handler:
private void comPort_DataReceived( object sender, SerialDataReceivedEventArgs e )
{
do
{
new Thread(() =>
{
OnReceivingData(new ComPortCommunicationEventArgs(DataTransferDirections.Receiving, DataTransferActions.Start));
}).Start();
byte[] packetData = null;
try
{
IsReceiving = true;
int bytesToReadCount = comPort.BytesToRead;
if ( bytesToReadCount == 0 )
{
return;
}
packetData = new byte[bytesToReadCount];
comPort.Read(packetData, 0, bytesToReadCount);
}
finally
{
IsReceiving = false;
new Thread(() =>
{
OnReceivingData(new ComPortCommunicationEventArgs(DataTransferDirections.Receiving, DataTransferActions.End));
}).Start();
}
OnPacketReceived(new PacketReceivedEventArgs(comPort.PortName, packetData.ToList()));
} while ( comPort.BytesToRead > 0 );
}
What I found out meanwhile, that if I comment out the OnPacketReceived call - which just fires event for the UI with the received data - than the data processing works fine. So it's not a COM port communication error I think...
Update:
I found the solution for my problem. It was not related to serial port handling.
In one of my data processing threads I run into a loop, which was supposed to be finished on succesfull processing, but with not enough data it was just run continously. Doing that it was blocked the DataReceived event handler - which is still not fully clear for my why, since the two process should be on diffrerent threads I supposed. But it seems that I'm wrong with this.
Anyway I corrected the processing method, and no I receive the data from the serisl port.
Sorry to take your time, and thanks for your help anyway your ideas helped my localize this problem.
Br,
Csaba
I worked with COM ports 5 years ago, and I know how tricky it can get sometimes. All sorts of tricky problems happened with the Siemens device I used to work with :)
First off, I couldn't follow your code thoroughly, so I can't know for sure if your DataReceived routine is sane. I suggest you try to replace all that code inside comPort_DataReceived to something very simple, only for test purposes.
private static void comPort_DataReceived(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Console.WriteLine("Data Received:");
Console.Write(indata);
}
If it still doesn't work, then the problem is not in your code. If you don't know what else to try, I would mess with parameters such as SerialPort.DtrEnable and SerialPort.RtsEnable and see if something happens, because these also caused some not-in-the-manual bugs for me in the past.
Piece of code extracted from MSDN.