Reading any string coming from Arduino - c#

I am developing an application to read data through Serial Port. What I am trying to read is a string that could be empty or with something in it.
My first attempt was creating an array where inside of it I would be able to insert what could come from Serial Port.
string[] pass = new string[4];
pass[0] = "";
pass[1] = "Something";
pass[2] = "To";
pass[3] = "Read";
for (int i = 0; i < pass.Length; i++)
{
string element = pass[i];
}
But this isn't work for me because I wanna read any thing from the Serial port.
In the next option, in the data.ToString() == "Any string I want".
string data = serPort.ReadExisting();
if (data.ToString() == "Any string I want")
{
Environment.Exit(0);
}
Basically, instead of the "Any string I want" I would like to every time I send something through the Arduino it will be recognized by the application.
Do you guys have any suggestions about this? In other words, if the incoming data is equal to the string written by the Arduino it will do something.

You need to decide on a termination char and add it to your arduino code that is sending the serial string and look for that char in the incoming data. I'm using carriage Return line feed.
private string receivedDate = string.Empty;
private System.IO.Ports.SerialPort mport;
private void Form1_Load(object sender, EventArgs e)
{
mport = new SerialPort("COM1", 9600, Parity.None,8, StopBits.One);
mport.DataReceived += new SerialDataReceivedEventHandler(mport_DataReceived);
}
private void mport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
receivedDate += mport.ReadExisting();
if (receivedDate.Contains("\r\n"))
{
//show data
//Clear receivedDate
}
}

Related

Is there code to receive data from a serial port?

I am working on a program that receives data from a serial port and displays this on a GUI. I am very new to C# and this is a part of a project I am working on. I have tried to look for code for the past few weeks and watched every tutorial on this matter, all to fail. I am still very new to programming and OOP.
The issue I am having is that the received data is not being pasted in the display box. I have verified that the serial port works using Putty so that cannot be the issue.
Edit: Quick update, upon learning how to use the meter I am working with and closer inspection of the user manual, I discovered that I was able to connect to the meter using serialportname.open(). The issue was that I was not requesting data. For example, by writing "READ?" into the meter, a reading would be returned.
I see that you're not using the DataReceived event.
It could be an approach to what you're trying to achieve; it will trigger each time your serial port receives data, so you could use it to insert into the textbox1
private void serialPort1_DataReceived(object sender,SerialDataReceivedEventArgs e)
{
string Data= serialPort1.ReadLine();
displayToTxt(Data);
}
private void displayToTxt(string Data)
{
BeginInvoke(new EventHandler(delegate
{
textBox1.AppendText(Data);
}));
}
I used delegate to avoid thread errors.
first you need to add EventHandler
SerialPort1.DataReceived += new SerialDataReceivedEventHandler(ReceiveData);
then get data and update UI
public void ReceiveData(object sender, SerialDataReceivedEventArgs e)
{
System.Threading.Thread.Sleep(30);
SerialPort _SerialPort = (SerialPort)sender;
int _bytesToRead = _SerialPort.BytesToRead;
byte[] recvData = new byte[_bytesToRead];
_SerialPort.Read(recvData, 0, _bytesToRead);
this.BeginInvoke(new SetTextDeleg(UpdateUI), new object[] { recvData });
}
private void UpdateUI(byte[] data)
{
string str = BitConverter.ToString(data);
textBox1.Text += str;
}
I know this is old. But since it is still showing up in searches, I thought I would add my answer.
As mentioned in another answer, you need to assign a handler to the serial port.
public void OpenPorts()
{
foreach (string nm in SerialPort.GetPortNames())
{
SerialPort sp = new()
{
PortName = nm,
ReadBufferSize = 2048,
DiscardNull = true,
RtsEnable = true,
DtrEnable = true,
ReceivedBytesThreshold = 1
};
try
{
//This should throw an exception if the port is already open.
sp.Open();
sp.DataReceived += DataReceived;
//Make sure the buffer is empty
if (sp.BytesToRead != 0)
{
sp.DiscardInBuffer();
}
}
catch (Exception ex)
{
//Handle the exception here
}
}
public void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
while ((sender as SerialPort).BytesToRead > 0)
{
SerialBuffer += (sender as SerialPort).ReadExisting();
}
(sender as SerialPort).DiscardInBuffer();
}
catch (InvalidOperationException ex)
{
_ = MessageBox.Show("exception thrown at DataReceived.", "Crashed", MessageBoxButton.OK, MessageBoxImage.Information);
}
}

