Serial COM just echoes what I send instead of data stream. C# - c#

I have a thermometer that has an RS232 connection, so I bought U-Port adapter to USB, per the manual you send it the string "Tcrlf" and it starts outputting data. Tried on PuTTy and it works like a charm.
I'm trying to automate some software with the data stream I am getting, however I am having problems communicating it, I have tried a few snippets from various tutorials around the webs but when I send it the same string via my app it just echoes it back and doesnt stream the data.
This is my Connect Button (after selecting COM port)
private void probeConnectBtn_Click(object sender, EventArgs e)
{
//Connect to the NIST-Reference Probe, using Omega HH42 settings:
if (refProbeCOMPort.SelectedIndex == -1)
{
MessageBox.Show("No COM Port selected for NIST-Reference Probe");
return;
}
if (!connectedreferenceProbePort.IsOpen)
{
connectedreferenceProbePort.DataBits = HH42DataBits;
connectedreferenceProbePort.BaudRate = HH42BaudRate;
connectedreferenceProbePort.PortName = HH42PortName;
connectedreferenceProbePort.Parity = Parity.None;
connectedreferenceProbePort.ReadTimeout = 600;
connectedreferenceProbePort.WriteTimeout = 800;
connectedreferenceProbePort.StopBits = StopBits.One;
connectedreferenceProbePort.DataReceived += new SerialDataReceivedEventHandler(probeDataReceived);
}
try
{
Console.WriteLine("Attempting to open port");
if (!connectedreferenceProbePort.IsOpen)
{
connectedreferenceProbePort.Open();
if (connectedreferenceProbePort.IsOpen)
{
Console.WriteLine("Port Opened, sending RTS");
connectedreferenceProbePort.RtsEnable = true;
connectedreferenceProbePort.WriteLine("Tcrl");
}
}
else
{
Console.WriteLine("Port is already open");
}
}
catch (Exception ex)
{
MessageBox.Show("Error opening/writing to Serial Port:: " + ex.Message, "Fatal Error!");
}
}
That's the connect and "attempting" to start the stream, then I have the datareceived part:
(Per the HH42 manual, after receiving the RTS signal, it sends a ">" character meaning that it's ready to listen).
private void probeDataReceived(object sender, EventArgs e)
{
string dataReceived = "";
Console.WriteLine("Data Incoming");
connectedreferenceProbePort.DiscardOutBuffer();
try
{
dataReceived = connectedreferenceProbePort.ReadExisting();
Console.WriteLine("Recevied :" + dataReceived);
} catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
if (dataReceived.Contains(">"))
{
Console.WriteLine("> Detected, attempting to write Tcrl");
connectedreferenceProbePort.Write("Tcrl");
}
}
This is my output from the console and a screenshot of PuttY:
Attempting to open port
Port Opened, sending RTS
Data Incoming
Recevied :
> Tcrl
> Detected, attempting to write Tcrl
Data Incoming
Recevied :Tc
Data Incoming
Recevied :rl

When you type "Tcrl" and press return in PuTTY, what PuTTY is actually sending are the bytes "T", "c", "r", "l", followed by a carriage return (CR) and a linefeed (NL).
I believe the manual is telling you to send "T", CR, LF, which in C# terms would be the string "T\r\n".

Related

communication from arduino to C# forms app

I'm following this tutorial. The goal is to receive periodic data from the arduino via serial port. I've been struggling with this for a while now. The com port connection is fine as i'm unable to connect with another terminal program to the arduino when my c# app is running ( port is already connected). At this point the SerialListen thread should start but this doesn't happen.
namespace TestReceiveArduino
{
public partial class Form1 : Form
{
//object serialport to listen usb
System.IO.Ports.SerialPort Port;
//variable to check if arduino is connect
bool IsClosed = false;
public Form1()
{
InitializeComponent();
//configuration of arduino, you check if com3 is the port correct,
//in arduino ide you can make it
Port = new System.IO.Ports.SerialPort();
Port.PortName = "COM11";
Port.BaudRate = 9600;
Port.ReadTimeout = 500;
try
{
Port.Open();
Console.WriteLine("open port ");
}
catch { }
}
private void Form1_Load(object sender, EventArgs e)
{
//A Thread to listen forever the serial port
Console.WriteLine("start thread ");
Thread Hilo = new Thread(ListenSerial);
Hilo.Start();
}
private void ListenSerial()
{
Console.WriteLine("start listener");
while (!IsClosed)
{
Console.WriteLine("in while");
try
{
//read to data from arduino
string AString = Port.ReadLine();
//write the data in something textbox
txtSomething.Invoke(new MethodInvoker(
delegate
{
txtSomething.Text = AString;
}
));
}
catch { }
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//when the form will be closed this line close the serial port
IsClosed = true;
if (Port.IsOpen)
Port.Close();
}
}
}
My arduino is sending data, i've checked this with terminal software. I'm also using the correct COM port
I have some experience with c# but i'm new to threads. What could be the reason for this?
OK:
See if these changes help:
namespace TestReceiveArduino
{
public partial class Form1 : Form
{
//object serialport to listen usb
System.IO.Ports.SerialPort Port;
//variable to check if arduino is connect
bool IsClosed = false;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
// Connect to Arduino
Port = new System.IO.Ports.SerialPort();
Port.PortName = "COM11";
Port.BaudRate = 9600;
Port.ReadTimeout = 500;
Port.Open();
Console.WriteLine("Port successfully opened: Name: {0}, Baud: {1}, ReadTimeout: {2}", Port.PortName, Port.BaudRate, Port.ReadTimeout);
//A Thread to listen forever the serial port
Console.WriteLine("start thread ");
Thread Hilo = new Thread(ListenSerial);
Hilo.Start();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
...
I moved "Open Serial Connection" and "Start Listener Thread" to the same place (Form1_Load), and wrapped both in the same try/catch block. You might even want to move the "try/catch" to a higher level (e.g. so you can display any exceptions in your Windows GUI).
I assume you're using Microsoft VisualStudio (e.g. MSVS Express 2019) as your GUI, correct? Definitely familiarize yourself with your IDE's debugger; definitely get in the habit of stepping through the code as you're developing it.
Your next steps:
Verify the code gets to "Open Serial Connection", and verify that it opens correctly (e.g.prints "Port successfully opened...").
Verify the code then gets to "ListenSerial()", and prints "start listener" and "in while" at least once.
'Hope that helps...

Closing a USB serial port leaves the port unavailable

My app uses USB based serial ports to connect to physical hardware devices. I can open any valid USB port and communicate with the external devices. However, when I close the connection, the USB port is left in some sort of indeterminate state for some time, and during that time further attempts to reconnect result in the "Access to port "COM--" is denied" error. However, after some few seconds, attempting to reconnect is successful. How can I determine WHEN the USB port will again support a new connection?
The code looks like this:
private void Setup(string Port)
{
bool ValidPort = false;
int CloseSleep = 10;
_PortName = Port;
_PortType = this;
string[] AvailablePorts = SerialPort.GetPortNames();
foreach(string aPort in AvailablePorts)
{
if (aPort == _PortName)
{
// The required port is listed in the list of available ports)
ValidPort = true;
break;
}
}
if (ValidPort)
{
try
{
if (_ThePort != null)
{
_ThePort.Close();
_ThePort.DataReceived -= ReceivedDataEventHandler;
while(CloseSleep-- > 0)
System.Threading.Thread.Sleep(100);
_ThePort.Dispose();
_ThePort = null;
}
}
catch (Exception ex)
{
EMS_Config_Tool.ModalDialog md = new EMS_Config_Tool.ModalDialog("Closing Port: " + ex.Message, "System Exception");
md.ShowDialog();
}
System.IO.Ports.SerialPort TheNewPort = new System.IO.Ports.SerialPort(Port, 38400);
// Setup the event handlers from Tx and Rx
Handler.DataOutEvent += CommsSender;
TheNewPort.DataReceived += ReceivedDataEventHandler;
TheNewPort.DataBits = 8;
TheNewPort.Parity = Parity.None;
TheNewPort.Handshake = System.IO.Ports.Handshake.None;
TheNewPort.StopBits = System.IO.Ports.StopBits.One;
// We will try 3 times to open the port, and report an error if we fail to open the port
try
{
TheNewPort.Open();
}
catch (Exception)
{
System.Threading.Thread.Sleep(1000);
try
{
TheNewPort.Open();
}
catch (Exception)
{
System.Threading.Thread.Sleep(1000);
try
{
TheNewPort.Open();
}
catch (Exception ex)
{
EMS_Config_Tool.ModalDialog md = new EMS_Config_Tool.ModalDialog("Opening Port: " + ex.Message, "System Exception");
return;
}
}
}
The final catch statement is where the error about Access being denied is issued. Note my attempt to retry opening the port 3 times doesn't really help. If I leave the port alone for about 5 to 10 seconds and retry calling the Setup method it succeeds immediately.
As #Neil said, there are many issues. The best thing to do, in my point of view, is to put the search in a loop, and as soon as the port can be opened, it will be.
I used to do like this :
public Task WaitingPort()
{
while (port is null)
{
port = CheckPort();
}
}
private SerialPort CheckPort()
{
string[] listPort = SerialPort.GetPortNames();
foreach(string namePort in listPort)
{
SerialPort port = new SerialPort(namePort, 9600);
if (!port.IsOpen)
{
try
{
port.Open();
port.ReadTimeout = 1500;
string data = port.Readline();
// I programmed my device to send an "A" until it receives
// "777" to be able to recognize it once opened
if (data.Substring(0, 1) == "A")
{
port.ReadTimeout = 200;
port.Write("777"); // to make it stop sending "A"
return port;
}
else
{
port.Close();
}
}
catch (Exception e1)
{
port.Close();
}
}
}
return null;
}
Of course, this is just some kind of a template which you have to reshape to your use
I have amended my code to use a constrained loop to give it a better chance to work, which it usually does. I was hoping that there was a better way to do it, as I tend to have pretty impatient users who will be posting defect reports if they have to wait 5 or 10 seconds to make a connection....
// We will try several times to open the port, upto 10 times over 5 seconds, and report an error if we finally fail to open the port
try
{
TheNewPort.Open();
}
catch (Exception ex)
{
RetryOpenTimer.Interval = 500;
RetryCount = 10;
RetryOpenTimer.Elapsed += new System.Timers.ElapsedEventHandler(RetryOpenTimer_Elapsed);
WaitForOpen = true;
RetryOpenTimer.Start();
while (WaitForOpen && RetryCount > 0)
{
System.Threading.Thread.Sleep(500);
}
if (WaitForOpen)
{
EMS_Config_Tool.ModalDialog md = new EMS_Config_Tool.ModalDialog("Opening Port: " + ex.Message, "System Exception");
return;
}
}
...
void RetryOpenTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
RetryOpenTimer.Stop();
RetryOpenTimer.Elapsed -= RetryOpenTimer_Elapsed;
try
{
if (RetryCount-- > 0)
{
TheNewPort.Open();
WaitForOpen = false;
}
else
return;
}
catch (Exception)
{
RetryOpenTimer.Start();
RetryOpenTimer.Elapsed += RetryOpenTimer_Elapsed;
}
}

Serial port read result contains response but also the command I give, how to solve this?

I am writing a GUI for Modem communication tool, able to receive AT command and also return the result from modem after execution in modem. I use serial port datareceived event to handle the received data but it contains not only the response from the modem but also the AT command I give. Now I think it is because:
1) send at command from my GUI
2) Modem receive it, then trigger datareceived events
3) Modem runs the command, the reply also trigger datareceived events.
4) the received data then contains both my given command and also the reply
For example:
Input: AT+COPS=0
Output:AT+COPS=0OK (OK is modem response)
Input: AT
Output:ATOK (OK is modem response)
I could not find a solution in MSDN. Are there two different buffers in Modem?
How to solve this?
Here is my code:
void serialPort_DataReceived(object s, SerialDataReceivedEventArgs e)
{
if (e.EventType != SerialData.Chars)
{
return;
}
try
{
System.Threading.Thread.Sleep(1000);
string indata = atPort.ReadExisting();
string status = timeStamp.ToShortDateString() + " " + timeStamp.ToUniversalTime() + " " + "Read from Modem: " + indata;
this.Invoke(new MethodInvoker(delegate () { this.listBox_CommandOutput.Items.Add(status); }));
}
catch (Exception ex)
{
}
}
private void executeCommandLine()
{
if (this.textBox_CommandLine.Text != "")
{
try
{
atPort.DiscardInBuffer();
atPort.DiscardOutBuffer();
this.atPort.Write(this.textBox_CommandLine.Text.ToString()+"\\r");
this.listBox_CommandOutput.Items.Add(timeStamp.ToShortDateString() + " " + timeStamp.ToUniversalTime() + " " + "Write to Modem: " + this.textBox_CommandLine.Text.ToString());
}
catch (Exception exc)
{
this.listBox_CommandOutput.Items.Add(exc.ToString());
}
}
else MessageBox.Show("Command can't be void.", "COM talk", MessageBoxButtons.OK);
}
The problem is not in your code. Some modem by default use the echo mode by default: they echo every character sent to them to the sender (so you can use them like a terminal).
You can disable the echo mode using the AT command:
ATE0

c# SerialPort DataReceivedHandler not being called for every event.

I am developing a desktop application which interacts with Arduino via SerialPort.
I want my application to respond every time arduino writes something on the serial port.
But DataReceivedHandler does not get triggered for all the events.
Here is the connection code -
public static bool connectToArduino()
{
foreach (string name in SerialPort.GetPortNames())
{
SerialPort serialPort = new SerialPort(name);
Console.WriteLine(name);
if (serialPort.IsOpen == false)
{
serialPort.PortName = name;
try
{
Console.WriteLine("Openning serial port.");
serialPort.WriteTimeout = 5000;
serialPort.ReadTimeout = 5000;
serialPort.BaudRate = 115200;
serialPort.Open();
serialPort.Write(Constants.CONNECT_APP_STRING);
Console.WriteLine("Written to serial port.");
string reply = serialPort.ReadLine();
//string reply = serialPort.ReadTo("\n");
Console.WriteLine("Reply is: " + reply);
Console.WriteLine("Read from serial port.");
if (reply == Constants.CONNECT_ACK)
{
Console.WriteLine(name);
Console.WriteLine("Connected with arduino controller");
//serialPort.DataReceived += DataReceivedHandler;
serialController = serialPort;
return true;
}
else if (reply+"\n" == Constants.CONNECT_ARDUINO_STRING) {
serialPort.WriteLine(Constants.CONNECT_ACK);
serialController = serialPort;
MessageBox.Show("Connected with arduino controller");
return true;
}
else
{
serialPort.Close();
}
}
catch (TimeoutException)
{
Console.WriteLine("Timeout occured.");
serialPort.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "ERROR");
Console.WriteLine(ex);
}
}
}
MessageBox.Show("Connection with Arduino failed!");
return false;
}
After this I set the data received handler -
SerialComm.serialController.DataReceived += DataReceivedHandler;
Now, the problem is that sometimes DataReceivedHandler is not being triggered.
I am not able to find a pattern in this. It randomly just skips some events.
Any idea what is going wrong?
Looking at the documentation you can find in the remarks:
The DataReceived event is not guaranteed to be raised for every byte received. Use the BytesToRead property to determine how much data is left to be read in the buffer.
If the event is in your case too unreliable to be trusted catch every incoming information from your device, then you could use an extra thread which would run in the background constantly checking the BytesToRead property and/or constantly reading with ReadExisting which is non-blocking.

