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;
}
Related
I am trying to retrieve weight data from a weight indicator which sends data through the RS232 com port ( Converted through USB)
following is the application I designed to receive data
enter image description here
the problem is it shows all the data which is sent from the indicator but the real weight reading is 15,000.
How can I achieve this?
Thank you
Data sheet of the indicator is as follows
Code is as follows
namespace Weight_Test
{
public partial class Form1 : Form
{
string dataIN;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] ports = SerialPort.GetPortNames();
cbComPort.Items.AddRange(ports);
btnOpen.Enabled = true;
btnClose.Enabled = false;
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
dataIN = serialPort1.ReadExisting();
this.Invoke(new EventHandler(ShowData));
}
private void ShowData(object sender, EventArgs e)
{
txtWeight.Text = dataIN;
}
private void btnOpen_Click(object sender, EventArgs e)
{
try
{
serialPort1.PortName = cbComPort.Text;
serialPort1.BaudRate = Convert.ToInt32(9600);
serialPort1.DataBits = Convert.ToInt32(8);
serialPort1.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "One");
serialPort1.Parity = (Parity)Enum.Parse(typeof(Parity), "None");
serialPort1.Open();
btnOpen.Enabled = false;
btnClose.Enabled = true;
}
catch (Exception err)
{
MessageBox.Show(err.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
btnOpen.Enabled = true;
btnClose.Enabled = false;
}
}
private void btnClose_Click(object sender, EventArgs e)
{
if (serialPort1.IsOpen)
{
serialPort1.Close();
btnOpen.Enabled = true;
btnClose.Enabled = false;
}
}
}
}
It all seems to work properly. All you need is processing of received data.
You said that your result should be 15,000.
Depends on what sensor you use, it can supply specified resolution, accuracy. Please edit your post and give us some information from datasheet about sending data.
Since you got "+01500001F🥹", it looks like you have 15,000.01, which very is good, but of course I can't be sure.
All you have to do is to process these data. If you have it in string format, you should use Substring method to get rid of decimal places.
For example, with:
string receivedText = DataIN.Substring(0,7);
You'll get "+015000", which you can easily convert to Int32 value, using:
int receivedValue = Convert.ToInt32(receivedText);
And you'll finally get your 15000 as integer.
Okay so I'm trying to do a two-way communication from C# to Arduino (using FTDI232) and viceversa, from Arduino to C#.
Here's the code:
public partial class Form1 : Form
{
public SerialPort myPort;
private DateTime dateTime;
private string inData;
const string com = "COM8";
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e) // TURN ON LED
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
try
{
myPort.Open();
myPort.WriteLine("A");
myPort.Close();
error_tb.Text = "";
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Errore");
}
}
private void stop_btn_Click(object sender, EventArgs e) // TURN OFF LED
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
try
{
myPort.Open();
myPort.WriteLine("B");
myPort.Close();
error_tb.Text = "";
}
catch (Exception exc2)
{
MessageBox.Show(exc2.Message, "Error");
}
}
void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
inData = myPort.ReadLine();
this.Invoke(new EventHandler(displayData_event));
}
private void displayData_event(object sender, EventArgs e)
{
dateTime = DateTime.Now;
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
values_tb.Text = time + "\t\t\t\t\t" + inData;
}
private void Form1_Load(object sender, EventArgs e) // PRESS PHYSICAL BUTTON TO SEND DATA
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
myPort.Parity = Parity.None;
myPort.DataBits = 8;
myPort.StopBits = StopBits.One;
myPort.DataReceived += MyPort_DataReceived;
try
{
myPort.Open();
values_tb.Text = "";
}
catch (Exception exc3)
{
MessageBox.Show(exc3.Message, "Error");
}
}
private void exit_btn_Click(object sender, EventArgs e) // Exit from Application
{
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
}
I have three problems. One is when I want to close the application, I want the Serial Communication to turn off, because I made it automatically open using Form1_Load, as soon as you start the debug, it also opens Serial Communication, and it remains on, but I don't want to use a button that I have to click first to close the application. I need to close Serial Communication automatically after I close the application.
The second problem is with the Serial Port that denies the communication, what I mean is that I need to switch from Receiving Data to Sending Data. Here's a picture of what it looks like: Application Image
The the third problem is the LED one. Well its similar to the second one, but this time when I click the button OFF, I want it to switch back to Receiving Data. Here's the picture:
Application Image 2
EDIT : This code is only temporary. I needed it to turn off the Serial Communication
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
You are initializing and opening the port many times. This is not allowed. Use a single initialization and keep the member. This makes the code much smoother, too.
public partial class Form1 : Form
{
public SerialPort myPort;
private DateTime dateTime;
const string com = "COM8";
public Form1()
{
InitializeComponent();
}
private void start_btn_Click(object sender, EventArgs e) // TURN ON LED
{
try
{
myPort.WriteLine("A");
error_tb.Text = "";
}
catch (Exception exc)
{
MessageBox.Show(exc.Message, "Errore");
}
}
private void stop_btn_Click(object sender, EventArgs e) // TURN OFF LED
{
try
{
myPort.WriteLine("B");
error_tb.Text = "";
}
catch (Exception exc2)
{
MessageBox.Show(exc2.Message, "Error");
}
}
void MyPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var inData = myPort.ReadLine(); // Use local variable
Invoke(new Action<string>(displayData_event), inData);
}
private void displayData_event(string data)
{
dateTime = DateTime.Now;
string time = dateTime.Hour + ":" + dateTime.Minute + ":" + dateTime.Second;
values_tb.Text = time + "\t\t\t\t\t" + data;
}
private void Form1_Load(object sender, EventArgs e) // PRESS PHYSICAL BUTTON TO SEND DATA
{
myPort = new SerialPort();
myPort.BaudRate = 9600;
myPort.PortName = com;
myPort.Parity = Parity.None;
myPort.DataBits = 8;
myPort.StopBits = StopBits.One;
myPort.DataReceived += MyPort_DataReceived;
try
{
myPort.Open();
values_tb.Text = "";
}
catch (Exception exc3)
{
MessageBox.Show(exc3.Message, "Error");
}
}
private void exit_btn_Click(object sender, EventArgs e) // Exit from Application
{
Application.Exit();
}
private void button2_Click(object sender, EventArgs e)
{
try
{
myPort.Close();
myPort = null;
}
catch (Exception exc4)
{
MessageBox.Show(exc4.Message, "Error");
}
}
}
I think I also fixed your event handling. One handler that gets the data and then forwards the received text is enough. You would also not really require the exception handling around WriteLine now, since that cannot really fail.
I'm working on project and I need to create a program that gets data from an Arduino to determine the status all sensors values. I've researched that the best way to send these data is to send them in one line through the serial port and then parse it in Visual Studio. The problem is I don't know how to parse the said data in order for them to show in different text boxes in the program. Any help would be much appreciated...in one textbox am already showing the data but I want to show all sensors values in different textboxes.
namespace Arduino_Data
{
public partial class Form1 : Form
{
private SerialPort myport;
private DateTime datetime;
private string in_data;
public Form1()
{
InitializeComponent();
}
// private void label3_Click(object sender, EventArgs e)
// {
// }
private void satrt_btn_Click(object sender, EventArgs e)
{
myport = new SerialPort();
myport.BaudRate = 9600;
myport.PortName = port_name_tb.Text;
myport.Parity = Parity.None;
myport.DataBits = 8;
myport.StopBits = StopBits.One;
myport.DataReceived += myport_DataReceived;
try{
myport.Open();
data_tb.Text = "";
}
catch (Exception ex)
{
MessageBox.Show(ex.Message , "Error");
}
}
void myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//throw new NotImplementedException();
in_data = myport.ReadLine();
this.Invoke(new EventHandler(displaydata_event));
}
private void displaydata_event(object sender, EventArgs e)
{
// throw new NotImplementedException();
datetime = DateTime.Now;
string time = datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
data_tb.AppendText( time + "\t\t\t"+in_data+"\n");
int data_value = Convert.ToInt32(in_data);
pb_value.Value = data_value;
pb_value.Minimum = 0;
pb_value.Maximum = 1023;
}
private void stop_btn_Click(object sender, EventArgs e)
{
try
{
myport.Close();
}
catch (Exception ex2)
{
MessageBox.Show(ex2.Message, "Error");
}
}
private void save_btn_Click(object sender, EventArgs e)
{
try {
string pathfile = #"C:\Users\irtaz\Desktop\DATA";
string filename = "arduino_data.txt";
System.IO.File.WriteAllText(pathfile + filename, data_tb.Text);
MessageBox.Show("Data has been saved to" + pathfile, "Save File");
}
catch(Exception ex3)
{
MessageBox.Show(ex3.Message, "Error");
}
}
}
}
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...
I have a system that makes a loop on all serial ports and send a command 'at' for them.
These ports return 'ok' in Putty, but in the C# the MessageBox is empty.
Why is this happening?
Putty: http://i.imgur.com/AZY7aRY.png /
C#: http://i.imgur.com/wgGyT2x.png
public partial class Form1 : Form
{
List<SerialPort> serialPort = new List<SerialPort>();
private delegate void SetTextDeleg(string text);
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
var portNames = SerialPort.GetPortNames();
foreach (var port in portNames)
{
SerialPort sp;
sp = new SerialPort(port, 9600, Parity.None, 8, StopBits.One);
sp.Handshake = Handshake.None;
sp.DataReceived += new SerialDataReceivedEventHandler(sp_DataReceived);
sp.ReadTimeout = 500;
sp.WriteTimeout = 500;
serialPort.Add(sp);
listPorts.Items.Add(port);
}
}
private void listPorts_SelectedIndexChanged(object sender, EventArgs e)
{
}
private void button1_Click_1(object sender, EventArgs e)
{
foreach (var sp in serialPort)
{
// Open port
try
{
if (!sp.IsOpen)
sp.Open();
sp.Write("at\r\n");
}
catch (Exception ex)
{
MessageBox.Show("Error opening/writing to serial port :: " + ex.Message, "Error!");
}
}
}
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
SerialPort sp = (SerialPort)sender;
string data = sp.ReadLine();
this.BeginInvoke(new SetTextDeleg(si_DataReceived), new object[] { data });
}
private void si_DataReceived(string data)
{
String retorno = data.Trim();
MessageBox.Show(data);
}
}
Your modem response something like this: \n\rOK\n\r you should read all stream in the buffer or you should read 3 time the serial port buffer with ReadLine() method.