はじめに anchor.png

機械・電気・電子・ソフトウェアといった広範な分野に渡るアプリケーションにおいてDYNAMIXELでつまづかないよう、導入から運転するところまでをこのページにまとめた。残念ながら印刷媒体では製品やソフトウェアの更新に追従できないのと、ソースコードを紹介しても手打ちの手間が解消できない事もあり、縦に長くてとても見にくい事は予めご了承の程。
PCの操作やOSについても説明をしなくてはならない事も多々あるが、ここでは「ひとまず」動かせるところまでを一気に紹介する事で、分かった気になってもらう事に主眼を置いた。
そのような中においても多少なりともTipをちりばめてあるので、最終的にはそれらを踏まえたシステムを構築して欲しい。

なお別ページへのリンクをクリックするとブラウザ上ではページが切り替わるが、何度も往来しているうちに元に戻るのが億劫になる事がある。リンク先を参照する際は「Ctrl」キーを押しながらクリックして新規タブで開けば、多少なりとも閲覧効率が良くなるかも知れない。

※ここに記述された内容は断り無く書き換えられる。

Page Top

ハードウェアの準備 anchor.png

ここではWindows PCからDYNAMIXELを動かす方法を紹介するので、それ以外から動かすケースはいずれ別のページで紹介する。

Page Top

PC anchor.png

ARM版ではないWindows 10がインストールされており、USBポートが装備されたPCを用意する。USBポートは後述のUSB I/Fを接続するためにも必須の装備となる。

Page Top

USB I/F anchor.png

DYNAMIXELは主に2種類のI/Fが規定され、3ピンコネクタ版を俗にTTL版、4ピンコネクタ版をRS-485版と呼んでおり、電気的には相互互換性は無い。ほとんどのDYNAMIXELにはいずれかのタイプのコネクタが2個装備されている。

まずこの2種類のI/Fのコネクタを紹介する。

  • TTL
    Pats NameJST Parts Number
    基板用ヘッダーS3B-EH
    ハウジングEHR-3
    ターミナルSEH-00x
    B3B-EH.png
    端子番号信号名
    1GND電源のマイナス側
    シリアル通信のGNDと共有
    2VDD電源のプラス側
    大半のDYNAMIXELは12V
    3TTL Signalシリアル通信の信号
    双方向
  • RS-485
    Pats NameJST Parts Number
    基板用ヘッダーS4B-EH
    ハウジングEHR-4
    ターミナルSEH-00x
    B4B-EH.png
    端子番号信号名
    1GND電源のマイナス側
    シリアル通信のGNDと共有
    2VDD電源のプラス側
    大半のDYNAMIXELはDC12V
    3RS-485 D+シリアル通信のプラス側差動信号
    双方向
    4RS-485 D-シリアル通信のマイナス側差動信号
    双方向

この2種類のI/Fは一般的なPCには標準装備されていないため、USBポートを介して増設する装置が用意されている。複数のI/Fに対応していたり、いずれか1つのI/Fにのみ対応していたり、電源の供給を行えたりとラインナップが複数あるため、以下に現行品のみの比較表を示す。

USB2RS485 dongleUSB2TTL dongleUSB2DX dongleDXHUBU2D2
www.besttechnology.co.jp_i00212i5af94f4945af8.png
www.besttechnology.co.jp_m00213m5af94f5d3e4b5.png
[Upload]
www.besttechnology.co.jp_a00255a5dcac2c8eed34.png
www.besttechnology.co.jp_k00208k5a9cf31f42b33.png
ManufactureBestTechnologyROBOTIS
USBUSB2.0 FS
USB Type-A
USB2.0 HS
USB Type-C
USB2.0 HS
micro USB Type-B
FTDI ChipFT234XFT232H
Max DTR Rate [Mbps]3126
DYNAMIXEL I/FRS-485 x1TTL x1RS-485 x1, TTL x1RS-485 x6, TTL x6RS-485 x1, TTL x2
IsolationYesNo
Dimension [mm]43.2x13.0x8.552x33x1548x18x14.6
Compatible softwareDYNAMIXEL Wizard 2.0, R+2.0, DXLIB, DX2LIB, DYNAMIXEL SDK
Other spec.SmallPower distributionPlastic enclosure

これらよりも古い製品は旧来のDYNAMIXELを前提としており、装備されているコネクタがmolex社で最大通信速度は3Mbpsといったものが主である。もちろんConvertible Cableを仲介させる事で現行モデルのDYNAMIXELにも接続できるので、持っているのであれば買い直す必要は無い。

Page Top

DYNAMIXEL anchor.png

dxl_series.png

現時点ではAX・MX・X・Pシリーズから選定する事になるが、シリーズごとの大雑把な特徴を紹介しておく。

  • AXシリーズ
    BIOLOIDというロボットキットにかつて同梱されており、12V・TTL・molex社コネクタ・コアドモータ・電流センサ非搭載の廉価モデル。単体で扱おうとすると取り付けが面倒。今後ファームウェアが更新されないので、新規設計の場合はXL/XCシリーズを強く推奨。
  • MXシリーズ
    絶版のRX及びEXシリーズとの形状互換を謳った後継機で、12V・TTL/RS-485・molex社コネクタ・コアド/maxon社コアレスモータ・電流センサ搭載/非搭載。トルクによって4種類の形状(12/28/64/106)がある。ファームウェアを更新する事でXシリーズと同等に扱えるようになるが、新規設計の場合はXシリーズを推奨。
  • Xシリーズ
    • XL-320
      ROBOTIS MINI Kitに同梱されており、7.4V・TTL・molex社2mmピッチコネクタ・コアドモータ・電流センサ非搭載。現行モデル。
    • XL
      12V・TTL・JST社コネクタ・コアドモータ・電流センサ非搭載で廉価モデルという位置付け。2軸を内蔵した2XLもある。現行モデル。
    • XC
      12V・TTL・JST社コネクタ・コアレスモータ・電流センサ非搭載で。2軸を内蔵した2XCもある。現行モデル。
    • XM
      12V・TTL/RS-485・JST社コネクタ・コアレスモータ・電流センサ搭載で、トルクによって2種類の形状(430/540)がある。スタンダードな現行モデル。
    • XH
      12/24V・TTL/RS-485・JST社コネクタ・maxon社コアレスモータ・電流センサ搭載で、トルクによって2種類の形状(430/540)がある。現行モデル。
    • XW
      12V・RS-485・防水コネクタ・maxon社コアレスモータ・電流センサ搭載。形状は1種類(540)。IP68に対応。現行モデル。
  • Pシリーズ
    24V・RS-485・JST社コネクタ・コアレス/ブラシレスモータ・電流センサ搭載・高分解能・低バックラッシュ・高トルク。3種類の形状があるのとかなり高価。唯一定格トルクを謳うハイエンド向け現行モデル。

MXとXシリーズのストールトルクと無負荷最大回転数をモデルごとにプロットしたグラフを紹介しておく。

mx_x_torque_vs_speed_graph.png

アプリケーションに要求されるトルクで選定するのが一般的なのだが、DYNAMIXELの大半のモデルは定格トルクではなくストールトルクを謳っている。ストールトルクはこれ以上は出せないといった値(瞬時最大トルクに近い)であり、連続的に使って良いというトルクでは無い。

なおここではあえてXシリーズ以降を前提とするので、AXやMXシリーズまたは廃盤品を使用する場合は差異を深掘りした上で適宜読み替えてもらうものとする。また廃盤品を含む全ラインナップの一覧はこちらに掲載した。

Page Top

各装置の接続 anchor.png

各USB I/Fを使用した場合の実態配線を紹介する。
いずれも複数のDYNAMIXELのコネクタをお互いに並列接続し、更にそこへUSB I/Fにて増設されるTTLないしRS-485 I/Fの信号と外部電源を接続する事が主な目的である。

なおmolex社のコネクタを装備したDYNAMIXELを使用する場合はJST社とmoelx社のコネクタを返還するConvertible Cableが必要だが、ここではXシリーズを前提で書き進めるので詳説しない。

Page Top
DXHUBの場合 anchor.png

