■HEWをWindows Vistaにインストールするときの注意事項
KCB-1は買ってすぐにマイコンプログラムを楽しむことができるように、ルネサスの統合開発環境HEW(High-performance Embedded Workshop)が付属しています。
ただしWindows VistaにHEWをインストールするには、いくつか手順を踏まなければなりません。
- インストーラー(CD-ROMの「開発環境」フォルダにある「nc30wav543r00_ev.exe」)をCD-ROMからいったん「ドキュメント」フォルダなどのローカルディスクへコピーします。
- nc30wav543r00_ev.exeを右クリックして、プロパティを選択します。
- 互換性タブを開き、「互換モード」欄で「互換モードでこのプログラムを起動する」にチェックを入れ、プルダウンメニューから「Windows XP (Service Pack2)」を選びます。
- 「特権レベル」欄の「管理者としてこのプログラムを実行する」にチェックを入れます。
- nc30wav543r00_ev.exeをダブルクリックして、通常のインストールを開始します。

インストール終了後にHEWをインストールしたフォルダ(通常は「C:\Program Files\Renesas\Hew」)を開き、「HEW2.exe」について、インストーラーファイルと同様に互換性モードと管理者権限を設定します。
- インストールしたフォルダにある「HEW2.exe」)を右クリックして、プロパティを選択します。
- 互換性タブを開き、「互換モード」欄で「互換モードでこのプログラムを起動する」にチェックを入れ、プルダウンメニューから「Windows XP (Service Pack2)」を選びます。
- 「特権レベル」欄の「管理者としてこのプログラムを実行する」にチェックを入れます。
- HEW2.exeをダブルクリックして、通常のインストールを開始します。

