ページへ戻る

− Links

 印刷 

BTE074B DXSHIELD :: Besttechnology

knowledge:BTE074B DXSHIELD

ページ内コンテンツ
    • 概要
    • 仕様
      • 同梱内容
      • 基本仕様
      • 内部簡略ブロック
      • 外観・レイアウト
      • 回路図
      • 各機能詳細
        • J1,J5
        • J2,J6
        • J3,J7
        • J4,J8
        • U1
        • JP1
        • JP2
        • JP3
        • SW1
        • CN1
        • CN12
        • CN2~CN6
        • CN7~CN11
        • ユーザランド
        • C2
    • 使用方法
      • 対応するデバイス
      • 接続方法
      • モード選択
        • ソフトウェアシリアルモード
        • ハードウェアシリアルモード
        • USBパススルーモード
      • ソフトウェア
        • DYNAMIXEL Wizard 2.0
        • Dynamixel Library for PC
        • Dynamixel Library for Arduino
    • その他
      • DXSHIELDのTTL・RS-485 I/Fについて
      • Arduino MEGAでの使用
        • ハードウェアシリアルモード(Serial0以外)
        • ソフトウェアシリアルモード
        • USBパススルーモード
      • Arduino UNO R4での使用
        • ハードウェアシリアルモード
        • ソフトウェアシリアルモード
        • ブリッジモード
      • 注意事項

ショップページへ[1]

E133C_3D.png

概要 anchor.png[2]

DXSHIELDはDynamixelシリーズと通信するためのI/F(RS-485・TTL)をArduinoに増設するシールドです。両I/Fのコネクタに電源を分配する機能も合わせ持ちます。
また、DXSHIELDのI/Fで通信できるデバイスであれば、Dynamixel以外のサーボモータにも適用できます。

※本製品は半田付け作業を要求します。
※旧バージョンのBTE074[3]に対してジャンパの追加やI/F部分のモジュール化などの仕様変更がなされています。
※文中でUNOとだけ記述している場合はArduino UNO R3未満を指します。

Page Top

仕様 anchor.png[4]

Page Top

同梱内容 anchor.png[5]

型式等数量備考
本体1E133C
I/F変換ボード1TTL2DXIF[6]
電源コネクタキット1式ハウジング JST VHR-2N[7] x1
コンタクト JST SVH-21T-P1.1[7] x2
ベース付ポスト JST B2P-VH-B[8] x1
ジャック CUI PJ-047AH[9] x1
シールド用ピンソケット1式6P x1, 8P x2, 10P x1
ジャンパ3個 
Page Top

基本仕様 anchor.png[10]

品番BTE074B
PCBリビジョンE133C (2層)
動作温度範囲0~60℃ 結露なきこと
外形寸法約52x53mm
重量
電源CN1/CN12:DC6~24V (Dynamixelが要求する電源)
内部ロジック:DC5V±5% (Arduinoより供給)
コネクタ等JST B4B-EH x5
JST B3B-EH x5
各I/F仕様TTL2DXIF[6]に準拠

Page Top

内部簡略ブロック anchor.png[11]

Page Top

外観・レイアウト anchor.png[13]

topside
3D
E133C 3D pdf[16]
※ダウンロードした上でAcrobat Readerで閲覧の事

※出荷時にピンソケット・電源用コネクタ・TTL2DXIFは未装着

Page Top

回路図 anchor.png[18]

※D1・D2・U1・J1~8・CN1・CN12・CN13~16・C2は未装着

Page Top

各機能詳細 anchor.png[20]

Page Top
J1,J5 anchor.png[21]
E133C_J1_5.png
  • 2.54mmピッチ 10ピンシングルラインヘッダ用ランド
  • J1とJ5の各端子は相互に接続
  • Arduinoと接続する際はJ1に任意のピンソケット等を装着
    Pin No.NameUsed in DXSHIELD
    1IO8yes
    2IO9yes
    3IO10/SSno
    4IO11/MOSIno
    5IO12/MISOno
    6IO13/SCKno
    7GNDyes
    8AREFno
    9AD4/SDAno
    10AD5/SCLno
Page Top
J2,J6 anchor.png[22]
E133C_J2_6.png
  • 2.54mmピッチ 8ピンシングルラインヘッダ用ランド
  • J2とJ6の各端子は相互に接続
  • Arduinoと接続する際はJ2に任意のピンソケット等を装着
    Pin No.NameUsed in DXSHIELD
    1IO0/RXyes
    2IO1/TXyes
    3IO2no
    4IO3no
    5IO4no
    6IO5no
    7IO6no
    8IO7no
Page Top
J3,J7 anchor.png[23]
E133C_J3_7.png
  • 2.54mmピッチ 8ピンシングルラインヘッダ用ランド
  • J3とJ7の各端子は相互に接続
  • Arduinoと接続する際はJ3に任意のピンソケット等を装着
    Pin No.NameUsed in DXSHIELD
    1-no
    2IOREFno
    3RESETno
    43V3no
    55Vyes
    6GNDyes
    7GNDyes
    8Vinyes
Page Top
J4,J8 anchor.png[24]
E133C_J4_8.png
  • 2.54mmピッチ 6ピンシングルラインヘッダ用ランド
  • J4とJ8の各端子は相互に接続
  • Arduinoと接続する際はJ4に任意のピンソケット等を装着
    Pin No.NameUsed in DXSHIELD
    1AD0no
    2AD1no
    3AD2no
    4AD3no
    5AD4/SDAno
    6AD5/SCLno
Page Top
U1 anchor.png[25]

TTL2DXIF[6]装着前のDXSHIELD

E133C_U1.png

TTL2DXIF[6]装着後のDXSHIELD