3ピンのTTLと4ピンのRS-485 I/Fのコネクタが複数備わっている。更にDYNAMIXELへ電源を分配供給する機能があり、その電源の入力用コネクタが装備されている。各装置をDXHUBへ接続すると基本的に接続が完結してしまう。

70&, E148_DXL_connect.png

TTLとRS-485 I/Fを同時に運用できる。

Page Top
USB2RS485 dongleの場合 anchor.png

4ピンのRS-485 I/Fのコネクタが1つのみ装備されており、DYNAMIXELへの電源の供給機能は無い。別途DXSharingBoard(RS485)等の分配基板を用意する事でDYNAMIXELへの電源の供給と複数台のDYNAMIXELの接続ができる。

rs485dongle_dxl_sharingboard_connect.png

この例ではPCとDYNAMIXEL間の距離はRobot Cable X4Pに支配されるが、USBドングルとPC間の接続を市販のUSB延長ケーブル等で中継する事で延長する事ができる。
更に正しく処置したRS-485ケーブルを作成する事で、USBドングルとDYNAMIXEL間の距離を延長できる。

Page Top
USB2TTL dongleの場合 anchor.png

3ピンのTTL I/Fのコネクタが1つのみ装備されており、DYNAMIXELへの電源の供給機能は無い。別途DXSharingBoard(TTL)等の分配基板を用意する事でDYNAMIXELへの電源の供給と複数台のDYNAMIXELの接続ができる。

ttldongle_dxl_sharingboard_connect.png

この例ではPCとDYNAMIXEL間の距離はRobot Cable X3Pに支配されるが、USBドングルとPC間の接続を市販のUSB延長ケーブル等で中継する事で延長する事ができる。

Page Top
USB2DX dongleの場合 anchor.png

USB2RS485 dongleとUSB2TTL dongleの機能を合わせ持っており、3ピンのTTL I/Fと4ピンのRS-485 I/Fのコネクタがそれぞれ1つずつ装備されている。
そもそもUSB2RS485 dongleとUSB2TTL dongleとUSB2DX dongleはコネクタの実装状況が異なる以外は全く同じ代物であるので、USB2RS485 dongleないしUSB2TTL dongleを参考に接続が行える。

Page Top
U2D2の場合 anchor.png

4ピンのRS-485 I/Fのコネクタが1つ、3ピンのTTL I/Fのコネクタが2つ装備されており、DYNAMIXELへの電源の供給機能は無い。別途U2D2 PHBやDXSharingBoard等の分配基板を用意する事でDYNAMIXELへの電源の供給と複数台のDYNAMIXELの接続ができる。

u2d2phb.png

TTLとRS-485 I/Fを同時に運用できる。
なおU2D2 PHBの電源供給用のジャックはROBOTIS社のキットに同梱されるSMPSのサイズに合わせてあり、日本国内で多く流通するものには適合しない。

Page Top

留意事項 anchor.png

机上では動作していたものが、実際に運用を始めた途端に問題が生じる事は良くある。DYNAMIXELを使用したアプリケーションを設計するにあたっての留意事項をいくつか紹介する。

Page Top
DYNAMIXELのI/FとRobot Cable anchor.png

TTL I/Fのシリアル信号は極めて微弱かつ脆弱で、距離を延長する事ができないまでか、DYNAMIXELの電気回路を容易に故障させる可能性すらある。弊社ではTTL I/Fの選択肢しかないモデルを除き、堅牢なシステムにおいてはRS-485 I/Fを搭載したモデルを強く推奨する(モデル名のサフィックスに「-R」と記載)。

また単体製品及びDYNAMIXELに同梱されているRobot Cableはケーブルを製作せずともすぐに接続できる事を念頭に用意されており、一般的に考え得る電気的な問題を解消できるものでは無い。
特にRS-485 I/Fの実力を発揮させるためには既成のRobot Cableは適さないため、電源容量と延長距離に対応したケーブルの製作を推奨する。

RS-485_IdealCable.png

RS-485の終端抵抗の処置も行っておきたいところだ。

Page Top
電源装置 anchor.png

先の図では電源装置をSMPS等と表記しているが、任意電圧に設定できる電源装置やバッテリを負荷が要求する電圧と電流に合わせて用意する。しかしDYNAMIXELに内蔵されたモータの回生電力によって電圧が上昇してしまう事までは注意が行き届かないと思う。特に固定出力の一般的なスイッチングACアダプタには出力電圧と電流は規定されているが、出力側の耐圧やシンク能力までを明記しているものはまず無い。少なくとも誘導性負荷に対応しているものを選定しないと容易に故障する。

また電源からの距離をかせぐための延長ケーブルは、平行線ではなくツイストペアケーブル(より対線)を使うべきだ。

Page Top
電気的絶縁 anchor.png

回路上PC・USBポート・USB I/F・DYNAMIXELの全てのGNDが共通になっている事自体は問題ないが、DYNAMIXEL側で電流サージが発生したりPCとDYNAMIXELに供給されている電源に大きな電位差があったりすると、このコネクタまみれの構成は難点が多すぎる。
大抵のPCのUSBポートには過電流保護機能が備わっているので、コネクタの抜き差し時に発生する電流サージ程度には耐性がある。しかしモータから生じるサージとなると、保護回路では太刀打ちできないレベルのものが発生する事があり得る。またUSBポートの過電流保護機能が働くとUSBポートが一時的に機能を失い、それを想定していないプログラムやOSであれば容易に暴走する。
更に各装置に供給される電源の電位差はサージ過電流以上に厄介で、瞬間的なものではなく定常的に過電流状態が維持されてしまい、あらゆる装置の永久破壊につながる。
いずれの問題にも幾度となく遭遇し、壊したPCやI/Fが何台ある事か。。。

そういった諸問題を解消する目的で、USB2RS485 dongle・USB2TTL dongle・DXHUBはいずれもUSBポートとDYNAMIXEL用I/F及び電源の間を電気的に絶縁している。

なお以後の解説では、接続の容易さを買って絶縁機能を持ったDXHUBを使用する。

Page Top

動作テストと設定変更 anchor.png

複数台のDYNAMIXELの運用は理解が進んでから行う事なので、まずは1台のDYNAMIXELのみを使って最低限必要な操作方法を習得する。

Page Top

DYNAMIXELについて知っておくべき事 anchor.png

DYNAMIXELに関係するID番号・通信速度・モデル番号・コントロールテーブル・ファームウェアといったキーワードがあるが、大半はDYNAMIXELの外観から判別できない内部情報であり、後述するPC用のツールを用いる事で初めて認識できる。

  • ID番号
    通信プロトコルにおいて個々のDYNAMIXELの識別を行う際に0~252,254の数値を用いており、ID番号と呼ぶ。
    出荷時および完全初期化時のID番号は一部を除き1。
  • 通信速度
    本来であれば最高速度で動作していれば良いのだが、電気的だったりやハード的な制約等を回避するため任意に設定できる。
    出荷時および完全初期化時の通信速度は一部を除き57600[bps]。
  • モデル番号
    モデル名(製品名のサフィックスにある「-T」と「-R」を除いた部分)に紐付く16ビット幅の値。
    全てのモデルが全く同じ機能を持っているものでは無いため、それを判別するためにモデル番号を用いる。
  • コントロールテーブル
    様々な情報(アイテム)をメモリ上に保持しており、それらを一覧にしたものをコントロールテーブルと呼ぶ。モデルによってアイテムの割り当て先(アドレス)が異なっていたり機能が異なっていたりする。
    前述のID番号・通信速度・モデル番号はコントロールテーブル上に割り当てられており、通信プロトコルは主にコントロールテーブルへのアクセス手段を提供する。
  • ファームウェア
    DYNAMIXELに内蔵されているマイコンの制御ソフトウェアをファームウェアと呼ぶ。そのファームウェアは時折更新される事があり、後述のツールを用いて必要に応じてDYNAMIXELに適用する事ができる。
Page Top

ハードウェアの準備 anchor.png

電源・電源ケーブル・USBケーブルは各製品に標準添付されていないため、必要に応じて別途調達する。

