【VB.NET】リアルタイムグラフ第二弾<折れ線>

リアルタイムグラフの使い勝手と見栄えを改良してます。
前回は、点プロットでしたが、線プロットに変更しました。
※2022年4月追記 本記事から1年半後、リアルタイムグラフテクニックも向上しました。
①2020年から2021年春までのグラフは、PictureBoxに直接プロットしていたのですが、それだとPCのグラフィック性能次第(Corei5のノートPCだと50msec周期程度までしか応答しない)
動くグラフカーソル付きグラフだともっと遅くてまともに動かないとか、不自由があります。入門では、PictureBoxに直接書き込む方式で練習を積んで、次から下記②のBITMAP書きこみ方式に進まれると良いです
②2021年夏からリアルタイムデータを一旦大きなBitMapメモリーの書き込んでから、メモリをDISPLAYに一括表示する方式に変更してから、ダイナミックに動くグラフ、拡大縮小が自在、カーソルの動作とデータ表示の自由度を獲得できました。シリーズで10記事ほどありますが、一番基本は下記記事です。

【VB.NET】リアルタイムグラフのBITMAP展開<その1小技在り>



●グラフ調整機能追加
オフセットと倍率を各CHで調整できるようにしました
ボタン6個TextBox19個ComboBox7個チェックボックス7個
Label3個 



■プログラムデバッグ中
課題1:BMオプションでLatency1msecにしてあるのですが、リアルタイムから0.1秒くらい遅れが発生しているような感じがします。

 

 

課題2:調整機能が未だ使いにくいので、自動化をしないと実用にならない

とりあえず、デバッグのコードGISTにアップしておきます。
部分的にご参考にしてください。
PlotCメソッドをLINE用に変更してあります。
https://gist.github.com/dj1711572002/9cbd515f02dd83bc291f69892b9ae884

 

‘Seril Port Recieve Sample Program
‘Form1 Object must create ,button1,2 & textbox 1,2Imports System.Drawing
Imports System.IO.PortsPublic Class Form1Private onetime As Integer = 1
Delegate Sub DataDelegate(ByVal sdata As String)
‘=========Available Parameters in thie Calss=================
Private dataAry(600000, 7) As Long
Private dataNo As Long
‘———Plotting parameters————–
Private xw As Integer = 600 ‘picturebox image width
Private yh As Integer = 240 ‘picturebox image height
Private rate() As DoublePrivate midvalue() As Double
‘—————————————–
Private Mave() As Double
Private sw As New System.Diagnostics.Stopwatch()
Private tp As TimeSpan
Private timestamp As Integer
Private stime As Integer ‘plot start sampling time
Private etime As Integer ‘plot end sampling time
Private totalsec As Double
Private startFlag As Integer = 0
Private px As Integer
Private py As Integer
Private px_1 As Integer
Private py_1 As Integer ‘1個前のY座標
‘=============================================================
Private Sub PrintData(ByVal sdata As String)Dim delimiter As String = “,”
Dim i As Integer
Dim dcount As String’TextBox1.text=sdata
If startFlag = 1 Then
‘dcount = sdata & “:” & TextBox2.Text
‘ListBox1.Items.Add(dcount)
‘Debug.Print(“sdata=” & sdata)
‘Debug.Print(“timestamp=” & CStr(timestamp))
Dim dStr() As String = Split(sdata, delimiter, -1, CompareMethod.Text)
Dim colN As Integer
colN = 7
‘Debug.Print(“dStr(0)=” & CStr(dStr(0)))
If (dStr.Length = 7) Then
dataNo += 1
‘dStr(0) = dataNo
For i = 0 To dStr.Length – 1
dataAry(dataNo, i) = CInt(dStr(i))
‘=================PLOT SUBへ=================
If i < 6 Then
plotC(dataNo, dataAry(dataNo, i), dataAry(dataNo – 1, i), i) ‘plotC(x,y,colorN)
Debug.Print(“dataAry()=” & CStr(dataAry(dataNo, i)) & “i=” & CStr(i))
End If
‘===========================================
NextTextBox2.Text = dataNo
‘TextBox3.Text = dStr.Length
‘TextBox4.Text = dStr(0)
‘TextBox5.Text = dStr(1)
‘TextBox6.Text = dStr(2)
‘TextBox7.Text = dStr(3)
‘TextBox8.Text = dStr(4)
‘TextBox9.Text = dStr(5)
‘TextBox10.Text = dStr(6)
‘Debug.Print(“dataAry(” & CStr(dataNo) & “,” & CStr(i) & “)=” & CStr(dataAry(dataNo, i)))End IfEnd If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
SerialPort1.PortName = TextBox1.Text ‘オープンするポート名を格納
SerialPort1.Open() ‘ポートオープン
Label2.Text = “OPENED”
End Sub

Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Label2.Text = “Program STOPPED”
If SerialPort1.IsOpen = True Then ‘ポートオープン済み
SerialPort1.Close() ‘ポートクローズ