E133C_E150.png
  • 向きを間違えないようにTTL2DXIF[6]のJ1とJ2の全てのランドを実装
  • TTL2DXIF[6]のCN1とCN2にコネクタが実装されている場合でも、それらを使用する事は可能
  • TTL2DXIF[6]をDXSHIELD以外で使用する場合は、J1とJ2に着脱式のコネクタを装備すると良い
Page Top
JP1 anchor.png[26]
E133C_JP1.png
  • DXSHIELDの電源をArduinoの外部電源として供給する場合に使用
  • ショート:CN1もしくはCN12から供給された電源をArduinoのVinに分配
    CN1もしくはCN12に供給する電圧はArduinoのVinが許容する電圧範囲を守る事
  • オープン:CN1もしくはCN12から供給された電源とArduinoのVinを切断
    CN1もしくはCN12とArduinoのVin各々に電源を供給するか、USBバスパワーで動作するArduinoであればPCとArduinoをUSBケーブルで常時接続する事
:idea:JP1をショートした状態でArduinoのVinから電源を供給してはならない。
CN2~CN11の電源がJP1を介してArduinoより供給されるため、使用デバイスの負荷条件によってはJP1等の許容電流を超え基板が損傷する。
:idea:JP1をショートした状態でCN1もしくはCN12とArduinoの外部電源に各々個別の電源を供給してはならない。
両電源が短絡するため、電源や負荷の条件によってはJP1や基板のみならず電源までが損傷する。
Page Top
JP2 anchor.png[27]
E133C_JP2_3.png
  • SW1で選択された送信端子とTTL2DXIF[6]のRXDを接続
  • ショート:I/FボードのRXD端子にDXSHIELD上の信号を接続
    SW1の機能が利用可能
  • オープン:I/FボードのRXD端子をDXSHIELD上の信号から切断
    SW1は一切機能しない
  • 2ピン側にTTL2DXIF[6]のRXD端子が接続
Page Top
JP3 anchor.png[28]
E133C_JP2_3.png
  • SW1で選択された受信端子とTTL2DXIF[6]のTXDを接続
  • ショート:I/FボードのTXD端子にDXSHIELD上の信号を接続
    SW1の機能が利用可能
  • オープン:I/FボードのTXD端子をDXSHIELD上の信号から切断
    SW1は一切機能しない
  • 2ピン側にTTL2DXIF[6]のTXD端子が接続
Page Top
SW1 anchor.png[29]
E133C_SW1.png
  • 3Tスライドスイッチ
  • シリアル通信に使用するArduinoの送受信端子を3パターンから選択
    詳細はこちら
  • SW1の機能を使用する場合はJP2及びJP3はいずれもショート状態である事
Page Top
CN1 anchor.png[30]

B2P-VH-Bを実装して使用。CN12を同時に実装する事はできない。

E133C_CN1.png
  • JST B2P-VH-B[8]
  • JP1をショートするとArduinoのVin端子へ本電源が接続
    その場合はArduinoのVinが許容する電圧範囲である事
  • CN2~6,CN7~11のVDD/GND端子へ接続
    PWR_connector.png
:idea:電源の逆接続は電源回路の即時破壊・全損扱いとなる。
Page Top
CN12 anchor.png[31]

PJ-047AHを実装して使用。CN1を同時に実装する事はできない。

E133C_CN12.png
  • CUI PJ-047AH[9]
  • 対応プラグ外形5.5mm, 内径2.1mm
  • 極性 センタープラス
    E133_CN12Pole.png
  • JP1をショートするとArduinoのVin端子へ本電源が接続
    その場合はArduinoのVinが許容する電圧範囲である事
  • CN2~6,CN7~11のVDD/GND端子へ接続
Page Top
CN2~CN6 anchor.png[32]
E133C_CN2_6.png
  • JST B3B-EH[33]
  • TTL I/Fを搭載したDynamixelシリーズ用のコネクタ
  • 5つのコネクタの各端子はいずれも内部で並列に接続
  • TTL I/Fと電源は以下の端子に接続
    B3B-EH.png
    端子番号信号名
    1GND
    2VDD
    3SIGNAL(BIDIRECTION)
Page Top
CN7~CN11 anchor.png[34]
E133C_CN7_11.png
  • JST B4B-EH[33]
  • RS-485 I/Fを搭載したDynamixelシリーズ用のコネクタ
  • 5つのコネクタの各端子はいずれも内部で並列に接続
  • RS-485 I/Fと電源は以下の端子に接続
    B4B-EH.png
    端子番号信号名
    1GND
    2VDD
    3RS-485 D+
    4RS-485 D-
Page Top
ユーザランド anchor.png[35]
E133C_URAND.png
  • 2.54mmピッチランド
  • 工作用
  • 5V0のシルクの囲みはArdunioから供給される5V、GNDのシルクの囲みはGNDに接続済
    それ以外のランドはフリー
Page Top
C2 anchor.png[36]
E133C_C2.png
  • 必要に応じてデカップリングコンデンサを装備
    100uF以上の容量を推奨
Page Top

使用方法 anchor.png[37]

Page Top

対応するデバイス anchor.png[38]

I/FDevice Name
TTLDynamixel AX・MX・Xシリーズ全般, DXMIO, ToFセンサ
RS-485Dynamixel DX・RX・EX・MX・X・PROシリーズ全般, UD3, UD3.5, UD4, USS3, DXMIO(RS-485版), ToFセンサ(RS-485版)

要求される電源電圧と対応するプロトコルが同じであれば、I/Fを問わず同時に使用できます。

Page Top

接続方法 anchor.png[39]

