F9PMovingBaseモードで フィールド測定の回数が増えてきました。UBXログデータのバイナリファイルをたくさんため込んだのですが、現在のVBAプログラムでは1MB程度のファイルをシートに展開するのに10分以上かかってしまって、とても、たくさんのUBXログファイルを処理するわけにはいきませんでした。
そこで、VBAの高速化に取り組みました。
●シート書き込みが遅い原因と対策
①バイナリファイルを読み込んでからセンテンス区分けしながら
for next ループでセル1個ずつに書き込んでいた。
対策①=>センテンス区分けした結果は、センテンス毎に2次元配列変数にしてメモリーに保存した状態にしてから各種処理をする。
対策➁=>変数をシートへ一括で書き込むコマンドをつかう
こちらのブログにやり方が書いてあって大感謝です。
https://brain.cc.kogakuin.ac.jp/~kanamaru/lecture/vba2003/11-summary02.html
Range(Cells(1, 1), Cells(nd, 2)) = 配列変数名 ‘ 実際のセルへの書き込み |
1 |
<span style="font-size: 18pt; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;">たった一行で、1MBのデータも数秒でシートへコピーしてくれました。</span> |
=>VBAもセルとかシートを使わないで通常のC言語のように使えば、コンパイラほどではありませんが、そこそこの速度がでることを実感しました。しかし、限界があって
シリアル受信では、115200bpsで、100msec程度の速度しかでません。これがコンパイラ言語のように早くなれば、他の言語いらないのにといつも思ってます。
VB.NETなら早いですがEXCELとリンクするのがVBAのようにはいかないので
データを処理した後EXCELで読み込まないといけないのが面倒です。
●読み込みバグとった
当初GNSSの寸断でデータが飛んでいたと思っていたのですが、あまりにも頻繁に
飛びが発生するので、読み込みプログラムを疑ってみたら、大バグがありました。
バイナリーファイルは、デリミターがないので、どこからセンテンスの始まりかをヘッダの数値を探す以外にないのですが、UBXの場合はB5で始まります。
UBXの仕様は、これです。
https://www.u-blox.com/sites/default/files/u-blox_ZED-F9P_InterfaceDescription_%28UBX-18010854%29.pdf
そこで、B5を見つけてそこからスタートをかけて次のB5がでるところで1センテンスが終了したとみなしていたのですが、データ内にB5が発生している箇所が結構あって、読み間違ってました。
バグ修正:B5を見つけたら、センテンス種類を区分けしてそのセンテンスのバイト数だけ一挙に読み込んでしまう。
具体的には、MBモードでの出力は、NAV-PVTとNAV-RELPOSNEDの2センテンスだけなので、どちらかを区別すればいい
=>UBX-NAV-PVT は, ヘッダーがB5,62,01,07で100バイト
=>UBX-NAV-RELPOSNEDは、ヘッダーがB5,62,01,3Cで72バイト
なので、次のような読み込みプログラムに作りなおしました
UBXファイルから読み込んだデータは、bData()配列に収納されています。
それをDo while ループ内でセンテンス区分けして
Rdata(行、桁)配列と個別のPVT(行、桁)、REl(行、桁)配列に分解します。
全部代入がおわってから、
range .xxxxx=変数名で一挙にシートへ書き込んでUBXファイルをシートへ読み込み完了です。
Private Sub CommandButton1_Click()
‘ファイル選択ダイアログでファイルを指定 ‘キャンセルボタンを押されたら、処理終了 ‘ファイルサイズが0バイトの場合も処理終了 ‘空いているファイル番号を取得 ‘指定されたファイルを取得したファイル番号としてバイナリモードで開く ‘ファイルサイズ分のバイト配列を用意 ‘バイト配列に指定ファイルを展開 End If ‘With Worksheets(“sheet1”) ‘Worksheets(“sheet1”).Cells(L, i) = Hex(bData(n)) Npvt = Npvt + 1 End If Debug.Print Time & ” – Sheet1,PVT,RELPOSNEDシートへのセル書き込み入完了” Application.ScreenUpdating = True Maxrow = Range(“A1”).End(xlDown).Row ‘End With End Sub |
●以後の処理
UBXファイルから得られるデータを抽出します。
PVTからは、iTOW(時刻msec)とLongtitude,Latitudeを得ます。
RELPOSNEDからは、iTowと相対位置relN,relE,relD(cm),relHead(deg),
標高relSeaElevation(m),水平精度HAcc(mm)垂直精度VAcc(mm)を得ます
このプログラムも備忘録しておきます。
Private Sub CommandButton2_Click() L = 2 K = 1 ‘longD = B2L(“FF”, “FF”, “FF”, “B0”) With Worksheets(“sheet2”) With Worksheets(“Sheet1”) For i = 1 To Maxrow ‘nFileLen – 1 If .Cells(i, 4) = “7” Then ‘PVT SeaHeight = B2L(.Cells(i, 46), .Cells(i, 45), .Cells(i, 44), .Cells(i, 43)) End If If .Cells(i, 4) = “3C” Then ‘RELPOSNED X1 = CLng(“&H” & .Cells(i, 15)) ‘ If .Cells(i, 18) <> “FF” Then Worksheets(“sheet2”).Cells(L, 4) = relTow End If Next i End With End Sub Function B2L(ByRef b4 As String, ByRef b3 As String, ByRef b2 As String, ByRef b1 As String) As Long Else End If End Function |
●以後
データが正確に読み取って処理できるようになったので、MBモードでの基礎的な精度検証をして、MBモードの理解を深めて、更なる応用をしていきます。