開発中のWinform GUIを使用してシリアルポート上でマイクロコントローラと通信しています。C#serialPort_DataReceivedイベントでフィードバックを待つ
私は、あらかじめ定義されたプロトコルに従って一連のコマンドを送信し、マイクロコントローラからフィードバック文字列を受信しています。
コマンドを送信した後で特定のフィードバックを待つ簡単な方法があるのだろうかと思います。
など。
- 設定した時間のための
- 待ちます(数分、数秒することができる)
- が時間内にあれば、フィードバックを表示し、次のコマンド/アクション
フィードバックが時間内に受信されない場合、タイムアウトが発生し、エラーメッセージが表示されます。データが時間内に戻った場合は、待機方法を直ちに停止し、次のアクション・コースに進む必要があります。私はフィードバックを待っている間にUIをブロックしたくありません。
私はデータを受け取るために次のコードを使用しています。
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);
}
}
これは私の書き込み方法です。
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);
}
}
私は遅延のために苦労しているクリックボタン方式を持っています(///開始待ち)。
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);
}
}
私はスレッドとManualResetEventに精通しておりません、など
コードサンプルで好ましくは、データを待つために最善の方法を確認するために助けてください。
ありがとうございます。ここでのパラメータは、ほとんどのために話している
Task.Factory.StartNew(() => {
}, _canecellationTokenSource.Token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
:によって行われることが 、アイデアはあなたがコマンドの送信を開始するときに別のスレッドを作成することであるhttps://1drv.ms/u/s!AnSTW4R3pQ5uitAnyiAKTscGPHpxYw
:ここ
ありがとう、BerserkerDotNet!これらのマルチスレッドの用語やコンセプトに慣れていないので、どのメソッドが何をしているのか、どのメソッドを呼び出すのか、どのように私のメソッドを変更するのかについて、初心者のレベルまで単純化してください。 – TLT
私は私の答えをより説明するように更新しました。私が提供したソリューションを使用するためのコードを更新するのは難しいことではありません。 DummyMicrocontrollerをあなたの実際のシリアルポート駆動コントローラで置き換えて、手元にあるコマンドの配列を持っていることを考えてください。そうすれば、コードを複製したり、別のコマンドを発行したりする必要がなくなります。 – BerserkerDotNet
私に辛抱強くご指摘いただきありがとうございます。私はあなたからたくさんのことを学んでいます。それは大きく役立ちます。別の質問:ここでのタイムアウトは3秒に固定されています。コマンドを送信する必要がある場合、30分後にPCB/UCレポートが完了した後、私に報告してください。各コマンドによってuCには異なる処理が行われるため、異なる処理には時間がかかります。 – TLT