ここでは予めJP1~JP4に同梱のピンソケットが実装され、CN1ないしCN12には電源供給用のコネクタないしジャックが実装され、U1にTTL2DXIFが装着されているものとします。

  1. JP1~JP4の実装
    付属のピンソケットはリードが長くて弱い。他のArduino用シールドをスタックして使用しないのであれば、市販の2.54mmピッチの1列ピンヘッダを使用しても構わない。
  2. CN1もしくはCN12の実装
    熱容量の大きいベタパターンに対して行う必要があるため、高い容量の半田ごてを使用すると作業性が上がる。また予めフラックスを塗布したり基板側を半田ごてで温めながら半田を流すと濡れが良くなる。
  3. TTL2DXIFへピンヘッダの実装
    TTL2DXIFに同梱のピンヘッダを2分割して半田付けし、DXSHIELDのU1(J1,J2)に装着する。ランド近傍に小さい部品があるので、半田の盛り過ぎや半田くずに注意が必要。
  4. C2の実装
    必要に応じてデカップリングコンデンサを実装するが、こちらも熱容量が大きい事と極性に注意が必要。

半田付けを終えたらDXSHIELDをArduinoに装着します。

  1. ArduinoにDXSHIELDをスタックさせる。その際に両基板のピンソケット以外が物理的に接触していない事。他のシールドを同時に使用する際は、DXSHIELDが使用している端子に十分配慮する事。
  2. Dynamixelのコネクタと同じDXSHIELD上のコネクタ同士を接続する。DXSHIELDにはTTL・RS-485 I/F共に各々5個のコネクタが装備されているが、I/Fの種類が一致してさえいればどのコネクタを使用しても構わない。
  3. DXSHIELDのCN1ないしCN12からDynamixelが要求する仕様の電源を供給する。この時絶対に電源の極性を間違えてはならない。
  4. DXSHIELDのJP1がオープンの場合はArduino本体への電源供給が必要なため、別途USBケーブルやACアダプタをArduinoへ接続して電源供給する。
    DXSHIELDのJP1がショートの場合はCN1からの電源がArduinoへも分配される。この状態でDXSHIELDとArduinoの両方からACアダプタ等を使って給電すると、電源が衝突して故障の原因となる。
Page Top

モード選択 anchor.png[42]

Arduinoの種類に依存する部分が多々ありますが、ここではDXSHIELDをArduino UNO R3[43]に装着して使用する前提として3つのモードを説明します。

Page Top
ソフトウェアシリアルモード anchor.png[44]

ArduinoのIO8・IO9ピンをソフトウェアシリアルで構成しDynamixelと通信するモードです。ArduinoのUSBシリアル通信機能(ハードウェアシリアル)はDynamixelの制御以外の目的に使用できます。
Arduinoには任意の端子をシリアル通信の送受信端子として使用するSoftwareSerialライブラリが用意されています。最大57600bps程度であれば概ね実用レベルです。
JP2とJP3はいずれもショートさせ、SW1を図の位置(SOFT)に切り替えます。

E133C_SW1_SOFT.png

本設定によりArduinoのデジタル入出力端子のうちIO8とIO9をソフトウェアシリアル用の端子として使用するため、この2つの端子は他の目的で使用してはなりません。
また、Arduinoにユーザのスケッチを転送する際は、無条件に本モードに変更しておかないと転送に失敗します。

Page Top
ハードウェアシリアルモード anchor.png[45]

ArduinoのIO0・IO1ピンをハードウェアシリアル(Serial0)で構成しDynamixelと通信するモードです。ArduinoのIO0・IO1に接続されたUSBシリアル通信機能を犠牲にしても高速かつ安定した通信を要求する場合にの設定です。
予めソフトウェアシリアルモードにおいてライブラリによる制御の理解が得られ、スケッチの書き込み時以外にUSBシリアルによる通信を必要としない場合に本設定を選択します。
JP2とJP3はいずれもショートさせ、SW1を図の位置(HARD)に切り替えます。

E133C_SW1_HARD.png

本設定を行った場合は、自身のスケッチでSerialライブラリを使用してはなりません。また、IO0・IO1ピンとUSBシリアル通信機能は他の目的で使用する事ができません。
なお、スケッチをコンパイルして描き込む際は、本設定が電気的にUSBシリアル通信機能に影響を及ぼすため、その都度ソフトウェアシリアルモードに切り替える必要があります。

Page Top
USBパススルーモード anchor.png[46]

Arduinoに搭載されたUSBシリアル通信機能を用いてPCなどからDXSHIELDをDXHUB[47]ライクに直接使用するモードです。Dynamixelの内部パラメータの変更や制御をPCから行う場合は本設定を行います。
まずArduino IDEにてデフォルトで生成されるコード(コードとしては意味を持たない無限ループするだけのスケッチ)をコンパイルし、予めArduinoに書き込んでおきます。このほぼ空のスケッチはDigital I/Oやシリアル通信を使用しないため、PCとDynamixel間の通信を阻害しません。なお、これに該当する独自スケッチであればこの限りではありません。

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

DXSHIELDをソフトウェアシリアルモードに設定してこの何もしないスケッチを書き込んだ後、USBパススルーモードにします。
JP2とJP3はいずれもショートさせ、SW1を図の位置(THROUGH)に切り替えます。

E133C_SW1_THROUGH.png

なお、ArduinoのUSBシリアルを担うマイコンに書き込まれているファームウェアの都合で、大きなデータを連続で送受信する事ができません。プロトコルV1を装備するDynamixelシリーズであれば概ね問題はありませんが、プロトコルV2を装備するDynamixelシリーズではコントロールテーブルの拡大に伴いこの問題が露見します。
また、ArduinoのUSBシリアルとRoboPlusやDYNAMIXEL Wizard 2.0との相性もよろしくないので、本モードを積極的に使用する事は推奨しません。

Page Top

ソフトウェア anchor.png[48]

Page Top
DYNAMIXEL Wizard 2.0 anchor.png[49]

DXSHIELDをUSBパススルーに設定にする事で、Dynamixelのコントロールテーブルの状態をモニタしたりパラメータの変更や動作確認を簡便に行うソフトウェアであるDYNAMIXEL Wizard 2.0[50]が一部利用できます。

