17: 2021-10-03 (日) 21:54:42 takaboo | 現: 2023-11-12 (日) 00:09:35 takaboo | ||
---|---|---|---|
Line 4: | Line 4: | ||
シリアル通信に関するAPI、タイミングやエラー処理、プロトコルの整合性チェック等をライブラリ内で行うため、シリアル通信である事をほとんど意識する事無くアプリケーションの作りこみに専念できます。 | シリアル通信に関するAPI、タイミングやエラー処理、プロトコルの整合性チェック等をライブラリ内で行うため、シリアル通信である事をほとんど意識する事無くアプリケーションの作りこみに専念できます。 | ||
- | なお、PCと[[BTE061D]]・[[BTE061E]]・[[BTE068]]・[[BTE068B]]・[[BTE068C]]・[[BTE082]]・[[BTE083]]・[[BTE074]]・[[BTE079]]・[[BTE080]]・[[BTE079B]]・[[BTE080B]]・[[BTE079C]]・[[BTE080C]]・[[BTE096]]・[[BTX229>http://emanual.robotis.com/docs/en/parts/interface/u2d2/]]のいずれかがUSBポートに接続され、PCのOSに仮想COMポートが増設された状態で使用するものとします。[[BTE100]]の場合はRaspberry Piに依存します。 | + | なお、PCと[[BTE061D]]・[[BTE061E]]・[[BTE068]]・[[BTE068B]]・[[BTE068C]]・[[BTE082]]・[[BTE083]]・[[BTE074]]・[[BTE074B]]・[[BTE079]]・[[BTE080]]・[[BTE079B]]・[[BTE080B]]・[[BTE079C]]・[[BTE080C]]・[[BTE096]]・[[BTE101]]・[[BTE110]]・[[BTX229>http://emanual.robotis.com/docs/en/parts/interface/u2d2/]]のいずれかがUSBポートに接続され、PCのOSに仮想COMポートが増設された状態で使用するものとします。[[BTE100]]の場合はRaspberry Piに依存します。 |
|CENTER:BGCOLOR(red): :idea:|[[DYNAMIXEL Communiation Protocol 1.0]]と[[DYNAMIXEL Communiation Protocol 2.0]]を装備した装置を同一ネットワーク上で同時に運用する事は推奨できない。| | |CENTER:BGCOLOR(red): :idea:|[[DYNAMIXEL Communiation Protocol 1.0]]と[[DYNAMIXEL Communiation Protocol 2.0]]を装備した装置を同一ネットワーク上で同時に運用する事は推奨できない。| | ||
Line 10: | Line 10: | ||
**ライブラリおよびサンプルプログラムのダウンロード [#j8bd290f] | **ライブラリおよびサンプルプログラムのダウンロード [#j8bd290f] | ||
以下のリンクよりライブラリ及びサンプルプログラムをアーカイブしたファイルがダウンロードできます。 | 以下のリンクよりライブラリ及びサンプルプログラムをアーカイブしたファイルがダウンロードできます。 | ||
- | -''2021/10/8 Ver.2.8''~ | + | -''2023/11/6 Ver.3.0''~ |
+ | #ref(https://www.besttechnology.co.jp/download/DX2LIB_V3.0.zip) | ||
+ | 更新内容 | ||
+ | --最新GCC Developer Liteの更新に伴うコンパイル環境の調整 | ||
+ | --python向けのサンプルを拡充 | ||
+ | -2022/3/1 Ver.2.9~ | ||
+ | #ref(https://www.besttechnology.co.jp/download/DX2LIB_V2.9.zip) | ||
+ | 更新内容 | ||
+ | --最新GCC Developer Liteの更新に伴うコンパイル環境の調整 | ||
+ | --新しく追加されたDynamixelの定義を追加 | ||
+ | --コンパイル用バッチファイルの名称を変更 | ||
+ | --バッチファイル中のパスの指定はジャンクションを使用する事で空白を含むファイル名によるコンパイル時の問題を回避 | ||
+ | -2021/10/8 Ver.2.8 | ||
#ref(https://www.besttechnology.co.jp/download/DX2LIB_V2.8.zip) | #ref(https://www.besttechnology.co.jp/download/DX2LIB_V2.8.zip) | ||
更新内容 | 更新内容 | ||
Line 76: | Line 88: | ||
|~|dx2lib_matlab.h|<|matlab用ヘッダ | | |~|dx2lib_matlab.h|<|matlab用ヘッダ | | ||
|~|dx2lib.py|<|python用モジュール | | |~|dx2lib.py|<|python用モジュール | | ||
- | |~|makelib.bat|<|Windows向けライブラリ再構築用バッチ | | + | |~|makelib.cmd|<|Windows向けライブラリ再構築用バッチ | |
- | |~|83.bat|<|~| | + | |
|~|build_dx2lib.sh|<|Linux向けライブラリ再構築用スクリプト | | |~|build_dx2lib.sh|<|Linux向けライブラリ再構築用スクリプト | | ||
|SampleCode|C|smpl??.c |サンプル | | |SampleCode|C|smpl??.c |サンプル | | ||
Line 83: | Line 94: | ||
|~|~|kbhit.h |kbhitエミュレーション | | |~|~|kbhit.h |kbhitエミュレーション | | ||
|~|~|makefile |サンプルコンパイル用makefile | | |~|~|makefile |サンプルコンパイル用makefile | | ||
- | |~|~|makewin.bat|Windows向け再構築用バッチ | | + | |~|~|makeexe.cmd|Windows向け再構築用バッチ | |
- | |~|~|83.bat|~| | + | |
|~|~|dx2lib.h |DX2LIBフォルダに収録されるものと同一 | | |~|~|dx2lib.h |DX2LIBフォルダに収録されるものと同一 | | ||
|~|~|dx2memmap.h |~| | |~|~|dx2memmap.h |~| | ||
Line 142: | Line 152: | ||
動的にDLLを使用する場合はDLL自体をコンパイラオプションへ追記する必要はありません。その代わりソース中でdx2lib.hをインクルードする前に_DYNAMICLOADマクロを定義しておきます。 | 動的にDLLを使用する場合はDLL自体をコンパイラオプションへ追記する必要はありません。その代わりソース中でdx2lib.hをインクルードする前に_DYNAMICLOADマクロを定義しておきます。 | ||
#html{{ | #html{{ | ||
+ | <style type="text/css"> | ||
+ | .syntaxhighlighter { | ||
+ | overflow-y: auto !important; | ||
+ | overflow-x: auto !important; | ||
+ | max-height: 900px; | ||
+ | -webkit-text-size-adjust: 100%; | ||
+ | } | ||
+ | </style> | ||
<pre class="brush: c;"> | <pre class="brush: c;"> | ||
#define _DYNAMICLOAD | #define _DYNAMICLOAD | ||
Line 165: | Line 183: | ||
****サンプルフォルダ内のmakefileを使用 [#a00c8b73] | ****サンプルフォルダ内のmakefileを使用 [#a00c8b73] | ||
- | サンプルをコンパイルするだけならばGCC Developer Liteを起動する必要は無く、サンプルフォルダ内に同梱される「makewin.bat」を実行すればmakefileを読み込んでGCC Developer Liteに同梱されるmakeを使用してコンパイルします。~ | + | サンプルをコンパイルするだけならばGCC Developer Liteを起動する必要は無く、サンプルフォルダ内に同梱される「makeexe.cmd」を実行すればmakefileを読み込んでGCC Developer Liteに同梱されるmakeを使用してコンパイルします。~ |
引数にソース名をしていするとそのソースだけコンパイル、何も付けなければフォルダ内の拡張子がCのソースファイル全てがコンパイル対象となります。 | 引数にソース名をしていするとそのソースだけコンパイル、何も付けなければフォルダ内の拡張子がCのソースファイル全てがコンパイル対象となります。 | ||
#html{{ | #html{{ | ||
<pre class="brush: bash;"> | <pre class="brush: bash;"> | ||
- | makewin sample2_ping2 (特定のソースのみコンパイル) | + | makeexe sample2_ping2 (特定のソースのみコンパイル) |
- | makewin (カレントの全ソースをコンパイル) | + | makeexe (カレントの全ソースをコンパイル) |
</pre> | </pre> | ||
}} | }} | ||
Line 288: | Line 306: | ||
#html{{ | #html{{ | ||
<pre class="brush: bash;"> | <pre class="brush: bash;"> | ||
- | wget https://www.besttechnology.co.jp/download/DX2LIB_V2.8.zip | + | wget https://www.besttechnology.co.jp/download/DX2LIB_V3.0.zip |
- | unzip DX2LIB_V2.8.zip | + | unzip DX2LIB_V3.0.zip |
</pre> | </pre> | ||
}} | }} | ||
Line 297: | Line 315: | ||
#html{{ | #html{{ | ||
<pre class="brush: bash;"> | <pre class="brush: bash;"> | ||
- | cd DX2LIB_v2.8/DX2LIB | + | cd DX2LIB_v3.0/DX2LIB |
bash ./build_dx2lib.sh | bash ./build_dx2lib.sh | ||
</pre> | </pre> | ||
Line 320: | Line 338: | ||
}} | }} | ||
コンパイルや実行にあたってI/Fやカーネル・ディストリビューションに依存しますので、そのまま使用できない場合は適宜ソースを修正下さい。またWindowsを前提とした_DYNAMICLOADマクロが宣言されているとコンパイルできません。~ | コンパイルや実行にあたってI/Fやカーネル・ディストリビューションに依存しますので、そのまま使用できない場合は適宜ソースを修正下さい。またWindowsを前提とした_DYNAMICLOADマクロが宣言されているとコンパイルできません。~ | ||
- | なおI/Fのポート名やボーレート等はサンプル共通として「dxmisc.h」に記述してありますので、環境に応じて修正した上でコンパイルして下さい。 | + | なおI/Fのポート名やボーレート等はサンプル共通として「dxmisc.h」に記述してありますので、環境に応じて修正した上でコンパイルして下さい。~ |
+ | またmacOSの場合のポート名は「/dev/tty.usbserial-????」ではなく「/dev/cu.usbserial-????」を指定してください。更に最近のmacOSにおける標準の機能ではlatency timeを変更できなかったので、以下のようなコードで対応してみてください(USB I/Fの抜き挿しの度に実行する必要がありますが...)。 | ||
+ | |||
+ | #html{{ | ||
+ | <pre class="brush: c;"> | ||
+ | // brew install libftdi | ||
+ | // cc -I/opt/homebrew/include/libftdi1 -L/opt/homebrew/lib -lftdi1 setlatency.c -o setlatency | ||
+ | |||
+ | #include <stdio.h> | ||
+ | #include <stdlib.h> | ||
+ | #include <stdbool.h> | ||
+ | #include <ftdi.h> | ||
+ | |||
+ | int main (void) { | ||
+ | int result = EXIT_FAILURE; | ||
+ | struct ftdi_context *ftdic; | ||
+ | struct ftdi_device_list *devlist; | ||
+ | bool f = true, b = false; | ||
+ | |||
+ | if ((ftdic = ftdi_new ()) != 0) { | ||
+ | ftdi_set_interface (ftdic, INTERFACE_ANY); | ||
+ | int num = ftdi_usb_find_all (ftdic, &devlist, 0, 0); | ||
+ | if (num > 0) { | ||
+ | for (int i = 0; i < num; i++) { | ||
+ | printf ("%d: ",i); | ||
+ | if (ftdi_usb_open_dev (ftdic, devlist[i].dev) == 0) { | ||
+ | char s[2][512]; | ||
+ | unsigned char prev_latency; | ||
+ | if (ftdi_read_eeprom(ftdic) == 0 && ftdi_eeprom_decode(ftdic,0) == 0 && ftdi_eeprom_get_strings(ftdic, s[0], 512, s[1], 512, NULL, 0) == 0) | ||
+ | printf("[%s][%s] ", s[0], s[1]); | ||
+ | if (ftdi_get_latency_timer (ftdic, &prev_latency) == 0) { | ||
+ | b = (ftdi_set_latency_timer (ftdic, 1) == 0); | ||
+ | printf ("prev latency = %i to %s\n", prev_latency, b ? "1" : "?"); | ||
+ | } else b = false; | ||
+ | f = f && b; | ||
+ | } | ||
+ | ftdi_usb_close (ftdic); | ||
+ | } | ||
+ | } else printf ("no device found.\n"); | ||
+ | |||
+ | if (f && b) result = EXIT_SUCCESS; | ||
+ | ftdi_list_free (&devlist); | ||
+ | ftdi_free (ftdic); | ||
+ | } | ||
+ | return result; | ||
+ | } | ||
+ | </pre> | ||
+ | }} | ||
**API [#ybae1454] | **API [#ybae1454] | ||
Line 466: | Line 531: | ||
if (dev) { | if (dev) { | ||
// ID=1にPINGを発行 | // ID=1にPINGを発行 | ||
- | if (DX2_Ping (dev, 1, &err)) | + | if (DX2_Ping (dev, 1, &err)) |
printf ("Found [%08X]\n", err); | printf ("Found [%08X]\n", err); | ||
else | else | ||
Line 506: | Line 571: | ||
if (dev) { | if (dev) { | ||
// 不明な対象に対してPINGを発行 | // 不明な対象に対してPINGを発行 | ||
- | if (DX2_Ping2 (dev, &num, stat, &err)) { | + | if (DX2_Ping2 (dev, &num, stat, &err)) { |
for (i = 0; i < num; i++) | for (i = 0; i < num; i++) | ||
printf ("Found ID=%d %02X\n", stat[i].id, stat[i].Status); | printf ("Found ID=%d %02X\n", stat[i].id, stat[i].Status); | ||
Line 570: | Line 635: | ||
if (dev) { | if (dev) { | ||
// ID=1にREBOOTを発行 | // ID=1にREBOOTを発行 | ||
- | if (DX2_Reboot (dev, 1, &err)) | + | if (DX2_Reboot (dev, 1, &err)) |
printf ("Success [%08X]\n", err); | printf ("Success [%08X]\n", err); | ||
else | else | ||
Line 607: | Line 672: | ||
if (dev) { | if (dev) { | ||
// ID=1のXL-320からLEDの状態を取得 | // ID=1のXL-320からLEDの状態を取得 | ||
- | if (DX2_ReadByteData (dev, 1, 25, &dat, &err)) { | + | if (DX2_ReadByteData (dev, 1, 25, &dat, &err)) { |
printf ("LED STAT=%d\n", dat); | printf ("LED STAT=%d\n", dat); | ||
} | } | ||
Line 643: | Line 708: | ||
if (dev) { | if (dev) { | ||
// ID=1のXL-320からLEDの状態を取得 | // ID=1のXL-320からLEDの状態を取得 | ||
- | if (DX2_ReadByteData (dev, 1, 25, &dat, &err)) { | + | if (DX2_ReadByteData (dev, 1, 25, &dat, &err)) { |
- | dat = (dat + 1) & 7; | + | dat = (dat + 1) & 7; |
// ID=1のXL-320へLEDの状態を設定 | // ID=1のXL-320へLEDの状態を設定 | ||
- | DX2_WriteByteData (dev, 1, 25, dat, &err); | + | DX2_WriteByteData (dev, 1, 25, dat, &err); |
} | } | ||
DX2_ClosePort (dev); | DX2_ClosePort (dev); | ||
Line 680: | Line 745: | ||
if (dev) { | if (dev) { | ||
// ID=1のXL-320から現在位置を取得 | // ID=1のXL-320から現在位置を取得 | ||
- | if (DX2_ReadWordData (dev, 1, 30, &dat, &err)) { | + | if (DX2_ReadWordData (dev, 1, 30, &dat, &err)) { |
printf ("PRESENT POS=%d\n", dat); | printf ("PRESENT POS=%d\n", dat); | ||
} | } | ||
Line 715: | Line 780: | ||
if (dev) { | if (dev) { | ||
// ID=1のXL-320へ位置(511)を指令 | // ID=1のXL-320へ位置(511)を指令 | ||
- | DX2_WriteWordData (dev, 1, 30, 511, &err); | + | DX2_WriteWordData (dev, 1, 30, 511, &err); |
DX2_ClosePort (dev); | DX2_ClosePort (dev); | ||
} | } | ||
Line 748: | Line 813: | ||
if (dev) { | if (dev) { | ||
// ID=1のXM430から現在位置を取得 | // ID=1のXM430から現在位置を取得 | ||
- | if (DX2_ReadWordData (dev, 1, 132, &dat, &err)) { | + | if (DX2_ReadWordData (dev, 1, 132, &dat, &err)) { |
printf ("PRESENT POS=%d\n", dat); | printf ("PRESENT POS=%d\n", dat); | ||
} | } | ||
Line 783: | Line 848: | ||
if (dev) { | if (dev) { | ||
// ID=1のXM430へ位置(2047)を指令 | // ID=1のXM430へ位置(2047)を指令 | ||
- | DX2_WriteWordData (dev, 1, 116, 2047, &err); | + | DX2_WriteWordData (dev, 1, 116, 2047, &err); |
DX2_ClosePort (dev); | DX2_ClosePort (dev); | ||
} | } | ||
Line 817: | Line 882: | ||
if (dev) { | if (dev) { | ||
// ID=1のXL-320からPIDゲインのデータを取得 | // ID=1のXL-320からPIDゲインのデータを取得 | ||
- | if (DX2_ReadBlockData (dev, 1, 26, gain, 3, &err) { | + | if (DX2_ReadBlockData (dev, 1, 26, gain, 3, &err) { |
printf ( | printf ( | ||
"D=%d I=%d P=%d\n", | "D=%d I=%d P=%d\n", | ||
Line 857: | Line 922: | ||
if (dev) { | if (dev) { | ||
// ID=1のXL-320のPIDゲインを変更 | // ID=1のXL-320のPIDゲインを変更 | ||
- | DX2_WriteBlockData (dev, 1, 26, gain, 3, &err); | + | DX2_WriteBlockData (dev, 1, 26, gain, 3, &err); |
DX2_ClosePort (dev); | DX2_ClosePort (dev); | ||
} | } | ||
Line 903: | Line 968: | ||
if ((dev = DX2_OpenPort ("\\\\.\\COM5", 1000000))) { | if ((dev = DX2_OpenPort ("\\\\.\\COM5", 1000000))) { | ||
uint32_t num = 3; // 3軸 | uint32_t num = 3; // 3軸 | ||
- | DX2_ReadSyncData (dev, ¶m, &num, (uint8_t *)&rdat, &err); | + | DX2_ReadSyncData (dev, &param, &num, (uint8_t *)&rdat, &err); |
printf("resul num=%d\n", num); | printf("resul num=%d\n", num); | ||
for (int i = 0; i < num; i++) { | for (int i = 0; i < num; i++) { | ||
Line 955: | Line 1020: | ||
if (dev) { | if (dev) { | ||
// 2台のXM430へ個別の位置を指令 | // 2台のXM430へ個別の位置を指令 | ||
- | DX2_WriteSyncData (dev, (uint8_t *)&syncw, sizeof(syncw), &err); | + | DX2_WriteSyncData (dev, (uint8_t *)&syncw, sizeof(syncw), &err); |
DX2_ClosePort (dev); | DX2_ClosePort (dev); | ||
} | } | ||
Line 988: | Line 1053: | ||
const TBulkReadParam param[3] = { | const TBulkReadParam param[3] = { | ||
- | {1,100,20}, // ID=1の124番地から20バイト分 | + | {1,100,20}, // ID=1の100番地から20バイト分 |
{2,124,12}, // ID=2の124番地から12バイト分 | {2,124,12}, // ID=2の124番地から12バイト分 | ||
{3, 0, 7} // ID=3の0番地から7バイト分 | {3, 0, 7} // ID=3の0番地から7バイト分 | ||
Line 997: | Line 1062: | ||
uint32_t num = 3; // 3軸 | uint32_t num = 3; // 3軸 | ||
PBulkReadResult pr = (void *)rdat; | PBulkReadResult pr = (void *)rdat; | ||
- | DX2_ReadBulkData (dev, ¶m[0], &num, (uint8_t *)&rdat, &err); | + | DX2_ReadBulkData (dev, &param[0], &num, (uint8_t *)&rdat, &err); |
printf("resul num=%d err=$%04x\n", num, err); | printf("resul num=%d err=$%04x\n", num, err); | ||
for (int i = 0; i < num; i++) { | for (int i = 0; i < num; i++) { | ||
Line 1048: | Line 1113: | ||
if (dev) { | if (dev) { | ||
// 3台のXM430へ個別の情報を書き込み | // 3台のXM430へ個別の情報を書き込み | ||
- | DX2_WriteBulkData (dev, (uint8_t *)&BW, sizeof(BW), &err); | + | DX2_WriteBulkData (dev, (uint8_t *)&BW, sizeof(BW), &err); |
DX2_ClosePort (dev); | DX2_ClosePort (dev); | ||
} | } | ||
Line 1084: | Line 1149: | ||
if (dev) { | if (dev) { | ||
// ID=1のAX-12+のLEDを消灯 | // ID=1のAX-12+のLEDを消灯 | ||
- | DX2_TxPacket (dev, 1, INST_WRITE, param, 2, &err); | + | DX2_TxPacket (dev, 1, INST_WRITE, param, 2, &err); |
DX2_ClosePort (dev); | DX2_ClosePort (dev); | ||
} | } | ||
Line 1126: | Line 1191: | ||
if (dev) { | if (dev) { | ||
// ID=1のAX-12+からLEDの状態を読み出す要求 | // ID=1のAX-12+からLEDの状態を読み出す要求 | ||
- | if (DX2_TxPacket (dev, 1, INST_READ, param, 2, &err)) { | + | if (DX2_TxPacket (dev, 1, INST_READ, param, 2, &err)) { |
// ステータスパケットを受信 | // ステータスパケットを受信 | ||
- | DX2_RxPacket (dev, dat, sizeof (dat), &len, 100, &err); | + | DX2_RxPacket (dev, dat, sizeof (dat), &len, 100, &err); |
for (i = 0; i < len; i++) { | for (i = 0; i < len; i++) { | ||
printf ("[%02X]", dat[i]); | printf ("[%02X]", dat[i]); |