■KCB-1とRCB-4の接続方法
KCB-1のアップデータVer.1.2を適応するとKHR-3HVを自律化させることができます。ケーブルなどの接続方法は従来と同じなのですが、今回はKHR-3HV付属のバックパックにKCB-1とRCB-4を収納する方法について紹介します。
KHR-3HVのバックパックに搭載されるパーツマウントA(センサーなどを取り付けるグレーのベース)にはKCB-1にぴったりのねじ穴が開いています。そこに、下の図のようにKCB-1を「2-8低頭タッピングビス」(KHR-3HVでRCB-4を取り付けているねじと同じもの)で取り付けます。
クリックで拡大表示
KCB-1に電源を供給するには電源ケーブルを二股にするか、RCB-4のSIO端子からKCB-1のSIO端子へケーブルを接続するとよいでしょう。図では「二又コード2(No.01132)」を短く変更してRCB-4のSIO端子に接続し、分岐先を元々SIO8に接続されていたサーボリードとKCB-1のSIO1としています。ここでサーボリードの信号線(白いケーブル)は抜いておかないとどちらのサーボも動作しなくなるので注意してください。
なお、図ではRCB-4のSIO8端子に二股ケーブルを接続していますが、これはどの端子でもかまいません。逆接には十分注意してください。
次にRCB-4とKCB-1が通信できるように、それぞれのCOMポートをクロスケーブルでつなぎますが、バックパックには元々「サーボ用延長コード(100mm)(No.01079)」を接続する穴が開いていますので、今回は「サーボ延長ケーブル(KHR-3には1本付属)」を1本追加し、クロスケーブルを外側から接続します。
クリックで拡大表示
こうすると、KCB-1やRCB-4へケーブルの挿抜だけで簡単にアクセスできるようになります。
最後にロボットの頭に超音波センサーを取り付けてみます。KHR-3HVでは頭が3パーツに分かれていますが、首と頭パーツの付け根にある隙間にケーブルを通せば、簡単に超音波センサーを取り付けることができます。また、KHR-3HVではまるで測ったかのようにビーチフラッグの超音波発信器の高さにぴったりと合います。
なお頭のサーボモーターだけKCB-1で動かしたい場合は、 サーボのループ接続から頭のサーボ(ID=0)を取り外し、KCB-1へ接続してください。
クリックで拡大表示
RCB-3で使っていたビーチフラッグのプログラムは、KCB-1 SDKの最新アップデータを使えば、ほとんど変更することなく動作します。KHR-3HVはKHR-2HVよりも大型で歩きも安定しているので、この機会に試してみてはいかがでしょうか。
■KCB-1アップデーターVer.1.2.0 Rev.20091005
KCB-1 SDK のアップデータ(Ver.1.2.0 Rev.20091005)を公開します。今回のアップデートを適用すると、RCB-4に登録されたKHR-3HVのモーションを呼び出して再生できるようになります。
- RCB-4のモーション再生
- RCB-3のモーション呼び出しと同様に、モーション番号指定でのモーション再生命令(rcb4_motion_play)とKRCの入力をエミュレートする命令(rcb4_put_7Bcode)の両方が追加されました。いままでと同様の使い方でKHR-3HVを動作させることができます。
- ICS3.0対応
- ICS関連のプログラムはICSバージョン3.0対応となりました。ICS3.0対応サーボモーター(たとえばKRS-2552HVなど)を1.25Mbpsの高速通信により制御可能です。
- KRI-3でコントローラーの使用が可能に
- KRI-3を使ってKRCのコントロール入力値を読み取れるように、kri3.hも新規作成しました。KRI-3をSIO端子に接続し、kri3_getkey関数で簡単にボタンコードを読み取れるようになりました。
インストーラーにはそれぞれサンプルプログラムが用意されていますので、サンプルを参考にすればすぐにオリジナルのプログラムが作成できます。 なお、今回のアップデートファイルはVer.1.0(発売時のバージョン)からVer.1.1(前回のバージョン)までのアップデートファイルも含みます。
KCB-1 SDKをアップデートするには下のリンクからZIPファイルをダウンロードして、解凍してできたインストールプログラムを実行してください。インストールにはKCB-1 SDK付属CDROMのジャケットにあるシリアル番号が必要です。
ダウンロードはこちらから> KCB1SDK_V12020091005.zip
■コントロールコード再生 モーション終了を知る方法
コントロールコードでモーションを再生したときに、一番ネックになるのがモーションの終了がわからないということです。モーションによって再生時間が違うため、モーションごとにwaitを調整しなくてはいけません。waitの調整がうまくいっていないとロボットが停止する可能性もあります。
そこで、RCB3のモーションを工夫して擬似的にモーションの終了フラグを作りたいと思います。

