【VB.NET】7CHリアルタイムモニターver1.0完成<Serial.CloseでPgmハングする対策済>

リアルタイムグラフの使い勝手UI関係のプログラムを一応完成させました。目的に応じて仕様は全く変わるので、機能をどのコントロールを使ってどのように組み込んであるかを参考にしていただければと存じます。
■仕様ESP32系USB Driverを使ってます)
①1周期5-10msecで7ch(ASCII37byte)のデータをプロットできます。
=>事前にWIn10のデバイスドライバのCOMのProperty詳細でオプションBM値を16msecから1msecに変更しないとリアルタイムになりません。
②受信ボーレートは460800bpsまでOKでした。
③OPENからCLOSEまで全部CSV自動ログできます。
④グラフの各CHスケール位置調整機能各種が付き

グラフ設定機能
①X(時間軸)スケール<ComboBox>   単位:dots/data
②Y(電圧軸)位置スライダ<TrackBar>単位:Y軸フルスケール100%
③Y(電圧軸)倍率CH毎設定<ComboBox>単位:dot/mV
④ゼロレベル自動合わせ全CHを中央位置50%にそろえる機能

■データ管理機能
①年月日時刻ファイル名で自動ログ(CSV)
②ダイアログで任意のフォルダー、ファイル名でログ
③グラフ描画速度測定機能(デバッグ中)

※2021年11月9日 流れるリアルタイムグラフを作ってみました。BITMAPに一旦データを書き込んでから、切り取って表示する方式
その2で、グラフ全体から所望の部分を瞬時に閲覧できるので、リアルタイムで測定データの確認作業が出来るように作ります。
【VB.NET】リアルタイムグラフのBITMAP処理化<その1小技在り>

※グラフィック備忘録
①PictureBoxとBitmapを定義してしまう場合
参考LINK PictureBox.Imageプロパティに設定している画像を描き変えた時、すぐに表示に反映する 
PictureBoxは、額縁に相当します。額縁に差し込む絵は、紙であるBitmapオブジェクトです。

 Bitmapに描画するには、それぞれのBitamap専用のグラフィック処理クラス graphicsを定義します。 
 Dim bmp as new Bitmap(PictureBox1.Width,PictureBox1.Height)’bmpオブジェクトを定義
 Dim g as Graphics =Graphics.FromImage(bmp)’bmpのグラフィクス処理を定義
 g.DrawLine(Pens Red,x0,y0,x1,y1)’ bmpビットマップへ線が描画されてPictureBoxに反映

