次の環境でプログラムを作っています。WindowsPCでプログラムは動き、CANバスとはIXXATのUSB-CAN変換モジュールを通してCANopenのプログラムを動かします。EPOSのライブラリは、IXXAT以外に、ベクターやKvaserなどのインターフェースのドライバが利用できるようです。IXXATは、検索して日本語で価格がわかったのでマルツから購入しました。
これ以外に、EPOSはRS232C/USBとCANバスのブリッジになるので、上記のインターフェースはなくてもDeviceOpenが実行できます。マニュアル類では、そちらの方法の事例しか掲載されていません。
ハローワールドから始める
コンパイルしてプログラムを実行したのは初めてなので、その手順を記します。VisualStudioの上部メニューから新規プロジェクトを選びます。
コンソールアプリのC++を選択し、次へをクリックします。
eposと名付けました。
最初の画面にハローワールドが出ています。
慣れたprintf()で書き換え、CTRL+Shift+Bでビルドします。画面下の出力に、ビルドでエラーなしが出ているので、メニューのローカルWindowsデバッガーの右の三角アイコンをクリックして実行します。黒地のコマンド・プロンプトが開き、printfの出力が出ました。
二つある状態変数だが
NMT(Network Management Object)は、電源投入時にInitialization、その後PRE-OPERATIONAL状態、最後に運転状態のOPERATIONAL状態に移行します。
けれど、状態を読み出す関数見つかりません。サンプルを見ても、自分でPRE-OPERATIONALに移行するとかの記述は見つかりません。OPERATIONALからPre-Opeに変更するのは、PDOマッピング時に必要だけど、それはStudioで設定すればいいので、使うことはありません。つまり、エンド・ユーザはNMTには感知せずでいいようです。
CiA-402 State Machineの状態変更や状態を調べる関数は多く用意されていますが、どうも状態はDisableとEnableしかみつかりません。もっと細かい遷移はエンド・ユーザはやらなくてもよいようです。
また、SYNCにかかわる関数は用意されていないようです。
SDOでいろいろ読み出す
必要なファイルの追加
VisualStudio左のソリューションエクスプローラのeposの上で、右クリックします。
追加から既存の項目を選択します。
前回ダウンロードしたサンプル・フォルダから、ヘッダ・ファイルはDefinitions.hを選択します。
同様に、ライブラリはEposCom64.dllとEposCom64.libファイルを追加します。
ソリューションエクスプローラの様子です。一度全部を保存して終了します。このあたりの操作がわかっていません。エクスプローラを使って物理的にファイルをeposフォルダにコピーをする必要があるかもしれません。もしくは、次に立ち上げたときに自動でコピペされるかもしれないです。
EPOS Command Library Documentationを参考に
いくつかのオブジェクト・ディクショナリのデータを読み出します。エラー・コードは無視しています。
#include <iostream>
#include "Definitions.h"
int main()
{
printf("start EPOS4\n");
HANDLE keyHandle = 0;
char* deviceName = (char*)"EPOS4";
char* protocolStackName = (char*)"CANopen";
char* interfaceName = (char*)"IXXAT_USB-to-CAN V2 compact 0";
char* portName = (char*)"CAN0";
DWORD errorCode = 0;
DWORD timeout = 0;
WORD nodeId = 5;
WORD MotorType = 0;
DWORD NominalCurrent = 0;
DWORD MaxOutputCurrent = 0;
WORD ThermalTimeConstant = 0;
BYTE NbOfPolePairs = 0;
WORD SensorType = 0;
DWORD EncoderResolution = 0;
BOOL InvertedPolarity = 0;
WORD EController = 1; // PI current controller
WORD EGain = 1; // 1:Current controller P gain, 2:Current controller I gain
DWORD64 Value = 0;
keyHandle = VCS_OpenDevice(deviceName, protocolStackName, interfaceName, portName, &errorCode);
if ((BOOL)keyHandle) {
VCS_Store(keyHandle, nodeId, &errorCode);
printf("nodeId is %d\n", nodeId);
VCS_GetMotorType(keyHandle, nodeId, &MotorType, &errorCode);
printf("MotorType:(10 is EC motor sinus commutated): %d\n", MotorType);
VCS_GetDcMotorParameterEx(keyHandle, nodeId, &NominalCurrent, &MaxOutputCurrent, &ThermalTimeConstant, &errorCode);
printf("NominalCurrent: %d MaxOutputCurrent: %d ThermalTimeConstant: %d\n", NominalCurrent, MaxOutputCurrent, ThermalTimeConstant);
VCS_GetEcMotorParameterEx(keyHandle, nodeId, &NominalCurrent, &MaxOutputCurrent, &ThermalTimeConstant, &NbOfPolePairs, &errorCode);
printf("EcMotor NbOfPolePairs: %d\n", NbOfPolePairs);
VCS_GetSensorType(keyHandle, nodeId, &SensorType, &errorCode);
printf("SensorType:(1 is Incremental encoder 1 with index (3-channel)): %d\n", SensorType);
VCS_GetIncEncoderParameter(keyHandle, nodeId, &EncoderResolution, &InvertedPolarity, &errorCode);
printf("EncoderResolution: %d InvertedPolarity: %d\n", EncoderResolution, InvertedPolarity);
VCS_GetControllerGain(keyHandle, nodeId, EController, 1, &Value, &errorCode);
printf("CurrentController PGain: %.3fmV/A\n", Value / 1000.0);
VCS_GetControllerGain(keyHandle, nodeId, EController, 2, &Value, &errorCode);
printf("CurrentController IGain: %.3fmV/(A*ms)\n", Value / 1000.0);
}
VCS_CloseDevice(keyHandle, &errorCode);
}