Getting a speed-bottleneck in data-communication when using anonymous pipes

I have a program setup where a MCU sends me sensor data via USART to a C# windows forms application. That application upon receiving the data via the serialdatareceived event sends it to a managed c++ application using anonymous pipes. As soon as the data is received it is plotted in an OpenGL 3d enviroment.
My problem is that the 3D application only refreshes a few times per second and the animation is quite slow and not smooth enough. I did my best to improve the USART speed but the result is the same. I believe the animations speed is bottlenecked by the anonymous pipes speed. I was wondering if anyone else encountered this problem before and possibly found ways to speed upthe anonymous pipes data transfer.
So my problem is the low data transfer speed between the two applications. Ideally I would want 20+ messages a second but at the very least the bottleneck of the data transfer should be the USART interface and not the anonymous pipes. I am running a BAUD-rate of 19200 and am transferring the command "get_angle" and receiving data back fairly fast (~20 ms for calculation of data on the MCU), the data received is ~12 chars.
My anonymous pipe client in managed c++ (in WinMain):
try
{
String^ args = gcnew String(lpCmdLine);
PipeStream^ pipeClient = gcnew AnonymousPipeClientStream(PipeDirection::In, args);
StreamReader^ sr = gcnew StreamReader(pipeClient);
String^ temp;
fullscreen = FALSE;
if (!CreateGLWindow("OpenGL Test", 640, 480, 16, fullscreen))
{
return 0; // Quit If Window Was Not Created
}
while (!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message == WM_QUIT) // Was the message a quit message?
{
done = TRUE; // Set Flag to execute program
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
temp = sr->ReadLine(); // Read text from pipeline
if (temp != "") // Make sure message is not empty/New message has been received
{
try
{
x_an = FLOAT::Parse(temp->Substring(0, 5)); // Parse X value from string to float
y_an = FLOAT::Parse(temp->Substring(7, 12)); // Parse Y value from string to float
}
catch (Exception^)
{
MessageBox(NULL, "Error parsing string to float", "Fatal error", MB_OK);
}
}
if ((!done)&& (1))
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?
{
done = TRUE; // ESC or DrawGLScene Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}
}
// Shutdown
sr->Close();
pipeClient->Close();
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
catch (Exception^)
{
MessageBox(NULL, "Pipe connection error", "Fatal error", MB_OK);
return 0x01;
}
My code for the C# anonymous pipes server part:
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (Ready_To_Receive)
{
if (Setup_Pipe)
{
try
{
pipeClient.StartInfo.FileName = "client.exe";
pipeClient.StartInfo.Arguments =
pipeServer.GetClientHandleAsString();
pipeClient.StartInfo.UseShellExecute = false;
pipeClient.Start();
pipeServer.DisposeLocalCopyOfClientHandle();
sw = new System.IO.StreamWriter(pipeServer);
sw.AutoFlush = true;
Setup_Pipe = false;
}
catch
{
MessageBox.Show("Error setting up pipeserver.");
button2_Click(this, null); // Resets application
}
}
Debug_String = serialPort1.ReadExisting();
Debug_String = Debug_String.Replace(serialPort1.NewLine, ""); // Delete newline character so all that remains are numbers
if (!(Debug_String == "")) // String is not empty
{
DataReceived = true;
try
{
sw.WriteLine(Debug_String);
}
catch (Exception)
{
MessageBox.Show("Connection to Pipe Client lost.");
button2_Click(this, null);
}
}
}
else if (Shutting_Down)
{
pipeClient.Close();
}
else
{
serialPort1.ReadExisting(); // Flush the data buffer
DataReceived = true;
}
}

Categories

Resources