End If

End Sub

Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
Dim ReceivedData As String = ” ” ‘受信データ用変数を宣言します

Try

ReceivedData = SerialPort1.ReadLine ‘データを受信します

Catch ex As Exception
ReceivedData = ex.Message ‘例外処理を行います

End Try
‘Invokeメソッドにより実行されるメソッドへのデリゲートの宣言を行い、受信データを表示します
Dim adre As New DataDelegate(AddressOf PrintData)
Me.Invoke(adre, ReceivedData)

End Sub

‘===============Sampling Start=======================
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
If startFlag = 0 Then
startFlag = 1
End If

End Sub
‘===============Sampling STOp===================================
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
If startFlag = 1 Then
startFlag = 0
End If
End Sub
‘================================メソッドPlotc()===================================================
‘===========-PLOT パラメータの定義 計算方式===================================================
‘===========ゼロレベルでデフォルト平均値(1650mV)をとってCenteringを実施してY軸中心にそろえる===============
‘===========負荷をいれながらrate値(ドット/mV)を手動で変えて最適値にセット========================
‘==========================================================================================
Sub plotC(ByVal dataNo As Integer, ByVal value As Integer, ByVal value_1 As Integer, ByVal colorN As Integer)
If PictureBox1.Image Is Nothing Then ‘初回だけBITMAPを定義する Picture1.imageという名称をつかうこと
PictureBox1.Image = New Bitmap(600, 240)
End If
Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)

‘==============Text Box Value Reading===================================
‘=======COLORS================
Dim b As Brush
Dim p As New Pen(Color.Black)
b = Brushes.Black
p.Width = 0.1

Select Case colorN
Case 1
b = Brushes.Red
p = Pens.Red

Case 2
b = Brushes.Blue
p = Pens.Blue
Case 3
b = Brushes.Green
p = Pens.Green
Case 4
b = Brushes.Magenta
Case 5
b = Brushes.Orange
p = Pens.Orange
Case 6
b = Brushes.Black
p = Pens.Black
End Select

‘=============PLOT パラメータ準備==============
Dim yh As Integer = 240
Dim xw As Integer = 600
Dim dstep As Double ‘x軸ドット単位 dot/dataNo
Dim dvalue As Double = 1 ‘Y軸ドット単位 dot/mV 10mvで1ドット

‘–Y軸
rate = rateCR() ‘ rate(0-6)はdot/mV
midvalue = aveTR() ‘midvalue(0-6)はゼロレベル値
‘————-ドット変換値は手計算する——-
dstep = 1

‘===================スクロール クリア&時間測定========================================
If dataNo Mod 600 = 0 Then ‘1画面終了したらimageクリア
tp = sw.Elapsed
totalsec = tp.TotalSeconds
‘ Debug.Print(“tp.sec=” & totalsec)
sw.Stop()
If totalsec > 0.6 Then
TextBox11.Text = CStr(totalsec)
End If
sw.Reset()
sw.Start()
PictureBox1.Image = Nothing ‘1スクロール毎に画面クリア
‘====================画面PLOT==============================================
Else
px = Int(dstep * dataNo Mod 600)
px_1 = Int(dstep * (dataNo – 1) Mod 600)