一部というのは、ArduinoのUSBシリアル通信機能は過度なトラフィックがかかるとデータがドロップするのと、RoboPlusにおいて検索を行わせている最中にボーレートの切り替えが発生するとArduinoが再起動する場合がある事がわかっているためです。注意事項に記載したNerOを使用する事で回避できます。

Page Top
Dynamixel Library for PC anchor.png[52]

DXSHIELDをUSBパススルーにする事で、Dynamixel Libraryを併用してシリアル通信やプロトコルを意識せずにPCから制御する事ができます。

詳細はDYNAMIXEL Protocol 1.0 Library[53]DYNAMIXEL Protocol 2.0 Library[54]にて。

なお、ArduinoのUSBシリアル通信機能は過度なトラフィックがかかるとデータがドロップするため、運用には予め十分な検証を行っておくべきです。

Page Top
Dynamixel Library for Arduino anchor.png[55]

Dynamixelを制御するためのプログラムを作成する際のライブラリを提供します。Arduino IDEにライブラリをインストールして使用します。
PC版DYNAMIXEL Protocol 1.0[53]/2.0[54] Libraryと同様にコントロールテーブルへの読み書きを行うAPIを用意しています。なおAVRではメモリの都合からV1.5から追加されたライブラリは使用できないのと、クラスのインスタンス化の際の引数が以前のバージョンから大幅に変更されている点に注意が必要です。

  • ライブラリのダウンロード
      • 定義の修正を行ったため一部β版との互換性なし
      • Arduino UNO以外も対象とするためにソースからシリアルライブラリに関する記述を削除し、シリアル通信にかかる8つのハンドラを新たに設置
      • Arduino UNOに限って初期化を始め送受信にかかるハンドラをソフトウェアシリアルとハードウェアシリアル用に提供
      • AVRを除くターゲットに適用した場合、PCやARM系マイコン用に提供しているDXLIBに追加されたAPI[57]が使用可能
        詳細は追って公開
      • 仕様変更に伴うサンプルプログラム修正
      • チェックサムの検証を厳密化
      • 新たにReadBlockDataとWriteBlockData関数を追加し、コントロールテーブルの読み出し及び書き込みはこの関数を介するように変更
      • プロトコルV2の例外時(0xFF 0xFF 0xFDの並びでデータが現れた場合に末尾に0xFDを付与)の処理を全ての関数へ適用(一部制約あり)
      • コンパイル時のwarningを抑止
      • 多少サンプルプログラムの構成を変更
      • Win版dxlibからアイテムのアドレスをマクロ定義したヘッダをコピー
      • Dynamixel Protocol V.2に対応
      • 低位の送受信関数追加
      • 32bitデータの送受信関数追加
      • アドレスとサイズに関する引数は全て16bitに統一

DXLIBのインストールは、ArduinoのIDEの「スケッチ→ライブラリのインクルード→.ZIP形式のライブラリをインストール...」メニューを使用してダウンロードしたZIPファイルを選択するだけです。
インストールが完了すると、ユーザーフォルダ配下に「Arduino/libraries/dxlib」が作られ、ライブラリのソースといくつかのサンプルプログラムがその中に展開されます。詳しくはサンプルプログラムとライブラリのソースを参照して下さい。

