EtherCATマスターSOEMを.NETで使う

この記事は EtherCATについて語る Advent Calendar 2019 の11日目です。

昨日は@nonNoiseさんの EtherCAT開発方法 フレーム編(ライトまで) でした。

今日はオープンソースのEtherCATマスターであるSOEMをWindows上の.NETアプリで使う方法を解説します。

SOEMとは?

SOEMはオープンソースのEtherCATマスターである。WindowsMacOSLinuxなどに対応している。ビルドシステムとしてCMakeを用いる。

github.com

方針

  1. SOEMをDLL化するためAPIC言語で定義する
  2. CMakeを使ってDLLをビルドする
  3. DLLをラップするクラスをC#で作成する
  4. C#アプリで使う

f:id:licheng:20191210124119p:plain:w640

(1) SOEMをDLL化するためAPIC言語で定義する

まず、SOEMをDLL化して外部から呼ぶ出せるようにするため、APIC言語で定義する。soemlib.c という名前でソースファイルを作成し、必要なAPI関数を定義する。DLLのAPI関数の定義には、__declspec(dllexport) と __stdcall というキーワードを付ける。一例を以下に示す。(2019/12/19 修正)

#include "ethercat.h"

int __stdcall soem_open(char* nif)
{
    int ret = ec_init(nif);
    return ret;
}

また、API関数をsoemlib.defというファイルに列挙する。 (2019/12/19 追記)

(2) CMakeを使ってSOEMのDLLをビルドする

Windows環境でのCMakeによるSOEMのビルド方法についてはまず以前の記事を参照。

SOEM/CMakeLists.txt の最後のほうに1行追加する。DLLのソースを置くサブディレクトリの追加である。親ディレクトリ名がlinuxになっているが気にしない。

if(BUILD_TESTS) 
  add_subdirectory(test/linux/slaveinfo)
  add_subdirectory(test/linux/eepromtool)
  add_subdirectory(test/linux/simple_test)
  add_subdirectory(test/linux/soemlib)     # ←この行を追加
endif()

SOEM/test/linux/soemlib/CMakeLists.txt を下記の内容で作成する。これがDLLをビルドするレシピである。add_library()で SHARED を指定することで共有ライブラリがビルドされる。Windowsでは共有ライブラリとはすなわちDLLである。

set(SOURCES soemlib.c soemlib.def)
add_library(soemlib SHARED ${SOURCES})
target_link_libraries(soemlib soem)
install(TARGETS soemlib DESTINATION lib)

(1)で作成したsoemlib.cを SOEM/test/linux/soemlib/ に置く。そしてCMakeによるビルドを実行する。ビルドが成功すると、SOEM/build/test/linux/soemlib/soemlib.dll が生成される。

(3) DLLをラップするクラスをC#で作成する

作成したDLLを.NETアプリから使うため、C#でラッパーを作成する。EtherCAT.cs という名前でソースファイルを作成しクラスを定義する。DLLが提供するAPI関数をC#で使うには、DllImport属性を使い、DLLファイル名とAPI関数名を指定する。一例を下記に示す。

using System.Runtime.InteropServices; // DllImport

(中略)
    // EtherCATラッパークラス
    class EtherCAT
    {
(中略)
        // 開く
        [DllImport("soemlib.dll", EntryPoint = "soem_open")]
        extern public static int open(string nif);

(4) C#アプリで使う

あとは作成したクラスを使った.NETアプリをC#で作成する。例として2個のEtherCATスレーブを接続してラジコンサーボの角度の指令とポテンショメータの角度の取得をおこなうアプリを作成した。


WindowsとArduinoでEtherCAT

ソース

この記事で作成したソースを下記に公開する。

github.com