Livechart WPF, how to read serial input (C#)

I've been trying to get a live updating chart to work with WPF using livecharts, my goal is to have a chart update as it reads a serial input from an Arduino that just gives some numbers.
Using this example: https://lvcharts.net/App/examples/v1/wpf/Constant%20Changes
Although the example includes a built in randomizer of numbers, I want to switch that out for the Arduino serial input.
I read the serial input like this:
private void Button_Serial_Click(object sender, EventArgs e)
{
Thread thread = new Thread(SerialThread);
thread.Start();
}
static SerialPort _serialPort;
private void SerialThread() //serial thread starts here
{
_serialPort = new SerialPort();
_serialPort.PortName = "COM3";//Set your board COM
_serialPort.BaudRate = 9600;
try
{
_serialPort.Open();
}
catch (Exception e)
{
Console.WriteLine("could not connect to serial");
}
while (true)
{
string serialMSG = _serialPort.ReadExisting();
Console.WriteLine(serialMSG);
Thread.Sleep(200);
}
}
My problem is that I don't know what code to switch out for it to read the serial instead of the built in randomizer the example uses. The example has no usable comments or explanation of how it works and my inexperience with coding makes me unable to understand it fully.
I've looked at similar issues, but most just say to read through livechart examples. Well I did, but I do not understand it enough still.
Any assistance is appreciated.
Instead of while(true), you should let c# you decided when data
class Program
{
private static SerialPort port = new SerialPort("COM3",
9600, Parity.None, 8, StopBits.One);
private static ChartValues<MeasureModel> _chartValues;
static void Main(string[] args)
{
SerialPortWorker();
Console.Read();
}
private static void SerialPortWorker()
{
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived); //called when the data waiting in the buffer
port.Open(); //// Begin communications
Console.ReadLine(); // keep console thread alive
}
private static void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if(port.BytesToWrite > 0)
{
var data = port.ReadExisting(); //read incoming data
_chartValues.Add(new MeasureModel
{
DateTime = DateTime.Now,
Value = data
});
SetAxisLimits(now);
//lets only use the last 150 values
if (ChartValues.Count > 150) ChartValues.RemoveAt(0);
}
}
}
class MeasureModel
{
public DateTime DateTime { get; set; }
public String Value { get; set; }
}

Get input from serial port (RS-232)

im writing a program which reads the input from the serial port. It does recieve something but its breaking the line without reason.
The right input
This right inout should be
Sending...Sending...Sending...Sending...Sending...
Without changing line.
The actual input
Sending...
Se
ndin
g...
S
endi
ng..
.
Send
ing.
..
Se
ndin
g...
The code
public void Serial ()
{
try
{
SerialPort serial = new SerialPort(this.comboBox1.Text);
serial.BaudRate = 9600;
serial.Parity = Parity.None;
serial.StopBits = StopBits.One;
serial.DataBits = 8;
serial.Handshake = Handshake.None;
serial.DataReceived += new SerialDataReceivedEventHandler(SerialDataReceivedHandler);
serial.Open();
}
catch
{
}
}
public void SerialDataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string dataIn = sp.ReadExisting();
if (log_time == true)
{
this.richTextBox1.AppendText(time + dataIn);
}
else
{
this.richTextBox1.AppendText(dataIn + "\n");
}
}
The this.combobox1.Text is working fine, im using try because if not the program would crash if the serial port wasnt on!
Im initializing the serial on an other void with Serial();
How can i get the right input?
In your else clause, you should not append "\n" to this.richTextBox1. That is the special character for a new line. If you want the right input, need something like this.richTextBox1.AppendText(dataIn + "...");

Why won't my AT Command read SMS messages?

