Serial Servo RTCs (Python)
手軽に利用できるアクチュエータモジュールである、シリアルサーボを動作させるRTCを作成する方法を解説します。
このページでは以下の知識を説明なく使用しますので、各解説ページで使用方法を学んでから読み進めてください。
1. はじめに
今回は、以下のRTCを作成し、シリアルサーボを動作させる方法を学びます。
シリアルサーボには、双葉電子工業製(株)のRSシリーズを用います。
ここでは、1つずつシリアルサーボを動作させるショートパケットに対応します。
作成するRTCは以下のようになります。
-
RSServoManager
RSシリーズのサーボモータを1つずつ動作させます。
-
RSServoMoveConsoleIn
シリアルサーボの角度(位置)と移動時間を指令します。
-
RSServoServoConsoleIn
シリアルサーボの保持トルクのON/OFF状態などを指令します。
-
RSServoSensorConsoleOut
シリアルサーボのセンサ値をコンソール上に出力します。
本解説で想定するシステムは、以下の様になります。
PCからUSB接続の変換器を通して、RSサーボに接続し制御します。
8. おわりに
シリアルサーボを動作させるRTCを作成しました。
専用のデータ型を作成することで、スッキリと通信することが出来ました。
複雑なRTCも専用のConsoleIn/Outを作成してその動作を確認できました。
このように、作成したRTCをテストするために、テスト用RTCを用いるのは面倒ですがとても重要です。
複雑なシステムになればなるほど、この手間は最終的には近道となると思います。
自分のRTCを作るときには、ぜひ応用してみてください。
参考文献
-
「RS405CB/RS406CB取扱説明書(ver.1.03)」<http://www.futaba.co.jp/robot/command_type_servos/rs405cb>(2014/02/19アクセス)
3. RSServoManager RTC
RSServoManager RTCを作成します。
テンプレートを以下に従って設定てください。
-
モジュール名
RSServoManager
-
ベンダ名
あなたの名前
-
モジュールカテゴリ
Hobby
-
実行周期
1000
-
アクションコールバック
onInitialize
onActivated
onDeactivated
onExecute
-
データポート
・moveポート
ポート名(InPort) move
データ型 RSServo::Move
変数名 move
表示位置 LEFT
・servoポート
ポート名(InPort) servo
データ型 RSServo::Servo
変数名 servo
表示位置 LEFT
・sensorポート
ポート名(OutPort) sensor
データ型 RSServo::Sensor
変数名 sensor
表示位置 RIGHT
-
コンフィギュレーション
・portコンフィギュレーション
名称 port
データ型 string
デフォルト値 COM1
変数名 conf_port
・baudrateコンフィギュレーション
名称 baudrate
データ型 long
デフォルト値 115200
変数名 conf_baudrate
-
言語
Python
プロジェクトの設定が終わったら、RSServoManager.pyに以下のコードを記述します。
以下のコードは抜粋となります。生成したテンプレートに当てはめて下さい。
なお、シリアル通信にはPYSERIALが必要です。Windowsを使用している場合はインストールしてください。
Ubuntuではデフォルトで入っていると思います。
それではソースコードを解説します。
-
1行目
シリアル通信のためにPYSERIALをインポートします。
-
16行目
シリアルオブジェクトをインスタンス化します。
-
20-30行目
シリアルポートをオープンする関数です。
open_port関数は以下のようになります。
open_port(ポート名, ボードレート, タイムアウト)
-
21行目
シリアルポートを指定します。
-
22行目
ボーレートを指定します。
-
23行目
タイムアウトを設定します。
タイムアウトの値は以下のようになっています。
None: 読み取れるまで待ちます
0: 非ブロッキングモード(読み取り時にすぐ戻ります)
x: x s待ちます
-
25-30行目
シリアルポートを開きます。
成功した場合は開いたポート番号を、失敗した場合はエラーメッセージを表示します。
-
32-33行目
シリアルポートをクローズじます。
close_port関数は以下のようになります。
close_port()
-
35-40行目
シリアルサーボに保持トルクのON/BRAKE/OFF指令を与える関数です。
保持/非保持/ブレーキモードから選択して動作させます。
on関数は以下のようになります。
void on(シリアルサーボのID, 保持モードのモード)
各コマンドやデータの意味は簡単に説明します。
詳しくは、RS405CB/RS406CB取り扱い説明書[1]をご覧ください。
RSシリーズのシリアルサーボには以下のような形式でコマンドを送信します。
[Header] [ID] [Flags] [Address] [Length] [Count] [Data] [Sum]
Header :パケットの先頭を表します。ここでは0xFA、0xAFとなります。
ID :シリアルサーボのIDです。
Flags : リターンパケットの設定やデータ書き込み時の設定を行います。
Address :メモリーマップ上のアドレスを表します。Lengthに指定した長さのデータをメモリーマップに書き込みます。
Length :データの長さ(byte数)を指定します。
Count :サーボの数を表します。今回は1に設定します。
Sum :チェックサムです。IDからDataまでの各バイトの排他的論理和(XOR)を計算した値を設定します。
on関数では、以下のようなバイト列で動作指令を与えます。
|0xFA|0xAF|ID|0x01|0x24|0x01|0x01|保持トルクのモード|Sum|
保持トルクのモードは、0x00で非保持、0x01で保持, 0x02でブレーキとなります。
-
37行目
リストに先ほど説明したコマンドを格納します。
-
38行目
チェックサムを計算し、リストに追加します。
-
40行目
コマンドを出力します。この関数は後ほど説明します。
-
42-50行目
シリアルサーボに動作指令を与える関数です。
シリアルサーボの角度(位置)と移動時間を与えて、動作させます。
move関数は以下のようになります。
move(シリアルサーボのID, 角度, 移動時間)
move関数では、以下のようなバイト列で動作指令を与えます。
目標位置と時間は1 byteを超えるため、上位(H)と下位(L)に分けて設定します。
各| |は1 byte単位となります。
|0xFA|0xAF|ID|0x01|0x1E|0x04|0x01|目標位置L|目標位置H|時間L|時間H|Sum|
-
44-48行目
リストに先ほど説明したコマンドを格納し、出力します。
位置と時間を上位バイトと下位バイトに分けるには、AND演算とビットシフトを用います。
下位バイトは0x00FFと論理的ANDを取ることで、上位ビットは全て0となり、下位ビットは元の値を残せます。
上位バイトは0xFF00と論理的ANDを取り、上位ビットを残した後に1 byteのサイズに収まるよう8 bitシフトしています。
-
50行目
シリアルサーボが動作している間スリープします。
スリープには以下の関数を使用します。
time.sleep(中断の時間 s)
-
53-75行目
シリアルサーボのセンサ値を取得する関数です。
これまでの関数と異なり、シリアルサーボからの返信を受け取ります。
get_sensor関数は以下のようになります。
センサ情報構造体とは、IDLで定義したRSServo::Sensorのことです。
get_sensor(シリアルサーボのID)
-
55-58行目
コマンドの出力まではこれまでと同様です。
-
60行目
センサ値を読み込みます。
読み込みには以下のメソッドを使用します。
read(読み込みバイト数)
-
60-70行目
先ほどまで2 byte以上のデータをエンコードしてコマンドを作成していました。
今度はこれと逆のことをして、センサ値をデコードします。
id以外は2 byteのデータなので、2 byteのデータを復元します。
上位バイトと下位バイトを合わせるには、ビットシフトとOR演算を用います。
上位ビットを8 bitずらし、下位ビットと論理的ORを取ります。
なお、読み込んだセンサ値は8bit文字列になっているので、ord関数を使ってバイトの値に変換しています。
もし、値が読み込めていなければ例外をスローします。
-
72-73行目
このサーボモータは-1500から1500の角度をとります。
1500よりも大きい値は二の歩数で表現された負の値でので、変換しています。
実際には1500より大きい値が返されることがあるので、マージンをとって1800より大きい値を変換しています。
-
77-81行目
この関数は他の関数の処理を助けるヘルパー関数です。
_calc_checksum(チェックサムを除いたコマンド)
チェックサムの計算を行い、値を返します。
-
83-86行目
この関数は他の関数の処理を助けるヘルパー関数です。
_write_serial(コマンド)
コマンドの出力を行います。
-
84行目
出力バッファをクリアします。
-
85行目
入力バッファをクリアします。
-
86行目
コマンドを出力します。
ここからは、上記の関数を使用してRTC本体の挙動をプログラムします。
-
89行目
ポートをオープンします。
引数のポート名とボーレートにはコンフィグレーションを与えます。
このようにすることで、ユーザーの環境に合わせてRTCを外部から操作できます。
このように環境により異なるものにはコンフィグレーションを使用します。
-
94行目
ポートをクローズします。
ポートのクローズには以下の関数を使用します。
-
99-104行目
サーボ指令がある場合は、シリアルサーボに保持トルクのON/BRAKE/OFF指令を与えます。
-
108-128行目
動作指令がある場合は、シリアルサーボに動作指令を与えます。
その後、センサ値を取得しセンサ値ポートから出力します。
以上で、RSServoManagerのコーディングは終了です。
今回はコードが長く、大変でしょうが頑張って最後までコーディングしてみて下さい。
RSシリーズ以外のシリアルサーボでも、同様の構造でRTC化できると思います。
ぜひ、お手元のシリアルサーボでお試し下さい。
7. 動作確認
作成したRTCを実行して下さい。
RSServoManagerのポート名とボーレートのコンフィグレーションは必ず変更し、各環境に合うよう設定してください。
その後、各RTCを接続し、Activateします。
まずは、RSServoServoConsoleInにシリアルサーボの保持トルクをOnにします。
ここでは、id: 1、on:1 と入力します。IDはご使用のサーボに合わせて下さい。
4. RSServoMoveConsoleIn RTC
RSServoMoveConsoleIn RTCを作成します。
テンプレートを以下に従って設定てください。
-
モジュール名
RSServoMoveConsoleIn
-
ベンダ名
あなたの名前
-
モジュールカテゴリ
Hobby
-
実行周期
1000
-
アクションコールバック
onInitialize
onExecute
-
データポート
・moveポート
ポート名(OutPort) move
データ型 RSServo::Move
変数名 move
表示位置 RIGHT
-
言語
Python
プロジェクトの設定が終わったら、RSServoMoveConsoleIn.pyに以下のコードを記述します。
以下のコードは抜粋となります。生成したテンプレートに当てはめて下さい。
コードの解説をします。
-
2-10行目
RSServo::Move構造体のメンバを、順にユーザに入力させます。
-
12行目
動作指令ポートから出力します。
以上で、RSServoMoveConsoleInのコーディングは終了です。
シリアルサーボの保持トルクがOnになったのを確認したら、RSServoMoveConsoleInでシリアルサーボを動かします。
ここでは、id: 1、angle: -450、duration: 200と入力します。IDはご使用のサーボに合わせて下さい。