py = Int(dvalue * (value – midvalue(0)))
py_1 = Int(dvalue * (value_1 – midvalue(0)))
‘Debug.Print(“dataNo=” & CStr(dataNo) & “value=” & CStr(value) & “midvalue=” & CStr(midvalue(0)) & “px=” & CStr(px) & “py=” & CStr(py))
‘g.FillEllipse(b, px, py, 3, 3) ‘ 点プロット
g.DrawLine(p, CSng(px_1), CSng(py_1), CSng(px), CSng(py))
g.Dispose()
‘b.Dispose()
PictureBox1.Invalidate()
End If
End Sub
‘=====================================================================================================================
‘=====================================================================================================================
‘=====================================================================================================================
‘========================================================================================
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
‘*********************Object Array set****************************************************************************
Dim dataTextBox() As TextBox
dataTextBox = {Me.TextBox4, Me.TextBox5, Me.TextBox6, Me.TextBox7, Me.TextBox8, Me.TextBox9, Me.TextBox10}
Dim adjustComboBox() As ComboBox
adjustComboBox = {Me.ComboBox1, Me.ComboBox2, Me.ComboBox3, Me.ComboBox4, Me.ComboBox5, Me.ComboBox6, Me.ComboBox7}
Dim midTextBox() As TextBox
midTextBox = {Me.TextBox13, Me.TextBox14, Me.TextBox15, Me.TextBox16, Me.TextBox17, Me.TextBox18, Me.TextBox19}
‘******************************************************************************************************************
‘Dim arry() As Integer = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}
‘================COMBOBOX Def=============================
ComboBox1.Items.Clear()
Dim n As Integer
For i = 0 To 6
adjustComboBox(i).Items.Add(“0”)
adjustComboBox(i).Items.Add(“10”)
adjustComboBox(i).Items.Add(“20”)
adjustComboBox(i).Items.Add(“30”)
adjustComboBox(i).Items.Add(“40”)
adjustComboBox(i).Items.Add(“50”)
adjustComboBox(i).Items.Add(“60”)
adjustComboBox(i).Items.Add(“70”)
adjustComboBox(i).Items.Add(“80”)
adjustComboBox(i).Items.Add(“90”)
adjustComboBox(i).Items.Add(“100”)

Next
ComboBox1.SelectedIndex = 1
ComboBox2.SelectedIndex = 1
ComboBox3.SelectedIndex = 1
ComboBox4.SelectedIndex = 1
ComboBox5.SelectedIndex = 1
ComboBox6.SelectedIndex = 1
ComboBox7.SelectedIndex = 1

‘==============Series Position TEXTBOX===========================
TextBox13.Text = CStr(1550)
TextBox14.Text = CStr(1550)
TextBox15.Text = CStr(1550)
TextBox16.Text = CStr(1550)
TextBox17.Text = CStr(1550)
TextBox18.Text = CStr(1550)
TextBox19.Text = CStr(1550)

End Sub

‘========================================================================
‘================Average Graph mid Data==================================
‘========================================================================
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click

Dim endnum As Integer
Dim startnum As Integer
Dim midave(7) As Double
endnum = CInt(TextBox2.Text)
startnum = endnum – 100

midave = dave(dataAry, startnum, endnum, 6)
Debug.Print(“AveButtn:” & CStr(startnum) & “,” & CStr(endnum) & “,” & CStr(midave(0)))
TextBox13.Text = midave(0)
TextBox14.Text = midave(1)
TextBox15.Text = midave(2)
TextBox16.Text = midave(3)
TextBox17.Text = midave(4)
TextBox18.Text = midave(5)

End Sub
‘==========================PLOTTING Parameter Check ===============================================
‘===================dataAry(,)=mV rate()=dot/mv=1/adjutvalue()(=mV/dot)============================================
‘=================== plot: py=(dataAry(,)-midvalue())*rate()+midvalue()==============================================
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click

Dim m, n As Integer
Dim px, py As Integer
Dim dn, ds, de As Integer
ReDim rate(8)
ReDim midvalue(8)
‘For m = 0 To 6
‘ rate(m) = 1 / CInt(adjustComboBox(m).Text)
‘ midvalue(m) = CDbl(midTextBox(m).Text)
‘Next
rate = rateCR()

midvalue = aveTR()

dn = CInt(TextBox2.Text) ‘現在データNo
ds = CInt(dn / 600) * 600 ‘左始点データスタートNO
de = dn Mod 600 ‘現在座標
Debug.Print(“dn=” & CStr(dn) & “ds=” & CStr(ds) & “de=” & CStr(de))
For n = 0 To 5
For m = 0 To de
px = m
py = CInt((CDbl(dataAry(ds + m, n)) – midvalue(n)) * rate(n) / 100 + yh / 2)
Debug.Print(“m=” & CStr(m) & “n=” & CStr(n) & “dataAry=” & CStr(dataAry(ds + m, n)) & “midvalue=” & CStr(midvalue(n)) & “sa=” & CStr((CDbl(dataAry(ds + m, n)) – midvalue(n))) & “rate=” & rate(n) & “Plotting:px=” & CStr(px) & “py=” & CStr(py))
‘Debug.Print(“Plotting:px=” & CStr(px) & “py=” & CStr(py))
plotD(px, py, n)
Next

