上肢帯のあるロボット5
毎週少しずつアップデートを重ねている”上肢帯のあるロボット”ですが、
先週、制御周期がWindowsの上限で20Hzが限界かも、と書きました。
これは、1往復につきドライバの問題で2msecのディレイが発生するため22個のサーボで、送受信を行うと、トータル46msecの時間がかかるというものでした。
この問題に対して、Facebookにて、
各サーボの返信ディレイ時間をID順に遅く設定して、全サーボに一斉送信でリターンパケット要求をすると、制御周期を早くできる(かも)
というコメントをいただいたので、さっそく試してみることにしました。
概念としてはこんな感じで、ID:0xFFで、全体送信するパケットに、応答要求を仕込みます。
デフォルトのサーボでは、全サーボが同時に返答してしまい、パケットが混信するのですが、各サーボのレスポンスタイムを少しずつずらして、順番に返事を受け取ろうという作戦です。
問題は、2つあり
- そもそも、0xFFの送信に対して、サーボが応答するのか
- 応答したとして、ずらすレスポンスタイムは何μsecが適正なのか
というところです。
どちらの問題も試してみて答えを見つける他ありません。
「1」の問題はすぐ解決しました。
1個のサーボを試してみたところ、返答がありました。
「2」に関しては試行錯誤しかありません。
次の画像が試行錯誤の結果です。
1つめのサーボが、デフォルトの100μsecのディレイのあと、2つめ、3つめと、350μsec以上ずつずらしたときに返答がありました。
つまり、パケットが混信しなかったということになります。
せっかくなので、一番速い350μsecを採用しました。
受信するデータは、下記の通りです。
“現在位置”から10バイト分取得します。
- 現在位置
- 現在時間
- 現在スピード
- 現在負荷
- 現在温度
送るパケットは下記のソースの通りです。
// パケット作成 sendbuf[0] = (unsigned char)0xFA; // ヘッダー1 sendbuf[1] = (unsigned char)0xAF; // ヘッダー2 sendbuf[2] = (unsigned char)0xFF; // サーボID sendbuf[3] = (unsigned char)0x0F; // フラグ(0x0F) 指定アドレスからの指定の長さを返答 sendbuf[4] = (unsigned char)0x2A; // アドレス(0x2A) 現在位置 sendbuf[5] = (unsigned char)0x0A; // 長さ(10byte) sendbuf[6] = (unsigned char)0x00; // 個数 (任意アドレスリターンの場合はcnt=0x00) // チェックサムの計算 sum = sendbuf[2]; for (i = 3; i < 7; i++) { sum = (unsigned char)(sum ^ sendbuf[i]); } sendbuf[7] = sum; // チェックサム
さて、準備は整いました。
どれくらいの速度が出るのか・・・
じゃん!
なんと、1サイクル11msecの速度で制御出来るようになりました。
ちなみに1サイクルの処理は
- サーボ22個分の情報取得
- サーボ22個分のトルク情報(ON/OFF)の送信
- サーボ22個への角度・速度の送信
と言う感じです。
つまり、20Hzが限界と思っていた制御周期が90Hzまで高速化できました!
20Hzの時とは比べ物にならないくらいヌルヌル動きます。
限界は勝手に決めてはダメということですね!
…で、そこから少し進めて、リアルタイムで、ティーチングプレイバックを行えるようにしました。
サーボの制御のスレッドとは別スレッドで、キャプチャと再生のスレッドを回すようにしたので、ある程度リアルタイム性は担保されているかと思います。
コントロールパネルにだいぶんボタンが増えてきました。
キャプチャしたデータは、とりあえず、CSV形式で保存しています。
ゆくゆくはちゃんとファイルフォーマット考えよう…。
動作するところを動画で撮影しています。
コメントを残す