2. Serial Servo RTCの構成
シリアルサーボを1つずつRTC化するのではなく、シリアルラインをRTC化します。
前述したUSB接続の変換器をRTC化するイメージです。
シリアルサーボをRTC化する方が、一見わかりやすい気もします。
しかし、シリアルラインは1つしかないため、システムから見た場合は、シリアルラインをRTC化するほうが素直です。
2.1 Serial Servo RTCのポート構成
Serial Servo RTCは、以下の様なポート構成で作成します。
-
動作指令ポート
シリアルサーボの角度(位置)と移動時間を指令します。
-
サーボ指令ポート
シリアルサーボの保持トルクのON/OFF状態などを指令します。
-
センサ値ポート
シリアルサーボのセンサ値を出力します。

2.2 ポートのデータ型
シリアルサーボ用のデータ型はRTミドルウェアに標準で定義されていないため、独自データ型を定義します。
RSシリーズのシリアルサーボ用に、以下の3つのデータ型を定義します。
-
RSServo::Move型
・tm
タイムスタンプ
・id
シリアルサーボのID
・angle
角度
・duration
移動時間
動作指令ポートに使用します。
-
RSServo::Servo型
・tm
タイムスタンプ
・id
シリアルサーボのID
・on
トルク保持のON/BRAKE/OFF
サーボ指令ポートに使用します。
-
RSServo::Sensor型
・tm
タイムスタンプ
・id
シリアルサーボのID
・angle
現在角度
・time
現在時間
・speed
現在スピード
・load
現在負荷
・temperature
現在温度
・voltage
現在電圧
センサ値ポートに使用します。
上記の定義を以下のようなIDLファイルに記述します。
適当なテキストエディタで以下のコードを入力し、HobbyRobotDataType.idlファイルに保存してください。
*一部の変数の型が雑誌掲載時と異なりますのでご注意下さい。
ここで説明するRTCは以下の様な構成で動作を確認しています。
-
USB-RS485変換器
Futaba製 RSC-U485
-
シリアルサーボ
Futaba製 RS405CB
-
電源スイッチ付きハブ
Futaba製 TB-RV71EH-7.4V/4W
5. RSServoServoConsoleIn RTC
RSServoServoConsoleIn RTCを作成します。
テンプレートを以下に従って設定てください。
-
モジュール名
RSServoServoConsoleIn
-
ベンダ名
あなたの名前
-
モジュールカテゴリ
Hobby
-
実行周期
1000
-
アクションコールバック
onInitialize
onExecute
-
データポート
・moveポート
ポート名(OutPort) servo
データ型 RSServo::Servo
変数名 servo
表示位置 RIGHT
-
言語
Python
プロジェクトの設定が終わったら、RSServoServoConsoleIn.pyに以下のコードを記述します。
以下のコードは抜粋となります。生成したテンプレートに当てはめて下さい。
コードの解説をします。
-
2-7行目
RSServo::Servo構造体のメンバを、順にユーザに入力させます。
-
9行目
サーボ指令ポートから出力します。
以上で、RSServoServoConsoleInのコーディングは終了です。
6. RSServoSensorConsoleOut RTC
RSServoSensorConsoleOut RTCを作成します。
テンプレートを以下に従って設定てください。
-
モジュール名
RSServoSensorConsoleOut
-
ベンダ名
あなたの名前
-
モジュールカテゴリ
Hobby
-
実行周期
1000
-
アクションコールバック
onInitialize
onExecute
-
データポート
・sensorポート
ポート名(OutPort) sensor
データ型 RSServo::Sensor
変数名 sensor
表示位置 LEFT
-
言語
Python
プロジェクトの設定が終わったら、RSServoServoConsoleOut.pyに以下のコードを記述します。
以下のコードは抜粋となります。生成したテンプレートに当てはめて下さい。
コードの解説をします。
-
3-11行目
センサ値ポートに値を取得した場合、コンソールにRSServo::Sensor構造体のメンバを出力します。
以上で、RSServoSensorConsoleOutのコーディングは終了です。

最後に、シリアルサーボが動作したのを確認したら、RSServoSensorConsoleOutでセンサ値を確認します。
ここでは、以下のようになりました。
これで、RTCの動作を確認することができました。

