I am communicating with a microcontroller on a serial port using Winform GUI, which I am developing.
I am sending a set of commands according to a predefined protocol and receiving feedback strings from the microcontroller.
I am wondering if there is a simple way to wait for a certain feedback after a command is sent.
E.g.
- Send a command
- Wait for a Set Amount of Time (could be a few seconds to several minutes)
- Display the feedback if in time and proceed to issue the next command/action
If the feedback is not received in time, the timeout will be triggered and failure message displayed. If the data comes back in time, the waiting method should be stopped immediately and proceed to the next course of action. I do not want to block the UI while awaiting a feedback as well.
I am using the following code for receiving the data.
delegate void SetTextCallback(string text);
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
string receivedData = serialPort1.ReadExisting();
SetText(receivedData);
}
catch (IOException exception)
{
MessageBox.Show(exception.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception exception)
{
MessageBox.Show(exception.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void SetText(string text)
{
if (this.textBoxReceive.InvokeRequired)
{
SetTextCallback d = SetText;
this.Invoke(d, new object[] { text });
//this.Invoke(new Action(() => { this.textBoxReceive.AppendText(text); }));
}
else
{
if (text.Length > 15)
{
CheckPosition(text); //To check for a position number from the feedback string
}
this.textBoxReceive.AppendText(text);
}
}
And here is my write method.
private void SendCommand(int move, int trigger)
{
try
{
if (serialPort1.IsOpen)
{
string cmd = string.Empty;
//Format: { “move”: 0, “trigger”: 0}
cmd = "{ " + "\"move\": " + move + ","
+ " \"trigger\": " + trigger
+ " }"
+ Environment.NewLine;
textBoxReceive.AppendText("Send:" + cmd + Environment.NewLine); // Display sent command
serialPort1.DiscardOutBuffer();
serialPort1.DiscardInBuffer();
serialPort1.Write(cmd);
}
else if (serialPort1.IsOpen != true)
{
MessageBox.Show(@"Lost COM Port.", "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (IOException e)
{
MessageBox.Show(e.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Message", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
And I have a click-button method which I have been struggling with the delay (///Start waiting) like so.
private void buttonDet_Click(object sender, EventArgs e)
{
ResetPositionMark();
serialPort1.DiscardInBuffer();
//Position 1 at Initial Stage
textBoxStatus.AppendText("Position 1: Init/Home." + Environment.NewLine);
SendCommand(0,1); //Trigger LED1
textBoxStatus.AppendText("LED1 triggered." + Environment.NewLine);
Thread.Sleep(200);
///Camera Capture
//============== Position 2 ==============
SendCommand(2,0); //Move to Position 2
textBoxStatus.AppendText("Moving to Position 2..." + Environment.NewLine);
**///Start waiting**
if (timeout)
{
textBoxStatus.AppendText("Position 2 Timeout reached." + Environment.NewLine);
}
else
{
textBoxStatus.AppendText("Data received in time." + Environment.NewLine);
textBoxStatus.AppendText("Position 2 OK." + Environment.NewLine);
SendCommand(0, 2); //Trigger LED2 once the motor reaches the position 2
textBoxStatus.AppendText("LED2 triggered." + Environment.NewLine);
}
///Camera Capture
//============== Position 3 ==============
SendCommand(3,0); //Move to Position 3
textBoxStatus.AppendText("Moving to Position 3..." + Environment.NewLine);
**///Start waiting**
if (timeout)
{
textBoxStatus.AppendText("Position 3 Timeout reached." + Environment.NewLine);
}
else
{
textBoxStatus.AppendText("Data received in time." + Environment.NewLine);
textBoxStatus.AppendText("Position 3 OK." + Environment.NewLine);
SendCommand(0, 3); //Trigger LED3 once the motor reaches the position 2
textBoxStatus.AppendText("LED3 triggered." + Environment.NewLine);
}
///Camera Capture
SendCommand(1, 0); //Move back to Home position (position 1)
textBoxStatus.AppendText("Moving Home to Position 1..." + Environment.NewLine);
**///Start waiting**
if (timeout)
{
textBoxStatus.AppendText("Back to Home Timeout!" + Environment.NewLine);
}
else
{
textBoxStatus.AppendText("Data received in time." + Environment.NewLine);
textBoxStatus.AppendText("Home now." + Environment.NewLine);
}
}
I am not well-versed with threading and ManualResetEvent, etc.
Please help to see how best to wait for the data, preferably with code samples.
Thanks a lot.