VB.NETのシリアル受信プログラム、3年間食わず嫌いでしたが、ようやくちょこちょこいじりだしました。結局、プログラムは慣れしかありませんので、慣れればその環境が良いと思えるようになるということだとあきらめてやってます。暇と根気がないとできませんので、いつでもできるわけではありません。
●何故VB.NETかというと、
①VBAでは、処理速度が遅すぎて将来困る。
(冬にスキーターン解析用GNSS_RTKシステムのリアルタイムグラフィック作りたい)
②Processingでは、ツールボックスなどオブジェクトUIが弱い点とExcelとのリンクができない点でVB.NETに負けている。
③C#でいけばいいと思ったが、VB.NETのほうがVBAに近いので手ごろ感があるので、VB.NETからVSに入るほうがよい。
一般的なメリットデメリットの記事はたくさんあります。
https://www.fenet.jp/dotnet/column/language/884/
●シリアル受信7CHデータを処理する準備にSPLITを使ってみた。
受信データは、6分力センサからFx,FyFz,Mx,MyMz,setNoの7個の
整数がASCIIで送信されてきます。速度は10msec前後で115200bpsです。
Form1(デザイン)は、ボタン2個、TextBox10個、ListBox1個作っておきます。
Form1.vbのコードは、GISTにアップしてあります。
https://gist.github.com/dj1711572002/b8468b3afb09ff1b5bd751a2fd0adb02以下、機能別に解説しておきます。
■全体の概要
シリアル受信のコンテック社様からコピペした基本ソースは
2つのSUB関数からできてます。
①Private Sub PrintData(ByVal sdata As String) 表示する関数
②Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
シリアルポート受信関数です。マルチタスクで受信します。
データの流れ沿って解説していきます。
■第一段:VB側の受信データは、receivedData as Stringです。
全7chデータがカンマ区切りで1本のSTRING変数で受信されます
Private Sub SerialPort1_DataReceived(sender As Object, e As SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived Dim ReceivedData As String = ” ” ‘受信データ用変数を宣言しますTryReceivedData = 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 |
■第二段:PrintData()でデータを処理する
SerrialPort1_DataReceived()では、表示処理するとエラーがでたので
PrintData()にデータ処理と表示機能をまとました。
受信データは、ReceiveDataからsdataとして引数として渡されます。
■第三段:SPLITでカンマ区切りのデータをばらす(配列宣言ではまった)
SPLITの使い方はMSDOCにあります。
https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.visualbasic.strings.split?view=netcore-3.1
以下上記リンクから抜粋 例文
Dim testString As String = “Look at these!”
‘ Returns an array containing “Look”, “at”, and “these!”.
Dim testArray() As String = Split(testString)
何もパラメータをつけてない場合はデフォルトで空白文字がデリミタになります。
▼配列宣言ではまった
①SPLIT
受け取る文字列配列をその場でDim宣言することが手間とトラブル防止になります。私は、上部で配列宣言してから、Redimしたのですが、エラーから抜け出せなくなってしまい、サンプル通りにSplit行で配列宣言をしたらエラーから抜け出せました。未だ、原因わからないのですが、初心者のうちは、サンプル通りにコピペしていったほうがいいと感じました。
②宣言の位置
CLASSとかメソッド(関数)を使ったプログラミングあまりしてこんかったので、メソッド内で宣言した変数がプログラムポインタがメソッドを抜け出した瞬間にゼロになってしまって、不思議な現象ではまりました。
CLASS内で共通して使う変数はCLASS直下で宣言しないとだめなことを怠ってしまって1日無駄しました。
パラメーター
- Expression
- String
必須。 部分文字列および区切り記号を含む String
型の式。
- Delimiter
- String
省略可能。 文字列の区切りを識別するために使用する任意の 1 文字。 Delimiter
が省略された場合、空白文字 (” “) が区切り記号として使用されます。
- Limit
- Int32
省略可能。 入力文字列を分割する場合の部分文字列の最大数。 既定値の -1 は、Delimiter
文字列が出現するたびに入力文字列が分割されることを示しています。
- Compare
- CompareMethod
省略可能。 部分文字列を評価する場合に使用する比較を示す数値。 値については、「設定」を参照してください。
戻り値
- String[]
String
配列 Expression
が長さ 0 の文字列 (“”) の場合、Split
は、長さ 0 の文字列を含む単一要素の配列を返します。 Delimiter
が長さ 0 の文字列である場合、または Expression
に Delimiter がない場合に、Split
は Expression
型の文字列を含む単一要素の配列を返します。
■第4段:printData()コード(GIST)
デバッグ用に無駄な部分がついてますが、やっていることは単純で、
sdataをSPLITしてdStr文字列配列にばらして、整数2次元配列dataAry(dataNo,i)に格納してます。
SPLITの結果は、dSTr()をTextBox4-10に表示させてます。
dataAry()は、60万個までRedimで確保してありますが、エラーになりません。
Private Sub PrintData(ByVal sdata As String) Dim dataNo As IntegerDim delimiter As String = “,” Dim dataAry(,) As Integer Dim dcount As String Timer1.Interval = 1 ‘タイマー開始 Timer1.Enabled = True ‘TextBox1.text=sdata dcount = sdata & “:” & TextBox2.Text ListBox1.Items.Add(dcount) Dim dStr() As String = Split(sdata, delimiter, -1, CompareMethod.Text) If (dStr.Length > 6) Then dataNo = CInt(TextBox2.Text) + 1ReDim dataAry(600000, dStr.Length) For i = 0 To dStr.Length – 1 dataAry(dataNo, i) = CInt(dStr(i)) TextBox2.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(CStr(dataNo) & “,” & CStr(i) & “,” & CStr(dataAry(dataNo, i)))Next End If End Sub |