Data read from serial port is separated. Code + result inside - c#

So, I am trying to read data from the serial port to communicate with an Arduino. Here is the code I am using:
public partial class Form1 : Form
{
SerialPort port = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);
public Form1()
{
InitializeComponent();
port.Open();
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
}
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.Invoke(new EventHandler(DoUpDate));
}
private void DoUpDate(object s, EventArgs e)
{
textBox1.AppendText(port.ReadLine() + "\r\n");
}
}
But the result I get in the textBox is (check the picture):
The value read should be 975 but I got separated values as well as many empty lines.
Any help is apperciated.
EDIT#1:
Here is the Arduino code:
int sensorPin=A0;
int sensorValue=0;
void setup()
{
Serial.begin(9600);
}
void loop()
{
sensorValue=analogRead(sensorPin);
Serial.print(sensorValue);
Serial.print("\n");
}
And here is the result when I click on the serial reader within arduino IDE (which what C# code should show)
EDIT#2
After thinking more about the problem, I think that the C# code is very fast that it is reading uncomplete data but I don't have a solution for it, do you know anything I can try to solve it?

I'm not fluent in C#, but maybe you should wait for data to be in the Serial buffer before trying to read them. A method for that is to use port.ReadExisting() as it can be seen here!
Hope it helps!

Insert a 20ms delay in your loop()

Related

c# constantly requesting and processing data from serial port

After a long time i need to program again.
I need to constantly send a command through serial port from a car ecu(? data).
Then i need to receive that data which i will process to be shown on a display(thinking racing display with car parameters like temperature etc).
I need to do this constantly
I wonder before i start whats best way to do this?
1 thread for constantly asking and receiving data
main thread for showing data in screen.
(store data in buffer and save once a minute or so)
anyone has any tips a guide or so how to start on this.
i tested receiving data with terminal and i got data back so config is working.
sent ? data => i got data back.
You could just use the SerialPort class and configure the BaudRate, DataBits etc.. and then just wait for the DataReceived event to fire:
public class SerialPortReader
{
public SerialPortReader(string yourPortName)
{
var serialPort = new SerialPort() {
PortName = yourPortName,
BaudRate = 57600; //This will control the rate at what you receive the data
}
serialPort.DataReceived += new SerialDataReceivedEventHandler(OnDataReceived);
serialPort.Open();
}
}
public void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
var serialPort = (SerialPort)sender;
// Process your data reading the stream with Read, ReadLine etc...
}
The approach we are using in our SerialPort Handler is, to have an AutoResetEvent to get notified as soon as there is an answer from the port.
SerialPort class of the FrameWork has a few issues with the integrated DataReceived event. It is sometimes fired when there is no complete package available (in case you defined the answer length). So you should check for the answer length you expect.
Our very stripped down implementation:
public class Serialport
{
private SerialPort _serialPort;
private List<byte> _buffer;
private AutoResetEvent _autoResetEvent;
private const int WriteTimeOut = 5;
private event EventHandler ReceivedDataChanged;
public Serialport()
{
_serialPort = new SerialPort();
// set PortName, BaudRate etc
_serialPort.Open();
_serialPort.DiscardInBuffer();
_serialPort.DiscardOutBuffer();
_serialPort.DataReceived += ReceiveData;
}
private void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
var bytes = _serialPort.BytesToRead;
byte[] buffer = new byte[bytes];
if (_serialPort.IsOpen)
{
_serialPort.BaseStream.Read(buffer, 0, bytes);
_buffer.AddRange(buffer);
}
ReceivedDataChanged?.Invoke(this, new ReceivedBytesEventArgs(_buffer.ToArray()));
_buffer.Clear();
}
private void SendData(byte[] message, int answerLength)
{
_serialPort.ReceivedBytesThreshold = answerLength;
_serialPort.WriteTimeout = WriteTimeOut;
_serialPort.Write(message, 0, message.Length);
}
public string SendDataCommand()
{
if (_serialPort.IsOpen)
{
ReceivedDataChanged += InterpretAnswer;
SendData(message, length);
if (_autoResetEvent.WaitOne(100))
{
ReceivedDataChanged -= InterpretAnswer;
//Data Received and interpreted and send to the caller
return _requestAnswer;
}
ReceivedDataChanged -= InterpretAnswer;
}
return "Connection not open";
}
private void InterpretAnswer(object sender, EventArgs e)
{
// handle all interpretation
// Set the event
_autoResetEvent.Set();
}
}
The serialPort is initialised and opened. After that, we wire up all needed events and call the SendDataCommand() Method. This method is the public visible method which is called from some task. This calls the method SendData. As soon as there is an answer, the event is triggered and the interpretation is started. If the interpretation is done in the specified amount of time (_autoResetEvent.WaitOne(msToWait)) the result is given back to the calling method.
This should be done in a separate task, so the ui will not Block while you wait for the answer
As mentioned, this is a very stripped down example. You should do more checking in the received handler of SerialPort, because there are some issues with the event. With this approach you will have a bit more of abstraction to your business logic.
Hope this helps.