Next

End Sub
Sub plotD(ByVal px As Integer, ByVal py As Integer, ByVal colorN As Integer)
If PictureBox1.Image Is Nothing Then ‘初回だけBITMAPを定義する Picture1.imageという名称をつかうこと
PictureBox1.Image = New Bitmap(600, 240)
End If
Dim g As Graphics = Graphics.FromImage(PictureBox1.Image)

‘======================COLORS=========================================
Dim b As Brush
b = Brushes.Black
Select Case colorN
Case 1
b = Brushes.Red
Case 2
b = Brushes.Blue
Case 3
b = Brushes.Green
Case 4
b = Brushes.Magenta
Case 5
b = Brushes.Orange
Case 6
b = Brushes.Black

End Select

‘===================================================================
If px Mod 600 = 0 Then ‘1画面終了したらimageクリア
PictureBox1.Image = Nothing
Else
g.FillEllipse(b, px, py, 3, 3)
g.Dispose()
‘b.Dispose()
PictureBox1.Invalidate()

End If

End Sub
‘********************************************************************************************************************
‘*********************************FORM Reading Functions*************************************************************
‘*******************************************************************************************************************
Private Function aveTR() As Double()
Dim ave(7) As Double
ave(0) = CDbl(TextBox13.Text)
ave(1) = CDbl(TextBox14.Text)
ave(2) = CDbl(TextBox15.Text)
ave(3) = CDbl(TextBox16.Text)
ave(4) = CDbl(TextBox17.Text)
ave(5) = CDbl(TextBox18.Text)
ave(6) = CDbl(TextBox19.Text)
Return ave
End Function
Private Function rateCR() As Double()
Dim rate(7) As Double
rate(0) = CDbl(ComboBox1.SelectedItem) / 100
rate(1) = CDbl(ComboBox2.SelectedItem) / 100
rate(2) = CDbl(ComboBox3.SelectedItem) / 100
rate(3) = CDbl(ComboBox4.SelectedItem) / 100
rate(4) = CDbl(ComboBox5.SelectedItem) / 100
rate(5) = CDbl(ComboBox6.SelectedItem) / 100
rate(6) = CDbl(ComboBox7.SelectedItem) / 100
Return rate
End Function

‘*******************************************************************************************************************
‘*******************************************************************************************************************
‘*******************************************************************************************************************

‘==================================================================================================================
‘==================================Static Calculation===========================================================
‘==========================Ave() MovingAve() ============================================================
‘==================================================================================================================
‘==================================================================================================================
Function dave(ByRef dA(,) As Long, ByVal startN As Integer, ByVal endN As Integer, ByVal ch As Integer) As Double()
Dim chN As Integer
Dim dataN As Integer
Dim dsum As Double
Dim avech() As Double
ReDim avech(ch)
For chN = 0 To ch – 1 ‘chは1-6chで与えられるがデータindexは0-5
For dataN = startN To endN ‘startNからendNまでendN-startN+1 個の総和をとって平均
dsum += dA(dataN, chN)
Next
avech(chN) = dsum / (endN – startN + 1)
dsum = 0
Next
Return avech

End Function

Function MovAve(ByRef dA(,) As Long, ByVal colN As Integer, ByVal MA As Integer, ByVal rowN As Integer) As Double()
Dim i, j As Integer
Dim dataSum() As Long
Dim dSum As Long
Dim dataA() As Double ‘= {0, 0, 0, 0, 0, 0, 0}
‘Debug.Print(“====colN=” & CStr(colN) & “MA=” & CStr(MA) & “rowN=” & CStr(rowN))
ReDim dataSum(colN + 1)
ReDim dataA(colN + 1)

For j = 0 To colN – 1
dSum = 0
For i = rowN – MA To rowN
dSum = dSum + dA(i, j)
‘Debug.Print(“dA(” & CStr(i) & “,” & CStr(j) & “)=” & CStr(dA(i, j)) & CStr(dataSum(j)))
Next
dataA(j) = CDbl(dSum / MA)
Next
MovAve = dataA
End Function

End Class

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です