接続は先に紹介したDXHUBの場合の通りとなるが、初期設定の場合は混乱を避けるため1台のみのDYNAMIXELを接続する。
DXHUBをPCのUSBポートに接続してデバイスドライバのインストールを行った後に、こちらの情報を元に仮想COMポートの設定を予め変更しておく事を推奨する。
またDXHUBの裏側が不用意に何かに触れてショートすると取り返しの付かない事になるため、予め四隅の取り付け穴にスペーサ等を取り付けて端子等がショートしないようにしておくと良いだろう。

Page Top

DYNAMIXEL Wizard 2.0のインストール anchor.png

wizard2_main_001.png

DYNAMIXEL Wizard 2.0はDYNAMIXELとコミュニケーションを行うソフトウェアで、主に以下の機能を有する。

  • 検索
    設定された条件が不明確なDYNAMIXELを検索し発見。
  • ファームウェアの更新
    インターネットを介してDYNAMIXELの最新ファームウェアをダウンロードし更新したり、異なるファームウェアへ書き換える事が可能。
  • 簡易運転
    コントロールテーブルのうち主要なアイテムへ簡便にアクセスして運転可能。
    主に動作モード・目標位置・目標速度・トルクの変更をスイッチやダイアル操作で行える。
  • 設定変更
    コントロールテーブルの情報全てを一覧でき、また変更可能なアイテムの編集が可能。
  • 複数台の一元管理
    異なるID番号を持つ複数のDYNAMIXELの一覧を列挙し個別に操作可能。

DYNAMIXELの専用通信プロトコルを用いて対象のDYNAMIXELのコントロールテーブルにアクセスしているに過ぎないが、このようなツールを使用しない場合はちょっとした設定変更をするにしても自前でプログラムを作らざるを得ない。ROBOTIS社のサイトからダウンロードしてインストールしておく。

なおDYNAMIXEL Wizard 2.0はインターネットを介してツール本体とファームウェアの更新版を取得する事ができる。ここでは詳説しないが、インターネットに接続された環境でDYNAMIXEL Wizard 2.0を起動した直後に自動的に更新がないかを確認し、必要があれば更新するか否かを問い合わせてくる。Install Nowボタンを押すと更新が開始されるが、特に適用する必要が無いと判断したらInstall laterボタンを押す事で更新はキャンセルされる。

dxlwiz_update.png
Page Top

DYNAMIXEL Wizard 2.0の検索条件の設定 anchor.png

インストールしたDYNAMIXEL Wizard 2.0を起動したらツールバーのOptionsボタンをクリックし、開いたOptionsダイアログボックスの左側のScanをクリックする。

DXLWiz2_Options.png

以下の項目を設定してOKボタンを押すと、DYNAMIXEL Wizard 2.0の検索条件の期設定はひとまず完了である。次回起動した際も本設定が反映される。

  • Select protocol to scan.
    「Protocol 2.0」のみにチェック。
  • Select port to scan.
    DXHUBをPCに接続した際に追加されたCOMポートのみにチェック。
  • Select baudrate to scan.
    「57600 bps」のみにチェック。
  • Set ID range to scan.
    Startには0、Endには252を設定。

なお本設定は出荷時のDYNAMIXEL Xシリーズを対象としているため、後々のDYNAMIXELの設定等によっては以下のように適宜変更する。

  • Select protocol to scan.
    DYNAMIXEL DX/AX/RX/EX/MXシリーズやプロトコル1.0に設定したXシリーズを対象とする場合には「Protocol 1.0」をチェック。
  • Select baudrate to scan.
    57600bps以外の通信速度に変更しているならばその通信速度をチェック、もし設定された通信速度が不明な場合は全ての通信速度をチェック。
Page Top

DYNAMIXEL Wizard 2.0による検索 anchor.png

DXHUBの電源スイッチをONにして電源の供給を開始すると青色のLEDが点灯し、DYNAMIXELに装備されたLEDが0.5秒だけ点灯する。その後DYNAMIXEL Wizard 2.0のツールバーのScanボタンをクリックすると、検索条件の設定に従って検索が開始される。検索中のダイアログボックスにはプログレスバーが表示され、見つかったDYNAMIXELはダイアログボックスとメイン画面の画面左側のCOMポート番号と通信速度のツリーの配下に逐次列挙される。

DXLWiz2_Scan.png

Select baudrate to scan.の全ての通信速度がチェックされていると検索の終了までにかなりの時間がかかるが、検索中に目的のDYNAMIXELが見つかったり途中で中断する場合はSkipボタンを押す。

DYNAMIXEL Wizard 2.0は検索によって見つかったDYNAMIXELのみを操作対象とするため、検索は起動直後に毎回強いられる。検索条件の設定のSelect baudrate to scan.のチェックを減らしたり、Set ID range to scan.のStat及びEndのID番号を適宜変更する事で検索時間を短縮できる。

もし検索で見つからない場合は、検索条件の設定が対象のDYNAMIXELに合致しない・COMポートが間違っている・電源が入っていない・装置の故障等の理由が考えられるので全て確認し直す。

Page Top

DYNAMIXEL Wizard 2.0による試運転 anchor.png

出荷時状態のDYNAMIXELの動作モードは大抵「位置決め制御」モードとなっており、任意の位置を指示する事でDYNAMIXELのサーボホーンの位置がそれに伴って移動する。DYNAMIXEL Wizard 2.0では以下の手順と操作で位置を指示できる。

  1. 検索
    対象のDYNAMIXELが見つかっていなければ検索する。
  2. 運転対象のDYNAMIXELを選択
    画面左側のCOMポート番号と通信速度のツリーの配下から任意のDYNAMIXELをクリックして選択すると(既に選択状態の場合もある)、DYNAMIXEL Wizardは対象のDYNAMIXELとの通信を開始する。正常であればステータスバー上のLEDやDXHUBのLEDが周期的に明滅しているはずである。
    DXLWiz2_SelDX.png
  3. TorqueをON
    画面右上のTorqueとあるスイッチをクリックしてON状態(赤色)にする。
    DXLWiz2_DXTorqueOn.png
  4. 位置を指示
    画面右上の円をクリックしたりドラッグするとDYNAMIXELへ位置(赤色の針の位置)が指示され、同時にDYNAMIXELのホーンの位置が移動する筈である。緑色の針は現在のホーンの位置を表している。
    DXLWiz2_DXGPos.png

この手順で思ったようにDYNAMIXELのホーンが動かない場合は、DYNAMIXELが故障している可能性が高い。

Page Top

DYNAMIXEL Wizard 2.0によるID番号の変更 anchor.png

複数のDYNAMIXELを同時に運用する場合は、個々に異なるID番号を設定しておかなくてはならない。通信プロトコルの仕様では複数のDYNAMIXELのID番号が同じだと個々を識別できないからである。

  1. 検索
    対象のDYNAMIXELが見つかっていなければ検索する。
  2. 変更対象のDYNAMIXELを選択
    画面左側のCOMポート番号と通信速度のツリーの配下から任意のDYNAMIXELをクリックして選択すると(既に選択状態の場合もある)、DYNAMIXEL Wizardは対象のDYNAMIXELとの通信を開始する。正常であればステータスバー上のLEDやDXHUBのLEDが周期的に明滅しているはずである。
    DXLWiz2_SelDX.png
  3. TorqueをOFF
    画面右上のTorqueとあるスイッチがON(赤色)ならばクリックしてOFF状態(灰色)にする。
    DXLWiz2_DXTorqueOff.png
  4. 画面中央のコントロールテーブルから「ID」を選択
    アドレスの7に「ID」が割り当てられているので、該当アドレスをクリックして選択状態にする。
    DXLWiz2_SelCtrlTableID.png
  5. ID番号を変更 画面右下の「ID」の一覧から任意のID番号を選択しSaveボタンを押す事で即時反映される(ここでは例として「ID 1」から「ID 3」へ変更)。
    DXLWiz2_ChangeID.png
    なお複数のDYNAMIXELが検索されている時は、既に見つかっているID番号は選択できない。
Page Top

DYNAMIXEL Wizard 2.0による通信速度の変更 anchor.png

