I am using an RFID device to read the data from it. After receiving the data from it I am using it in Visual Studio 2008. I use data-receive event of serial port and timer to get data.
The problem is when I get the RFID data and try to put it in a text field on the data receive event.
Continuously getting data because timer is continuously checking the data and putting this in text box. That's why my back end query is always running and inserting the same data continuously. I want to stop the timer and serial port and then want to open the serial again without closing and opening the form again. Is there any other way to get the data from serial port except timer, and after getting data it stop itself..
Here is my code:
private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
//Serialtimer.Start();
if (sp.IsOpen)
{
data = sp.ReadExisting();
RFIDtB.Text = data;
}
else
{
MessageBox.Show("Please Check the device");
}
}
You can't access form controls from other threads than the UI thread. See this article: http://msdn.microsoft.com/en-us/library/ms171728.aspx for the solution.
Related
I am working on making GUI for a Smart Water flow meter whose communication protocol is RS485,
as per instructions from Communication Manual i am sending an inquiry packet and i am receiving proper response in serial port terminal. But when i am trying to do it on my C# app.
Things are happening oppositely.
string data = "[H201815000081]";
private void button1_Click(object sender, EventArgs e)
{
serialPort1.Write(data);
incoming_data = serialPort1.ReadExisting();
text_reciever.Text = incoming_data;
}
// text_reciver is the text box of my gui where i want to display the
// values from flow meter.Data Type of incoming_data is string
Here is the code, i am sending an inquiry code to the device and in return i am getting garbage values on my text box. Some times it is stream of Question mark symbol (?), some time it shows nothing.
But when i revert myself to serial port terminal (Real Term).
It is showing proper values as mentioned in communication manual.
Please assist in this regards.
After looking around i just found the answer to my question.
The point is previously i was communicating with serial port teminal, where everything was working fine, but when it comes to interacting with peripherals one need to make sure that Serialport.DTRProperty is enabled.
When opening the serial port one must enable the DTR property by:
serialPort1.DtrEnable = true;
Otherwise the windows form will read the garbage value.
the incoming data would be serial number of device (ASCII Format) and Water flow values
The problem is complicated, and my code is large, but let me try to explain it.
See the code below:
private void button13_Click(object sender, EventArgs e)
{
serialPort1.Write("0800"); // Write to serial port for reading
Thread.Sleep(1);
serialPort1.Write("0800"); // Write to serial port for reading
in_data = serialPort1.ReadLine();
textBox7.Text = in_data;
Console.WriteLine(in_data);
in_data = "";
serialPort1.DiscardInBuffer();
serialPort1.DiscardOutBuffer();
}
Let me explain it:
I implemented a button in C# form. When i press the button, it sends 0800 towards an arduino through serialPort1. It sends it two times. After each command sent, Arduino writes to serial port through Serial.println(receivedData, HEX). This data from Arduino is read by C#(the function above through in_data = serialPort1.ReadLine() line and is displayed in textBox7. In last of the function, I am clearing both buffers.
The problem however is, whenever I am pressing this button, some new data is being display in textbox.
And I don't understand the reason, because the circuit connected to arduino should always respond with same code. I have tested the circuit with other fixtures, and otherwise that circuit is working fine.
Writing into serialport is working just fine. For example this function:
private void button6_Click(object sender, EventArgs e)
{
serialPort1.Write("EXTADC"); // Write to serial port
Console.WriteLine("EXTADC");
}
Please note: sending two commands each time is necessary in order to get the desired output from the circuit. Also, I am pretty new to Arduino and C# (you might be having an idea from my post).
I need to read data from COM port. The data comes from Arduino, it needs to be parsed by the C# program and do certain things on the host PC. I can read the data, but only with endless "while true" loop. which is blocking the form and other tasks to be executed. So currently it looks like that:
while (true) {
oneLine = myPort.ReadLine();
this.Invoke(new EventHandler(display_data_Event));
// TBD: add analysis of data from port
// TBD: execute according to data from Arduino
}
the handler:
private void display_data_Event(object sender, EventArgs e)
{
string curr_time = DateTime.Now.ToString("h:mm:ss tt");
port_in_TextBox.AppendText(curr_time + " " + oneLine + "\n");
}
So I can display the data to a textbox, but not use it with my main program.
How can I use the "one line" string only when the event occurs, instead of the "while true"?
I tried calling functions from the handler - I guess it failed because it is another thread. So perhaps the problem is how to share the string from one thread to another.
I am lost, here is the core program:
https://learn.microsoft.com/en-us/dotnet/api/system.io.ports.serialport.datareceived?view=netframework-4.8
Now, the question is do you need one input or many. If the former, add AutoResetEvent so the main program will be blocked, and reading the data will signal it to unblock. Or if there are many lines add your "main" action in the event just after you read each line.
For my project I need to communicate with an Cypress PSoC5. I can use a serial connection or a USB HID connection.
I created a C# project for sending and reading data to/from PSoC5. Right now I'm using the ReceivedData event of the serialport to get notified if there is new data. Basically my project can either receive a datastream that should be plotted in realtime or just some settings I want to update within the GUI.
Right now I face the problem that the ReceivedData event fires very often (every 32 bytes), which is of course not good when there is a datastream. Basically I receive 24000 bytes per second if I get data for the plot. I know I can adjust the ReceivedBytesThreshold, but then I will not get an event for data below the threshold.
Can anyone tell if there is an approach to handle this?
Would it be an advantage to use the PSoC5 as a HID device instead?
By default SerialPort.ReadBufferSize is set to 4096 bytes. Slighly more info here. But you can easily change it to accomodate necessary amount of data. Then in DataReceived event handler do something like this
static void Serial_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (Serial.BytesToRead < 24000) return;
... //Recieve and process your data here
}
24000 is given here for example.
I have a C# program that reads from two serial ports at the same time. The serial port device is a Prolific USD to 4 serial ports adapter and I plug the two hardware on separate ports of the adapter. The problem is when I read from each port one at a time, everything works fine but when I try to read from both ports at the same time, one of the port is not responding. To troubleshoot the problem, I started two instances of the application and was able to read from the two ports at a time (one from each instance of the application). Does anyone know how to read from two separate serial ports in one application at the same time? Thank you.
Adding some codes:
Port 1:
// button to start or stop reading from port 1. Because the hardware requires me to write to it before reading the response, the writing is done in the timer
private void buttonPort1_Click(object sender, EventArgs e)
{
if (buttonPort1.Text == "Start Recording")
{
if (!port1.IsOpen)
{
port1.Open();
}
timerPort1.Start();
buttonPort1.Text = "Stop Recording";
}
else
{
timerPort1.Stop();
buttonPort1.Text = "Start Recording";
}
}
// Write "D" to the hardware each time to receive back the response
private void timerPort1_Tick(object sender, EventArgs e)
{
port1.Write("D");
}
void port1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string result = port1.ReadLine();
oneParamDelegate dg = PHandCondResult; // send back the result to the main thread
this.Invoke(dg, result);
}
catch
{
}
}
Port 2
The code for the second port is similar to the above really, the difference being different port, datareceived event and timer.
I'll try the multiple thread options suggested by Grant Thomas: I didn't try this before because I thought serial ports are already working on separate threads: the datareceived event doesn't block the main thread and you can't access controls created on the main thread but I'll still give it a go using background worker and revert back later. Thank you all for the quick response.
You're going to need to do some reading, specifically on Threading.
If you have, say, some code that looks like this:
ReadDataFromSomePort();
ReadDataFromSomeOtherPort();
Then the first will execute synchronously (blocking) and then the latter. This happens on the same thread, the main application thread. When you want to do asynchronous things, including just doing one thing while keeping a UI interactive/responsive, then you need to delegate work to other threads.
So, you end up with something like this:
var thread1 = new Thread(ReadDataFromSomePort);
var thread2 = new Thread(ReadDataFromSomeOtherPort);
thread1.Start();
thread2.Start();
There's more to it than this, rest assured, so I recommend some research on the concept before proceeding.
MSDN has a tutorial/programming reference for threading that should get you started.
Creating two different objects of SerialPort and different DataReceived events for both should work.