DXLIB v1.5以降で使用できるヘッダファイルとAPIは以下の通りです。

  • dxlib.h
    DYNAMIXEL Communiation Protocol 1.0[63]対応デバイスを対象とする場合、dxlib.hをスケッチにインクルードする事でDXLIBクラスが利用できるようになります。dx2lib.hとの共存は想定していません。
    #include <dxlib.h>
    #include "avr_uno_softserial.h"
    const DXLIB::TDXHost_ConfParam param {
      us_init, us_deinit, us_setbaudrate, us_rxpurge, us_putc, us_puts, us_gets, us_flush
    };
    
    DXLIB dxif ((DX2LIB::TDXHost_ConfParam *)&param);
    
    void setup() {
      dxif.begin (57600);
    }
  • dx2lib.h
    DYNAMIXEL Communiation Protocol 2.0[64]対応デバイスを対象とする場合、dx2lib.hをスケッチにインクルードする事でDX2LIBクラスが利用できるようになります。dxlib.hとの共存は想定していません。
    #include <dx2lib.h>
    #include "avr_uno_softserial.h"
    const DX2LIB::TDXHost_ConfParam param {
      us_init, us_deinit, us_setbaudrate, us_rxpurge, us_putc, us_puts, us_gets, us_flush
    };
    
    DX2LIB dxif ((DX2LIB::TDXHost_ConfParam *)&param);
    
    void setup() {
      dxif.begin (57600);
    }
  • DXLIB/DX2LIB::TDXHost_ConfParam
    ライブラリv1.5より導入された通信を担う8つの関数のポインタを保持する構造体で、クラスをインスタンス化する際に引数として渡します。
    各メンバーの関数のプロトタイプに合わせた通信処理関数を予め作成しておく必要があります。
    // Assuming HardwareSerial of Arduino UNO
    #include <dx2lib.h>
    
    // Initialize UART
    uint32_t us_init (uint32_t baud) {
      Serial.begin (baud);
      Serial.setTimeout (20);
      return baud;
    }
    
    // Terminate use of UART
    void us_deinit (void) {
      Serial.end();
    }
    
    // Changing the baudrate
    uint32_t us_setbaudrate (uint32_t baud) {
      us_deinit();
      return us_init (baud);
    }
    
    // Purge receive buffer
    void us_rxpurge (void) {
      while (Serial.available()) Serial.read();
    }
    
    // Send one byte
    void us_putc (uint8_t c) {
      Serial.write (c);
    }
    
    // Send specified number of bytes
    void us_puts (const uint8_t *buf, int len) {
      Serial.write (buf, len);
    }
    
    // Receive specified number of bytes (Timeout must be set in advance)
    int us_gets (uint8_t *buf, int len) {
      return Serial.readBytes (buf, len);
    }
    
    // Waiting for transmission completion
    void us_flush (void) {
      Serial.flush();
    }
    
    // Enclose each communication function in a structure
    const DX2LIB::TDXHost_ConfParam param {
      us_init, us_deinit, us_setbaudrate, us_rxpurge, us_putc, us_puts, us_gets, us_flush
    };
    
    DX2LIB dx2 ((DX2LIB::TDXHost_ConfParam *)&param);
    
    なおライブラリに同梱されるサンプルスケッチでは avr_uno_hardserial.havr_uno_softserial.h のヘッダファイルにArduino UNOを前提としたこれらの通信処理関数がまとめて記述してあります。
  • DXLIB/DX2LIB (const PDXHost_ConfParam param)
    ヘッダファイルに応じてDXLIBないしDX2LIBいずれかのクラスが使用できます。外部で定義したシリアル通信処理部分をまとめた構造体TDXHost_ConfParamを指定した上でオブジェクトを生成できます。
    #include <dx2lib.h>
    // Select SoftwareSerial
    //#include "avr_uno_hardserial.h"
    #include "avr_uno_softserial.h"
    
    const DX2LIB::TDXHost_ConfParam param {
      us_init, us_deinit, us_setbaudrate, us_rxpurge, us_putc, us_puts, us_gets, us_flush
    };
    
    // Instantiate Dynamixel Protocol V.2 Library with the name dxif
    DX2LIB dxif((DX2LIB::TDXHost_ConfParam *)&param);
    
  • void DXLIB/DX2LIB::begin (long baud)
    ライブラリを使用可能にします。引数(baud)にはDynamixelに設定されたボーレートを指定します。
    ボーレートの精度や範囲は使用するシリアルポートに依存します。
    // Initialize dxif at 57143bps
    void setup() {
      dxif.begin (57143);
    }
  • bool DXLIB/DX2LIB::TxPacket (uint8_t id, uint8_t inst, uint8_t *param, uint16_t len)
    指定されたID(id)・インストラクション(inst)・パラメータ(param)・パラメータ長(len)のインストラクションパケットを送信します。
    // Send ping instruction packet to ID=1
    dxif.TxPacket (1, 0x01, NULL, 0);
  • bool DXLIB/DX2LIB::RxPacket (uint8_t *rdata, uint16_t rdatasize, uint8_t *rid, uint16_t *rlen, uint8_t *err)
    ステータスパケットを受信します。成功するとパケット内のパラメータがrdataへコピーされ、そのパラメータのサイズがrlenに返されます。なお、ステータスパケットを受信するのに十分なサイズを確保し、そのポインタをrdataへ、サイズをrdatasizeに指定します。ridにはID、errにはDynamixelのエラーが返ります。
    uint8_t buf[10], id, err;
    uint16_t len;
    // Send ping instruction packet to ID=1
    dxif.TxPacket (1, 0x01, NULL, 0);
    // Receive status packet
    dxif.RxPacket (buf, sizeof (buf), &id, &len, &err)
  • bool DXLIB/DX2LIB::ReadBlockData (uint8_t id, uint16_t addr, uint8_t *data, uint16_t len, uint8_t *err)
    指定されたID(id)・アドレス(addr)から8ビットのデータをdatalenの長さ分読み出します。errにはDynamixelのエラーが返ります。
    なおDX2LIBで4バイト以上を読み出す場合、まずサフィックスが付与された状態でdataへ読み出し、その後に必要に応じてサフィックス削除が行われます。そのため実際に必要なサイズよりも大きめにdataを確保しておく必要があります(最大で1.34倍)。
    // Get Compliance for AX-12 with ID=1
    uint8_t compliance[4];
    dxif.ReadBlockData (1, 26, &compliance, 4, NULL);
  • bool DXLIB/DX2LIB::ReadByteData (uint8_t id, uint16_t addr, uint8_t *data, uint8_t *err)
    指定されたID(id)・アドレス(addr)から8ビットのデータをdataへ読み出します。errにはDynamixelのエラーが返ります。
    // Get the status of the LED on AX-12 with ID=1
    uint8_t led;
    dxif.ReadByteData (1, 25, &led, NULL);
  • bool DXLIB/DX2LIB::ReadWordData (uint8_t id, uint16_t addr, uint16_t *data, uint8_t *err)
    指定されたID(id)・アドレス(addr)から16ビットのデータをdataへ読み出します。errにはDynamixelのエラーが返ります。
    // Get PresentPosition from AX-12 with ID=1
    uint16_t ppos;
    dxif.ReadWordData (id, 36, &ppos, NULL);
  • bool DXLIB/DX2LIB::ReadLongData (uint8_t id, uint16_t addr, uint32_t *data, uint8_t *err)
    指定されたID(id)・アドレス(addr)から32ビットのデータをdataへ読み出します。errにはDynamixelのエラーが返ります。
  • bool DXLIB/DX2LIB::WriteBlockData (uint8_t id, uint16_t addr, const uint8_t *data, uint16_t len, uint8_t *err)
    指定されたID(id)・アドレス(addr)・8ビットのデータ(data)・指定バイト数(len)をDynamixelに書き込みます。errにはDynamixelのエラーが返ります。
    // Set Compliance for AX-12 with ID=1
    uint8_t err;
    uint8_t compliance[4] = {1,1,32,32};
    dxif.WriteBlockData (1, 26, &compliance, 4, &err);
  • bool DXLIB/DX2LIB::WriteByteData (uint8_t id, uint16_t addr, uint8_t data, uint8_t *err)
    指定されたID(id)・アドレス(addr)・8ビットのデータ(data)をDynamixelに書き込みます。errにはDynamixelのエラーが返ります。
    // Lights up the LED of AX-12 with ID=1
    uint8_t err;
    dxif.WriteByteData (id, 25, 1, &err);
  • bool DXLIB/DX2LIB::WriteWordData (uint8_t id, uint16_t addr, uint16_t data, uint8_t *err)
    指定されたID(id)・アドレス(addr)・16ビットのデータ(data)をDynamixelに書き込みます。errにはDynamixelのエラーが返ります。
    // Set GoalPosition of AX-12 with ID=1 to 511
    dxif.WriteWordData (id, 30, 511, NULL);
  • bool DXLIB/DX2LIB::WriteLongData (uint8_t id, uint16_t addr, uint32_t data, uint8_t *err)
    指定されたID(id)・アドレス(addr)・32ビットのデータ(data)をDynamixelに書き込みます。errにはDynamixelのエラーが返ります。
  • bool DXLIB/DX2LIB::WriteSyncByteData (const uint8_t *pid, uint16_t addr, const uint8_t *pdata, int num)
    指定されたid数(num)分のIDの配列(pid)・アドレス(addr)・8ビットのデータ配列(pdata)をDynamixelに書き込みます。
    // Lights up AX-12 LEDs with ID=1 to 5
    uint8_t ids={1,2,3,4,5};
    uint16_t leds={1,1,1,1,1};
    dxif.WriteSyncByteData (ids, 30, leds, 5);
  • bool DXLIB/DX2LIB::WriteSyncWordData (const uint8_t *pid, uint16_t addr, const uint16_t *pdata, int num)
    指定されたid数(num)分のIDの配列(pid)・アドレス(addr)・16ビットのデータ配列(pdata)をDynamixelに書き込みます。
    // Set different GoalPositions for each AX-12 with ID=1-5
    uint8_t ids={1,2,3,4,5};
    uint16_t poss={100,200,300,400,500};
    dxif.WriteSyncWordData (ids, 30, ppos, 5);
  • bool DXLIB/DX2LIB::WriteSyncLongData (const uint8_t *pid, uint16_t addr, const uint32_t *pdata, int num)
    指定されたid数(num)分のIDの配列(pid)・アドレス(addr)・32ビットのデータ配列(pdata)をDynamixelに書き込みます。
  • bool DXLIB/DX2LIB::Ping (uint8_t id, uint16_t *err)
    指定されたID(id)のDynamixelを検索します。errにはDynamixelのエラーが返ります。
  • bool DXLIB/DX2LIB::Reset (uint8_t id, uint16_t *err)
    指定されたID(id)のDynamixelを出荷時状態に戻します。errにはDynamixelのエラーが返ります。

