ExcelマクロでEtherCATの制御

EtherCATについて語る Advent Calendar 2019 はもう埋まりそうなので、こちらはニッチすぎる番外編記事です。

やりたいこと

オープンソースのEtherCATマスターであるSOEMをDLL化し、ExcelVBAマクロから呼び出せるようにする。これによって、ExcelからEtherCATスレーブの制御が可能となり、Excel上で自動計測とデータ処理ができるようになる。

SOEMのDLL化

SOEMのDLL化については、以前の記事「EtherCATマスターSOEMを.NETで使う」に書いた。ここで作成したsoemlib.dllを使用する。(ただし、今回DLLをExcelから呼び出すにあたって不都合があったので少し加筆修正した。)
lipoyang.hatenablog.com

Excelマクロからの呼び出し

VBAで下記のようにDLL(soemlib.dll)のAPIを宣言する。

' soemlib.dll のAPI
Declare Function soem_open Lib "soemlib.dll" (ByVal nic As String) As Integer
Declare Sub soem_close Lib "soemlib.dll" ()
Declare Function soem_config Lib "soemlib.dll" () As Integer
Declare Function soem_transferPDO Lib "soemlib.dll" () As Integer

ただし、DLLはパスの通っているディレクトリにないと読み込めない。パスの通ってないディレクトリにDLLを置く場合には下記のようにしてDLLを読み込む必要がある。

Private Declare PtrSafe Function LoadLibrary Lib "kernel32.dll" _
            Alias "LoadLibraryA" (ByVal fileName As String) As Long

' 初期化
Sub ethercat_init()
    ' soemlib.dll の読み込み
    LoadLibrary ("C:\tool\SOEM\build\test\linux\soemlib\soemlib.dll")
    
End Sub

あとは、ふつうにVBAからDLLのAPIを呼び出すことができる。

    ret = soem_findAdapters()
    If ret = 0 Then
        MsgBox ("ネットワークアダプタが見つかりません")
        Exit Sub
    End If

自動計測の実験

ためしに簡単な自動計測装置を作ってみた。Arduinoで作ったEtherCATスレーブ(上記記事を参照)にマイクロサーボと可変抵抗を接続し、マイクロサーボと可変抵抗の回転軸を連結した。

f:id:licheng:20191220221316p:plain

f:id:licheng:20191220232828j:plain:w480

サーボの角度を0°から180°まで10°ずつ変化させ、そのときの可変抵抗のADC値を測定するマクロを以下に示す。

' 計測
Sub ethecat_measure()
    
    ' サーボの角度 0°から180°まで10°ずつ
    For i = 0 To 18
        ' 10msec周期で100回繰り返す
        For j = 0 To 100
            ' サーボの角度
            deg = i * 10
            soem_setOutputPDO 1, 0, deg
            ' 転送
            ret = soem_transferPDO()
            ' 可変抵抗のADC値
            h = soem_getInputPDO(1, 0)
            l = soem_getInputPDO(1, 1)
            volume = (h * (2 ^ 8)) + l
            ' 10msec待つ
            Sleep (10)
            ' これを入れないと画面が固まる
            DoEvents
        Next
        ' 表へ記入
        Cells(2 + i, 1).value = deg
        Cells(2 + i, 2).value = volume
    Next
End Sub


これを実行すると自動計測がおこなわれ、下図のようなグラフが得られた。

f:id:licheng:20191220223705p:plain

注意事項

  • VBAは昔のVB6と同じでスレッドは使えない。なので時間のかかるループ処理ではDoEventsを入れないと画面が固まる。
  • 上の例では10msecごとに通信をおこないつつ、サーボの(メカ的な)応答待ちのために1秒待っている。通信せずに1秒待つとなぜかOutputPDOの値がリセットされてしまう。マスター側でリセットされるのかスレーブ側でリセットされるのか、不具合なのか仕様なのか、要調査。

動画


ソース

今回作成したマクロ入りExcelシートを参考までに置いておく。

また、EtherCATスレーブのソースは下記のものを使用した。
github.com