②PictureBoxとは独立させてBitmapを処理するしてからPictureBoxに反映させる場合
(参考https://dobon.net/vb/dotnet/graphics/createimage.html )

 Dim bmp as new Bitmap(1000,400)’1000×400にビットマップを定義
   Dim g as Graphics =Graphics.FromImage(bmp)’bmpのグラフィクス処理を定義
 g.DrawLine(Pens Red,x0,y0,x1,y1)’ bmpビットマップへ線が描画する
 PictureBox1.Image=bmp ‘bmpをPictureBox1へ差し込む
 この場合ビットマップに各種処理をした後で、PictureBox表示できるので、便利です。

■使っているメソッド(関数)クラス備忘録
ソースはGIT GISTにアップしてあります。
https://gist.github.com/dj1711572002/580544a86669ce72455a3341c030edfe

FORMを手作りするのが大変なので、今回からソリューションをZIPで添付します。
Serial_Graphic_Monitor_rev01

※7ch受信専用に作ってあるので、後日CH指定自由にできるバージョンにして配布します。
=>splitでマイコン側が変な文字列を送ってくるとエラーがでる点を防ぎきれてません。

機能 メソッド、クラス 使用例
折れ線グラフ

 

【Sub plotC()内】
graphObj.Draw.Line()
※CHARTは使わずにグラフィックで描画
Imports System.Drawing
g.DrawLine(p6, CSng(px_1), CSng(py_1), CSng(px), CSng(py))

1個前のデータと今のデータを結び線
描画
UNIT
【Sub plotC()内】
グラフ調整機能をCH単位でUNITにしてある
変数解説
dstep:dot/data
rate():dot/mV
Mag:時間軸倍率
midvalue():ゼロレベル値
dataAry():6ch電圧データ
px_1:1個前のX軸データ
py_1:1個前のY軸データ
‘************Plot Unit 1ch******************************
If Ch_sel(0) = 1 Then
px = Int((dstep * dataNo Mod CInt(600 / Mag)) * Mag)
px_1 = Int((dstep * (dataNo – 1) Mod CInt(600 / Mag)) * Mag)
py = yh – (Int(rate(0) * (dataAry(dataNo, 0) – midvalue(0))) + TBposition)
‘Debug.Print(“——1ch_py:dataAry=” & CStr(dataAry(dataNo, 0)) & “midvalue=” & CStr(midvalue(0)))
py_1 = yh – (Int(rate(0) * (dataAry(dataNo – 1, 0) – midvalue(0))) + TBposition)
‘Debug.Print(“1ch_py_1:dataAry=” & CStr(dataAry(dataNo, 0)) & “midvalue=” & CStr(midvalue(0)))
g.DrawLine(p1, CSng(px_1), CSng(py_1), CSng(px), CSng(py))
‘Debug.Print(“——1ch:px_1=” & CStr(px_1) & “px=” & CStr(px) & “py_1=” & CStr(py_1) & “py=” & CStr(py))
End If
‘**********************************************************
グラフの色

 

【Sub plotC()内】
  PENS
Dim p1, p2, p3, p4, p5, p6 As New Pen(Color.Black)p1 = Pens.Red
p1 = Pens.Red
p2 = Pens.Blue
P3 = Pens.Green
p4 = Pens.Magenta
p5 = Pens.Orange
p6 = Pens.Black
グラフの線幅

 

【Sub plotC()内】
  PEN
p1.Width = 0.1
画面クリア 【Sub plotC()内】

 P.image=Nothing

PictureBox1.Image = Nothing ‘1スクロール毎に画面クリア
画面の定義 【Sub plotC()内】
 P.image=New Bitmap()
初回だけBITMAPを定義する Picture1.imageという名称をつかうこと

If PictureBox1.Image Is Nothing Then
 PictureBox1.Image = New Bitmap(600, 240)
End If
Dim g As Graphics =Graphics.FromImage(PictureBox1.Image)

多コントロールの
配列指定
【Sub Form1_Load()内】
  Me.ComboBox1
Dim adjustComboBox() As ComboBox
adjustComboBox = {Me.ComboBox1, Me.ComboBox2, Me.ComboBox3, Me.ComboBox4, Me.ComboBox5, Me.ComboBox6, Me.ComboBox7}
日付ファイル名と任意ファイル名をダイアログ指定 File指定ボタン
【Sub Button7_Click()内】

時刻:
   Nowダイアログ:
  SaveFileDialog
‘——FILE SAVE準備———————-
Dim sfd As New SaveFileDialog()
Dim fname As String
fname = Format(Now, “yyyyMMdd_HHmmss”)
Debug.Print(“fname=” & fname)
sfd.FileName = fname
sfd.Filter = “TXTファイル|*.txt|CSVファイル|*.csv|すべてのファイル|*.*”
sfd.InitialDirectory = “C:\vb_LOG ”
sfd.FilterIndex = 2
sfd.Title = “保存先のファイルを選択してください”
If sfd.ShowDialog() = DialogResult.OK Then
‘OKボタンがクリックされたとき、選択されたファイル名を表示する
Console.WriteLine(sfd.FileName)
TextBox21.Text = sfd.FileName
End If
CSVファイル
宣言
【Sub PrintData()内】

使いまわすので
Privateでクラス直下で宣言
‘=======file===============
Public fname As String = “”
Public file As System.IO.StreamWriter

‘========First CSV File Declaration======================
If CheckBox8.Checked = True And fname = “” Then
fname = Format(Now, “yyyyMMdd_HHmmss”)
fname = “C:\vb_LOG\” & fname & “.csv”
TextBox21.Text = fname
‘—MS Example——————————
‘Dim file As System.IO.StreamWriter
‘file = My.Computer.FileSystem.OpenTextFileWriter(“c:\test.txt”, True)
‘file.WriteLine(“Here is the first string.”)
‘file.Close()
‘——————————————
Dim enc As System.Text.Encoding = System.Text.Encoding.GetEncoding(“Shift_JIS”)
file = My.Computer.FileSystem.OpenTextFileWriter(fname, False, enc)
End If
ファイル書き込み 【Sub PrintData()内】

 File.write(data)

ファイルが存在するときに書き込む

‘========sdata File writing====================
If System.IO.File.Exists(fname) Then
file.Write(sdata)
Label7.Text = “Logging”
End If


■使い方
1)SerialPort1のPropertyでCOM文字とボーレートを設定
2)OPENボタンを押すと接続して、受信データが各CHのTextBoxに表示されます
3)CSV自動ログするには、右上のAutoSavingLogにチェックが入っていること
AutoSavingLogは、ファイル名は年月日時刻名で”¥C¥vb_Log”フォルダーに保存