以上でHEWは画面にちょっと不具合があるものの、普通に使用できます。ただし、AutoUpdate.exe(標準では「Renesas\Hew\AutoUpdate\AutoUpdate.exe」)などはそのままでは使用できませんので、もしアップデートしたい場合はこちらにも「互換レベル」と「管理者権限」の設定を行います。
HEWをアップデートした場合は、「Hew2.exe」の「互換レベル」と「管理者権限」の設定を再確認して下さい。
Windows Vistaでは「C:\Program Files」フォルダにインストールしたつもりでも、実際は別の場所に保存されてしまうことと、管理者権限を持っていてもシステム関連のフォルダにあるファイルは自由に読み書きできないという仕様となりましたので、HEWが設定ファイルなどの保存が今まで通りできなくなってしまいました。ご面倒ですがVistaをご使用の方は、上記内容をよくお読みいただき、ご利用なさいますようお願いします。
さらに詳しい内容はルネサスサポートページ「ルネサステクノロジ, Windows Vista(TM)対応, ツールニュース, 20070516」をご覧になって下さい。
裏技として、「C:\Program Files」ではなくて、全くちがうフォルダへインストールするという方法もあります。この方法ではHEWの設定は不必要になりますが、AutoUpdateやDocumentUpdaterなどは設定が必要です。
アップデートに関しては、Renesasの対応をもう少し待った方がよいかもしれません。
■インサイド・KRS40XX
KCB-1でシリアルサーボモーターの制御をしているときに、時々動かなくなってしまうことがありませんか?これはサーボモーターに命令を立て続けに送ったときなどに起きる現象です。
KRS-40XXシリーズなどの弊社製サーボモーターは、単に位置制御を行っているだけではなく、デイジーチェーンで接続する場合は信号線を全てのモーターと共有しますので、自分への信号なのかどうかを調べたりしています。もちろんKCB-1からだけではなく、他のサーボモーターが出した返事についても調べなくてはなりません。
このような内部処理を正しく行うために、KRS-40XXシリーズではデータの受け渡しを行った後に若干の時間を必要としています。その時間は約300~400[us]。KRS-40XXは115kbpsでデータの送受信を行いますので、位置制御(set_pos)に必要な6バイトの送受信時間を合わせると、一台のモーターあたり1[ms]程度の余裕が必要です。
--- 例 ---
while (1) {
...
sio1_set_pos (1, 目標位置); // 送受信に約600[us]を使用している
wait (200); // 若干の待ち時間(300~400[us])待つ
sio1_set_pos (1, 目標位置); // 再度目標位置を送信
wait (200);
sio1_set_pos (2, 目標位置); // IDが変わっても、同じSIO端子を使う場合はちょっと待つ
...
}
KCB-1では、このデータ送受信時間以外に必要な300~400[us]をさらに詰めるために、SIO端子を2つもうけています。SIO1,2に交互にデータを送信することで、たくさんのサーボモーターを短い(約半分の)時間で動かすことができるようになります。または処理が完全に終わるだけの間隔を持ったタイマーを使う方法もありますよ。
■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回一致したら目標に到達したと判断しています。
■KCB-1でKHR-1を動かす方法(2)
前回の続きです。
このプログラムでは2バイトコントロールコード再生のプログラムを、RCB-1対応に変更をしています。2バイトコントロールコード再生は、KCB-1からKRCと同じ再生コマンドをRCB-1へ送信し、モーションを再生する方法です。モーションを再生するには、モーションを各ボタンに割り付ける必要があります。
なお、コントロールコード再生を行う際は、更新プログラム「KCB1Update20080510.exe」をダウンロードする必要があります。詳しくは「KCB-1 SDK更新(Rev.20080510)」をご覧ください。
・ プログラム
#include <ad.h>
#include <rcb3.h>
#include <led.h>
// プログラム中で実行するモーションをHTHで割付してください
#define FORWARD BTN2B_LU // 前進
#define LEFTSTEP BTN2B_LL // 左サイドステップ
#define RIGHTSTEP BTN2B_LR // 右サイドステップ
#define LEFTTURN BTN2B_LL | BTN2B_LD // 左ターン
#define RIGHTTURN BTN2B_LR | BTN2B_LD // 右ターン
#define BOW BTN2B_RU // あいさつ
#define NP_WA 1200000 //停止後の待機時間(前に再生したモーションとかぶらないために余裕を持って設定する)
void khr_2Bmotion(int cc) //2BYTEcodeモーション再生関数
{
rcb3_put_2Bcode (cc); //2BYTEcodeでモーション再生
while (ad_read(1) > 500) {} //モーションが終了するまで待つ
rcb3_put_2Bcode (BTN2B_NP); //モーション終了後ニュートラルを送信
wait (NP_WA); //少しだけ待つ
}
void main(void)
{
cpu_init (); // CPUの初期設定を行う
ad_oneshotmode (); // ADはワンショットモードで読み込む
ledgrn_on (); // 起動確認用LEDを点灯する
rcb3_rx_open (); // RCBのRXポートを接続します
wait (5000000); // RCBの起動が安定するまで待ちます
ledred_on(); // 赤LED点灯後、モーション再生可能
while(1){
rcb3_put_2Bcode (BTN2B_NP); //何もしていないときはニュートラルを送信
if (ad_read(2) > 500) { //もしスイッチが押されたら
khr_2Bmotion(BOW); //モーション再生
khr_2Bmotion(FORWARD);
khr_2Bmotion(RIGHTSTEP);
}
}
}
・解説
▼変更点①
通常の2バイトコントロールコード再生のプログラムと違うところは、モーションを再生していないときに、常にニュートラル信号を送信していることです。これは、通常、KRCの電源を入れて何も操作していない場合に、KRCからはニュートラル信号が送信されているためです。
▼変更点②
1)コントロールコード再生
2)再生終了待ち
3)ニュートラル送信
4)ニュートラル状態に戻るまで待つ
以上の④項目を今回はkhr_2Bmotionという関数にまとめました。
■KCB-1でKHR-1を動かす方法(1)
今回は、KCB-1のコントロールコード再生でKHR-1(RCB-1)を動かす方法を紹介します。
(※RCB-1とKCB-1では、コマンド再生、7バイトコントロールコード再生はできません。また、RCB-1に接続された6VバッテリーでKCB-1を動かすため、シリアルサーボはお使いになれません)
①ではKCB-1の実装やケーブルの配線などの準備、②ではプログラムの紹介をします。
・ 通信の準備
RCB-1をKRCで操作できるように設定し、再生するモーションをKRCの各ボタンに割り付けてください。RCB-1のKRRに接続するポートとKCB-1のCOMポートを接続ケーブルでつなぎます。
電源は空いているRCB-1のサーボ接続端子とKCB-1の空いているシリアルポートを接続します。その際、白線は外してください。
・ モーション終了を知るための準備
モーション終了後、RCB-1を1度ニュートラルに戻す必要があります。モーション終了をwaitでタイミングを取ることもできますが、モーションごとに調整が必要になり、不便です。そこで、RCB-1の空いているサーボ端子をモーション中は「H」、モーション終了後は「L」に設定し、その信号をKCB-1のADポートで受け取ります。②で紹介するプログラムでは、RCB-1のCH4とKCB-1のAD1を接続し、モーションの終了を受け取っています。これは以前紹介した「コントロールコード再生 モーション終了を知る方法」と同じ方法です。
なお、モーション再生を手動でスタートさせるため、AD2の信号ラインと電源ラインにスイッチを接続してください。
KCB-1との接続は、全てRCB-1のID0に行います。