(画像1 クリックで拡大)
画像1が、終了の返事をもらう仕組みです。モーション開始時に、KCB-1のADとつないでいるRCB-3の空いているサーボ端子をHighにします。モーション終了時にHighにしていた端子をLowに落とします。こうすることで、ADがHighの間はモーション中、Lowになればモーションは終了ということがわかるようになります。
・KCB-1とRCB-3を接続する
次に設定したサーボ端子とKCB-1の接続です。接続ケーブルでRCB3のサーボ端子とKCB-1のアナログ端子を接続してください。この際、必ず真ん中の赤い電源ラインはコネクタからはずしてください。RCB-3のハイボルテージをアナログ端子に接続してしまうとマイコンが発熱し、破損します。はずしたコネクタはビニールテープなどを巻いてショートしないように気をつけてください。
・Heart to Heartでモーションを変更する
Heart to Heartで適当なモーションを読み出してください。
最初のPOSの空いているポートをHighに設定します(例ではCH5)。次にPOS7のコピーでPOS8を作ります。POS8では、さっきHigh出力にしたCH5をLowに設定します。Lowに設定する最後のPOSのSPEEDは1で十分です。(画像2)

(画像2 クリックで拡大)
・KCB-1のプログラム
コントロールコード再生のプログラムを変更します。
rcb3_put_7Bcode (BTN7B_RR);
while(ad_read(3) >= 500){} //RCB3がHighの間ここで待機
rcb3_put_7Bcode (BTN7B_NP); //ニュートラルコマンド送信
wait (300000); //完全に停止するまで少し待つ
上記は、以前公開したAutonomous_system_ccのモーション再生部分を一部変更したです。以前waitでタイミングを取っていた部分がwhile(ad_read(3) >= 500){}となっています。これは、AD3の値が500以上の間何もしないという処理です。モーションが終わってADポートがLowになったとき、条件を抜けてニュートラルを送ることができます。
以上の作業をすれば、モーションが確実に終了した後に次の命令に移れるため、モーション同士がぶつかって停止するなどのトラブルを避けやすくなります。お試しください。
■自律ロボット作例 ver.2
以前『自律ロボット作例』の記事で自律ロボットの制作例を紹介しましたが、第二回ビーチフラッグ競技会を開催するにあたって、進化した自律ロボットをご紹介します。
<制作例マニュアルダウンロード>
<サンプルプログラム>
今回は頭部のセンサーをPSD測距センサーからUSRX-1超音波センサー(受信部)に変更しました。このセンサーでフラッグから発信されている超音波を受信し、フラッグの位置を検出します。
前回、KRS4013シリアルサーボに変更していた頭部は、KRS-788に戻しKCB-1のPIOポートに接続して制御しています。KCB-1でのPWMサーボの制御は『KRS-788HVをKCB-1で動かす① ②』で紹介した方法で行っています。
サンプルプログラムでは最初の起き上がりからフラッグを倒すまでのプログラム例を公開しています。
内容:
・kyoris_s02_cc.c ― コントロールコード再生で制御する自律ロボットのプログラムです。
・kyoris_s02_mp.c ― コマンド再生で制御する自律ロボットのプログラムです。
・sonic_search2.h ― バブルソートなど、自律ロボットに必要な関数をまとめたヘッダーファイルです。
作例のように、KCB-1とRCB-3を使用すれば簡単に自律ロボットを製作することができます。是非お試しください!
■KHR-1自律ロボット作例
今回はKHR-1での自律ロボットを紹介します。
画像のKHR-1には前後左右に計4つのPSDセンサーを実装しています。これらのセンサーの値を読み取り、最も近い物体へKHR-1が向かうようにプログラムを組みました。