DYNAMIXELのデフォルトの通信速度は57600bpsだが、軸数が増えたりタイトな通信をし始めるとトラフィックが渋滞し体感的にも応答が遅いと感じるようになる。高い通信速度は様々な環境に影響されやすいので最高速にする必要までは無いが、1000000bps程度であれば経験的に安定して使用できる速度と考える。以下に通信速度を変更する手順を示す。

  1. 検索
    対象のDYNAMIXELが見つかっていなければ検索する。
  2. 変更対象のDYNAMIXELを選択
    画面左側のCOMポート番号と通信速度のツリーの配下から任意のDYNAMIXELをクリックして選択すると(既に選択状態の場合もある)、DYNAMIXEL Wizardは対象のDYNAMIXELとの通信を開始する。正常であればステータスバー上のLEDやDXHUBのLEDが周期的に明滅しているはずである。
    DXLWiz2_SelDX.png
  3. TorqueをOFF
    画面右上のTorqueとあるスイッチがON(赤色)ならばクリックしてOFF状態(灰色)にする。
    DXLWiz2_DXTorqueOff.png
  4. 画面中央コントロールテーブルから「Baud Rate (Bus)」を選択
    アドレスの8に「Baud Rate (Bus)」が割り当てられているので、該当アドレスをクリックして選択状態にする。
    DXLWiz2_SelCtrlTableBaudrate.png
  5. 通信速度を変更
    コントロールテーブル上では通信速度そのものの値ではなく、代わりに0~7の値で指示する。
    Value通信速度[bps]
    09,600
    157,600
    2115,200
    31,000,000
    42,000,000
    53,000,000
    64,000,000
    74,500,000
    1000000bpsに変更するには画面右下のリストから「3 1Mbps」を選択しSaveボタンを押す事で即時反映される。
    DXLWiz2_ChangeBaud.png
Page Top

自作のプログラムから動かす anchor.png

プログラミングの知識が無ければ何も始まらないし、それ相応の環境を整える必要もある。
ここでは弊社が提供するWindows向けの簡易的な統合環境と専用のライブラリを用い、C言語でコーディングする。コンパイル後に生成されるプログラムは、いずれもCUIベースである。

Page Top

Dynamixel Protocol 2 Library anchor.png

DYNAMIXELは専用の通信プロトコルでのみ通信できるが、通信プロトコルを処理するプログラムを自前でコーディングするのにはそれ相応の知識と労力が要求される。その手間を軽減させる目的で提供しているのがDynamixel Protocol 2 Library(DX2LIB)である。
他にもこういった目的のライブラリはあるが、DYNAMIXELの主要な機能を利用する際にモデルやコントロールテーブルの差異をほぼ意識しなくて済む追加APIをDX2LIBは持っている。追加APIを使用している限りユーザーはCOMポート番号・通信速度・ID番号程度を把握していれば良く、最終的には少ないソースコード量で大抵の処理が行えると謳っている。また各APIはコンパイル済みのDLLに含まれているので、自分のプログラムから呼び出す手段さえあれば言語は問わない。
ライブラリのソースコードファイルを参照すれば分かるが追加APIの実態は大した事はしておらず、モデルによって異なるアイテムの変換や手順を強いられるアイテムの手順操作、物理値とアイテム間の単位変換、複数IDの一括処理に終始している。追加APIを使わない場合は、コントロールテーブルのアイテムの機能を習熟する段取りから始めざるを得ないので、説明を端折るにはありがたい :-P

またプロトコルV1.0用のライブラリも用意されているので、どうしてもDX/AX/RX/EX/MXシリーズを動かしたいという場合は所々読み替えて対応してもらいたい。

Page Top
ダウンロードと必要なファイル anchor.png

こちらより最新のアーカイブファイルをダウンロードし、適宜解凍する。

以後に紹介するGCC Developer Liteでコーディング・コンパイル・実行には、ライブラリに含まれる次の4つのファイルがソースコードファイルを保存したフォルダと同じ場所に配置されている必要がある。

ファイル名説明
dx2lib.h各APIのプロトタイプ宣言等を含むヘッダファイル
dx2memmap.hコントロールテーブル上の主要アイテムのアドレスが定義されたヘッダファイル
dx2lib_x32.dllライブラリ本体が含まれた32ビット版DLL
dx2lib_x64.dllライブラリ本体が含まれた64ビット版DLL

このうち「dx2memmap.h」は一部のDYNAMIXELのコントロールテーブルに配置されたアイテムのアドレスを記述しているファイルだが、アイテムのアドレスを指定してアクセスしない限り必須ではない。また32ビット版と64ビット版のDLLはコンパイル時の条件によっていずれか一方で構わない。その他のファイルは一切必要ない。

Page Top

GCC Developer Lite anchor.png

gdl.png

GCC Developer Liteはマイコンボード製品向けにプログラムを手っ取り早く動かせるツールとして提供している(こちらのリンク先のインストーラは使用しない)が、ここではWindows上で動作するプログラムをコーディング及びコンパイルする事が目的となる。
最近の統合環境の類いに比べたら極めて少ない機能しか備えておらず正直なところ今更な感じではあるのだが、無償かつ簡単な設定でソースコードの編集とコンパイルはできるという理由だけで選定した。

Page Top
インストーラのダウンロードとインストール anchor.png

Windows向けの実行プログラムを生成する事のみを目的としたインストーラを用意した。今後はWindows XP以前のOSにはインストールできないので悪しからず。

GDL4Win2.6.0.86.exe
ファイルサイズ: 229,582,988 byte
MD5ハッシュ値: e42a1cc2980324216fffc18aae153611

他のバージョンのGCC Developer Liteと共存させる事を想定していないため、インストール済みのGCC Developer Liteがあれば予めアンインストールしておく事。
インストーラーを実行するとPCの設定によってはスマートスクリーン・セキュリティー警告・ユーザアカウント制御等のメッセージがしつこく表示される。ダウンロードしたファイルのサイズやハッシュ値が上記と同一であれば「実行(R)」や「はい」を選択してインストールを進めて構わないが、気がかりな場合はインストールそのものを止めここで示す作業を諦めるしかない。

GDL_CAmess0.png
GDL_CAmess1.png
GDL_CAmess2.png

これらのメッセージが表示されないままインストールそのものを拒否されたり、インストーラーファイルが削除される事も考えられる。その場合はWindowsの署名に関するポリシーを変更したり、アンチウィルスの制限を緩める等の措置を講じる必要がある。
OSの設定において8.3形式のファイルの生成が有効になっていない場合もインストールを拒否される。その場合は管理者権限でコマンドプロンプトを起動し、以下の様にfsutilを使って8.3形式のファイル名の生成を有効化してからインストールを行う。

C:\>fsutil behavior set disable8dot3 0
現在のレジストリの状態は 0 です (すべてのボリューム上で 8dot3 名の作成を有効にします)。

C:\>

なお極めて少ない機能と書きつつもかなりの数のライブラリやPythonまで同梱しているので、ファイルの数とサイズは莫大になっている。そのためインストールが完了するまにではそれ相応の時間がかかる。

Page Top
ソースコード編集・ファイル操作 anchor.png

後述のソースコードを使用する際に必要な操作を紹介する。

まずブラウザから該当のソースコードをクリップボードにコピーし、GCC Developer Liteのエディタウィンドウ上にペーストする。ソースコード中のCOMポート番号の部分("\\\\.\\COM3")の数値を自身の環境に合わせて書き換えたら編集作業は完了である。
編集中のソースコードをファイルとして保存しておけば、後々再度読み出して再利用できる。保存するには「ファイル(F)」メニュー内の「名前を付けて保存(A)...」をクリックし任意の場所と名前で保存する。なおファイル名のフルパスに全角文字・機種依存文字・空白が含まれているとコンパイルに支障をきたすので、基本的には半角の英数字で構成しておく事。

Page Top
コンパイルオプション anchor.png

