Serial-port Datareceive - c#

I'm having a problem with serial port data. I have designed a form where I have used a datareceived handler event and the whole of data needs to be printed in the RichTextBox placed in the form. The problem is I'm only receiving the last bits of data on the RichTextBox, while the MessageBox that is provided with the code runs the whole of data in part. Please suggest where I'm going wrong.Thanks in advance.
public partial class Form1 : Form
{
char po='\0';
string indata,pi;
string[] buffer;
public Form1()
{
InitializeComponent();
System.ComponentModel.IContainer components = new System.ComponentModel.Container();
serialPort1 = new System.IO.Ports.SerialPort(components);
serialPort1.PortName = "COM1";
serialPort1.BaudRate = 9600;
serialPort1.DtrEnable = true;
serialPort1.DataReceived += new SerialDataReceivedEventHandler(serialPort1_DataReceived);
serialPort1.Open();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
po = Convert.ToChar(serialPort1.BytesToRead);
indata = sp.ReadExisting();
//return (indata);
//for (int p = 0; p <= 256; p++) ;
//MessageBox.Show(buffer[0]);
//MessageBox.Show(indata);
//richTextBox1.Text += indata;
//richTextBox1.Text = indata;
}
private void button1_Click(object sender, EventArgs e)
{
richTextBox1.WordWrap = true;
richTextBox1.Text = indata;
}
}

It looks like you should be appending the data each time data is received over the serial port, so perhaps you should change
indata = sp.ReadExisting();
to:
indata += sp.ReadExisting();
To hold all of the contents of the Serial Data, including historical data that was previously sent.
Hope this helps!

