B3Mサーボモータを動かそう(Python編(1))
B3Mサーボは、ホストからコマンドを送信することで簡単に制御することができます。プログラミング言語に依存することなく、B3Mに合わせてコマンドが送信できればサーボが動作します。
現在(2021年12月)は、C#とArduino向けの記事を公開しました。C#はライブラリも用意されていますので、簡単にプログラムすることができます。
今回は、Pythonでコマンドを送信する方法をご紹介したいと思います。Pythonのプログラムは、処理の内容がわかりやすいようになるべくシンプルに書きました。Pythonで開発できる環境があれば、Windowsのみならず、LinuxでもB3Mを制御できるようになります。この記事を参考にぜひB3Mサーボをご利用ください。
RS-485 USBアダプターHSをご利用の場合は『B3Mサーボモータを動かそう(準備編(1))(改訂版)』をご覧ください。
【過去の記事】
第1回 B3Mサーボモータを動かそう(準備編(1))(改訂版)
第5回 B3Mサーボモータを動かそう(Arduino制御編)(改訂版)
B3Mの通信プロトコルについては『B3Mソフトウェアマニュアル』をご参照ください。
■B3Mサーボシリーズ
内蔵しているモータの違いにより、3種類をラインアップしています。通信プロトコルは全種同じですので、同じプログラムで制御することができます。もちろん、違う種類を組み合わせて使用することもできます。
ブラシレスモータ:B3M-SB-1040-A
コアレスモータ:B3M-SC-1040-A
コアレスモータ(ハイトルク):B3M-SC-1170-A
■必要な製品
必要な製品は、下記のとおりです。
・電源
6~12V(9~12V推奨)の電源をご用意ください。バッテリーの場合は、ROBOパワーセルF3タイプをご利用いただけます。
・XH接続ケーブル
サーボに付属しています。長さを変更する場合は、「サーボ用4本ケーブルセット【3m】」と「XHケーブル用コネクターセット(30セット入り)」を組み合わせて自作することができます。
・HV電源スイッチハーネス
USBアダプターと電源を中継するためのスイッチ付きケーブルです。弊社の電源を使用する場合にお勧めです。
・RS485USB/シリアル変換アダプター
PCと接続するためにはUSB-A⇔mini-Bケーブルが別途必要です。PCからコマンドを送信し、接続されたB3Mサーボモータを動かします。
詳細は記事でご紹介していますのでこちらをご参照ください。
■開発環境
Pythonの開発環境を用意してください。この記事ではAnacondaを利用しました。
※Anacondaのインストール、ご利用方法はこの記事ではご紹介していません。別途お調べになりご準備をお願いします。
また、USB経由でデバイスと通信するためにpySerialのライブラリをインストールする必要があります。Anacondaの場合は、Anacondaのコンソールから下記のコマンドを実行してインストールすることができます。
1 |
pip install pyserial |
正常にインストールできたかを確認するために、pySerialのバージョンを確認してみます。エディターに下記にプログラムを書いて実行してください。
1 2 3 |
import serial print(serial.__version__) |
コンソールにバージョン情報が表示されましたらインストールが成功しています。
■KOドライバをインストール
RS485USB/シリアル変換アダプターをPCに認識させるためにKOドライバをインストールします。上記のページからファイル一式をダウンロードしてください。Windowsの場合は、ダウンロードしたフォルダ内にある付属のマニュアルをご参照ください。
Linux系のOSの場合は、下記の記事をご参照ください。弊社ではRaspberryPiのRaspbianOSにて動作を確認しました。
■B3Mサーボを制御する流れ
B3Mを制御するプログラムを解説する前に、B3Mが電源ONから動き出すまでの制御の流れを説明します。
【動作するまでの流れ】
1.サーボの状態をFreeモードにします。
2.制御モードを「位置制御モード」に変更します。
3.制御モードに応じてPIDゲインのプリセットを変更します。
4.サーボの状態をNomalモードにします。(サーボがトルクONします)
5.目標値のポジションを指定します。
B3Mの設定を変更する場合はWRITEコマンド、角度を指定する場合はSET POSITIONコマンドを利用します。以下の処理は、位置制御でサーボを動かすプログラムですが、同じ手順でコマンドの内容を変えるだけで位置制御のモード変更、速度制御への切り替えなどができます。詳細は『B3Mソフトウェアマニュアル』をご参照ください。
【B3Mの設定】
以下のサンプルプログラムでは、B3Mサーボの設定は工場出荷状態のID0、通信速度1500000bps、個数は1個とします。
ID番号を変更することで複数のサーボをデイジーチェーン接続して制御することができますが、通信速度はすべて同じである必要があります。
■プログラム解説
COMを開く
まずは、PCとB3Mの通信を開始するために、COMを開きます。
1 2 3 4 5 6 |
import serial import time #COMポートを開く b3m = serial.Serial('COM4', baudrate=1500000, parity=serial.PARITY_NONE, timeout=0.5) |
最初に上記の通りimportで「serial」をインポートします。「time」は後ほど時間を待つのにsleep関数を使うので、インポートしておいてください。
「serial.Serial()」でCOMポートを開くことができます。
引数の「COM4」は、USBアダプタがつながれているCOM番号です。Windowsのデバイスマネージャーから調べることができます。詳しくは、KOドライバ付属のマニュアルを参照してください。
Linuxでポートを指定する場合は、'/dev/ttyAMA0'と表記します。※ポートの表記方法は環境により異なる場合があります。
「baudrate」はPC、サーボ間の通信速度です。制御するB3Mの通信速度を指定してください。B3Mは工場出荷状態で「1500000」(1.5Mbps)に設定されています。
「parity」でパリティを指定します。B3Mサーボは「パリティなし」なので「serial.PARITY_NONE」を指定します。
「timeout」は、デバイスからの返事がない場合の待ち時間です。B3Mサーボが接続されていない、または電源が入っていないなど、通信ができない状態の時にどれくらいの時間を待つのか指定できます。今回は0.5秒に設定しました。
以上を「b3m」という名称でインスタンス化しました。以降は「b3m」でpySerialの各機能を使用できるようになります。
1 |
b3m.close() |
プログラムの最後にb3m.close()を書くことでCOMを閉じることができます。
WRITEコマンドを作成する
B3MサーボのRAMを書き換え、設定を変更するためにWRITEコマンドを用意します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
#WRITEコマンド #メモリーマップ(RAM)のアドレス指定でデバイスのRAM上に書き込みます。 def B3M_Write_CMD(servo_id, TxData, Address): #送信コマンドを作成 txCmd = [0x08, #SIZE 0x04, #CMD 0x00, #OPTION servo_id, #ID TxData, #DATA Address, #ADDRRESS 0x01] #COUNT #チェックサムを用意 checksum = 0 for i in txCmd: checksum += i #リストの最後にチェックサムを挿入する txCmd.append(checksum & 0xff) #WRITEコマンドを送信 b3m.write(txCmd) #サーボからの返事を受け取る rxCmd = b3m.read(5) #もしリスト何になにも入っていなかったら正常に受信できていないと判断 if len(rxCmd) == 0: return False #問題なければ返事を返す return True |
この関数の内容はとてもシンプルで、配列にコマンドを用意し、pySerialのwrite関数で送信しているだけです。今回この部分は説明がしやすいように1バイトのみを書き換えるようにしました。2バイトデータなど複数バイトを書き換える場合については次回の記事で説明します。
送信コマンドについて一つずつ解説します。
※以下の説明は、ソフトウェアマニュアルのP.20により詳細な解説が掲載されています。また、WRITEコマンドについては、P.31を参照してください。
・0x08 #SIZE
SIZEは、送信するコマンドの総バイト数です。今回は8バイトありますので、0x08を格納しています。
・0x04 #CMD
このコマンドが何をするための処理かを指定しています。今回は設定を変更するWRITEコマンドですので0x04を指定しています。
この数値を変更するだけで、B3Mを制御するコマンドの種類を変更することができます。コマンド体系はコマンドの種類によって若干の違いはありますが、基本的にはリストに設定したい数値を入れて送信するだけです。B3Mサーボから情報を取得したい場合は、CMDを0x03にすることでREADコマンドになります。設定をROMに保存したい場合は0x02(SAVE)、ROMの情報を読み出す場合は0x01(LOAD)です。
コマンドについては、ソフトウェアマニュアルのP.20をご参照ください。
0x00 #OP
オプションを指定しています。B3Mサーボの状態を返事として何を受け取るかを指定できます。もし通信や制御がうまくいかなかった場合、B3Mがどのようなトラブルを抱えているのかを取得することができます。これは、戻り値としてこの通信コマンド呼び出し元に返しますが、通信が失敗した場合は-1を返します。
オプション、ステータスについては、ソフトウェアマニュアルのP.41をご参照ください。
servo_id #ID
制御するサーボのID番号を指定します。引数で受け取ったB3MのID番号を、送信コマンドの4番目に送信することで、制御するサーボを指定することができます。
TxData #DATA
Address #ADDRRESS
WRITEコマンドで書き込むデータと書き込み先のアドレスを格納します。
B3Mはメモリーマップにより、各機能をアドレスで指定して変更することができます。例えば、今回の位置制御モードへの設定はアドレス0x28にあります。ここに0x02を書き込むことで位置制御モードに設定することが可能です。
他にも機能がたくさんありますので、詳細はソフトウェアマニュアルのP.60をご参照ください。
0x01 #COUNT
通信するサーボの個数を指定します。0x01だと1個でシングルモードになります。2個以上はマルチモードになります。
B3Mサーボは、複数のサーボを同時に制御するためにマルチモードが実装されています。マルチモードでは、一連のコマンドに複数のサーボに対してのコマンドを連結して送信することが可能です。ただし、サーボからの返事は来なくなりますのでご注意ください。
詳細は、ソフトウェアマニュアルのP.18をご参照ください。
checksum = 0
for i in txCmd:
checksum += i
txCmd.append(checksum & 0xff)
チェックサムを計算し、送信コマンドの最後に追加します。
b3m.write(txCmd)
rxCmd = b3m.read(5)
以上で用意された送信コマンドをpySerialのwrite関数で送信します。B3Mサーボがコマンドを受け取ると、返信データを返してきますので、pySerialのread関数でデータを受け取ります。
read関数の引数にある(5)は、返信されるデータのSIZEです。WRITEコマンドの場合、サーボからは5バイトのデータが返ってきますので、ここでは5を指定しました。
SET POSITIONコマンドを作成する
SET POSITIONコマンド(以下POSITIONコマンド)はサーボの角度と到達時間を指定しサーボを動かすことができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
def B3M_setPos_CMD(servo_id, pos, MoveTime): #送信コマンドを作成 txCmd = [0x09, #SIZE 0x06, #CMD 0x00, #OPTION servo_id, #ID pos & 0xff, #POS_L pos >> 8 & 0xff, #POS_H MoveTime & 0xff, #TIME_L MoveTime >> 8 & 0xff] #TIME_H #チェックサムを作成 checksum = 0 for i in txCmd: checksum += i #リストの最後にチェックサムを挿入する txCmd.append(checksum & 0xff) #コマンドを送信 b3m.write(txCmd) #サーボからの返事を受け取る rxCmd = b3m.read(7) #もしリスト何になにも入っていなかったら正常に受信できていないと判断 if len(rxCmd) == 0: return False #問題なければ返事を返す return True |
B3Mサーボに角度を指定する場合は、POSITIONコマンドを使用します。基本的な構成は、前述のWRITEコマンドと同じです。ここでは、WRITEコマンドと異なる内容のみ解説します。また、POSITIONコマンドの詳細はP.37をご参照ください。
0x06 #CMD
POSITIONコマンドは、0x06により実行することができます。
pos & 0xff #POS_L
pos >> 8 & 0xff #POS_H
上記により動作角度を指定します。B3Mサーボは、正転は0~0x7d00(0~320°)、逆転は0~0x8300(0~-320°)により角度を指定できますが、データの大きさが1バイトに収まりません。そこで、上記の方法で2バイトに分けて送ります。
ポジションデータについては、P.39、データの分割についてはP.24をご参照ください。
MoveTime & 0xff, #TIME_L
MoveTime >> 8 & 0xff] #TIME_H
指定した角度に対して、サーボがどれくらいの時間で到達するかを指定できます。時間はは0~65535msの範囲で指定できます。なお、時間の指定は起動生成タイプがNormal以外の時に有効です。Normalのときは最速で動きます。
B3MサーボにPOSITIONコマンドを送った場合、返事が返ってきます(シングルモード限定)。返事の中にはステータスの他に現在位置も含まれています。このB3M_setPos_CMD()関数はオプションデータを返しますが、5バイト、6バイト目に現在位置も含んでいますので、現在位置を返すことも可能です。
ただし、返事で取得できる現在値は、サーボが動き出す前の位置ですので、動作中の位置、到達したかの確認は「現在位置(0x2C)」をREADコマンドで取得してください。ポジションデータは2バイトですのでご注意ください。「現在位置」については、マニュアルのP.69を参照してください。
サーボを動かす
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#B3Mサーボが動作するまでの準備 #B3M_Write_CMD(servo_id, TxData, Address) #動作モード:Free (動作モードと特性を設定するため、設定書き換え中の誤動作を防止するため脱力にしておく) reData = B3M_Write_CMD(0x00, 0x02, 0x28) #位置制御モードに設定 (角度を指定して動作するモードです) reData = B3M_Write_CMD(0x00, 0x02, 0x28) #軌道生成タイプ:Even (直線補間タイプの位置制御を指定) reData = B3M_Write_CMD(0x00, 0x01, 0x29) #ゲインプリセット:No.0 (PIDのプリセットゲインを位置制御モード用に設定) reData = B3M_Write_CMD(0x00, 0x00, 0x5C) #動作モード:Normal (Freeの状態からトルクオン) reData = B3M_Write_CMD(0x00, 0x00, 0x28) |
ソフトウェアマニュアルP.48~52の「6.B3Mサーボを動かしてみる」に従って順番にコマンドを送信します。最終行の実行により、サーボのトルクがONの状態になります。
1 2 3 4 5 6 7 8 9 |
#ID0、500msかけて5000(50度)の位置に移動する reData = B3M_setPos_CMD(0, 5000, 500) time.sleep(0.5) #サーボが到達するまで次の指示を待つ reData = B3M_setPos_CMD(0, -5000, 500) time.sleep(0.5) #サーボが到達するまで次の指示を待つ reData = B3M_setPos_CMD(0, 0, 500) time.sleep(0.5) #サーボが到達するまで次の指示を待つ |
サーボが無事に起動できたら、POSITIONコマンドとして作成したB3M_setPos_CMD()関数で角度と時間を指定します。
「time.sleep」は処理を一時停止する処理です。引数で秒数を指定します。B3Mサーボは500msで目標地点に到達するように指定されていますので、0.5秒と指定しました。
プログラムを実行し、B3Mサーボが左右に動作すれば成功です。
【参考】
B3Mサーボの角度を指定する数値は下記のようになっています。詳細はソフトウェアマニュアルのP.39をご参照ください。
プログラムの全体は、下記からダウンロードしてください。
以上で、基本的な使用方法の解説は終わりです。WRITEコマンドで解説した通り、コマンドの各変数内に格納する数値を変更すれば、B3Mサーボの全ての機能を簡単に利用することができます。B3Mサーボは、機能が豊富で高性能なサーボです。この記事を参考にぜひご利用ください。
次回は、WRITEコマンドで書き換えることができる各パラメータについて解説します。また、パラメータによっては複数のバイトを書き換える必要がありますので、今回作成したWRITEコマンドをベースに改造していきたいと思います。
次の記事『B3Mサーボモータを動かそう(Python編(2))』
B3M-SB-1040-Aの詳細をみる B3M-SC-1040-Aの詳細をみる B3M-SC-1170-Aの詳細をみる