以降のAPIはライブラリv1.5から新設されたAPIで、AVRシリーズを除いたターゲットで使用できます。詳細はこちら[57]を参照してください。

  • int DXLIB/DX2LIB::ScanDevices (uint8_t *ids)
  • PDXL_ModelInfo DXLIB/DX2LIB::GetModelInfo (uint8_t id)
  • bool DXLIB/DX2LIB::PrintDevicesList (int (*pf) (const char *, ...))
  • void DXLIB/DX2LIB::InitDevicesList (void)
  • TErrorCode DXLIB/DX2LIB::GetErrorCode (uint8_t id)
  • bool DXLIB/DX2LIB::GetHWErrorCode (uint8_t id, uint8_t *hwerr)
  • bool DXLIB/DX2LIB::SetDriveMode (uint8_t id, uint8_t mode)
  • bool DXLIB/DX2LIB::SetDriveModesEquival (const uint8_t *ids, int num, uint8_t mode)
  • bool DXLIB/DX2LIB::SetOperatingMode (uint8_t id, uint8_t mode)
  • bool DXLIB/DX2LIB::SetOperatingModesEquival (const uint8_t *ids, int num, uint8_t mode)
  • bool DXLIB/DX2LIB::GetOperatingMode (uint8_t id, uint8_t *mode)
  • bool DXLIB/DX2LIB::SetLED (uint8_t id, bool en)
  • bool DXLIB/DX2LIB::SetTorqueEnable (uint8_t id, bool en)
  • bool DXLIB/DX2LIB::SetTorqueEnables (const uint8_t *ids, const bool *ens, int num)
  • bool DXLIB/DX2LIB::SetTorqueEnablesEquival (const uint8_t *ids, int num, bool en)
  • bool DXLIB/DX2LIB::GetTorqueEnable (uint8_t id, bool *en)
  • bool DXLIB/DX2LIB::GetTorqueEnables (const uint8_t *ids, bool *en, int num)
  • bool DXLIB/DX2LIB::SetGoalAngle (uint8_t id, double angle)
  • bool DXLIB/DX2LIB::SetGoalAngles (const uint8_t *ids, const double *angles, int num)
  • bool DXLIB/DX2LIB::GetPresentAngle (uint8_t id, double *angle)
  • bool DXLIB/DX2LIB::GetPresentAngles (const uint8_t *ids, double *angles, int num)
  • bool DXLIB/DX2LIB::StandStillAngle (uint8_t id)
  • bool DXLIB/DX2LIB::StandStillAngles (const uint8_t *ids, int num)
  • bool DXLIB/DX2LIB::SetGoalVelocity (uint8_t id, double velocity)
  • bool DXLIB/DX2LIB::SetGoalVelocities (const uint8_t *ids, const double *velocities, int num)
  • bool DXLIB/DX2LIB::GetPresentVelocity (uint8_t id, double *velocity)
  • bool DXLIB/DX2LIB::GetPresentVelocities (const uint8_t *ids, double *velocities, int num)
  • bool DXLIB/DX2LIB::SetGoalAngleAndVelocity (uint8_t id, double angle, double velocity)
  • bool DXLIB/DX2LIB::SetGoalAnglesAndVelocities (const uint8_t *ids, PAngleVelocity anglevelocity, int num)
  • bool DXLIB/DX2LIB::SetGoalAngleAndTime (uint8_t id, double angle, double sec)
  • bool DXLIB/DX2LIB::SetGoalAnglesAndTime (const uint8_t *ids, const double *angles, int num, double sec)
  • bool DXLIB/DX2LIB::SetGoalAngleAndTime2 (uint8_t id, double angle, double sec)
  • bool DXLIB/DX2LIB::SetGoalAnglesAndTime2 (const uint8_t *ids, const double *angles, int num, double sec)
  • bool DXLIB/DX2LIB::SetGoalCurrent (uint8_t id, double current)
  • bool DXLIB/DX2LIB::SetGoalCurrents (const uint8_t *ids, const double *currents, int num)
  • bool DXLIB/DX2LIB::GetPresentCurrent (uint8_t id, double *current)
  • bool DXLIB/DX2LIB::GetPresentCurrents (const uint8_t *ids, double *currents, int num)
  • bool DXLIB/DX2LIB::SetGoalPWM (uint8_t id, double pwm)
  • bool DXLIB/DX2LIB::SetGoalPWMs (const uint8_t *ids, const double *pwms, int num)
  • bool DXLIB/DX2LIB::GetPresentPWM (uint8_t id, double *pwm)
  • bool DXLIB/DX2LIB::GetPresentPWMs (const uint8_t *ids, double *pwms, int num)