4)グラフの開始は、左上のSTARTボタン、STOPボタンで表示ONOFFができるが、ログはグラフに関係なく継続している
5)シリアルポートを閉じるとプログラムがハングする現象があるので、それを防ぐためにCLOSEボタンは、Recevingチェックボックスのチェックを外さないと押せません。
これは、受信中にシリアルポートをCLOSEすると、マルチスレッドがハングすることで発生するため、対策として、Receivingを完全に停止してからCLOSEする操作を確実にするためのUI仕様です。
参考にさせていただいた記事は、こちらです。

   SerialPortをCloseするとフリーズする

6)シリアルをCLOSEすると同時にFILE LOGGINGもCLOSEになります。

■以後
EXEの配布版を作って配布します。
 あくまでも動作確認用でご自分でお使いになるには、ソースをいじって改良されることをお勧めします。
 配布版以降は、自分の測定用にシステム開発をしますので、多分力センサテーマで扱います。
何かご質問がある場合は、ich48397@wd5.so-net.jpへどうぞ
コメント欄の記入されても海外からのスパムが大量にきているため
正規のコメントを探すのに時間がかかります。

 

 

anchor

■必須項目:Win10の設定
USBシリアルFTDIドライバのLatencyTimer機能が働いていて、64byte以下の少量データの連続転送時に遅延が発生するようになってるそうです。
詳細はこちらのページです。https://www.hdl.co.jp/USB/FTDI/lt/
この設定をBM設定といいます。これが、デフォルトだと16msecとなってるとバッファ遅延でリアルタイムになりませんので、BM=1msecに設定しなおせば、リアルタイムになります。
●変更方法:
デバイスマネージャ>ポート(COMxx)>Property>ポートの設定タブ
>詳細設定>BMオプション待ち時間を1msecにします。
QIITAのこちらの記事に感謝です。

※2021年6月30日追記
本記事から10か月経過して、グラフ描画プログラムは、BITAMAPを切り取って高速表示するテクニックを身に着けて劇的に向上しました。グラフデータアニメーションのように動かせるので、過去データを一瞬で表示したり、回転、移動、拡大、縮小、リアルタイムで現在のプロットを中心固定してグラフ全体を動かしたり自由自在です。
データ数が数千行から数万行になると高速で処理しないと全体を目視できないのでBITMAPとGraphicsを使ってグラフを描画する方法が一番いいです。参考記事をご覧ください。初めてのグラフィクスからこの方法でプロットしたほうがVB学習の効率は良くなります。

【VB.NET】6chシリアル受信データをリアルタイムグラフできた<Chartでは遅すぎる>
RTKデータ解析用グラフィック機能開発ーその1ー<自動追尾機能便利>
RTKデータ解析用グラフィック機能開発ーその2ー<ソースBITMAP表示基礎>
RTKデータ解析用グラフィック機能開発ーその3ー<自動追尾機能の中身>

コメントを残す

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