PMXサーボを使ってみよう マイコンボードから制御「MemREAD編」

Posted on 2024.01.09 in

 

今回の記事から具体的にPMXサーボを制御する方法を解説します。まずはサーボから情報を読み出す「MemREAD」コマンドについて解説します。

 

【関連記事】

  PMXサーボを使ってみよう マイコンボードから制御「準備編」

 

●PMXサーボ商品ページ

 

この記事で解説するArduino向けライブラリ、及びサンプルプログラムは、下記のページからダウンロードしてください。

『PMX Library for Arduino』

 

PMXシリーズのサーボモータを制御するためのオンラインマニュアルを公開しています。PMXサーボを制御するための詳しい情報が記載されていますので、下記の解説と一緒にご一読ください。

『PMXサーボシリーズ オンラインマニュアル』

 

■MemREADコマンドについて

MemREADコマンドは、メモリマップのRAM領域から情報を読み出すためのコマンドです。PMXサーボのメモリマップにはRAM領域とROM領域があります。サーボ起動時にROM領域からRAM領域にデータが展開され、サーボの制御にはRAM領域のデータが使用されます。

このコマンドを使用することで下記の情報を読み出すことができます。

・サーボの現在の状態(現在位置、速度、消費電流、入力電圧など)

・PIDゲインなど制御に関連する設定値

・入力電圧最小値設定など制限値の設定値

・トルクON/OFFの状態、現在の制御モードなど

メモリマップの内容や、各設定値の解説はオンラインマニュアルの『6.メモリマップ』をご参照ください。

なお、サーボIDや通信速度、パリティの読み出しはSystemREADコマンドを使用します。こちらの使用方法については別の記事で解説します。

 

■コマンドの使用方法

MemREADコマンドは、「先頭アドレス」と「読出データ数」を指定してデータを読み出します。

「先頭アドレス」とは、メモリマップのアドレスを指し、読み出すデータの先頭のアドレスを指定することができます。下図はメモリマップの一部を抜粋した表です。たとえば「現在位置」を読み出す場合、アドレスは300ですので、先頭アドレスとして黄色いセルの300を指定します。

「読出データ数」は、先頭アドレスから何バイトのデータを読み出すかを指定することができます。「現在位置」のみを読み出す場合は、「現在位置」のデータは2バイトですので、「読出データ数」は2となります。また「現在位置」から「現在電流値」までを一気に読み出す場合は、各2バイトのデータが3つ選択しますので6と指定します。つまり、下図の緑のセルの内容が読み出されます。

メモリマップの詳細は、オンラインマニュアルの『メモリマップ一覧』をご参照ください。こちらに各データのアドレスとデータバイト数が一覧になっています。

 

■リトルエンディアンについて

PMXサーボの2バイト以上のデータは、リトルエンディアンに分割されて格納されています。データを読み出す場合は、読み出したデータをリトルエンディアン方式で変換してご利用ください。詳しくはオンラインマニュアルの『データ構造』にある「データ」の解説をご参照ください。

 

■プログラム解説

ここからArduinoライブラリのサンプルプログラム「MemREAD_Sample」を使用してMemREADコマンドを実行し、PMXサーボからデータを読み出す方法をご紹介します。

なお、本サンプルはArduino Nano Everyで使用することを想定していますが、ピン番号やシリアルのポート番号を変更することにより多数のArduinoに対応します。使用できるシリアルポートなどについてはArduinoの仕様をご確認ください。解説の「●ライブラリを使用するための準備と通信の設定」がボードに依存する設定項目です。これ以降はすべてのボードに対して共通で使用できます。

 

●ライブラリを使用するための準備と通信の設定

まずは必要なファイルやライブラリを参照し、PMXと通信を行うクラス(PmxHardSerial)をインスタンス化して使用できるようにします。

「const byte EN_PIN = 2;」は、Enableを指定するピン番号です。こちらはデジタルI/Oで入出力が可能であればどの端子でも構いません。

通信速度は、サーボに設定されている通信速度です。工場出荷状態では115200bpsに設定されています。

タイムアウトは、なんらかのトラブルによりサーボからの返事が返ってこない場合の待ち時間です。単位は[ミリ秒]ですので1000は1秒になります。短くしすぎると正常にパケットを受け取れない場合がありますのでご注意ください。

「pmx(&Serial1,EN_PIN,BAUDRATE,TIMEOUT);」の「&Serial1」がシリアルポートを指定する引数です。サンプルプログラムでは、Serial1をPmxHardSerialクラスの中で直接使用するので「&」をつけてポインタを渡します。「RS-485変換基板」からArduinoに接続した「R」「D」のポート番号を指定してください。

「const byte ServoID = 0;」でこのサンプルプログラムで制御するサーボを指定します。今回はID0のサーボと通信しますので"0"を代入しています。

 

「pmx.begin()」は、サーボと通信を開始するための関数です。この関数が記述されている場所からArduinoがサーボと通信を開始します。同時にサーボから読み出したデータをPCに表示するため「Serial.begin(115200);」でArduinoとPC間の通信を開始しています。プログラムの最初に1度だけsetup()が実行されますのでここに記述してください。

 

●基本のMemREAD()関数

この行からMemREADコマンドを実行します。PMXサーボのPythonライブラリには、MemREADコマンドを実行するために多彩な関数を用意しました。上記の関数はMemREADコマンドの基本となる関数です。

第一引数はサーボIDです。「ServoID」は、MemREADコマンドの命令の対象になるサーボを指定しています。前のプログラムで「ServoID = 0」と代入していますので、この関数はID0のサーボに対して命令を送信しています。