Page Top

その他 anchor.png[65]

Page Top

DXSHIELDのTTL・RS-485 I/Fについて anchor.png[66]

  • 送信はTTL・RS-485の両I/Fに対して同時に行われ、受信はTTL・RS-485の両I/FがOR接続されているため同時に受信できない。
  • Arduino側では送受信の切り替えタイミングを意識する必要はないが、半二重通信である事は十二分に意識する必要がある。
  • TTL・RS-485のいずれのI/Fにかかわらず同じIDを持ったDynamixelが存在してはならない。
  • TTLとRS-485のI/F間をまたいだ送受信はできないため、TTL・RS-485の両I/FにDynamixelが接続された環境において一部のインストラクションが正常動作しない。
Page Top

Arduino MEGAでの使用 anchor.png[67]

少しの改造でDXSHIELDをArduino MEGAで使用する事ができます。DXSHIELDは次の図の位置に装着します。

Page Top
ハードウェアシリアルモード(Serial0以外) anchor.png[69]

Serial0を利用する限りUNOと同様の運用になります。MEGAに備わっているSerial1~Serial3のハードウェアシリアルポートを利用する際は以下に従います。

  • JP2とJP3はオープンにする。
  • SW1はどの位置にあっても構わない。
  • Serial3を利用する際は、DXSHIELDのJP3-2とMEGAのIO15(RX3)、JP2-2とMEGAのIO14(TX3)を各々ジャンパ線等でつなぐ。
    Serial2ならJP3-2とIO17(RX2)、JP2-2とIO16(TX2)をつなぐ。
    Serial1ならJP3-2とIO19(RX1)、JP2-2とIO18(TX1)をつなぐ。
  • 使用するSerial??に合わせてavr_uno_hardserial.ht中のSerialとある部分を変更(DXLIB v1.5以降)。
Page Top
ソフトウェアシリアルモード anchor.png[71]

MEGAの仕様上IO8がソフトウェアシリアルとして使用する事ができないため、UNOで想定するソフトウェアシリアルモードで運用する事ができません。それでもソフトウェアシリアルで使用する場合は、MEGAのハードウェアシリアルモードと同様にJP2-2とJP3-2を直接MEGAのソフトウェアシリアルとして利用できる任意の端子に直結します。

  • JP2とJP3はオープンにする。
  • SW1はどの位置にあっても構わない。
  • 接続した端子に合わせてavr_uno_softserial.h中のMY_RX_PINとMY_TX_PINのマクロを変更(DXLIB v1.5以降)。
Page Top
USBパススルーモード anchor.png[72]

UNOのUSBパススルーモードと同様です。

Page Top

Arduino UNO R4での使用 anchor.png[73]

Arduino UNO R4[74]はCPUがARMに変わり、メモリ容量や動作スピードが大幅にUPしています。使わないのが勿体ない程の恩恵に与れます。minimaは形状やGPIOの割り当てに互換性があるので、DXSHIELDはそのまま利用できます。

※現状ではArduinoライブラリに問題があるため、解消するまで適用は控えてください。それでも115.2kbps以下であれば使えない事もありません。

Page Top
ハードウェアシリアルモード anchor.png[75]

SCI(AVRで言うUART)とUSBポートが分離しているため、ハードウェアシリアルモードで使用しても書き込みやデバッグ用に用いるUSBポートが同時に使用できます。
ハードウェアシリアル通信に用いられるSCI2はライブラリによってSerial1に割り当てられているので、DXLIB用に以下の通信用のサブルーチンを用意します。

#pragma once

#include <stdint.h>

uint32_t us_init (uint32_t baud) {
  Serial1.begin (baud);
  Serial1.setTimeout (20);
  return baud;
}

void us_deinit (void) {
  Serial1.end();
}

uint32_t us_setbaudrate (uint32_t baud) {
  us_deinit();
  return us_init (baud);
}

void us_rxpurge (void) {
  while (Serial1.available()) Serial1.read();
}

void us_putc (uint8_t c) {
  Serial1.write (c);
}

void us_puts (const uint8_t *buf, int len) {
  Serial1.write (buf, len);
}

int us_gets (uint8_t *buf, int len) {
  return Serial1.readBytes (buf, len);
}

void us_flush (void) {
  Serial1.flush();
}

ARM用のGCCはコードを厳密に評価するため、クラスの宣言時の引数は型変換して渡します。

#include <dx2lib.h>
#include "uno_r4_hardserial.h"

const DX2LIB::TDXHost_ConfParam param {
  us_init, us_deinit, us_setbaudrate, us_rxpurge, us_putc, us_puts, us_gets, us_flush
};