64ビット版のWindows上で32ビット版のプログラムは実行できるが、その逆はできない。32ビット版と64ビット版のどちらを選んでも大きな違いは感じないと思うが、ここではどちらのOSでも実行できる32ビット版のプログラムを生成する事にする。
コンパイルしたいソースコードを開いている状態で、「ツール(T)」メニュー内の「コンパイルオプション(O)」をクリックしコンパイルオプションダイアログボックを開く。上端の設定リストをドロップダウンし「Windows x86 (Console)」を選んでOKボタンを押すと、32ビット版のコンパイル条件の設定は全て完了する。

GDL_SelCompileOption.png

ちなみに「Windows x64 (Console)」を選ぶと64ビット版の実行ファイルを生成するためのコンパイル条件となる。

なお後述のビルドデバッグ情報付きビルドを行った既存のソースコードファイルを開き直した場合、「保存済みの環境設定ファイルが見つかりました。」というメッセージダイアログボックスが表示される。

GDL_ReloadCfg.png

このメッセージは過去にコンパイルオプションを設定してコンパイルされた事を意味し、OKボタンを押す事でコンパイラオプションを設定したのと同等の扱いとなる。

Page Top
ビルドと実行 anchor.png

後述のライブラリを利用したソースコードをコンパイルするには、ライブラリに含まれる4つのファイルが必要となる。それらファイルを予めソースコードを保存したフォルダにコピーしておく事を忘れないように。
コンパイラオプションが正常に設定されていれば、「コンパイル(C)」メニュー内の「ビルド(B)」が利用できるようになる。「ビルド(B)」をクリックする(もしくは「F9」キーを押す)とコンパイラが呼び出され、問題が無ければソースコードから実行可能なプログラムが同じフォルダの中に生成される。

GDL_Build.png

例えばソースコードのファイル名が「test1.c」ならば、「test1.exe」というファイル名で実行ファイルが生成される。実行ファイルが生成されたら、そのファイルをエクスプローラー等から開いて実行する。

GDL_AppRun.png

実行中はコマンドプロンプトが表示され、標準出力へ何かしらのメッセージが出力される。

CMD_Execute.png

なおエクスプローラーから起動したプログラムは、メッセージを確認する間もなく終了と同時にコマンドプロンプトが閉じてしまう。メッセージを確認する必要がある場合は予めコマンドプロンプト(cmd.exe)を起動しておき、その中でコンパイルしたプログラムを実行すると良い。

Page Top
デバッグ情報付きビルドとデバッガ anchor.png

ビルドと実行と大差は無いが、コンパイル後にデバッガを介してプログラムを実行する。ここではデバッガを使ってデバッグする事が目的というよりも、GCC Developer Liteのみでコンパイルからプログラムの実行まで全て行うためだけに使う。

コンパイラオプションが正常に設定されていれば、「コンパイル(C)」メニュー内の「デバッグビルド&デバッガで開く(G)」が利用できるようになる。「デバッグビルド&デバッガで開く(G)」をクリックする(もしくは「Ctrl」+「F9」キーを押す)とコンパイラが呼び出され、問題が無ければソースコードから実行可能なプログラムが同じフォルダの中に生成される。

GDL_DebugBuild.png

コンパイルが成功すると「デバッガ(GDB)を起動しますか?」と問い合わせてくるので、OKを押すとデバッガ(GDB)が開く。

GDL_GDBRun.png

GDBの操作説明は省くが、そのプロンプト上で「r」と入力してエンターキーを押すとコンパイルしたプログラムが実行される。

GDB_Execute.png

なおデバッガに興味を持ったのであれば使い方を検索してみると良い。

Page Top
その他の機能 anchor.png

ソースコードの編集以外には大した機能は無いが、その中でも余り知られていない機能を紹介する。

  • 外部ファイル参照
    ソースコードのヘッダ等のファイル名が記述されたところにマウスカーソルを置き「Ctrl」キーを押しながらダブルクリックすると、該当のファイルを検索して別ウィンドウでそのファイルを開く事ができる。
    GDL_NewWindow.png
    ソースコードファイルとは別のヘッダファイル等を参照する際に利用できる。
  • ブラウザ機能
    外部ファイル参照と似ているが、ソースコード中にコメント等でURLを記述しておき、そこにマウスカーソルを置き「Ctrl」キーを押しながらダブルクリックすると、別ウィンドウでそのサイトを開く事ができる。
    GDL_NewIEWindow.png
    APIのドキュメントはホームページにのみ公開しているので、そのURLをソース中のコメントに記述して参照する際に利用してはどうだろうか。
  • タグジャンプ
    「検索(S)」メニュー内の「タグファイル自動生成(C)」と「タグ生成オプション」内の「タグ生成時にカレントフォルダを含める」をチェックしておく。ソースコードをファイルに保存するとタグファイルが生成し直される(特に見かけ上変化はない)。
    準備ができたらソースコードの関数名が書かれた部分にカーソルを置き、「Ctrl」キーを押しながら「]」キーを押してから「]」キーのみを放す(「Ctrl」キーのみが押された状態)とエディタウィンドウ中央にその関数名の宣言がなされているファイルの一覧が表示される。
    GDL_TagJump.png
    その関数名の参照先が見つからなかった場合は、ファイルの一覧は表示されない。「Ctrl」キーが押されままの状態でファイルの一覧が表示されている間にカーソルキーの上下やマウスのクリックでファイル一覧から任意のファイル名を選択すると、そのファイルが別ウィンドウが開いてかつ該当するタグが記述されている場所にジャンプする。もし編集中のソースコードが参照先の場合は、別ウィンドウは開かずにそのまま該当箇所にジャンプする。
    なおタグとソースコードとの相関はほぼ皆無なので、あくまで参考程度に。
  • エンコード
    ソースコードファイルはテキストファイルではあるが、コンパイラは文字コードに影響を受けやすい。エディタ上では問題無く閲覧できるが、いざコンパイルする段階になって不明なエラーが生じる事がある。
    GCC Developer LiteのデフォルトエンコードであるShift_JISでは問題が生じやすいため、できればUTF-8もしくはBOM付きUTF-8に変更た上でソースコードファイルを保存する事を推奨する。画面最下段のステータスバーの右側に現在のエンコードと改行の状態が表示されており、右クリックして表示されるポップアップメニューより任意のエンコードと改行に変更できる。
    GDL_Encode.png
  • 文字サイズ
    GCC Developer Liteは最近の高DPIなPCに対応していないため、高解像度になればなるほどエディタ上の文字サイズが小さく表示され、場合によっては普通の視力では識別できない程小さく表示される。その場合は「Ctrl」キーを押しながらマウスホイールを回転させるかピンチイン・アウトさせると、それと連動して文字サイズが変わる。ソースコード全体の見通しを良くするために縮小したり、小さすぎて見えないから拡大するといった使い方ができる。
    GDL_Zoom.png
Page Top

トライアウト anchor.png

紹介するソースコード上ではID番号が1~4に設定されたDYNAMIXELがあり、信速度は1Mbpsに変更してあるものとした。自身の環境向けにはPC上のDXHUBに割り当てられたCOMポートの番号を修正する程度で済む筈だ。ID番号が4つよりも少なくても多くても動かす事はできるが、少なくともID番号が1と2に設定されたDYNAMIXELが無いと一部の機能の確認ができない。
またDYNAMIXELのコントロールテーブルには機能を大きく左右するOperating Modeなるアイテムがあり、出荷時は3(Position Control Mode)に設定されている。紹介するソースコードによってはそのモードを変更しており、DYNAMIXELの電源を投入し直してもモードはそのまま保持される。他の目的でDYNAMIXELを使用する際はOperating Modeが変更されている可能性がある事を常に失念しないよう注意する事。
さらに初期条件を整える時を除いてエラー処理の類いを行っておらず、何かしらの不都合があったとしてもプログラムの実行は停止しないまでか異常終了する事も考えられる。DX2LIBのAPIの大半は戻り値で実行の正否の判定ができるので、堅牢なアプリケションを構成する際は判断材料にすると良いだろう。

少なくともソースコードをコンパイルするに当たっての前提は、

である。

なおGCC Developer LiteはGNUツールを用いてコンパイルしているため、MSYS2の環境でもコンパイルできる。またCOMポート名や時間にかかる関数を修正すれば、他のOSでも容易に流用できる。

