エンコーダー (QSB を備えた US デジタル S5 光軸エンコーダー) に接続されたシリアル ポートから読み取る各データ エントリに正確な時間 (ms) を必要とするプロジェクトに取り組んでいます。
エンコーダーを小さなカートに取り付け、カートの速度をカウントするために使用しました。
これが私がこれまでにしたことです:
シリアル ポートに接続し、QSB にコマンドを書き込んで、エンコーダーにデータをストリーミングするように指示します。ここで利用可能なコマンド:
www.usdigital.com/assets/general/QSB%20Commands%20List_1.pdf www.usdigital.com/assets/general/QSB%20Applications%20Examples.pdf
受信したデータを読み取るには、readline() を使用します。
- データのすべての行を 1 つの StringBuilder に入れ、それをファイルに出力します。
出力値のしきい値とインターバル レートをできるだけ速く設定すると、1 ミリ秒の間にデータ エントリを取得できます。これが私が得たものです:
----time stamp(h/m/s/ms)-------value
タイムスタンプが正しいデータ: https://www.dropbox.com/s/pvo1dz56my4o99y/Capture1.JPG
ただし、データが連続している場合は約 200 ミリ秒の突然の「ジャンプ」があります (カートを一定の速度で転がしています)。
タイムスタンプが正しくないデータ: https://www.dropbox.com/s/sz3sxwv4qwsb2cn/Capture2.JPG
これが私のコードです:
private void buttonOpenEncoderPort_Click(object sender, EventArgs e)
{
serialPortEncoder.Write("S0E\r\n");//start streaming data
System.Threading.Thread.Sleep(500);
serialPortEncoder.Write("W0B0\r\n");//set threshold to 0 so the encoder will stream data a the interval I set.
System.Threading.Thread.Sleep(500);
serialPortEncoder.Write("W0C0000\r\n");//set output interval to 0 so it will stream as fast as possible
System.Threading.Thread.Sleep(1500);
backgroundWorkerEncoder.RunWorkerAsync();}
//I am using a background worker to pull data out.
private void backgroundWorkerEncoder_DoWork(object sender, DoWorkEventArgs e)
{
while (serialPortEncoder.IsOpen)
{
if (serialPortEncoder.BytesToRead != 0)
{
try
{
String s = serialPortEncoder.ReadLine();//read from encoder
LazerBucket.Add(getCurrentTimeWithMS(timeEncoder) + "-----" + s + "\r\n");//put one line of data with time stamp in a List<String>
richTextBoxEncoderData.BeginInvoke(new MethodInvoker(delegate()
{
richTextBoxEncoderData.Text = s; })); //update UI
}
catch (Exception ex) { MessageBox.Show(ex.ToString()); }
}
}
}
private String getCurrentTimeWithMS(DateTime d)//to get time
{
StringBuilder s = new StringBuilder();
d = DateTime.Now;
int hour = d.Hour;
int minute = d.Minute;
int second = d.Second;
int ms = d.Millisecond;
s.Append(" ----" + hour.ToString() + ":" + minute.ToString() + ":" + second.ToString() + ":" + ms.ToString());
return s.ToString();
}
誰かがタイムジャンプの原因を見つけることができれば、私はそれを歓迎します. 200ms は無視するには多すぎます。
EDIT:
提案どおり、試してみStopwatch
ましたが、まだ 200ms の遅延があります。しかし、タイムスタンプと BytesToRead を一緒に出力すると、readLine() が実行されているため、バッファ内のデータが減少していることがわかりました。最終的に BytesToRead は 1 桁に低下し、そこで遅延が発生します。スレッドの実装方法に関するより良い解決策を探しています。遅延の説明も。多分私は速く読んでいるので、バッファが私に追いつくことができませんか?
EDIT:
問題が解決しました。以下の私の答えを見てください。でも返信ありがとう。ストップウォッチは本当に役に立ちます。現在、イベント駆動型とポーリングのどちらが優れているかを調べています。