The following code is called several times to read data from a serial port in response to different commands sent to an attached chip & pin terminal.
However it fails to report any further responses after the 1st command.
Although there is data there, for the following commands, is not picked up or read.
How can I fix that?
I'm using ReadExisting serial port property.
private void MySerialReader()
{
ip_serialport.Open();
ip_serialport.DataReceived += serialPort_DataReceived;
//ip_serialport.Close(); //This causes the problems
}
public string RxString;
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
RxString = ip_serialport.ReadExisting();
this.Invoke(new EventHandler(DisplayText_RX)); //<<-- ????!!!
}
private void DisplayText_RX(object sender, EventArgs e)
{
RX_Box.Items.Add(RxString);
}
I think if you use timer then you can read remaining data
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
RxString = ip_serialport.ReadExisting();
this.Invoke(new EventHandler(DisplayText_RX));
}
private void DisplayText_RX(object sender, EventArgs e)
{
RX_Box.Items.Add(RxString);
if(RxString!="")
timer.start();
}
void timer_Tick(object sender, EventArgs e)
{
if(serialport.isopen)//check for open
{
RxString = ip_serialport.ReadExisting();
this.Invoke(new EventHandler(DisplayText_RX));
}
timer.stop();
}
Related
I have a problem with backgroundworker. I wrote program to copying files from local disc to network disk and I want to shows progressbar spinning in circles (not shows progress) when process is running.When I set backgroundworker into empty button everything works fine, but when I set backgroundworker into button which have function to coping files progressbar shows when copying process is finished. Why and how can I solved that? Below code.
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
circularProgressBar1.BeginInvoke(new MethodInvoker(sd));
}
public void sd()
{
circularProgressBar1.Visible = true;
circularProgressBar1.Enabled = true;
circularProgressBar1.Style = ProgressBarStyle.Marquee;
}
private void backgroundWorker1_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
circularProgressBar1.Value = e.ProgressPercentage;
}
private void backgroundWorker1_RunWorkerCompleted(object sender,
RunWorkerCompletedEventArgs e)
{
MessageBox.Show("End");
}
private void button1_Click_1(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void copy_Click(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
List<string> pathList = new List<string>();
// for example add 1000 path
pathList.add("C:\test\2.jpg");
pathList.add("C:\test\3.jpg");
foreach(string in in pathList)
{
File.Copy(in,"D:\test2",true);
}
}
You need to put the File.Copy in backgroundWorker1_DoWork - this is where the background work is done.
You may activate the circularProgressBar before the call to backgroundWorker1.RunWorkerAsync and disable it in backgroundWorker1_RunWorkerCompleted.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace WindowsFormsApp7
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
getavaialbleports();
}
void getavaialbleports()
{
String[] ports = SerialPort.GetPortNames();
comboBox1.Items.AddRange(ports);
}
private void button1_Click(object sender, EventArgs e)
{
try
{
if (comboBox1.Text == "" || comboBox2.Text == "")
{
textBox2.Text = "Please select port settings";
}
else
{
serialPort1.PortName = comboBox1.Text;
serialPort1.BaudRate = Convert.ToInt32(comboBox2.Text);
serialPort1.Open();
button1.Enabled = false;
}
}
catch(UnauthorizedAccessException)
{
textBox2.Text = "Unauthorised Access";
}
}
private void button2_Click(object sender, EventArgs e)
{
serialPort1.Close();
}
private void button3_Click(object sender, EventArgs e)
{
serialPort1.WriteLine(textBox1.Text);
textBox1.Text = "";
}
private void button4_Click(object sender, EventArgs e)
{
richTextBox1.Text = serialPort1.ReadLine();
}
}
}
I'm able to send data from the above code but for reception I'm not able to read data from it. There are no build errors. Please help me out to solve this problem.
You can implement "SerialPortDataReceivedEvent" to read data from serial port.
Before opening connection to serial port register with "DataReceivedEvent", Inside
button1_Click event add below code.
serialPort1.DataReceived += new SerialDataReceivedEventHandler(mySerialPort_DataReceived);
Then add below event handler
private static void mySerialPort_DataReceived(
object sender,
SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
//data received on serial port is asssigned to "indata" string
//Console.WriteLine("Received data:");
//Console.Write(indata);
}
Also, try to configure other properties like Parity, StopBits, DataBits etc. similar to the device on other end (with which you are trying to communicate).
Update data on UI:
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_DataReceivedhandler 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 indata = sp.ReadExisting();
textbox1.Invoke(this.myDelegate, new Object[] {indata});
}
Let us know if you need further clarification.
Hope this helps..
In my opinion, first just try test, when initing serial port add
serialPort1.DataReceived += new
SerialDataReceivedEventHandler(port_DataReceived);
private void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int bytesToRead = serialPort1.BytesToRead;
System.Diagnostics.Debug.WriteLine(bytesToRead);
}
after that in Output window you will sea is there any data in port or not
I'm currently working on a C# application and where I read Serial Data send through the USB port, where this data is to be shown on a textbox then eventually into a database. The code I have right now has it refresh to read serial data coming in every 2 seconds, but I cannot get the data onto the textBox. I'm fairly new to C# development so I am unsure as to what the best way to output my data onto a textbox or how to fix my problem in the first place. My code is below.
public partial class Form1 : Form
{
SerialPort mySerialPort = new SerialPort("COM3");
OleDbConnection connection = new OleDbConnection();
public Form1()
{
InitializeComponent();
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
mySerialPort.BaudRate = 9600;
mySerialPort.Parity = Parity.None;
mySerialPort.StopBits = StopBits.One;
mySerialPort.DataBits = 8;
mySerialPort.Handshake = Handshake.None;
mySerialPort.RtsEnable = true;
mySerialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
if (mySerialPort.IsOpen == false)
{
mySerialPort.Open();
}
}
public void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
//gets data values from serial port
SerialPort sp = (SerialPort)sender;
string data = sp.ReadExisting();
string time = GetTimestamp(DateTime.Now);
int indata;
long timeStamp;
//parses strings to integers
indata = Int32.Parse(data);
timeStamp = Int64.Parse(time);
//writes to console
Console.WriteLine(indata);
Console.WriteLine(timeStamp);
//writes to text box
textBox1.Text = data;
Thread.Sleep(2000);
}
private void button3_Click(object sender, EventArgs e)
{
mySerialPort.Close();
}
private void label1_Click(object sender, EventArgs e)
{
}
public static string GetTimestamp(DateTime value)
{
return value.ToString("yyyyMMddHHmmss");
}
private void label1_Click_1(object sender, EventArgs e)
{
}
}
The event DataReceived is handled with the method DataReceivedHandler on a different thread than the control textBox1 is created. So when running your program you should have get a System.InvalidOperationException. Which states exactly what I just described.
To get out of this dilemma you can use the Control.BeginInvoke method which would:
Execute the specified delegate asynchronously on the thread that the control's underlying handle was created on.
Basically it would drag the piece of code down to the thread that cretated the control. In this case the main thread. This is how you would use it:
//writes to text box
textBox1.BeginInvoke(new Action(() => { textBox1.Text = data; }));
I hope it helps.
I'm developing an application which communicates with my electronic circuit via Port 4. I can send data from the PC to the circuit without a problem; I then get data back from the circuit. However, when I try to get data from my circuit for the second time, I receive incorrect data from it. Any pointers on how to solve this?
This is C# code:
byte[] Sent_Byte = {1,2,3,4,5,6};
byte[] Received_Byte = new byte[10];
private void button_sendData_Click(object sender, EventArgs e)
{
// I send this data because the circuit is ready to get data
serialPort1.Write("G");
serialPort1.Write(Sent_Byte, 0, 6);
}
private void button_getData_Click(object sender, EventArgs e)
{
// I send this data because the circuit is ready to send data
serialPort1.Write("A");
}
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
serialPort1.Read(Received_Byte, 0, 10);
}
This is Arduino code:
char Control_OP=0;
char Received_Data[6];
byte Sent_Data[10];
void loop()
{
while(Serial.available())
{
Control_OP = Serial.read(); // determines whether receiving data or sending data
if(Control_OP=='G') // receiving data
{
Number=Serial.readBytes(Received_Data,6);
}
else if(Control_OP=='A') // sending data
{
Serial.write(Sent_Data,10);
}
}
}
I found the solution.
I changed this code
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
serialPort1.Read(Received_Byte, 0, 10);
}
into this one
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
for (int i = 0; i <Received_Byte.Length; i++)
{
Received_Byte[i] = Convert.ToByte(serialPort1.ReadByte());
}
}
Thanks everyone for helping me
I have two Arduinos that allow messages exchange via Serial Port using Serial Monitor.
If I use Serial Monitor in both sides everything works fine. If I use my C# application nothing happens. I tried to send from Serial Monitor for C# App and it works but not the reverse.
// ...
comPort1.Open();
// ...
private void comPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.Invoke(new EventHandler(processData));
}
private void processData(object sender, EventArgs e)
{
string inData = comPort1.ReadExisting();
msgBoxLog.AppendText(inData);
}
// ...
private void sendButton_Click(object sender, EventArgs e)
{
string my_str = "my string";
msgBoxLog.AppendText(msgBox.Text + my_str);
comPort1.Write(msgBox.Text);
}
RtsEnable and DtrEnable are both Enabled
Well, with Console.Write(msgBox.Text); I realized it was just a silly problem, I was not sending msgBox.Text as I wanted. It should be:
private void sendButton_Click(object sender, EventArgs e)
{
string my_str = "my string";
comPort1.Write(msgBox.Text); //Console.Write(msgBox.Text);
msgBoxLog.AppendText(msgBox.Text + my_str);
}