Page Top
DYNAMIXELの検索とモデル名の列挙 anchor.png

以後のソースコードには、APIを使用するのに共通する最低限必要な処理が含まれている。

  1. LoadDLL
    「dx2lib.h」をインクルードする前に「_DYNAMICLOAD」を宣言しているので、LoadDLLを実行してAPIを提供するDLLを動的に読み込む。実行プログラムと同じフォルダにDLLが無い場合は実行を終了させる。
  2. DX2_OpenPort
    COMポート名と通信速度を指定し、オープンに成功した際の戻り値を以後APIの引数に用いる。ソースコードでは"\\\\.\\COM3"といった具合にポート名に「\\\\.\\」といったプレフィクスを付与しているが、常に記述しておく事を推奨する。
  3. DXL_ScanDevices
    全ID番号を対象としたDYNAMIXELの検索と見つかったID番号のテーブルの生成を行う。戻り値は見つかったDYNAMIXELの数で、引数に指定した配列にはそのID番号が保存される。以後検索で見つからなかったID番号を指定してAPIを呼び出しても、実際には処理は行われずに無視される。
  4. DX2_ClosePort
    DX2_OpenPortでオープンしたCOMポートのクローズする。以後は引数で指定したデバイスIDが使用できなくなる。
  5. UnloadDLL
    DLLの破棄を行う。この処理以後は全APIが使えなくなり、万が一呼び出してしまうと一般保護エラーが発生する。

最終的には検索とCOMポートのクローズの間に実際に行いたい処理を追記する事になる。
DXL_ScanDevicesによる検索はDYNAMIXELのモデルが想定と違っていてもある程度順応できるようにと考えての事だが、諸設定が最適に設定されていたとしても検索が終わるまではそれ相応の時間(約10秒程度)かかる。

// DYNAMIXELの検索とモデル名の列挙
#include <stdio.h>
#define _DYNAMICLOAD  // DX2LIBの動的呼び出しを宣言
#include "dx2lib.h"   // DX2LIBのヘッダ

void main (void) {
  // DLLの読み込み(成功は必須)
  if (LoadDLL ()) {
    uint8_t IDs[253];   // 見つかったIDのリスト
    int detectnum = 0;  // 見つかった数

    // COMポートのオープン
    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);

    // devが0でなければオープン成功
    if (dev) {
      // 検索
      detectnum = DXL_ScanDevices (dev, IDs);

      // 見つかったモデルをコンソールに列挙
      DXL_PrintDevicesList ((void *)&printf);

      // この辺りに目的の処理を追記

      // COMポートのクローズ
      DX2_ClosePort (dev);
    }
    // DLLの破棄
    UnloadDLL ();
  }
}

正常に検索が終了すると左からID番号・モデル名・モデル番号の順に次のような情報が表示される。

[  1] 2XL430-W250    ($0442)
[  2] 2XL430-W250    ($0442)
[  3] 2XL430-W250    ($0442)
[  4] 2XL430-W250    ($0442)

なおID番号が1~4のDYNAMIXELが存在する前提でのDXL_GetModelInfo APIを使った登録方法も一応紹介しておく。こちらは指定されたID番号のみを対象に登録できるかを判断するので、全ID番号を対象とした検索を行った場合と異なりほぼ一瞬で処理が終了する。

// ID番号を決め打ちする場合
#include <stdio.h>
#define _DYNAMICLOAD
#include "dx2lib.h"

void main (void) {
  // DLLの読み込み(成功は必須)
  if (LoadDLL ()) {
    // COMポートのオープン
    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);

    // devが0でなければオープン成功
    if (dev) {
      // 検索の代わりにID番号を直接指定して登録
      DXL_GetModelInfo (dev, 1);
      DXL_GetModelInfo (dev, 2);
      DXL_GetModelInfo (dev, 3);
      DXL_GetModelInfo (dev, 4);

      // 登録されたモデルをコンソールに列挙
      DXL_PrintDevicesList ((void *)&printf);

      // この辺りに目的の処理を追記

      // COMポートのクローズ
      DX2_ClosePort (dev);
    }
    // DLLの破棄
    UnloadDLL ();
  }
}
Page Top
LEDのON/OFF anchor.png

サイレントに動作確認を行うには、DYNAMIXELに搭載されているLEDを使うと良いだろう。

ID番号を指定してLEDを明滅させるDXL_SetLED APIを用いて、個々のID番号を順に指定してLEDをON/OFFさせる。なおAPIの処理そのものは一瞬で終わってしまうので、目に見えるように10回のループ内のLEDのONとOFFの後にSleep命令で500msの中断を挿入した。

// LEDのON/OFF
#include <stdio.h>
#define _DYNAMICLOAD
#include "dx2lib.h"

void main (void) {
  if (LoadDLL ()) {
    uint8_t IDs[253];   // 見つかったIDのリスト
    int detectnum = 0;  // 見つかった数

    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);
    if (dev) {
      detectnum = DXL_ScanDevices (dev, IDs);
      DXL_PrintDevicesList ((void *)&printf);

      // とりあえず10回繰り返す
      for (int i = 0; i < 10; i++) {
        // 全軸のLEDをONに設定
        printf ("ON ");
        for (int j = 0; j < detectnum; j++) DXL_SetLED (dev, IDs[j], true);
        Sleep (500);
        // 全軸のLEDをOFFに設定
        printf ("OFF ");
        for (int j = 0; j < detectnum; j++) DXL_SetLED (dev, IDs[j], false);
        Sleep (500);
      }

      DX2_ClosePort (dev);
    }
    UnloadDLL ();
  }
}

なおDYNAMIXELに何らかのアラームが発生した事によりLEDが自動点滅している間は、LEDの制御ができない。

Page Top
トルクのON/OFF anchor.png

試運転の際にも行っている通りトルクのONという操作を予め行っておかないと、位置や速度を指令してもホーンは動かない。コントロールテーブルのアイテム名が「Torque Enable」となっているためにトルクと称しているが、実際には設定された制御モードに従って制御を開始・停止する事を意味している。

DXL_SetTorqueEnablesEquival APIを用いて引数で指定されたID番号の一覧を用いて一斉にトルクのON/OFFを切り替える。

// トルクのON/OFF
#include <stdio.h>
#define _DYNAMICLOAD
#include "dx2lib.h"

void main (void) {
  if (LoadDLL ()) {
    uint8_t IDs[253];   // 見つかったIDのリスト
    int detectnum = 0;  // 見つかった数

    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);
    if (dev) {
      detectnum = DXL_ScanDevices (dev, IDs);
      DXL_PrintDevicesList ((void *)&printf);

      // とりあえず意味も無く5回繰り返す
      for (int i = 0; i < 5; i++) {
        // 全軸のトルクをONに設定
        printf ("ON ");
        DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, true);
        Sleep (1000);
        // 全軸のトルクをOFFに設定
        printf ("OFF ");
        DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, false);
        Sleep (1000);
      }

      DX2_ClosePort (dev);
    }
    UnloadDLL ();
  }
}

トルクがOFFの時にDYNAMIXELは脱力し、外力でホーンを動かす事ができる。
またコントロールテーブル中のアイテムの一部にはトルクがONの状態では変更できないものもあるため、APIによっては必要に応じてトルクのOFFを発行しているものがある。

Page Top
角度指令 anchor.png

DYNAMIXELの本分である位置決め制御を行う。

DXL_SetOperatingModesEquival APIを使用して全DYNAMIXELの動作モードを3:Position Control Modeに設定(このAPIは内部でトルクOFFを発行する)。全軸のトルクをON。コメントにあるように1秒かけて全軸の角度を45度へ移動→2秒かけて全軸の角度を-45度へ移動→1秒かけて全軸の角度を0度へ移動。最後に全軸のトルクをOFFにして終了する。foo関数内のDXL_SetGoalAnglesAndTime APIは軸数分の角度の配列と現在の角度からの移動時間を秒で指定するAPIだが、DYNAMIXELへの指令を終えると移動時間を待たずに即時復帰する。そのため直後にSleep関数で移動している間だけプログラムの進捗を意図的に停止させている。