I'm attempting to write a program which would enable texts to be sent out to customers, I'm using AT Commands with a GSM modem to accomplish this, I have looked at various bits of Documentation but have been unable to find a solution for the following problem.
I am attempting to make the GSM modem return all of the text messages contained within its memory, I have tried many combinations of AT Commands and Parsing techniques to throw this into a text box, but to no avail.
Any help on this would be most appreciated, my code is below
private SerialPort _serialPort2 = new SerialPort("COM3", 115200);
private void MailBox_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
_serialPort2.Open();
//_serialPort2.Write("AT+CMGF=1 \r");
_serialPort2.Write("AT+CMGL=\"ALL\"");
string SerialData = _serialPort2.ReadExisting();
var getnumbers = new string((from s in SerialData where char.IsDigit(s) select s).ToArray());
var getText = SerialData;
SendTxt.Text = getnumbers;
SendMsgBox.Text = getText;
//for (int i = 0; i < SerialData.Length; i++ )
//{
// if (char.IsDigit(SerialData))
//}
//.Text = _serialPort2.ReadExisting();
//string[] text = { textBox1.Text };
//IEnumerable<string> formattext = from words in text where words.("+447") select words;
// foreach (var word in formattext)
//{
//SenderBox.Items.Add(word.ToString());
// }
_serialPort2.Close();
//_serialPort2.DataReceived += new SerialDataReceivedEventHandler(_serialPort2_DataReceived);
}

Multiple Serial Ports in C# / Trouble using List <>

I have a system that sends an "at" command to a serial port and displays the return on a MessageBox.
But I needed to do this in all available serial ports. So I created a List and I'm adding all the ports on it.
I managed to send the command, but could not continue the rest of the code to catch the return because I am having trouble handling the lists. I am a beginner in C #.
Below is my current code.
The part that is commented out is what I'm struggling to continue.
This part belongs to the old code (when it was just one serial port).
public partial class Form1 : Form
{
List<SerialPort> serialPort = new List<SerialPort>();
// delegate is used to write to a UI control from a non-UI thread
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, 19200, 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(object sender, EventArgs e)
{
foreach (var sp in serialPort) {
// Open port
try
{
if (!sp.IsOpen)
sp.Open();
MessageBox.Show(sp.PortName + " aberto!");
sp.Write("at\r\n");
}
catch (Exception ex)
{
MessageBox.Show("Error opening/writing to serial port :: " + ex.Message, "Error!");
}
}
}
/* HELP START
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
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(retorno);
// Fecha a porta após pegar o retorno
sp.Close();
}
HELP END */
}
What to put in place 'sp.ReadLine ();' and 'sp.Close ();'?
I don't know do this because of the List <>
The simplest approach would be to use a lambda expression which would capture the port you're using. A lambda expression is a way of building a delegate "inline" - and one which is able to use the local variables from the method you declare it in.
For example:
foreach (var port in portNames)
{
// Object initializer to simplify setting properties
SerialPort sp = new SerialPort(port, 19200, Parity.None, 8, StopBits.One)
{
Handshake = Hanshake.None,
ReadTimeout = 500,
WriteTimeout = 500
};
sp.DataReceived += (sender, args) =>
{
Thread.Sleep(500); // Not sure you need this...
string data = sp.ReadLine();
Action action = () => {
MessageBox.Show(data.Trim());
sp.Close();
};
BeginInvoke(action);
};
serialPort.Add(sp);
listPorts.Items.Add(port);
}
A few notes about this:
Just because some data has been received doesn't mean that a whole line has, so ReadLine may still block
If you only need to show a message box, you may not need Control.BeginInvoke. (If you need to do more here, you might want to extract most of that code into a separate method which just takes a string, then create an action which would call that method.)
Are you sure you want to close the serial port as soon as the first line has been received?
You can chage your sp_DataReceived method as,
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 });
sp.Close();
}
and remove the sp.Close(); from si_DataReceived method.
If you want to have a Serial port value in your si_DataReceived method,
you should pass it there:
// First, add port into your delegate
private delegate void SetTextDeleg(SerialPort port, string text);
...
/* HELP START */
void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
SerialPort sp = (SerialPort) sender; // <- Obtain the serial port
string data = sp.ReadLine();
// Pass the serial port into si_DataReceived: SetTextDeleg(sp, ...
this.BeginInvoke(new SetTextDeleg(sp, si_DataReceived), new object[] { data });
}
// "SerialPort sp" is added
private void si_DataReceived(SerialPort sp, string data) {
String retorno = data.Trim();
MessageBox.Show(retorno);
// Fecha a porta após pegar o retorno
sp.Close();
}
/* HELP END */
See also:
http://msdn.microsoft.com/library/system.io.ports.serialport.datareceived.aspx

Categories

Resources