Proper implementation of C# <-> Arduino serial communication

I'm trying to communicate back and forth with an Arduino via serial through a C# program. I've got a basic working example, but it's not pretty and not fault-less. I've included it at the end. I have done some research online, but it's difficult to look for something when you don't know all the details and intricacies of what you're looking for.
I'm under the impression that good serial communication protocol should include a handshake, send data and wait for response, receive data and send response, data clocking, etc. My question is how best to implement this. My existing code is one-way, from C# to the arduino's serial port, and it just sends the data and assumes that it was received. It's also very simple, sending just two bytes (a 1 or 0 to turn on or off an LED, and a 0-255 to control the LED's brightness via PWM). I'd like to be able to send sensor data or confirmation that the data was received and acted on, back from the arduino to the program.
I'm also curious about syncing. Does that go hand in hand with the handshake (no pun intended)? How can I reliably send data either way and be assured that nothing will be lost due to being out of sync?
Anywho, I've rambled, sorry. Hopefully someone can shed a little learning light on this subject. Here's my current messy code:
Arduino:
#define LEDPin 9
byte SerialCmd = 0;
byte SerialVal = 0;
void setup() {
Serial.begin(9600);
pinMode(LEDPin, OUTPUT);
digitalWrite(LEDPin, LOW);
}
void loop() {
while(Serial.available() > 1) {
SerialCmd = Serial.read();
SerialVal = Serial.read();
switch(SerialCmd) {
case 0:
digitalWrite(LEDPin, LOW);
break;
case 1:
analogWrite(LEDPin, SerialVal);
break;
}
}
}
C#:
using System;
using System.Windows.Forms;
namespace ArduinoTest2
{
public partial class Form1 : Form
{
byte[] SerialData = new byte[] { 0, 0 };
public Form1()
{
InitializeComponent();
serialPort1.PortName = "COM3";
serialPort1.BaudRate = 9600;
serialPort1.Open();
}
public void SerialWrite()
{
serialPort1.Write(SerialData, 0, 2);
}
private void button1_Click(object sender, EventArgs e)
{
SerialData[0] = 1;
SerialWrite();
}
private void button2_Click(object sender, EventArgs e)
{
SerialData[0] = 0;
SerialWrite();
}
private void trackBar1_Scroll(object sender, EventArgs e)
{
SerialData[1] = Convert.ToByte(trackBar1.Value);
label1.Text = trackBar1.Value.ToString();
SerialWrite();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
serialPort1.Close();
}
}
}

serial port myPort.Datareceived C#