// 角度指令
#include <stdio.h>
#define _DYNAMICLOAD
#include "dx2lib.h"

// 角度指令と時間待ち関数
bool foo (TDeviceID dvid, const uint8_t *ids, const double *angles, int num, double sec) {
  bool result = DXL_SetGoalAnglesAndTime (dvid, ids, angles, num, sec);
  Sleep (sec * 1000); // 移動完了まで待機
  return result;
}

void main (void) {
  if (LoadDLL ()) {
    uint8_t IDs[253];   // 見つかったIDのリスト
    int detectnum = 0;  // 見つかった数
    double angles[253]; // 角度の配列

    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);
    if (dev) {
      detectnum = DXL_ScanDevices (dev, IDs);
      DXL_PrintDevicesList ((void *)&printf);

      // 全軸を 3: Position Control に設定
      DXL_SetOperatingModesEquival (dev, IDs, detectnum, 3);
      // 全軸のトルクをONに設定
      DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, true);

      // 1秒かけて全軸の角度を45度へ移動
      printf ("45deg ");
      for (int j = 0; j < detectnum; j++) angles[j] = 45.0;
      foo (dev, IDs, angles, detectnum, 1.0);

      // 2秒かけて全軸の角度を-45度へ移動
      printf ("-45deg ");
      for (int j = 0; j < detectnum; j++) angles[j] = -45.0;
      foo (dev, IDs, angles, detectnum, 2.0);

      // 1秒かけて全軸の角度を0度へ移動
      printf ("0deg ");
      for (int j = 0; j < detectnum; j++) angles[j] = 0.0;
      foo (dev, IDs, angles, detectnum, 1.0);

      // 全軸のトルクをOFFに設定
      DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, false);

      DX2_ClosePort (dev);
    }
    UnloadDLL ();
  }
}

角度や時間を変えて実際の挙動がどのようになるか試して欲しい。

Page Top
角度取得 anchor.png

こちらもDYNAMIXELの本分であるフィードバック値の取得を行う。

全軸のDYNAMIXELのトルクをOFFにして外力でホーンを動かせる状態にした後、DXL_GetPresentAngles APIを使用して複数軸の現在角度を取得し、ID番号と合わせて取得した角度を全軸分表示する。角度の取得と表示を何かしらのキー入力を行うまでループし続ける。

// 角度取得
#include <stdio.h>
#include <conio.h>
#define _DYNAMICLOAD
#include "dx2lib.h"

void main (void) {
  if (LoadDLL ()) {
    uint8_t IDs[253];   // 見つかったIDのリスト
    int detectnum = 0;  // 見つかった数
    double angles[253]; // 角度の配列

    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);
    if (dev) {
      detectnum = DXL_ScanDevices (dev, IDs);
      DXL_PrintDevicesList ((void *)&printf);

      // 全軸を 3: Position Control に設定
      DXL_SetOperatingModesEquival (dev, IDs, detectnum, 3);
      DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, false);

      // キー入力があるまでループ
      while (!_kbhit ()) {
        // 全軸の現在角度を取得
        DXL_GetPresentAngles (dev,IDs, angles, detectnum);
        // 取得した角度を表示
        printf ("\r");
        for (int j = 0; j < detectnum; j++) printf("[%d]%6.1f ", IDs[j], angles[j]);
      }

      DX2_ClosePort (dev);
    }
    UnloadDLL ();
  }
}
Page Top
角度取得と角度指令 anchor.png

現在のDYNAMIXELのホーンの位置を取得して他のDYNAMIXELへの角度指令値として利用する。

ID番号が1のDYNAMIXELのトルクをOFFにして外力でホーンを動かせる状態にし、DXL_GetPresentAngle APIで現在のホーンの角度を取得する。その後DXL_SetGoalAngles APIを用いてその角度を全軸のDYNAMIXELへ指令する。ID番号1に対しても角度を指令しているが、予めトルクをOFFにしているのでホーンは動かない。角度の取得と位置の指令を何かしらのキー入力を行うまでループし続ける。

// 角度取得と角度指令
#include <stdio.h>
#include <conio.h>
#define _DYNAMICLOAD
#include "dx2lib.h"

void main (void) {
  if (LoadDLL ()) {
    uint8_t IDs[253];   // 見つかったIDのリスト
    int detectnum = 0;  // 見つかった数
    double angle = 0;   // 現在の角度
    double angles[253]; // 角度の配列

    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);
    if (dev) {
      detectnum = DXL_ScanDevices (dev, IDs);
      DXL_PrintDevicesList ((void *)&printf);

      // 全軸を 3: Position Control に設定
      DXL_SetOperatingModesEquival (dev, IDs, detectnum, 3);
      DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, true);

      // ID=1のみトルクをOFFに設定
      DXL_SetTorqueEnable (dev, 1, false);

      // キー入力があるまでループ
      while (!_kbhit ()) {
        // ID=1の現在角度を取得
        DXL_GetPresentAngle (dev, 1, &angle);
        printf("\rPresent Angle = %4.1f  ", angle);
        // 全軸に同じ目標角度を指令
        for (int j = 0; j < detectnum; j++) angles[j] = angle;
        DXL_SetGoalAngles (dev, IDs, angles, detectnum);
      }

      DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, false);
      DX2_ClosePort (dev);
    }
    UnloadDLL ();
  }
}

なお前述のDXL_SetGoalAnglesAndTime APIを使ったプログラムを実行すると、移動時間の情報がDYNAMIXELに残ったままになる。その直後に本プログラムを実行した場合、ID番号1のホーンの動きに他のホーンが即応しないように見える。その場合はDYNAMIXELへ供給していた電源を一旦OFFにした後に再度ONにしてからプログラムを実行する事。

Page Top
角速度指令 anchor.png

最高速度はあまり速くはないが、DYNAMIXELにホイールを装着して台車の足回りに使う事ができる。

DXL_SetOperatingModesEquival APIを使用して全DYNAMIXELの動作モードを1:Velocity Controlに設定(このAPIは内部でトルクOFFを発行する)。全軸のトルクをON。DXL_SetGoalVelocities APIを使用して全軸の角速度を30deg/sに設定→全軸の角速度を-30deg/sに設定→全軸の角速度を0deg/sに設定。最後に全軸のトルクをOFFにして終了する。

// 角速度指令
#include <stdio.h>
#include <conio.h>
#define _DYNAMICLOAD
#include "dx2lib.h"

void main (void) {
  if (LoadDLL ()) {
    uint8_t IDs[253];   // 見つかったIDのリスト
    int detectnum = 0;  // 見つかった数
    double velo[253];   // 角速度の配列

    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);
    if (dev) {
      detectnum = DXL_ScanDevices (dev, IDs);
      DXL_PrintDevicesList ((void *)&printf);

      // 全軸を 1: Velocity Control に設定
      DXL_SetOperatingModesEquival (dev, IDs, detectnum, 1);
      DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, true);

      // 全軸の角速度を30deg/sに
      printf ("30deg/s ");
      for (int j = 0; j < detectnum; j++) velo[j] = 30.0;
      DXL_SetGoalVelocities (dev, IDs, velo, detectnum);
      Sleep (5000); // 5秒待ち

      // 全軸の角速度を-30deg/sに
      printf ("-30deg/s ");
      for (int j = 0; j < detectnum; j++) velo[j] = -30.0;
      DXL_SetGoalVelocities (dev, IDs, velo, detectnum);
      Sleep (5000); // 5秒待ち

      // 全軸の角速度を0deg/sに
      printf ("0deg/s ");
      for (int j = 0; j < detectnum; j++) velo[j] = 0.0;
      DXL_SetGoalVelocities (dev, IDs, velo, detectnum);
      Sleep (1000); // 1秒待ち

      DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, false);
      DX2_ClosePort (dev);
    }
    UnloadDLL ();
  }
}
Page Top
モーション再生 anchor.png

角度指令の応用で、各軸に与える角度指令値を時間に応じて複数パターンで変遷させる。