Trying This Code....
private string StrValue = "";
private void Port_DataReceived(object sender,
System.IO.Ports.SerialDataReceivedEventArgs e)
{
double DouRWeight = 0;
try
{
DouRWeight = Val.ToDouble(Port.ReadLine());
if (DouRWeight != 0)
{
this.Invoke((System.Windows.Forms.MethodInvoker)delegate()
{
StrValue = Val.Format(DouRWeight.ToString(), "####0.000");
}
}
}
}
private void button1_Click(object sender, EventArgs e)
{
richTextBox1.WordWrap = true;
richTextBox1.Text = StrValue ;
}
It's Completely Worked...

Related

C# - Change format of Data received from Serial Port

I am making a C# form application that receives data from an instrument communicating at Baud Rate 2400, parity None, 8 bit data, 1 stop bit.
The data is coming in a continuous string line in the form [000000][000000][000000]. For example if during a procedure the reading on the instrument is varying like 0.50,0.49,0.72,0.61,0.48 then the string of received data would be [000050][000049][000072][000061][000048], which is how it is currently being displayed in the textbox.
I need to display the Maximum value reached during a procedure into the textbox and in the correct format, like in this case it should be 0.72. I am at a loss about what would be the code for that.
Below is my current code for serial port communication.
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void Main_Load(object sender, EventArgs e)
{
}
//this is the button to open port.
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = true;
try
{
serialPort1.PortName = comboBox1.Text;
serialPort1.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
//Event handler for data received.
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Regex rx = new Regex(#"\[(\d+)\]");
double.TryParse(richTextBox2.Text, out double max);
foreach (Match match in rx.Matches(indata))
{
double val = int.Parse(match.Groups[1].Value) / 100.0;
if (val > max)
max = val;
}
richTextBox2.Text = max.ToString();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
//this is the button to close port
private void button2_Click(object sender, EventArgs e)
{
button1.Enabled = true;
button2.Enabled = false;
try
{
serialPort1.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button3_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.DataReceived += DataReceivedHandler;
}
else
{
MessageBox.Show("Error : Port needs to be open or wrong port selected!");
}
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (serialPort1.IsOpen)
serialPort1.Close();
}
private void button4_Click(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
comboBox1.Items.AddRange(ports);
comboBox1.SelectedIndex = 0;
button2.Enabled = false;
}
So you want to process data every time there is data to process right?
If you are using the "System.IO.Ports", and your serialPort1 is of the type SerialPort, you have the "DataReceived" event available. So after you instantiate the serialPort1 you can:
private void button1_Click(object sender, EventArgs e)
{
button1.Enabled = false;
button2.Enabled = true;
try
{
//check and set the settings of your device
serialPort1 = new SerialPort
{
PortName = comboBox1.Text,
BaudRate = 2400,
Parity = Parity.None,
StopBits = StopBits.Odd,
DataBits = 8,
Handshake = Handshake.None,
RtsEnable = true
};
serialPort1.DataReceived += DataReceivedHandler;
serialPort1.Open();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Then you just need to declare the event handler, something like this:
private void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
Regex rx = new Regex(#"\[(\d+)\]");
double.TryParse(textBox13.Text, out double max);
foreach (Match match in rx.Matches(indata))
{
double val = int.Parse(match.Groups[1].Value) / 100.0;
if (val > max)
max = val;
}
textBox13.Text = max .ToString();
}
This will compare the values received and the current value in the textbox.
If I understand you're formatting requirement correctly you basically want to remove zeros at the front from each of the numbers and then compare them to find the max value and display them in the format of x.xx If that's the case create a separate method to handle it like this:
private decimal GetMaxReading(string rawReadingData)
{
decimal maxReading = 0;
var readings = rawReadingData.Split('[',).ToList();
foreach (var reading in readings)
{
var readingString = reading.TrimStart('0')
.TrimEnd(']');
var isInt = int.TryParse(readingString, out int readingValue);
var value = isInt ? (decimal)readingValue / 100 : 0;
maxReading = value > maxReading ? value : maxReading;
}
return maxReading;
}

Scoreboard data transfer Serial Port c#

There's some outdated software that's used to control the scoreboard at my local athletics track and I've been tasked with creating a new advanced one. However, I cannot seem to get the scoreboard to do what I ask it to do.
I've installed the original software to the my laptop and it works fine, however, when I run my test software that sends data to the board through the serial port, it isn't doing what I want.
I have the "Scoreboard Data Protocol" supplied by the manufacturer and I've been following this. I will supply the code to my test program that I've been using to see if I can get it to work and I will also supply the Data Protocol.
In the text box, I type 010D0201SPAIN and 003C630 and send it to the board and this doesn't work.
public partial class Form1 : Form
{
private SerialPort m_port;
public Form1()
{
InitializeComponent();
m_list.Items.AddRange(SerialPort.GetPortNames()); // Adds ports to combobox
m_port = new SerialPort();
m_port.BaudRate = 9600;
m_port.DataBits = 8;
m_port.Parity = Parity.Even;
m_port.StopBits = StopBits.One;
//m_port.Handshake = Handshake.None;
m_port.Encoding = new ASCIIEncoding();
m_port.RtsEnable = true;
m_port.DtrEnable = true;
m_port.ReceivedBytesThreshold = 1;
m_port.DataReceived += DataReceivedEvent;
}
private void button1_Click(object sender, EventArgs e)
{
m_port.Close();
m_port.PortName = (string)m_list.SelectedItem;
try
{
m_port.Open();
m_sendbutton.Enabled = true;
button2.Enabled = true;
}catch(UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
}
private void m_sendbutton_Click(object sender, EventArgs e)
{
m_port.Write(m_textbox.Text);
}
private void DataReceivedEvent(object sender, SerialDataReceivedEventArgs args)
{
Invoke(new EventHandler(DoUpdate));
}
private void DoUpdate(object s, EventArgs e)
{
label1.Text += m_port.ReadLine();
}
private void button2_Click(object sender, EventArgs e)
{
byte[] r_bytes = Encoding.ASCII.GetBytes(m_textbox.Text);
m_port.Write(r_bytes, 0, r_bytes.Length);
}
}
}
Scoreboard Data Protocol
Code: https://hastebin.com/epirobuduv.cs
Here's how to add STX and ETX around your message, in a byte array.
private void button2_Click(object sender, EventArgs e)
{
var msg = Encoding.ASCII.GetBytes(m_textbox.Text).ToList();
msg.Insert(0, 0x02); // STX at the start
msg.Add(0x03); // ETX at the end
m_port.Write(msg.ToArray(), 0, msg.Count);
}

Read string from textbox

I have the below code in WPF application.
It reads the strings from the serial port and displays in textbox.
I want to execute an operation according to the serial input.
This I'm thinking to do either by reading the string variable (RData) or by reading the textbox.text.
I've tried with if statements in the functions but it doesn't work. Please help.
public partial class MainWindow : Window
{
SerialPort serial = new SerialPort();
string RData;
public MainWindow()
{
InitializeComponent();
getPorts();
}
void getPorts()
{
String[] ports = SerialPort.GetPortNames();
comboBoxPorts.ItemsSource = ports;
}
private void buttonConnect_Click(object sender, RoutedEventArgs e)
{
serial.PortName = comboBoxPorts.Text;
serial.BaudRate = 9600;
serial.DataBits = 8;
serial.Handshake = System.IO.Ports.Handshake.None;
serial.StopBits = StopBits.One;
serial.ReadTimeout = -1;
serial.WriteTimeout = -1;
serial.Open();
if (serial.IsOpen)
{
buttonConnect.IsEnabled = false;
labelConState.Content = "Connected";
labelConState.Foreground = System.Windows.Media.Brushes.Green;
serial.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(Recieve);
}
}
private delegate void UpdateUiTextDelegate(string text);
private void Recieve
(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
RData = serial.ReadExisting();
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUiTextDelegate(WriteData), RData);
}
private void WriteData(string text)
{
textBoxPrompt.Text += text;
}
}
You should set parity property of SerialPort.

C# Received data from Arduino

I'm building a weather station and I have a little problem. How do the received data to run at a textbox or rich box? The application connects Arduino, but does not operate to read data.
Thank you,
[enter image description here][1]
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
string InputData = String.Empty;
delegate void SetTextCallback(string text);
public Form1()
{
InitializeComponent();
string[] ports = SerialPort.GetPortNames();
Console.WriteLine("The following serial ports were found:");
// Display each port name to the console.
foreach (string port in ports)
{
comboBox1.Items.Add(port);
}
}
public void guzikpolacz_Click(object sender, EventArgs e)
{
serialPort1.PortName = comboBox1.Text; // Ustawiamy numer Portu COM
// Ustawiamy wartość baudrate portu
//Inne ustawienia zdefiniowane na stałe
serialPort1.Parity = Parity.None; // bez parzystości
serialPort1.StopBits = StopBits.One; // jeden bit stopu
serialPort1.DataBits = 8; // osiem bitów danych
serialPort1.Open();
polestatusu.Text = "Port Otwarty";
polestatusu = SerialPort;
panel1.BackColor = Color.Lime;
guzikpolacz.Enabled = false; //blokujemy przycisk Połącz
guzikrozlacz.Enabled = true;
}
private void guzikrozlacz_Click(object sender, EventArgs e)
{
serialPort1.Close(); //Zamykamy SerialPort
panel1.BackColor = Color.Red;
polestatusu.Text = "Port Zamknięty";
guzikpolacz.Enabled = true; //aktywujemy przycisk Połącz
guzikrozlacz.Enabled = false; // deaktywujemy przycisk Rozłącz
}
private delegate void UpdateUiTextDelegate(string text);
}
}
Thank you very much, but unfortunately it did not work :( The application connects to the serialport but nothing happens. The connection to the Arduino program Putty works.
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
string InputData = String.Empty;
delegate void SetTextCallback(string text);
public Form1()
{
InitializeComponent();
string[] ports = SerialPort.GetPortNames();
Console.WriteLine("The following serial ports were found:");
// Display each port name to the console.
foreach (string port in ports)
{
comboBox1.Items.Add(port);
}
;}
public void guzikpolacz_Click(object sender, EventArgs e)
{
serialPort1.PortName = comboBox1.Text; // Ustawiamy numer Portu COM
// Ustawiamy wartość baudrate portu
//Inne ustawienia zdefiniowane na stałe
serialPort1.Parity = Parity.None; // bez parzystości
serialPort1.StopBits = StopBits.One; // jeden bit stopu
serialPort1.DataBits = 8; // osiem bitów danych
serialPort1.Open();
polestatusu.Text = "Port Otwarty";
panel1.BackColor = Color.Lime;
guzikpolacz.Enabled = false; //blokujemy przycisk Połącz
guzikrozlacz.Enabled = true;
}
private void guzikrozlacz_Click(object sender, EventArgs e)
{
serialPort1.Close(); //Zamykamy SerialPort
panel1.BackColor = Color.Red;
polestatusu.Text = "Port Zamknięty";
guzikpolacz.Enabled = true; //aktywujemy przycisk Połącz
guzikrozlacz.Enabled = false; // deaktywujemy przycisk Rozłącz
}
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() => serialPort1_DataReceived(sender, e)));
}
else
{
var sp = sender as SerialPort;
//this assumes you want the data from the arduino as text.
// you may need to decode it here.
textBox1.Text = sp.ReadExisting();
}
}
private delegate void UpdateUiTextDelegate(string text);
public Delegate myDelegate { get; set; }
}
}
enter image description here
try adding this event handler to your serial port
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (this.InvokeRequired)
{
this.Invoke(new Action(() => serialPort1_DataReceived(sender, e)));
}
else
{
var sp = sender as SerialPort;
//this assumes you want the data from the arduino as text.
// you may need to decode it here.
polestatusu.Text = sp.ReadExisting();
}
}

