2016-10-17 2 views
2

나는 직렬 포트를 통해 데이터를 1 초에 3 번 출력하는 센서 (실제로 Quartzonix 압력 변환기)를 가지고 있습니다. 샘플의 x- 양을 기준으로 평균 읽기를 제공하는 코드를 설정하고 싶습니다.롤링 평균, vb.net

출력은 다음과 같이 보입니다 :

01+ 1.502347091823e01 
01+ 1.501987234092e01 
01+ 1.50234524524e01 
01+ 1.502123412341e01 
01+ 1.502236234523e01 
01+ 1.50198345e01 
01+ 1.502346234523e01 

.. 및 COM 포트를 닫을 때까지 영원히 계속됩니다 또는 변환기는 다른 명령을 가져옵니다.

은 "$ 01MC"
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click 
    Dim a As String 
    a = "$01MC" & Chr(13) 
    MyComPort.WriteLine(a) 

    Do 
     Dim Incoming As String = MyComPort.ReadLine() 
     Dim incomingtext As String = Incoming.Remove(0, 3) 

     If Incoming Is Nothing Then 
      Exit Do 
     Else 
      txtRawData.Text = Incoming 
      boxPSIA.Text = Format(Val(incomingtext), "##0.000") 

     End If 
     Application.DoEvents() 
    Loop 

End Sub 

이 변환기가 밖으로 뱉어 시작하는 데 필요한 명령입니다

내가 지금까지 가지고 있고, 코드 변환기가 실제로 출력되는 걸 보여주기 위해 작동하는 무슨 코드 데이터. 시작 버튼을 클릭 할 때 몇 가지 이상한 시간 초과 현상이 발생하지만, 다른 프로그램 (어쩌면 .readtimeout 조정이 필요하고, 확실하지 않은 경우)입니다.

나는 평균값으로 읽어야하는 값을 입력하기 위해 텍스트 상자 txtReadingsToAvg가 있습니다. 실제로 평균을 계산하는 방법에 대해 머리를 감싸는 것이 아닙니다. (예를 들어, 버튼을 클릭 한 다음 침을 뱉어 요. 메시지 상자에 넣거나 다른 텍스트 상자에 넣기).

+3

n 개의 판독 값에 대해 대기열 또는 시프트 레지스터 n 요소는 어떻습니까? 새로운 독서가 생길 때마다 대기열에 넣고 가장 오래된 독서가 떨어져 나가십시오. 그런 다음 대기열을 평균화합니다. – peterG

+0

프로그램 시작 후 평균값을 원하십니까? 아니면 센서가 기록을 시작한 후 평균값을 원하십니까? –

+0

아니면 지난 n 초/m 샘플의 평균? – djv

답변

1

코드가 어떻게 작동하는지 잘 모릅니다. 약 3Hz의 값을 얻는다 고하셨습니까? 그렇다면 똑 바른 Do...Loop은 너무 빠를 것입니다. 직렬 포트가 데이터를 수신 할 때 발생하는 이벤트가 있습니다. 그걸 이용하십시오.

당신은 아마 당신의 요구 그런데

' WithEvents allows events to be handled with "Handles" keyword 
Private WithEvents myComPort As SerialPort 
Private dataQueue As Queue(Of Double) 
Private numReadingsToAvg As Integer = 0 

Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click 
    ' make a new queue here to initialize or clear an old queue 
    dataQueue = New Queue(Of Double)() 
    ' read the num avgs text box. you may want to change on the fly also 
    numReadingsToAvg = Integer.Parse(Me.txtReadingsToAvg.Text) 
    myComPort.WriteLine("$01MC" & Chr(13)) 
End Sub 

Private Sub myComPort_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles myComPort.DataReceived 
    Dim incomingLine As String = myComPort.ReadLine() 
    ' DataReceived event happens on its own thread, not the UI 
    ' must invoke call back to UI to change properties of controls 
    txtRawData.Invoke(Sub() txtRawData.Text = incomingLine) 
    Dim incomingValue As String = incomingLine.Remove(0, 3).Trim() 
    If Not String.IsNullOrWhiteSpace(incomingValue) Then 
     Exit Sub 
    Else 
     Dim measurement As Double = Double.Parse(incomingValue) 
     boxPSIA.Invoke(Sub() boxPSIA.Text = Format(measurement, "##0.000")) 
     dataQueue.Enqueue(measurement) 
     ' if there are too many items, remove the last one 
     If dataQueue.Count > numReadingsToAvg Then 
      dataQueue.Dequeue() 
     End If 
     Dim average As Double = dataQueue.Average() 
     ' you need to add this textbox 
     anotherTextBox.Invoke(Sub() anotherTextBox.Text = Format(average, "##0.000")) 
    End If 
End Sub 

, Application.DoEvents() should rarely (never) be used, as there's always a better way to remedy whatever problem you are bandaging with DoEvents에 맞게 약간의 주위에이 설정을 변경해야합니다. 원래의 예제는 UI에서 실행되는 끊이지 않는 루프로 UI 스레드가 막히는 것을 겪었습니다. 이와 같은 루프를 실행해야한다면 UI 스레드와 다른 스레드에서 거의 항상 실행해야합니다. 예제에서는 루프가 없으며 타이밍은 포트 자체에 의해 결정됩니다. UI 스레드에서이 문제가 발생하지 않아도됩니다.

+0

다음에 무엇이 있는지 알려주지 마십시오. 작동하지 않는 것 같습니다. boxPSIA 및 anotherTextBox가 업데이트되지 않습니다. – diashto

+0

디버깅해야합니다. if/then 명령문 위에 boxPSIA.Text = Format (Val (incomingValue), "## 0.000")을 추가하면'Exit Sub'에 중단 점을 놓고'incomingLine'이 – djv

+0

과 같은지 확인하십시오. (그러나 올바른 형식으로) rawdata 텍스트 .. – diashto