Hello friends have a form in C # that reads data from a serial device connected, my problem is that I even changing form of the method myPort.DataReceived still running and receiving data. There's no way I close the connection with the serial port because the method does not stop excutar. I've tried a command to zip it when I change my form but it crashes when you try to run the myPort.Close, I believe that is why the myPort.DataReceived still running, so I removed the code and it continues myPort.Close open in another form. I think my solution would be to stop the myPort.DataReceived to then close connection, but can not find way to do this.Below is an excerpt from my code:
namespace EntradaFinalCliente
{
public partial class ConsultaSerial : Form
{
string SerialString;
private SerialPort myport;
public ConsultaSerial()
{
InitializeComponent();
abrirSerial();
lerDados();
}
public void abrirSerial()
{
myport = new SerialPort();
myport.BaudRate = 9600;
myport.PortName = SerialPort1;
myport.DataReceived += myport_DataReceived;
}
private void lerDados()
{
if (myport.IsOpen == false)
{
try
{
myport.Open();
}
catch
{
return;
}
}
}
private void myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(100);
SerialString = myport.ReadExisting();
this.Invoke(new EventHandler(Analisa));
}
private void Analisa(object sender, EventArgs e)
{
checarSerial();
}
And this is my closing the form button:
private void button1_Click (object sender, EventArgs e)
{
myPort.Close ();
this.Hide ();
var form1 = new Form1 ();
form1.Closed + = (s, args) => this.Close ();
Form1.Show ();
}
The issue you have it that once the event has been triggered, your application would have entered the function myport_DataReceived. The function will continue to execute regardless of whether the port has been closed. If the port has been closed, the function would execute for the last time. Waiting for 100ms makes it worse. So my advice is to remove the wait and put a try catch statement around the code to make the thread terminate cleanly.
Furthermore, it is better if you use the sender to read the incoming data than using the member myPort because the sender is the one that fires the event. It also helps to remove confusion when you open two or more ports.
It is also advised that the body of DataReceived event handler function should be kept to minimum. Only do what you need to get the data out. You can then store the data in memory and do more complicated handling somewhere else using the stored data.
private void myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(100); // Why do you need to wait for 100 ms? If the event reaches here, it will have the data to read. Can remove?
try
{
SerialPort sp = (SerialPort)sender;
SerialString = sp.ReadExisting();
this.Invoke(new EventHandler(Analisa));
}
catch (Exception ex)
{
// Do something else
Console.WriteLine(ex.Message);
}
}

Why I get data after closing COM port?

I have methos that recieve data from opening COM port:
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
try
{
if (sp.IsOpen)
{
if (sp.BytesToRead > 0)
{
// Get data
}
}
}
}
Also I have method that does connection to COM port:
private void connectPort()
{
SerialPort mySerialPort = new SerialPort(port);
...
}
When I call method that closes port:
mySerialPort.DiscardInBuffer();
mySerialPort.DiscardOutBuffer();
mySerialPort.Close();
After I get data from device still. What is wrong?
I don't know for sure, but from the docs it sounds like the fact that the data is being raised from another thread may be buffering and/or lagging a bit behind the actual data (plus it's possible for you to receive data between when you've discarded the buffer and when you close it).
I'd probably unhooking the DataReceivedHandler first, then close the connection, finally discard the data, ex.
mySerialPort.DataReceived -= new SerialDataReceivedEventHandler(DataReceivedHandler);

Store data from the SerialPort.ReadExisting() method in a variable?

I would like to read information from a device connected to a SerialPort. I did this previously using a form (code below) but I am trying to do it without one, just storing the information into an array of string.
Code used with a form:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
string line = port.ReadExisting();
this.BeginInvoke(new LineReceivedEvent(LineReceived), line);
}
private delegate void LineReceivedEvent(string line);
private void LineReceived(string line)
{
textBox3.AppendText(line);
}
How far i got without a form (the DA method is allows to store variables within the program). I get the following error on the last line Cannot implicitly convert type 'string' to 'System.IO.Ports.SerialDataReceivedEventHandler'.
protected override void SolveInstance(IGH_DataAccess DA)
{
string selectedportname;
DA.GetData(1, ref selectedportname);
int selectedbaudrate;
DA.GetData(2, ref selectedbaudrate);
bool connecttodevice;
DA.GetData(3, ref connecttodevice);
bool sendtoprint;
DA.GetData(3, ref sendtoprint);
port = new SerialPort(selectedportname, selectedbaudrate, Parity.None, 8, StopBits.One); //Create the serial port
port.DtrEnable = true; //enables the Data Terminal Ready (DTR) signal during serial communication (Handshaking)
port.Open(); //Open the port
port.DataReceived += port.ReadExisting();
}
Assuming ReadExisting is a method with the right parameters:
//port.DataReceived += port.ReadExisting();
port.DataReceived += port.ReadExisting;
But the error indicates it is returning a 'string' so there is more to solve here.
Edit:
Looks like it should be:
port.DataReceived += this.serialPort1_DataReceived;

Categories