TITLE:Dynamixel Protocol Library **概要 [#va21cbfb] Dynamixel Protocol LibraryはDynamixel Protocol 1の通信プロトコルをサポートした製品をWindows等のOSから操作するためのライブラリ集です。~ シリアル通信に関するAPI、タイミングやエラー処理、プロトコルの整合性チェック等を本ライブラリ内で行っているため、シリアル通信である事をほとんど意識すること無くアプリケーションの作りこみに専念することができます。 なお、PCと[[BTE061D]]・[[BTE061E]]・[[BTE068]]・[[BTE068B]]・[[BTE068C]]・[[BTE082]]・[[BTE083]]・[[BTE074]]・[[BTE079]]・[[BTE080]]・[[BTE079B]]・[[BTE080B]]・[[BTX229>http://emanual.robotis.com/docs/en/parts/interface/u2d2/]]のいずれかがUSBポートに接続され、PCのOSに仮想COMポートが増設された状態で使用するものとします。 **ライブラリおよびサンプルプログラムのダウンロード [#j8bd290f] 以下のリンクよりライブラリ及びサンプルプログラムをアーカイブしたファイルがダウンロードできます。 -''2019/11/15 Ver.4.3''~ #ref(http://www.besttechnology.co.jp/download/DXLIB_V4.3.zip) 内容 --Visual Studio上での動作検証を行いヘッダを一部修正 --ライブラリソースのエンコードをUTF-8のBOM付きに統一 --新しく追加されたDynamixelの定義を追加 -2019/03/27 Ver.4.2~ #ref(http://www.besttechnology.co.jp/download/DXLIB_V4.2.zip) 内容 --追加APIの正式リリース --C言語による追加APIのサンプルプログラムを拡充 --Pythonによるサンプルプログラムを拡充 -2016/07/13 Ver.3.3~ #ref(http://www.besttechnology.co.jp/download/DXLIB_V3.3.zip) 内容 --Linux上でのttyの初期化処理を修正 --Linux上でのスリープ命令をusleepに置換する様に変更 -2016/01/12 Ver.3.2~ #ref(http://www.besttechnology.co.jp/download/DXLIB_V3.2.zip) 内容 --ヘッダファイルを最近のVCで使用するとエラーになるのを修正 --DLLMainの不用意な呼び出しで余計な処理をしないよう対応 --デバイス毎に異なるパケットサイズの制限のうち最小に合わせていたが、ライブラリ内では250バイトとする --GCCがやたらエラーを吐くので、ライブラリソースのエンコードをUTF-8に統一 -2015/11/18 Ver.3.1~ #ref(http://www.besttechnology.co.jp/download/DXLIB_V3.1.zip) 内容 --TDxAlarmStatus構造体のアライメントがGCCのバージョンによって1バイト境界にならない事があるのを修正 --ヘッダファイルの一部の記述がMSVCに対応していなかったのを修正 --DX_SetBaudrateの処理に待ち時間を挿入 -2014/06/11 Ver.3.0~ #ref(http://www.besttechnology.co.jp/download/DXLIB_V3.0.zip) 内容 --各APIのアドレス指定が8bit幅だったものを16bitに拡張(後継のDYNAMIXEL2に合わせた) --TDxAlarmStatus構造体のアライメントを1バイト境界に変更 --不定なDevice IDを指定された際のクラッシュを簡易的にブロック --似非ReadSync APIを追加 --DX_Reset処理後に1秒の待ち時間を挿入 --dllのソースをC++に --API引数の変更に伴い各サンプルを修正 --LabVIEWのサンプルを大幅に拡充 --EXCELのVBAを64bitに対応 --アーカイブファイル名を変更 -2013/10/10 Ver.2.9.1~ 内容 --DX_SetTimeOutOffsetでオフセットタイムを指定していない場合のデフォルト値が0ではタイムアウトが生じやすいため20に変更 --DX_Ping2の検索最大数を254に修正 --DXLIB.pasに追加したDX_SetTimeOutOffsetの定義ミスを修正 -2013/09/15 Ver.2.9~ 内容 --タイムアウトの値を見定めるのが困難という事から基本的に引数から排除し、内部で理論値を算出する様に変更。 --タイムアウト以外にタイムラグが必要ということでDX_SetTimeOutOffsetを新設。 --USB搭載のマイコンのファームにおいてポートオープンの状態検出の仕様を変更したため、DTRの制御をイネーブルに変更。 --DX_ChangeBaudrateをDX_SetBaudrateに改名。 --サイズを指定する引数はuint32_tに統一。 --Linux対応をさらに進め、USB搭載のマイコン等でioctlによるボーレートの変更が使えないケースに一部対応。 --Win32とLinuxの相違部分を整理して多少見やすくしてみた。 -2013/03/28 Ver.2.8.1~ 内容 --DX_Ping2の初期化部において不定なTDevicdIDを想定していなかったのを修正。 -2013/03/28 Ver.2.8~ 内容 --名称をDXLIB2からDXLIBに戻す。 --ROBO-ONE標準化フォーラムでの総意を元にAPIの定義と型を変更。~ dxlib2.7以前と互換性がなくなるので注意が必要。~ もちろんサンプルも修正。 --64ビット環境が増えてきたため、DLL名のサフィックスを統一。 --Linuxを真面目に対応。 --受信スレッドを完全に廃止し処理をブロッキング化し可読性を向上。 --パケットの整合性チェックを厳密化。 --デバイスからのアラームステータスがAPIの応答に反映されないケースを修正。 -2011/07/20 Ver.2.6~ 内容 --DX_SyncWriteDataをDX_WriteSyncDataへ改名。 --ByteおよびWordのRead/WriteをBlock Read/Writeで簡素化。 --余計な受信データがあった場合でもできるだけ受信処理が進捗する様に改変。 --古いバージョンのmatlabがDEVICEIDを誤認するため型を変更。 -2011/03/28 Ver.2.5.1~ 内容 --放置していたLinuxへの対応をマトモに見直し。 -2011/03/16 Ver.2.5~ 内容 --内部のイベント処理をさらに整理しパフォーマンスを改善。 --イリガルクローズ時のリソースリーク対策。 --DELPHI向けのサンプル追加。 -2011/03/08 Ver.2.4~ 内容 --内部のイベント処理が一部破綻していたのを修正。 --シリアルエラー時の停止措置を解除。 --ゴミデータ受信時の停滞を解消。 -2011/03/03 Ver.2.3 内容 --内部のイベント処理がことごとく破綻していたのを修正。 --DX_ChangeBaudrateの返り値が反転していたいのを修正。 --BROADCASTING IDを使用したPING(DX_Ping2)を追加。 -2011/02/02 Ver.2.2 内容 --ライブラリ構築のオプションを修正し、各言語毎の呼出規約に囚われないファンクション名を吐く様にした。 -2011/02/01 Ver.2.1~ 内容 --呼出規約をstdcallに変更 --LabVIEWのラッパーviの設定を共通化 --新規ターゲット向けにサンプルを追加~ -2010/12/24 Ver.2.0~ 内容 --初期リリース~ アーカイブファイルには以下のファイルが同梱されます。必要に応じて解凍してください。(※最新版のフォルダ構成を記載しています) |DXLIB|dxlib_x32.dll|<|ライブラリ本体 | |~|dxlib_x64.dll|<|~| |~|libdxlib_x32.a|<|GCC用ライブラリ(定義のみ) | |~|libdxlib_x64.a|<|~| |~|dxlib_x32.llb|<|MSVC用ライブラリ(定義のみ) | |~|dxlib_x64.lib|<|~| |~|dxlib.cpp|<|ライブラリソース | |~|dxlib.h|<|ライブラリヘッダ | |~|dxlib_matlab.h|<|matlab用ヘッダ | |~|dxlib.py|<|python用API定義 | |~|dxmemmap.h|<|DX/AX/RX/EX/MXシリーズ用コントロールテーブル定義ヘッダ | |~|makelib.bat|<|ライブラリ再構築用バッチ | |~|83.bat|<|~| |SampleCode|GCCDeveloperLite|smpl*.c |サンプル | |~|~|dxlib.h |DXLIBフォルダに収録されるものと同一 | |~|~|dxmemmap.h |~| |~|~|dxlib_x32.dll |~| |~|~|dxlib_x64.dll |~| |~|DELPHI|Project1.dpr |サンプル | |~|~|Unit1.dfm |~| |~|~|Unit1.pas |~| |~|~|DXLIB.pas |~| |~|~|dxlib_x32.dll |DXLIBフォルダに収録されるものと同一 | |~|~|dxlib_x64.dll |~| |~|LabVIEW2011|sample*.vi |サンプル | |~|~|DXLIB.llb |dllの呼び出しをvi化 | |~|~|DXLIB_DXL.llb |dllの呼び出しをvi化 | |~|~|DXLIB_Wrapper.llb |アクチュエータに特化したvi | |~|~|dxlib_x32.dll |DXLIBフォルダに収録されるものと同一 | |~|EXCEL|text.xls |サンプルシート | |~|~|dxlib_x32.dll |DXLIBフォルダに収録されるものと同一 | |~|~|dxlib_x64.dll |~| |~|Linux|smpl*.c |サンプル | |~|Ruby|smpl*.rb |サンプル | |~|Python|smpl*.py |サンプル | |~|~|dxlib.py |DXLIBフォルダに収録されるものと同一| |~|~|dxlib_x32.dll |~| |~|~|dxlib_x64.dll |~| **開発環境毎の設定 [#u3ff03d9] サンプルを元にいくつかのツール・環境で使用する場合の設定方法を説明します。ここで紹介されないツールにおいても、dllを利用できるのであれば必要とされる操作は概ね同様だと思います。、 ***GCC Developer Lite [#e1d4017c] GCC Developer Liteの詳細については[[こちら>GCC Developer Lite]]。~ 'SampleCode\GCCDeveloperLite'フォルダにはAPIの基本的な使い方を紹介したサンプルが同梱されます。ポート・ボーレート・ID等は使用する環境に合わせて適宜修正して使用します。 ****DLLの静的リンク [#la562acf] 静的にDLLを使用する場合は以下の手順でDLLをリンクする指定を行った上でコンパイルします。なお32bit環境を前提とします。 +ファイルの準備~ ~ダウンロードファイルを解凍後、コンパイルするソースファイルと同一フォルダに以下のファイルをコピー~ |=ファイル |=ファイル名 |=備考 | |<ヘッダ |<dxlib.h |<必要な宣言を集約 | |<DLL |<dxlib_x32.dll |<DLL本体(実行時およびリンク時に必要) | +コンパイルオプションの選択 ~ツールメニュー→コンパイラオプションをクリックし、表示されるダイアログボックスの設定リストから'x86 (Console)'を選択~ #ref(GCC_CompileOption_sel.png)~ +ライブラリの追加 ~etc...タブ内の追加ボタンを押し、新規に行を追加~ #ref(GCC_CompileOption_AddEtc.png)~ ~新規に追加された空の行をクリックし'dxlib_x32.dll'と入力~ #ref(GCC_CompileOption_AddDxlib2.png)~ ~OKを押して設定を反映 ****DLLの動的リンク [#y15bf22f] 動的にDLLを使用する場合はDLL自体をコンパイラオプションへ追記する必要はありません。その代わりにソース中でdxlib.hをインクルードする前に_DYNAMICLOADマクロを定義しておきます。 #define _DYNAMICLOAD #include "dxlib.h" これによりヘッダファイル内の諸定義が切り替わり、DLLのロード及びアンロードを行うLoadDLLとUnloadDLLが利用できるようになります。 TDeviceID dev; // DLLをロード if (LoadDLL ()) { if ((dev = DX_OpenPort (COMPORT, BAUDRATE))) { ... DX_ClosePort (dev); } // DLLをアンロード UnloadDLL (); } ***Microsoft Visual C++ [#j5a74d33] [[Visual C++ 2010 Express:http://www.microsoft.com/japan/msdn/vstudio/express/]]でDLLの静的なリンク方法のみ紹介します。 +ファイルの準備~ ~ダウンロードファイルを解凍後、コンパイルするソースファイルと同一フォルダに以下のファイルをコピー~ |=ファイル |=ファイル名 |=備考 | |<ヘッダ |<dxlib.h |<必要な宣言を集約 | |<DLL |<dxlib_x32.dll |<実行時に必要 | |<ライブラリ |<dxlib_x32.lib |<リンク時に必要 | +プロジェクトのプロパティを変更~ ~構成プロパティ→C/C++→全般→追加のインクルードディレクトリの項目にヘッダファイルの格納フォルダを指定~ #ref(VCC_property_include.png)~ ~構成プロパティ→リンカー→全般→追加のライブラリディレクトリの項目にLIBファイルの格納フォルダを指定~ #ref(VCC_property_lib_path.png)~ ~構成プロパティ→リンカー→入力→追加の依存ファイルの項目にLIBファイル名を指定~ #ref(VCC_property_lib_file.png)~ ~構成プロパティ→C/C++→プリコンパイル済ヘッダーの項目にプリコンパイル済ヘッダーを使用しないを指定~ #ref(VCC_property_precompile.png) ***National Instruments LabVIEW [#mdd5d507] 'SampleCode\LabVIEW2011'フォルダにサンプルが同梱されます。ポート・ボーレート・ID等は使用する環境に合わせて適宜修正して使用します。~ [[LabVIEW:http://www.ni.com/labview/ja/]]には外部のDLLへアクセスする手段が提供されています。しかしながらDXLIBそのままの定義ではLabVIEWからは使いづらいため、サンプルプログラムではサブviでラッピングしてDXLIB.llbにまとめて提供しています。 #ref(vi_frontpanel.png) #ref(vi_diagram.png) ****関数パレットへの登録 [#v135be5a] DXLIB.llbから各viを開き、開いたviの右上にあるアイコンを自分のブロックダイアグラムにドラッグドロップするという操作でviを使用しても良いのですが、頻繁に操作するとなると少々煩雑です。~ 関数パレットに登録すればスムーズに操作できますので、その手順を紹介します。 +LabVIEWのメニューの「ツール」→「上級」→パレットセットを編集」をクリック。 #ref(lvmenu_step1.png,100%) +開いた関数パレットの空いたスペースで右クリックし、ポップアップメニューから「挿入」→「サブパレット」をクリック。 #ref(lvmenu_step2.png,100%) +開いたダイアログボックスから「LLBへリンク(.llb)」を選びOKを押す。 #ref(lvmenu_step3.png,100%) +LLBを選択するファイルダイアログボックスから、先に解凍したファイルの中から「DXLIB.llb」を選択しOKを押す。 #ref(lvmenu_step4.png,100%) +次の様なメニューが追加されたらOK。 #ref(lvmenu_step5.png,100%) ***DELPHI [#bdd8ef87] 'SampleCode\DELPHI'フォルダにサンプルが同梱されます。ポート・ボーレート・ID等は使用する環境に合わせて適宜修正して使用します。~ [[DELPHI:http://www.embarcadero.com/jp/products/delphi]]はPASCAL言語によるPC向け開発ツールであり、外部のDLLへ容易にアクセスする事が出来ます。サンプルに含まれるDXLIB.pas内にdxlib_x32.dllないしdxlib_x64.dllを動的にロードする関数を用意しましたので、ユーザソースのuses節にdxlibを追記すればDynamixel Libraryの各APIへ簡便にアクセスできます。 ***VB [#p8d7963b] 'SampleCode\EXCEL'フォルダにサンプルが同梱されます。~ ここではVBと似たMicrosoft OfficeのVBAを使用し、マクロの標準モジュールにDXLIB_HEADという名称でDLLに含まれるいくつかのAPIが定義してあります。~ Module1にPingTestとMotorTestというマクロが記述されていますので、ワークシートから適宜マクロを呼び出して実行してください。結果がシート上に反映されます。 なお、Officeにも32bit版と64bit版があるため、Declare宣言の方法が異なります。その部分はDXLIB_HEADにて判定していますので、参考にしてください。 ***Ruby [#r63b1e3e] 'SampleCode\Ruby'フォルダにサンプルが同梱されます。ポート・ボーレート・ID等は使用する環境に合わせて適宜修正して使用します。~ [[Ruby:http://www.ruby-lang.org/ja]]はオープンソースの動的なプログラミング言語で、外部のDLLへ簡易にアクセスすることが出来ます。~ require 'dl/import' molude dxlib extend DL::Importer dlload "./dxlib_x32.dll" extern "int DX_OpenPort( char *, long )" end devid = dxlib.DX_OpenPort( "ポート名", ボーレート ) ***Python [#mc6a5a49] 'SampleCode\Python'フォルダにサンプルが同梱されます。ポート・ボーレート・ID等は使用する環境に合わせて適宜修正して使用します。~ [[Python:http://www.python.jp/]]はオープンソースの動的なプログラミング言語で、外部のDLLへ簡易にアクセスすることが出来ます。~ 各APIのPython用の宣言を定義したdxlib.pyをimportするだけで済みます。 from dxlib import * # dxlibをインポート ***Java [#ceff395d] ***MathWorks MATLAB [#mad2ebed] [[MATLAB:http://www.mathworks.co.jp/products/matlab]]からの使用例を紹介します。ポート・ボーレート・ID等は使用する環境に合わせて適宜修正して下さい。また、mex-setupにて[[Cコンパイラを選択>http://www.mathworks.co.jp/jp/help/matlab/matlab_external/building-mex-files.html#f23734]]しておく必要があります。~ +事前準備 ~まずはMATLAB起動後、「ファイル(F)」→「パス設定(H)」でdxlib_x32.dll(MATALBが64bitの場合はdxlib_x64.dll)とdxlib_matlab.hの格納されたパスを指定します。dxlib.hはMATLABでは解釈できない記述が多いため使用しないでください。~ +DLLのロード loadlibrary('dxlib_x32.dll','dxlib_matlab.h','alias','dxlib') +ポートのオープン ~ロードされたdxlibのDX_OpenPortを呼出します。関数名の後はポートとボーレートです。 devid = calllib('dxlib','DX_OpenPort','\\.\COM3',1000000) +TErrorCodeの取得 ~TErrorCodeはポインタで引き渡しているため、事前に型宣言をしておきます。値はErr.Valueで取得可能です。必要なければ0を指定しても構いません。 Err = libpointer('uint16Ptr', 0); Ret = calllib('dxlib', 'DX_Ping', devid, 1, Err); fprintf('%x', Err.Value); +ポートのクローズ ~DX_OpenPortを行ったので、DX_ClosePortを使用してポートを閉じます。 calllib('dxlib','DX_ClosePort',devid) +DLLのアンロード unloadlibrary('dxlib') ***Linux [#w5c096b8] Linux上でdxlibをコンパイルする方法を紹介します。~ +コンパイル準備~ ダウンロードファイルを解凍~ +ライブラリファイルの生成~ $ gcc -c -D__MAKE_LIB__ dxlib_intuitive.cpp dxlib.cpp $ ar -rcsv libdxlib.a dxlib_intuitive.o dxlib.o +共有ライブラリの作成~ RubyやPython等で使用する場合等~ $ gcc -fPIC -shared -D__MAKE_LIB__ dxlib_intuitive.cpp dxlib.cpp -o dxlib.so.4.2 +ユーザプログラムとのリンク~ 生成したライブラリファイルと自身のソースをリンクする。~ ポート・ボーレート等は使用する環境に合わせて適宜追加・修正する。~ ライブラリは必要に合わせて追加する。~ $ gcc sample.c -ldxlib -o sample なお、コンパイルや実行にあたってI/Fやカーネル・ディストリビューションに依存するのがLinuxですので、そのまま使用できない場合は適宜ソースを修正下さい。 **API [#ybae1454] 本ライブラリはシリアル通信を行うコードを記述しなくて良いのですが、デバイスIDという番号を用いて使用するシリアルI/Fを一元的に管理します。また、制御対象となるDynamixelのIDを指定し、そのコントロールテーブルへの読み書き行うAPIが用意されています。~ 自身のC言語で記述されたソースプログラムにdxlib.hをインクルードする事で、APIを使用するのに必要なプロトタイプとマクロの定義がなされます。 ''注意事項'':~ DynamixelのStatus Return Levelを必ず''2''に設定した上で使用する事。それ以外の値が設定されていた場合はAPIが想定した応答が得られず、タイムアウトするまでAPIから返らない。 ***DX_OpenPort [#zbd2f6ef] ライブラリの内部情報を初期化すると同時に指定されたCOMポートをオープンし、[[DX_SetBaudrate>#ba9f52b8]]を使用して通信速度を設定した後、ユニークな[[TDeviceID>#TDeviceID]]を返す。以後はこの[[TDeviceID>#TDeviceID]]を使用して各APIを使用する。~ 複数のCOMポートを使用する場合は、使用するポート毎にDX_OpenPortを行い[[TDeviceID>#TDeviceID]]を取得しなくてはならない。~ なお、Linuxにおけるボーレートの指定に関しては、[[DX_SetBaudrate>#ba9f52b8]]の解説に注意の事。 TDeviceID DX_OpenPort (char *name, uint32_t baud); -パラメータ --char '''*name''' ~インターフェースが提供するCOMポート名。~ 記述方法は[[こちら:http://support.microsoft.com/default.aspx?scid=kb;ja;JP115831]]の情報に従う。 --long '''baud''' ~インターフェースとデバイス間の通信速度[bps]。 -戻り値 --[[TDeviceID>#TDeviceID]]~ ~オープンに成功した場合は0以外の値、失敗した場合は0を返す。~ -使用例 TDeviceID dev; // COM10を9600bpsでオープン dev = DX_OpenPort ("\\\\.\\COM10", 9600); ***DX_ClosePort [#w1ab7cbb] DX_OpenPortで開いたCOMポートを閉じる。~ DX_ClosePortが実行された以後は指定された[[TDeviceID>#TDeviceID]]での通信が行えなくなる。 bool DX_ClosePort (TDeviceID dvid); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 -戻り値 --bool ~クローズに成功した場合はtrue、失敗した場合はfalseを返す。 -使用例 TDeviceID dev; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 9600); if (dev) { ... (中略) // クローズ DX_ClosePort (dev); } ***DX_SetBaudrate [#ba9f52b8] 既にオープンされている[[TDeviceID>#TDeviceID]]の通信速度の変更を行う。~ 実行すると強制的に受信バッファがクリアされる。~ なお、Linux環境におけるボーレートの設定は、POSIX.1でサポートする値(50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000)であればtcsetattrを使用して処理するが、これらの値に当てはまらない場合はioctrlを使用する。その際I/Fがこれらのボーレートに対応していなかったり、ioctrlをサポートしない場合、本APIは失敗する。 bool DX_SetBaudrate (TDeviceID dvid, long baud); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --long '''baud'''~ ~新しい通信速度[bps]。 -戻り値 --bool ~通信速度の変更が成功するとtrue、失敗するとfalseを返す。~ -使用例 TDeviceID dev; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 9600); if (dev) { // 通信速度を1M[bps]に変更 DX_SetBaudrate (dev, 1000000); ... (中略) // クローズ DX_ClosePort (dev); } ***DX_Active [#ie20e4a7] 指定された[[TDeviceID>#TDeviceID]]のポートが開かれており、使用可能であるかを確認する。~ USB接続等によりインターフェース自体が取り外し可能な場合に、実際に使用可能であるかを判断するために使用するが、状況によっては正確に判断できない場合もある。 bool DX_Active (TDeviceID dvid); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 -戻り値 --bool ~指定されたdvidが使用可能な場合はtrue、使用不可の場合はfalseを返す。 -使用例 TDeviceID dev; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 9600); if (dev) { while (DX_Active (dev)) { ... (中略) } // クローズ DX_ClosePort (dev); } ***DX_SetTimeOutOffset [#h4a1b54e] I/FやOSの都合で生じるであろうタイムラグを予め設定する。~ ライブラリ内で想定した受信時間と指定されたタイムアウトオフセット時間を加算した時間を超えた場合に、タイムアウトエラーとして処理される。~ デフォルトは20。 void DX_SetTimeOutOffset (TDeviceID dvid, uint32_t offsettime); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint32_t '''offsettime''' ~タイムアウトオフセット時間[ms] -戻り値 --bool ~指定されたdvidが使用可能な場合はtrue、使用不可の場合はfalseを返す。 ***DX_Ping [#v393b505] PINGインストラクションを使用して対象IDからの応答を確認する。 bool DX_Ping (TDeviceID dvid, uint8_t id, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~254)。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~正常な応答が得られた場合はtrue、それ以外はfalseを返す。~ -使用例 TDeviceID dev; TErrorCode err; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 57143); if (dev) { // ID=1にPINGを発行 if (DX_Ping (dev, 1, &err)) printf ("Found [%08X]\n", err); else printf ("Not found [%08X]\n", err); // クローズ DX_ClosePort (dev); } ***DX_Ping2 [#g16504b3] PINGインストラクションでBROADCASTING IDを指定して不特定の対象の応答を確認する。~ 応答時間がDynamixelの種類によって差があるため、それらが混在している環境では正確な情報を取得できない場合がある。 bool DX_Ping2 (TDeviceID dvid, uint32_t *num, TDxAlarmStatus *AlarmStatus, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint32_t '''*num''' ~検索する最大数及び検索で見つかったデバイス数の保存先。 --[[TDxAlarmStatus>#TDxAlarmStatus]] '''*AlarmStatus''' ~検索で見つかったデバイス情報の保存先。~ 少なくともnumで指定したサイズを確保しておく必要がある。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~1台以上のデバイスからの応答が得られた場合はtrue、それ以外はfalseを返す。~ -使用例 TDeviceID dev; TErrorCode err; uint8_t id; TDxAlarmStatus stat[254]; int i; uint32_t num = 254; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 57143); if (dev) { // 不明な対象に対してPINGを発行 // numには予め254の値を指定したので、最大254台まで見つけようとする if (DX_Ping2 (dev, &num, stat, &err)) { // 1台以上見つかるとnumには見つかった数が返ってくる for (i = 0; i < num; i++) printf ("Found ID=%d %02X\n", stat[i].id, stat[i].Status); } // クローズ DX_ClosePort (dev); } ***DX_ReadByteData [#u7d86432] 対象IDのコントロールテーブルから1バイトのデータを読み出す。 bool DX_ReadByteData(TDeviceID dvid, uint8_t id, uint16_t adr, uint8_t *rdata, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~253)。 --uint16_t '''adr''' ~コントロールテーブルのアドレス。 --uint8_t '''*rdata''' ~読み出した値の保存先。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~正常な応答が得られた場合はtrue、それ以外はfalseを返す。~ -使用例 TDeviceID dev; TErrorCode err; uint8_t dat; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のAX-12からLEDの状態を取得 if (DX_ReadByteData (dev, 1, 25, &dat, &err)) { printf ("LED STAT=%d\n", dat); } DX_ClosePort (dev); } ***DX_WriteByteData [#ma2205f0] 対象IDのコントロールテーブルへ1バイトのデータを書き込む。 bool DX_WriteByteData(TDeviceID dvid, uint8_t id, uint16_t adr, uint8_t dat, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~253, 254)。 --uint16_t '''adr''' ~コントロールテーブルのアドレス。 --uint8_t '''dat'''~ ~書き込む値。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~正常な応答が得られた場合はtrue、それ以外はfalseを返す。~ BROADCASTING IDを指定した場合は応答待ちを行わない。 -使用例 TDeviceID dev; TErrorCode err; uint8_t dat; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のAX-12からLEDの状態を取得 if (DX_ReadByteData (dev, 1, 25, &dat, &err)) { dat ^= 1; // ビット反転 // ID=1のAX-12へLEDの状態を設定 DX_WriteByteData (dev, 1, 25, dat, &err); } DX_ClosePort (dev); } ***DX_ReadWordData [#x202d573] 対象IDのコントロールテーブルから1ワード(2バイト)のデータを読み出す。 bool DX_ReadWordData(TDeviceID dvid, uint8_t id, uint16_t adr, uint16_t *rdata, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~253)。 --uint16_t '''adr''' ~コントロールテーブルのアドレス。 --uint16_t '''*rdata''' ~読み出した値の保存先。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~正常な応答が得られた場合はtrue、それ以外はfalseを返す。~ -使用例 TDeviceID dev; TErrorCode err; uint16_t dat; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のAX-12から現在位置を取得 if (DX_ReadWordData (dev, 1, 36, &dat, &err)) { printf ("PRESENT POS=%d\n", dat); } DX_ClosePort (dev); } ***DX_WriteWordData [#pcc1b3ce] 対象IDのコントロールテーブルへ1ワード(2バイト)のデータを書き込む。 bool DX_WriteWordData(TDeviceID dvid, uint8_t id, uint16_t adr, uint16_t dat, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~253, 254)。 --uint16_t '''adr''' ~コントロールテーブルのアドレス。 --uint16_t '''dat''' ~書き込む値。 --[[TErrorCode>#TErrorCode]] '''*errcode''' ~エラーコード。 -戻り値 --bool ~正常な応答が得られた場合はtrue、それ以外はfalseを返す。~ BROADCASTING IDを指定した場合は応答待ちを行わない。 -使用例 TDeviceID dev; TErrorCode err; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のAX-12へ位置(511)を指令 DX_WriteWordData (dev, 1, 30, 511, &err); DX_ClosePort (dev); } ***DX_ReadLongData [#w341e7a5] 対象IDのコントロールテーブルから2ワード(4バイト)のデータを読み出す。 bool DX_ReadLongData(TDeviceID dvid, uint8_t id, uint16_t adr, uint32_t *rdata, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~253)。 --uint16_t '''adr''' ~コントロールテーブルのアドレス。 --uint32_t '''*rdata''' ~読み出した値の保存先。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~正常な応答が得られた場合はtrue、それ以外はfalseを返す。~ -使用例 TDeviceID dev; TErrorCode err; uint32_t dat; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のXM430から現在位置を取得 if (DX_ReadLongData (dev, 1, 132, &dat, &err)) { printf ("PRESENT POS=%d\n", dat); } DX_ClosePort (dev); } ***DX_WriteLongData [#k42e5e5f] 対象IDのコントロールテーブルへ2ワード(4バイト)のデータを書き込む。 bool DX_WriteLongData(TDeviceID dvid, uint8_t id, uint16_t adr, uint32_t dat, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~253, 254)。 --uint16_t '''adr''' ~コントロールテーブルのアドレス。 --uint32_t '''dat''' ~書き込む値。 --[[TErrorCode>#TErrorCode]] '''*errcode''' ~エラーコード。 -戻り値 --bool ~正常な応答が得られた場合はtrue、それ以外はfalseを返す。~ BROADCASTING IDを指定した場合は応答待ちを行わない。 -使用例 TDeviceID dev; TErrorCode err; // オープン dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のXM430へ位置(1024)を指令 DX_WriteLongData (dev, 1, 30, 1024, &err); DX_ClosePort (dev); } ***DX_ReadBlockData [#b8a1ae1e] 対象IDのコントロールテーブルから指定サイズのデータを読み出す。 bool DX_ReadBlockData (TDeviceID dvid, uint8_t id, uint16_t adr, uint8_t *rdata, uint32_t len, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~253)。 --uint16_t '''adr''' ~コントロールテーブルのアドレス。 --uint8_t '''*rdata''' ~読み出したデータの保存先。 --uint32_t '''len''' ~読み出すデータのサイズ。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~正常な応答が得られた場合はtrue、それ以外はfalseを返す。~ -使用例 TDeviceID dev; TErrorCode err; uint8_t comp[4]; dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のAX-12+からコンプライアンスのデータを取得 if (DX_ReadBlockData (dev, 1, 26, comp, 4, &err) { printf ( "CWM=%d CCWM=%d CWS=%d CCWS=%d\n", comp[0], comp[1], comp[2], comp[3] ); } DX_ClosePort (dev); } ***DX_WriteBlockData [#fcf55aa0] 対象IDのコントロールテーブルへ指定サイズのデータを書き込む。 bool DX_WriteBlockData(TDeviceID dvid, uint8_t id, uint16_t adr, uint8_t *dat, uint32_t len, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~253, 254)。 --uint16_t '''adr''' ~コントロールテーブルのアドレス。 --uint8_t '''*dat''' ~書き込むデータの保存先。 --uint32_t '''len''' ~書き込むデータのサイズ。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~正常な応答が得られた場合はtrue、それ以外はfalseを返す。~ BROADCASTING IDを指定した場合は応答待ちを行わない。 -使用例 TDeviceID dev; TErrorCode err; uint8_t comp[4] = { 0, 1, 200, 200 }; dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のAX-12+のコンプライアンスを変更 DX_WriteBlockData (dev, 1, 26, comp, 4, &err); DX_ClosePort (dev); } ***DX_ReadSyncData [#oc111b2e] SYNCインストラクションには読み出し機能が無いが、DX_ReadBlockDataを使用して指定された複数IDからブロック読み出しを行う。正確には「同期」していない。 bool DX_ReadSyncData (TDeviceID dvid, uint8_t *dat, uint32_t size, uint8_t *retdat, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''*dat''' ~読み出す情報の保存先~ [addr][length][ID1][ID2]...[IDn]~ addr:先頭アドレス (1バイト)~ length:先頭アドレスからのバイト数 (1バイト)~ IDn:読み出す対象IDを列挙 (nバイト)。 --uint32_t '''size''' ~datのサイズ。 --uint8_t '''result'''~ 読み出したデータの保存先~ [ID1][ALARM1][DATA1_0]....[DATA1_m]~ [ID2][ALARM2][DATA2_0]....[DATA2_m]~ ... [IDn][ALARMn][DATAn_0]....[DATAn_m]~ IDn:対象ID (1バイト)~ ALARMn:TErrorCode (2バイト)~ DATAn_m:読み出されたデータ --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~指定された全てのIDに対する読み出しが正常に完了したらtrue、それ以外はfalseを返す。~ ***DX_WriteSyncData [#v566e16b] SYNCインストラクションを使用して複数IDへブロック書き込みを行う。~ 書き込まれるデータの構成はユーザに委ねられる。 bool DX_WriteSyncData (TDeviceID dvid, uint8_t *dat, uint32_t size, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''*dat''' ~書き込むパラメータの保存先。 --uint32_t '''size''' ~パラメータのサイズ。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 --bool ~インターフェースより送信が行われた場合はtrue、それ以外はfalseを返す。~ -使用例 #define _POS1 (400) #define _POS2 (511) TDeviceID dev; TErrorCode err; uint8_t param[8] = { 30, // アドレス (Goal Position) 2, // データ長 (2 byte) // ID=1用データ 1, _POS1 & 0xff, _POS1 >> 8, // ID=2用データ 2, _POS2 & 0xff, _POS2 >> 8 }; dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // 2つのAX-12へ同時に位置を指令 DX_WriteSyncData (dev, param, 8, &err); DX_ClosePort (dev); }; ***DX_TxPacket [#r051327a] 任意のインストラクションパケットを送信する。 bool DX_TxPacket (TDeviceID dvid, uint8_t id, TInstruction inst, uint8_t *param, uint32_t len, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''id''' ~対象とするID (0~254)。 --[[TInstruction>#TInstruction]] '''inst''' ~使用するインストラクション。 --uint8_t '''*param''' ~送信するパラメータの保存先。 --uint32_t '''len'''~ ~送信するパラメータのサイズ。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 ~インターフェースより送信が行われた場合はtrue、それ以外はfalseを返す。 -使用例 TDeviceID dev; TErrorCode err; uint8_t param[2] = { 25, // アドレス (LED) 0, // データ }; dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のAX-12+のLEDを消灯 DX_TxPacket (dev, 1, INST_WRITE, param, 2, &err); DX_ClosePort (dev); }; ***DX_RxPacket [#r280cda8] ステータスパケットを受信する。~ 基本的にDX_TxPacketとペアで使用する。ステータスパケットが得られない状況で使用するとタイムアウトするまで返らない。~ なお、本APIは[[DX_SetTimeOutOffset>#h4a1b54e]]で設定されたオフセット値は使用せず、引数で指定された受信タイムアウトのみが適用される。 bool DX_RxPacket (TDeviceID dvid, uint8_t *rdata, uint32_t rdatasize, uint32_t *rlen, uint32_t timeout, TErrorCode *err); -パラメータ --[[TDeviceID>#TDeviceID]] '''dvid''' ~DX_OpenPortで開いた際の[[TDeviceID>#TDeviceID]]。 --uint8_t '''*rdata''' ~受信バッファ。~ ステータスパケットを受信するのに十分なサイズを確保しておく必要がある。 --uint32_t '''readsize''' ~rdataのサイズ。~ --uint32_t '''*rlen''' ~実際に受信されたステータスパケットのサイズ。 --int '''timeout''' ~受信タイムアウト[ms]。 --[[TErrorCode>#TErrorCode]] '''*err''' ~エラーコード。 -戻り値 ~受信成功時はtrue、それ以外はfalseを返す。 -使用例 int i; uint32_t len; TDeviceID dev; TErrorCode err; uint8_t param[2] = { 25, // アドレス (LED) 1, // サイズ }; dev = DX_OpenPort ("\\\\.\\COM10", 1000000); if (dev) { // ID=1のAX-12+からLEDの状態を読み出す要求 if (DX_TxPacket (dev, 1, INST_READ, param, 2, &err)) { // ステータスパケットを受信 DX_RxPacket (dev, dat, sizeof (dat), &len, 100, &err); for (i = 0; i < len; i++) { printf ("[%02X]", dat[i]); } } DX_ClosePort (dev); }; ***DXLIBのオリジナルな定義 [#af9ca340] &aname(TDeviceID); :TDeviceID | ''(uint32_t|uint64_t)''~ インターフェース毎に割り当てられるユニークな値。DX_OpenPortにて自動的に生成される。 &aname(TInstruction);~ :TInstruction | ''(uint8_t)''~ DX_TxPacketにてインストラクションパケットを送信する場合に使用される。~ 使用可能なマクロは以下の通り。~ ~INST_PING~ INST_READ~ INST_WRITE~ INST_REG_WRITE~ INST_ACTION~ INST_RESET~ INST_SYNC_WRITE~ INST_SYNG_REG_WRITE &aname(TDxAlarmStatus); :TDxAlarmStatus | struct {&br; uint8_t id;&br; TErrorCode Status;&br; }~ idとTErrorCodeを対にした構造体。 &aname(TErrorCode); :TErrorCode | ''(uint16_t)''~ API内で検出される16ビットのエラーコード。上位8ビットはAPI内部で検出したエラー、下位8ビットはステータスパケットに含まれるエラーフラグが割り当てられている。~ |CENTER:|LEFT:|LEFT:|c |bit|macro name| |h |15|ERR_INVALID_DEVID|使用できないTDeviceID | |14|ERR_INVALID_ID|指定できないID | |13|ERR_DIFF_ID|異なるIDからの応答 | |12|ERR_ILLEGAL_SIZE|異常なデータサイズ | |11|ERR_INVALID_PARAM|異常なパラメータ | |10|ERR_COMM|シリアルポートエラー | |9|ERR_CHECKSUM|異常なチェックサム | |8|ERR_TIMEOUT|受信タイムアウト | |7| | | |6|ERR_DX_INST|未定義のインストラクションが指定された、もしくはreg_writeなしでactionが指定された| |5|ERR_DX_OVERLOAD|指定された最大トルクで現在の負荷を制御できない| |4|ERR_DX_CHECKSUM|インストラクションパケットのチェックサムが正しく無い| |3|ERR_DX_RANGE|パラメータの設定範囲を超えた| |2|ERR_DX_OVERHEAT|内部温度が設定温度を超えた| |1|ERR_DX_ANGLE|Angle Limitの範囲外にGoal Positionが指定された| |0|ERR_DX_OVERVOLTAGE|電源電圧が指定動作電圧の範囲を超えた| **追加API [#i7e58b8f] #include(DXL_intuitive,notitle)
(This host) = https://www.besttechnology.co.jp