第二引数は、読み出すデータが格納されているメモリの先頭のアドレスを指定します。「PMX::RamAddrList::NowPosition」は、「現在位置」のアドレスを示しライブラリで300が代入されています。またアドレスの数値として「300」と指定しても同じ番地からデータを読み出すことができます。

第三引数は読出データ数です。6が指定されていますので、先頭アドレス300から6バイトのデータを読み出します。

第四引数の「rxData」にMemREADコマンドで読み出したデータが代入されます。Arduino言語のベースとなるC++は、複数の戻り値を返すことができませんので、予め作成しておいた変数、配列のポインタを引数で渡し、関数内でここに代入してもらうことでデータを受け取ります。戻り値で受け取るデータは、サーボの状態や通信状態を知ることができるステータスのみ返ってきます。

戻り値の「flag」は、サーボとの通信状態とサーボの状態が正常かどうかのステータスを足したものが返ってきます。データが0であれば問題ありません。0以外の場合は、なんらかの問題が発生していますので、ステータス部がエラーの場合はオンラインマニュアルの『5.エラー状態』を参照してください。

 

前述の通り、2バイト以上のデータはリトルエンディアンで分割されていますので連結する必要があります。本ライブラリには、リトルエンディアンで分割されたデータを組み合わせるために便利な関数が用意されています。

2Byte以上の分割されたのデータを都度数値に変換するとプログラムが長くなりますので、DataConvクラスを用意しました。DataConv::bytesToInt16()でデータを連結することができます。この関数に連結する配列を渡します。

今回は例として6バイトのデータを読み出しましたが「現在位置」は先頭の2バイトのみですので、「byte rxPosByte[2] = {rxData[0], rxData[1]};」で「現在位置」のデータのみ別の配列に分けます。

※pmx.MemREAD()で2バイトのみ読み出した場合は、そのまま渡しても問題ありません。

「DataConv::bytesToInt16(rxPosByte);」を実行すると、戻り値として連結したデータが返ってきます。このデータを「Serial.println(posData);」によりArduino IDEのシリアルモニタに表示することができます。

成功すると、現在の値が表示されます。角度値は角度x100のデータですので、100度は10000のデータで返ってきます。実際のサーボの角度と照らし合わせてご確認ください。

 

PMXのデータは、符号の有無、Byte数で複数の種類が存在します。今回使用した「bytesToInt16()」は符号あり2Byteのデータを対象としていますが、他のデータ形式に対応した関数もご用意しています。下記を参考に使い分けてください。

 

●1つにまとまったデータを受け取ることができるMemREADコマンドの便利な関数

基本的な使い方は以上ですが、MemREAD()で読み出したデータを毎度bytesToInt16()などで連結するとプログラムの行数が増えてしまいます。そこで、戻り値として連結したデータを受け取ることができる関数を用意しました。

関数は下記の5種類です。

・MemREADToByte(id, address, rxData)  =Byte型(1バイト)符号なし

・MemREADToInt16(id, address, rxData)  =Int型(2バイト)符号あり

・MemREADToUint16(id, address, rxData)  =Int型(2バイト)符号なし

・MemREADToInt32(id, address, rxData)  =Int型(4バイト)符号あり

・MemREADToUint32(id, address, rxData)  =Int型(4バイト)符号なし

いずれも引数にサーボIDとアドレス、基本のMemREAD()関数と同じく読み出したデータを受け取る変数のポインタを渡します。オンラインマニュアルの『メモリマップ一覧』を参照し、型と符号が一致する関数を使用してください。

すべての関数で戻り値はサーボの状態や通信状態が返ってきます。

 

●各パラメータの専用関数でプログラムを読みやすく

また、読み出すデータによっては、アドレスの指定や読出データ数の指定を省くために専用の関数が用意されています。こちらを使用するとサーボIDと読み出したデータを受け取る変数を渡すことで機能を実行できますので便利です。関数の種類はライブラリをご参照ください。

 

■エラーの解除方法

最後に、サーボにエラーが発生した場合のフラグの解除方法を解説します。受信パケットのステータスにエラーが発生した場合は、受信パケットのステータスがエラー(0以外)になります。同時にアドレス400番台の該当のデータが変化しています。エラーの種類のよっては、安全のためエラーを解除しない限り動作が停止する場合がありますので解除が必要です。

エラーは、アドレス400番台をMemREADコマンドで読み出しますことでエラーを解除することができます。また、getFullStatus()関数を使用するとステータスの情報を一気に読む出すこともできます。

getFullStatus()関数で読み出す場合は、予め「システムエラー」「モータエラー」「RAMアクセスエラー」の情報を格納する変数を用意し、関数の引数にポインタで渡します。

関数実行後に、各変数にデータが入っていますので、printで出力し状態を確認してください。すべて0であれば異常はありません。

ただし、電源電圧が低い、高いなど原因が解消していない状態でエラー情報を読み出してもエラーを解除することはできません。エラーが発生した場合は、エラーの内容をよく確認し安全にご利用ください。

エラー情報については、オンラインマニュアルの『5.エラー状態』をご参照ください。

 

以上でMemREADコマンドの解説を終わります。次回はメモリマップの情報を書き換えることができるMemWRITEコマンドについて解説します。

 

次の記事『PMXサーボを使ってみよう マイコンボードから制御「MemWRITE編」』

前の記事『PMXサーボを使ってみよう マイコンボードから制御「準備編」』

 

 

PMX-SCR-9203HVの詳細をみる PMX-SCR-9204HVの詳細をみる PMX-SCR-5203HVの詳細をみる PMX-SCR-5204HVの詳細をみる