ここでは各DYNAMIXELの目標角度とその角度へ移行させる時間をTMotion構造体とし、複数のTMotion構造体を連続して実行させる事で一連の動きを実現している。またID番号1~8があるものとしてDXL_GetModelInfo APIを使用して検索時間を無くした。
GetQueryPerformanceCounter APIはPCの起動からの時間をmsで取得できるので、モーションで指定された時間を待機する際に利用している。

// モーション再生
#include <stdio.h>
#include <conio.h>
#define _DYNAMICLOAD
#include "dx2lib.h"
#define AXISNUM   (8)   // 軸数
#define MSize(d)  (sizeof(d) / sizeof(d[0]))

// 存在の有無にかかわらず指定軸数分のID番号のテーブル
const uint8_t IDs[AXISNUM] = { 1,  2,  3,  4,  5,  6,  7,  8 };

// 各軸の角度と遷移時間の構造体
typedef struct {
  double  angles[AXISNUM];  // 軸数分の角度情報
  double  sec;              // 遷移時間
} TMotion;

// モーションデータ1
//  8軸を1秒かけて0度(センター)に移動
const TMotion motion1[] = {
  {{   0,   0,   0,   0,   0,   0,   0,   0}, 1.0},
};

// モーションデータ2
//  8軸の5つの様々な型を各秒数かけて移動
const TMotion motion2[] = {
  {{  90, 390,  90,  90,  90,  90,  90,  90}, 3.0},
  {{   0,   0,   0,   0,   0,   0,   0,   0}, 2.0},
  {{-290,-190, -90, -90, -90, -90, -90, -90}, 3.0},
  {{  45, 145,  45,  45,  45,  45,  45,  45}, 3.0},
  {{ -30,-230, -30, -30, -30, -30, -30, -30}, 3.0},
};

// モーション再生
void PLAY (TDeviceID dev, const uint8_t *ids, const TMotion *motion, int framenum) {
  for (int i = 0; i < framenum; i++) {
    double t = GetQueryPerformanceCounter () + motion[i].sec * 1000;
    DXL_SetGoalAnglesAndTime (dev, ids, motion[i].angles, AXISNUM, motion[i].sec);
    while (t > GetQueryPerformanceCounter ()) Sleep (1);
  }
}

void main (void) {
  if (LoadDLL ()) {
    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);
    if (dev != 0) {
      for (int i = 0; i < AXISNUM; i++)
        printf ("id=%2d, ModelName=%s\n", IDs[i], DXL_GetModelInfo (dev, IDs[i])->name);

      // 全軸を 4: Expand Position Control に設定
      DXL_SetOperatingModesEquival (dev, IDs, AXISNUM, 4);
      DXL_SetTorqueEnablesEquival (dev, IDs, AXISNUM, true);

      // motion1を再生
      printf("motion1 ");
      PLAY (dev, IDs, motion1, MSize (motion1));

      // motion2を再生
      printf("motion2 ");
      PLAY (dev, IDs, motion2, MSize (motion2));

      DXL_SetTorqueEnablesEquival (dev, IDs, AXISNUM, false);
      DX2_ClosePort (dev);
    }
    UnloadDLL ();
  }
}
Page Top
並列処理 anchor.png

1つのパケット処理にかかる時間が短ければ単位時間当たりにこなせるパケット数が増えるため、自ずと通信速度が高い環境が望まれる。その恩恵に与かれるものとしてOSの並列処理が挙げられる。

ここでは角度と電流値を取得してモニタし続ける処理をthread1、角度を指令し続ける処理をthread2といった具合に個別のスレッドに割り当てた。下準備と終了処理はmain内で行っているが、それ以外は各々のスレッドが各々独立して処理している。
各々のスレッドに使用しているAPIが互いを意識しないコードになっているのは、DX2LIBのAPIが排他的に処理されるように作られているためである。しかし1つのスレッドでAPIを無限ループで遅滞なく呼び出し続けられてしまうとリソースを独占されてしまうため、ループ中にSleepを入れて適宜コンテキストスイッチを促している。

// マルチスレッド
#include <stdio.h>
#include <conio.h>
#define _DYNAMICLOAD
#include "dx2lib.h"
#include <pthread.h>
#include <math.h>

bool term = false;    // スレッド終了フラグ

// スレッドに渡すパラメータ
typedef struct {
  TDeviceID dev;      // デバイスID
  const uint8_t *ids; // IDの配列
  int num;            // ID数
} TThInfo;

// スレッド1 (モニタ)
void *thread1 (TThInfo *info) {
  double pangle[info->num], pcur[info->num];

  while (!term) {
    // 現在位置取得
    if (DXL_GetPresentAngles (info->dev, info->ids, pangle, info->num)) {
      // 現在電流取得
      if (DXL_GetPresentCurrents(info->dev, info->ids, pcur, info->num)) {
        printf("\r");
        for (int i = 0; i < info->num; i++)
          printf ("(%d:%5.1f %6.1f) ", info->ids[i], pangle[i], pcur[i]);
      }
    }
    Sleep (5);
  }
  return (void *)NULL;
}

// スレッド2 (正弦波で角度指令)
void *thread2 (TThInfo *info) {
  double ang, angle[info->num];

  while (!term) {
    // 時間から±60度の角度を生成 (4秒周期)
    ang = sin (0.5 * M_PI * GetQueryPerformanceCounter () * 0.001) * 60.0;
    for (int i = 0; i < info->num; i++) angle[i] = ang;
    DXL_SetGoalAngles (info->dev, info->ids, angle, info->num);
    Sleep (5);
  }
  return (void *)NULL;
}

void main (void) {
  pthread_t th1, th2;

  if (LoadDLL ()) {
    uint8_t IDs[253];
    int detectnum = 0;

    TDeviceID dev = DX2_OpenPort ("\\\\.\\COM3", 1000000);
    if (dev) {
      detectnum = DXL_ScanDevices (dev, IDs);
      DXL_PrintDevicesList ((void *)&printf);

      // 全軸を 3: Position Control に設定
      DXL_SetOperatingModesEquival (dev, IDs, detectnum, 3);
      DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, true);

      // 2つのスレッドを作成
      TThInfo info = { dev, IDs, detectnum };
      pthread_create(&th1, NULL, (void *)thread1, (void *)&info);
      pthread_create(&th2, NULL, (void *)thread2, (void *)&info);

      // キー入力があるまでループ
      while (!_kbhit ()) {
        Sleep (100);
      }

      // スレッド終了を励起
      term = true;

      // スレッド終了待ち
      pthread_join(th1, NULL);
      pthread_join(th2, NULL);

      DXL_SetTorqueEnablesEquival (dev, IDs, detectnum, false);
      DX2_ClosePort (dev);
    }
    UnloadDLL ();
  }
}

同時に他のアプリケーションを使用すると、大抵の場合DYNAMIXELの挙動がおかしくなる。実際にはプログラムの実行が他のアプリケーションによって阻害され、 単純なループで高速に角度指令を行っている処理(こういった角度指令の仕方は旧来のDYNAMIXELの常套手段だった)が間延びしてしまう事が原因だ。マルチタスク環境において何がどのように影響するかを微調整する術はあるので、時間があるときにでも調べて欲しい。
またあえて諸々の通信速度を9600bpsに変更した場合も、最終的な動作にどの程度影響するかを試しても面白い。
その結果、Windows上でいわゆるリアルタイム性を担保するのは一筋縄ではいかない事が分かってもらえれば良いかと。

Page Top

他の言語 anchor.png

既にDX2LIBのページに紹介されている通りだが、基本的にC言語上で動作させることが前提となっているために扱いづらい事が多々ある。それでも使えない事も無いので、やけに流行っているPythonで遊んでみても面白いかと思う。
紹介したGCC Developer LiteにはPython3が含まれているので、コンパイルオプションで「Python(32bit)」を選んでライブラリのサンプルソースコードを適宜修正して是非実行してみて欲しい。


Front page   Diff ReloadPrint View   Page list Search Recent changes   RSS of recent changes (RSS 1.0) RSS of recent changes (RSS 2.0) RSS of recent changes (RSS Atom)
Last-modified: 2020-08-07 (Fri) 20:16:36 (JST) (15h)