2016-08-12 8 views
1

私はシリアルポートへの一定の出力を持つ体重計を持っています。私はスケールで最新の重量を読み取るために3秒ごとにループするアプリケーションを作った。ループはAsync Subを使い、次にAwait Task.Run(Sub()は3秒間スリープする。私は2つの問題を抱えています。COMport.Readline()問題:バッファされたバッファと文字列の操作

最初に、バッファはデータでフラッディングされています。したがって、体重を100ポンドとすると、バッファ内の古いデータを読み込みますが、実際の体重は0です。秒。 Backgroundworkerでreadline()を連続してループしようとしましたが、スケールがまだ高速に出力されています。 readline()の前に 'DiscardBuffer()'を試してください。または別の読書方法がありますか?

コード:COMポートの小道具

With COMScale 'COM Port Properties 

     .PortName = cmbPorts.Text 'COM Port Name 

     .Parity = IO.Ports.Parity.None 

     .DataBits = 8 

     .StopBits = IO.Ports.StopBits.One 

     .BaudRate = 9600 

     .ReceivedBytesThreshold = 1 

     .NewLine = vbCr 

     .ReadTimeout = 5000 

    End With 

コード:BackgroundWorkerの第二の問題は、スケールの出力は、それは次のように好きな文字列である

Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork 

    WeightA = 0 

    COMScale.DiscardInBuffer() 

    Try 

     COMScale.ReadTimeout = 10000 

     Do 

      Dim Incoming As String = COMScale.ReadLine() 

      If Incoming Is Nothing Then 

       Exit Do 

      Else 

       WeightA &= Incoming 

      End If 

     Loop 

    Catch ex As TimeoutException 

     WeightA = "N/A" 

     MsgBox(COMScale.PortName & "Timed Out") 

    Finally 

     'If com1 IsNot Nothing Then com1.Close() 

     lblWeightA.Text = WeightA 

    End Try 

End Sub 

...

"5?" & ChrW(2)& ChrW(2)& "?J" & ChrW(2)& "; 47" & ChrW(2)& ChrW(2)& ChrW(2)& ChrW(2)&「? J」& ChrW(2)& "475" & ChrW(2)& ChrW(2)& ChrW(2)& "?J" & ChrW(2)& "; 475 00"

オンそれは47.5ポンドと言うスケール

私が必要とするのは、最後に「475」という数字がありますが、小数点は47.5です。私が考えることができるのはRight(string)です。Right(String)を使ってみると、それは1000ポンド、100ポンド、10ポンドとなりますので、必要なものを切ることになります。ここで私の最高のオプションは何ですか?

+0

それぞれが読んだ後の読み取りは、キャリッジリターンまたはラインフィードを持っていますか?メッセージ全体を取得してから使用するまで、文字列を作成する必要があります。 datarecievedイベントは多少ランダムに発生し、ときどき文字列全体の一部しか取得できません。ストリームが終了した時点を知るには、charをキーオフしてから使用する必要があります。私は一般にコールバック関数や[代理人](https://msdn.microsoft.com/en-us/library/ms172879.aspx)を使用します。ほとんどの場合、はストリームの終わりを意味し、私はそれをオフにして、応答を処理するために代理関数を起動します。 – Baddack

+0

2番目の部分については、文字 'Split'に対して文字'; 'を実行してください。文字列を各セミコロンの文字列配列に分割し、47500の最後のレコードを解析することができます。スケールのマニュアルを読んでください。その値を解析して1000で割ることができます。 – Baddack

+0

'newline = vbCr'を使うのはそれが何を意味するのでしょうか?新しいシリアルポートを使用しています。私はそれを使用しない場合、表示されるデータはありません。 – holi4683

答えて

0

3秒間スリープする代わりに、アプリケーションを継続的に読み取る必要があります。その後、バッファはいっぱいになりません。

あなたのBackgroundWorkerをループで実行させてください。また、バックグラウンドワーカーのUI要素を変更しないでください。代わりに、ReportProgressを使用してフォームに送信します。

Private Sub BackgroundWorker1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BackgroundWorker1.DoWork 
    COMScale.DiscardInBuffer() 
    Dim buffer As String 
    While e.Cancel = False 

     Try 

      buffer &= COMScale.ReadLine() 

      buffer = ProcessBuffer(buffer) 

     Catch ex As TimeoutException 
      BackgroundWorker1.ReportProgress(0, ex) 
     End Try 

    End While 
End Sub 

Private Sub BackgroundWorker1_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged 
    If TypeOf e.UserState Is TimeoutException Then 
     lblWeightA.Text = "N/A" 
     MessageBox.Show("Timeout") 
    ElseIf TypeOf e.UserState Is Decimal Then 
     lblWeightA.Text = CDec(e.UserState).ToString() 
    End If 
End Sub 

Private Function ProcessBuffer(inputBuffer As String) 
    'Parse your string. Looking for the last occurrence of the data you need. 

    If extractedPortion IsNot Nothing 
     BackgroundWorker1.ReportProgress(0, Decimal.Parse(extractedPortion)) 
    End If 

    Return leftOverChacters 
End Function 
+0

私は仕事に出るときにこの月を試してみます。 – holi4683

+0

ああ、私が3秒待っていた理由は、体重が変化した後に体重を落ち着かせる必要があったからです。 – holi4683

+0

私はあなたのコードとmsdnの間で動作するようにしました。私は、例の中から 'Me。 BackgroundWorker1.RunWorkerAsync(2000) 'バックグラウンドスレッドを開始します。 2000年が何を意味するか知っていますか? – holi4683

関連する問題