DX2LIB dx2 ((DX2LIB::TDXHost_ConfParam *)& param);
Page Top
ソフトウェアシリアルモード anchor.png[76]

ソフトウェアシリアル通信に用いられる端子用いた以下の通信用のサブルーチンを用意し、クラスを初期化します。

#pragma once

#include <stdint.h>
#include <SoftwareSerial.h>

SoftwareSerial *mysoftuart = NULL;

#define MY_RX_PIN 8
#define MY_TX_PIN 9

uint32_t us_init (uint32_t baud) {
  mysoftuart = new SoftwareSerial (MY_RX_PIN, MY_TX_PIN);
  mysoftuart->begin (baud);
  mysoftuart->setTimeout (20);
  return baud;
}

void us_deinit (void) {
//  mysoftuart->end();
  mysoftuart = NULL;
}

uint32_t us_setbaudrate (uint32_t baud) {
  us_deinit();
  return us_init (baud);
}

void us_rxpurge (void) {
  while (mysoftuart->available()) mysoftuart->read();
}

void us_putc (uint8_t c) {
  mysoftuart->write (c);
}

void us_puts (const uint8_t *buf, int len) {
  mysoftuart->write (buf, len);
}

int us_gets (uint8_t *buf, int len) {
  return mysoftuart->readBytes (buf, len);
}

void us_flush (void) {
  mysoftuart->flush();
}

AVRよりも高いボーレートが使用できます。

Page Top
ブリッジモード anchor.png[77]

上記の通りSCIとUSBが電気的に分離しているため、MPUを介在させないで通信するパススルーモードは使えません。DXSHIELDをハードウェアシリアルモードにし、以下のスケッチにてUSBにて提供される仮想シリアルポートとSCIの間をブリッジさせUSBシリアルコンバータとして機能させることができます。

#define _LED_TX   BSP_IO_PORT_00_PIN_12
#define _LED_RX   BSP_IO_PORT_00_PIN_13

uint32_t baud;
uint8_t b_usb[4096], b_uart[4096];

void setup() {
  R_IOPORT_PinCfg(NULL, _LED_TX, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
  R_IOPORT_PinCfg(NULL, _LED_RX, IOPORT_CFG_PORT_DIRECTION_OUTPUT);
  R_IOPORT_PinWrite(NULL, _LED_TX, BSP_IO_LEVEL_HIGH);
  R_IOPORT_PinWrite(NULL, _LED_RX, BSP_IO_LEVEL_HIGH);
  baud = 115200;
  Serial.begin (baud);
  Serial1.begin (baud);
}

void loop() {
  uint32_t l;

  if ((l = Serial.available()) > 0) {
    if (l > sizeof(b_usb)) l = sizeof(b_usb);
    R_IOPORT_PinWrite(NULL, _LED_TX, BSP_IO_LEVEL_LOW);
    Serial.readBytes (b_usb, l);
    Serial1.write (b_usb, l);
    R_IOPORT_PinWrite(NULL, _LED_TX, BSP_IO_LEVEL_HIGH);
  }
  if ((l = Serial1.available()) > 0) {
    if (l > sizeof(b_uart)) l = sizeof(b_uart);
    R_IOPORT_PinWrite(NULL, _LED_RX, BSP_IO_LEVEL_LOW);
    Serial1.readBytes (b_uart, l);
    Serial.write (b_uart, l);
    Serial.flush ();
    R_IOPORT_PinWrite(NULL, _LED_RX, BSP_IO_LEVEL_HIGH);
  }
  if (Serial.baud() != baud) {
    Serial1.end();
    baud = Serial.baud();
    Serial1.begin (baud);
  }
}

なおUSBポート側の仮想シリアルポートがハードフローを要求するため、利用できるホスト側のアプリケーションは限定的です。一応以下のように「%LOCALAPPDATA%\Arduino15\packages\arduin​o\hardware\renesas_uno\1.0.1\cores\ardui​no\tinyusb\class\cdc\cdc_device.c」に手を加えれば、ハードフローなしで通信できます。

--- cdc_device.c.org
+++ cdc_device.c
@@ -113,7 +113,7 @@
 bool tud_cdc_n_connected(uint8_t itf)
 {
   // DTR (bit 0) active  is considered as connected
-  return tud_ready() && tu_bit_test(_cdcd_itf[itf].line_state, 0);
+  return true;
 }
 
 uint8_t tud_cdc_n_get_line_state (uint8_t itf)
@@ -388,7 +388,7 @@
         p_cdc->line_state = (uint8_t) request->wValue;
         
         // Disable fifo overwriting if DTR bit is set
-        tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr);
+//        tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr);
 
         TU_LOG2("  Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
 

また「%LOCALAPPDATA%\Arduino15\packages\arduin​o\hardware\renesas_uno\1.0.1\cores\ardui​no\Serial.h」に宣言されているSERIAL_BUFFER_SIZEの値を大きくしておくことで、巨大なパケットの送受信においても取りこぼしが軽減されます。

Page Top

注意事項 anchor.png[78]

  • いずれの端子も絶縁されていない。そのためArduinoとPCをUSBケーブルで活線接続した際に、突入電流などでPCがArduinoを認識しない問題が生じる事がある。そういった場合は、USBISO[79]でPCのUSBポートを絶縁する事で解消する。
  • Dynamixelシリーズがサポートする2M[bps]を超えるボーレートは、Arduino UNOの機能に依存するため使用できない。必ず2M[bps]以下で運用する事。
  • USBパススルーを積極的に使用したいのであれば、Arduino UNO互換のNerOモジュール[80]をお勧めする。
    USBシリアル変換チップにATmega16U2ではなくFT231Xが搭載されているので、バッファフローの問題解消や最大通信速度の向上が期待できる。

Last-modified: 2023-07-02 (日) 09:39:14 (JST) (292d) by takaboo