How to display the data read in DataReceived event handler of serialport

I have the following code which needs the data to be read from port and then display in a textbox. I am using DataReceived event handler for this purpose but donot know how to display this data in textbox. From various sources i learnt that Invoke method should be used for this but donot know how to use it. Suggestions please...
private void Form1_Load(object sender, EventArgs e)
{
//SerialPort mySerialPort = new SerialPort("COM3");
mySerialPort.PortName = "COM3";
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_DataReceived);
mySerialPort.Open();
}
private void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string s= sp.ReadExisting();
// next i want to display the data in s in a textbox. textbox1.text=s gives a cross thread exception
}
private void button1_Click(object sender, EventArgs e)
{
mySerialPort.WriteLine("AT+CMGL=\"ALL\"");
}
The MSDN contains a good article with examples about using control methods and properties from other threads.
In short, what you need is a delegate method that sets the Text property of your text box with a given string. You then call that delegate from within your mySerialPort_DataReceived handler via the TextBox.Invoke() method. Something like this:
public delegate void AddDataDelegate(String myString);
public AddDataDelegate myDelegate;
private void Form1_Load(object sender, EventArgs e)
{
//...
this.myDelegate = new AddDataDelegate(AddDataMethod);
}
public void AddDataMethod(String myString)
{
textbox1.AppendText(myString);
}
private void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string s= sp.ReadExisting();
textbox1.Invoke(this.myDelegate, new Object[] {s});
}
Try this (works for me):
private delegate void UpdateUiTextDelegate(string text);
private void Receive(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
if (mySerialPort.IsOpen)
{
RxString = mySerialPort.ReadLine();
Dispatcher.Invoke(DispatcherPriority.Send, new UpdateUiTextDelegate(DisplayText), RxString);
}
}
private void DisplayText(string RxString)
{
myTextBox.Text = RxString;
}
I'm creating a GUI "Form" for USB COM Ports. This is how I send data to the window without getting a "Cross-Thread" error.
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string inData = serialPort1.ReadLine(); // ReadLine includes the + "\n"
displayToWindow(inData);
}
private void displayToWindow(string inData)
{
BeginInvoke(new EventHandler(delegate
{
richTextBox1.AppendText(inData);
richTextBox1.ScrollToCaret();
}));
}

Categories