(画像 クリックで拡大)
・ KHR-1へのKCB-1実装
KHR-1では腹部にネジ止めをします。このとき、ボード裏とボディーが接触するとショートする恐れがあるので、6mm程度のスペーサーをはさみます。また、ボードがむき出しのままだと転倒したときに破損する可能性があるため、KHR-HVシリーズのフロントカウルをかぶせることをお勧めします。例はテープで固定しました。

(画像 クリックで拡大)
②へ続く
■センサーで目標を探す(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を調整して読み取る角度を作らなくてはいけませんでした。この方法だと、正確な角度でアナログ値を読み取るために調整を繰り返す手間があります。
ところが、シリアルサーボは、正確に回転角を指定することができるため、角度や読み込むタイミングを調節する手間が大幅に減ります。プログラムで細かい角度を指定し、それを連続して命令するだけで物体を簡単に探すことができるようになるのです。
③に続く
■センサーで目標を探す(KRS788使用)①
ビーチフラッグや、自律バトル競技など、自律ロボット競技に参加するためには、目標を探す処理が必要になります。今回はKRS788を頭部に使用して物体を探すプログラムを解説します。
・目標を探すには
目標を探す方法のひとつに、頭部を旋回している間に一定のタイミングでアナログ値を読み取り、最大値を求めるという方法があります。PSDセンサーや超音波センサーは、物体が近いほど高い値を示します。ビーチフラッグや自律バトル競技の場合、フィールド上で最も近い物体が目標になる確率が高いので、読み取った値の最大値を目標と判断し、その方向へ近づくプログラムを組みます。

(画像1 クリックで拡大)
画像1はロボットが目標を探しているところを、上から見た図です。0~24の番号はアナログ値を取るタイミングと順番です。
・プログラム作成の流れ
1) 頭部を180°旋回させるモーションをつくり、その動作時間を計る
2) 頭部が旋回している間にセンサーの値を読み取る
3) どの物体が一番近いのかを求める
4) ロボットを物体の方向に歩かせる
・用意するもの
1) 頭部を180°旋回させるモーションをつくり、その動作時間を計る
・モーション作成
まず、首を180°旋回するモーションをHeart to Heartで作成します。下記の三つのモーションを作ってください。
- モーション①. 頭部を正面(ホームポジション)から左に向かせる
- モーション②. 左に向いた頭部を180°旋回して右に向かせる
- モーション③. 右に向いた頭部を正面(ホームポジション)に向かせる
モーションを3つに分けた理由は、アナログ値を読むモーション②を別にして、読み込むタイミングを正確に取るためです。
・モーション②の移動時間を測る
左に向いている頭部が右へ動きだしたところから、右に向いて停止するところまでの時間を計ります。計った時間を分割してアナログ値を読む取るタイミングを取ります。
②へ続く