<画像 クリックして拡大>
写真は「KCB-1でKHR-1を動かす①、②」でKCB-1を実装したKHR-1にPSDを取り付けた画像です。頭部のフレームの前後と、両肩にPSDセンサーをひとつずつ取り付けました。
<ムービー (2.31 MB)>
画像のKHR-1を実際に動かした動画です。それぞれのPSDセンサーに手をかざすと、KHR-1が近づいてきます。
<サンプルプログラム ダウンロード>
サンプルプログラムは動画のKCB-1に書き込まれているものと同じです。以下はこのプログラムを説明します。
・サンプルプログラムの流れ:
①. ボードの初期化、RCB-1と通信開始。通信の準備ができたら赤LEDが点灯する
②. スイッチが押されるまで(AD2がHになるまで)待機している間、ニュートラル信号を流し続ける
③.スイッチが押されると、お辞儀モーションを一回再生
④ 無限ループ開始。ループ内では1回ループする度に必ずニュートラル信号を送信すること
⑤. 前後左右に取り付けたセンサーの値を読み取り、グローバルで宣言した配列に代入
⑥. センサーの値をバブルソートして、最も高い値を求める
⑦. バブルソートで求められた値を元に、モーション再生分岐
⑧. ④~⑦の処理を繰り返す
・解説:
②、④のように、モーションを再生していないときはなるべくニュートラル信号を送信するようにしてください。ニュートラル信号なしにモーションを再生すると、うまく動作しません。
⑥のバブルソートは複数の値の中で最も大きい値、または小さい値を求める処理です。詳しくは「センサーで目標を探す(KRS788使用)③」の解説をご覧ください。
■シリアルサーボの簡易位置制御
シリアルサーボモーターを回す場合は、sio_set_pos関数などで指定した目標角度に到達するまでには時間がかかります。かといって次のようなプログラムでは、むだ時間が発生します。
while (1) {
pos == sio1_set_pos(id, 目標)
if ((pos <= 目標 + 5) && (pos >= 目標 - 5) {
//目標位置に到達した(誤差付き)と見なして、何か処理をする
}
else {
wait (100000); // モーターが目標に到達するまでちょっと待つ
}
}
シリアルサーボモーターは目標位置へ到達すると停止しますので、現在位置を数回調べても移動していない場合は、目標へきちんと到達したと判断します。
while (1){
wait (300); // タイミング調整
現在位置 = sio1_set_pos(ID, 目標); //シリアルサーボに目標位置を送って現在位置を取得
if (前回位置 == 現在位置) { // もし、現在位置が前回位置と同じだったら
cnt = cnt + 1; // cntが一つ増える
}
if (cnt == 適当な数){ // cntが適当な数になったら、目標位置で停止したと判断して
break; // ループを抜ける
}
前回位置 = 現在位置; //現在の値を保持
}
sio_set_posは、処理の後に現在の位置を返します。その現在の位置と前回の位置を比べて変化が無かった場合は、サーボが目標の位置に到着していると判断してcntを増やします。数回命令を送って同じ位置にいた場合は、サーボが完全に目標の位置にいると判断し、ループを抜けて次の処理に移ることができます。
同一サーボに連続して命令を送るときには、ある程度間隔をあける必要があるので、ここでは約500us(wait(300))待ちます。
ビーチフラッグロボットでは8回一致したら目標に到達したと判断しています。
■センサーで目標を探す(KRS788使用)④
前回からの続きです。
4) ロボットを物体の方向に歩かせる
前回までで、目標の位置を特定することができました。今回は、ロボットが見つけた目標に向かって歩くためのモーションの分岐方法を紹介します。
・switch文でモーションを分岐
上記は、モーション分岐のプログラムです。読み取ったアナログ値の最大値の位置の番号は、前回説明したバブルソートによってadk[0]に代入されています。このadk[0]を元にどのモーション再生するか決めます。
switch (adk[0]){
case 0:
case 1:
case 2:
rcb3_motion_play(9); //左旋回2回
rcb3_motion_play(9);
break;
case 3:
・・・(中略)
case 8
rcb3_motion_play(9); //左旋回1回
break;
case 9:
rcb3_motion_play(3); //左サイドステップ
break;
case 10:
・・・(中略)
case 14:
rcb3_motion_play(1); //前進
break;
・・・(中略)
}
画像は、それぞれにモーション割り当てを図式化したものです。0~24までの数字は、adk[ ]に代入したモーションを読み取った位置の番号で、Left turnなどは再生するモーションの名前です。
(画像 クリックで拡大)
上記のプログラムと画像を見て、adk[0]が「3」だった場合を考えてみます。「3」は左側の緑のエリアの番号です。目標に向かうためには、記述のLeft turn(左旋回)を1回再生すれば、ロボットは目標へ向くことになります。
以上で「センサーで目標を探す(KRS788使用)」の説明を終わります。この方法を応用すれば、いろいろ自律ロボットを作ることができると思います。お試しください!
■センサーで目標を探す(KRS788使用)③
前回のプログラムの続きです。
3) どの物体が一番近いのかを求める
void search(void){ // アナログ値の読み取りとバブルソート
unsigned int i;
int s, t, tmp;
rcb3_motion_play(37); // 正面から左に向くモーション再生
wait(300000); // サーボが動ききるまで少し待つ
rcb3_motion_play(38, mesure_distance); // 180度旋回中にアナログ値を読む
wait(600000); // サーボが動ききるまで少し待つ
rcb3_motion_play(39); // 右から方面に向くモーション再生
wait(300000); // サーボが動ききるまで少し待つ
}
// ここからバブルソート開始
for(s = 0; s <= 7; s++){
for (t = s+1; t <= 8; t++){
if (adj[t] > adj[s]){ //adj[t]の値がadj[s]よりも大きかったら順番を入れ替える
tmp = adj[t];
adj[t] = adj[s];
adj[s] = tmp;
tmp = adk[t]; //adj[t] > adj[s]だったらadkも同じ処理を行う。
adk[t] = adk[s]; //最大値のアナログ値の場所はadk[0]に代入される。
adk[s] = tmp;
}
}
}
この関数では首を旋回する一連のモーションの再生と、最大値を求めるためのバブルソートの処理を行います。
・コマンド再生の特殊な使い方
rcb3_motion_play(38, mesure_distance) は、「モーション番号38を再生している間に関数mesure_distanceの処理を行う」という命令です。モーション番号38は頭部を180度旋回させるモーションなので、前回紹介したmesure_distanceの処理を同時に行うと、弧を描くように正面全体のアナログ値を検出することができます。
・バブルソートについて
バブルソートとは、複数の数値の中でどの数値が最も大きいかを求めるための処理です。rcb3_motion_play(38, mesure_distance)で読み取ったアナログ値をバブルソートにかけて最大値を求め、どこに目標があるのかを割り出します。
配列に代入されたアナログ値を2つずつ比べます。もし、ひとつ前の値より今の値のほうが大きかったら順番を入れ替えます。その際、そのまま大きい値を小さい値の配列番号に入れてしまうと、小さい値が消えてしまいます。そこで、小さい値は別の変数(tmp)に一時保存して、大きい値が移動した後に、大きい値がいた配列のところにもう一度小さい値を代入します。これを繰り返すと、最も大きな値が配列の先頭に来て、最も小さな値が配列の一番後ろに来ることになります。 (画像1)
(画像1 クリックで拡大)
アナログ値(adj[ ])が移動すると、読み取った番号(adk[ ])も同時に移動するので、adk[0]には最も高いアナログ値を読み取ったときの番号が代入されます。あとは、この番号にモーションを割り当て、分岐すれば、ロボットは目標に向かって歩き出します。
④へ続く
■センサーで目標を探す(KRS788使用)②
前回の続きです。
2) 頭部が旋回している間にセンサーの値を読み取る
・プログラムの解説
void mesure_distance ( ) // アナログ値を一定間隔で読み取る関数
{
unsigned int i;
wait(47370);
for(i = 0; i < 8; i++){ // 頭を一度振る間に9回アナログ値を読み取り、
adj[i] = ad7_read(); // adj[i]に代入していく
ledgrn_switch();
wait (47370); // アナログ値を読む間隔は47370
// 426330(約0.7秒) / 9 = 47370
}
adj[8] = ad7_read( ); // 最後の1回
for (i = 0; i <= 8; i++) { //読みとった場所の番号を0からadk[]に代入
adk[i] = i;
}
}
この関数はアナログ値を一定の間隔で読み取る処理を行います(画像)。この処理を頭部が旋回している間に行うことによって、ロボットの正面180°のどこに物体があるのかを知ることができます。
読み取るタイミングはwaitで調整します。正面で読み取ることを基準にして、左右がほぼ同じ角度を読み取るように調節してください。読み取ったアナログ値は配列(例ではadj[ ])に代入してください。
同時に、アナログ値を読み取った場所を、別の配列(例ではadk[ ])に代入します。この配列は次回の③で説明するバブルソートで使います。

(画像 クリックして拡大)
・自律ロボット実装例で頭部サーボがシリアルサーボになっている理由
アナログ値を読み取るタイミングを作るために、PWMサーボKRS788では時計を使って旋回時間を計り、waitを調整して読み取る角度を作らなくてはいけませんでした。この方法だと、正確な角度でアナログ値を読み取るために調整を繰り返す手間があります。
ところが、シリアルサーボは、正確に回転角を指定することができるため、角度や読み込むタイミングを調節する手間が大幅に減ります。プログラムで細かい角度を指定し、それを連続して命令するだけで物体を簡単に探すことができるようになるのです。
③に続く