教育用ロボットビュートローバーを使用して簡単な制御を行ったので、その方法を紹介します。
前回=>教育用ロボットビュートローバー開発環境構[
ビュートシリーズ用 赤外線センサ(1個) -ROBOT SHOP
目次
- ライントレースとは
- 使用する機能の詳細
- プログラム
- 雑記
- 参考
ライントレースとは
ライントレースというのは、その名の通り、「線に追従する」ことで、ロボットに電車のように線の上を走らせます。 自動運転技術の1つとして、高速道路の白線を認識していることもあります。
ライントレースの精度や速さを競う大会がいくつもあります。私が知ってるのはこれとか =>ロボトレース -NIF 共益財団法人ニューテクノロジー振興財団
使用する機能の詳細
- モータードライブ
- アナログ入力
モーターのサンプルコード
サンプルコードをダウンロードしてビルドします。(詳細は環境構築編)
VS-WRC003LV-ヴイストン株式会社
電池をいれてスイッチを倒して接続します。すると、前後に動いているのがわかります。モーターを動かす関数は以下の通りです。
Mtr_Run_lv(-20000,20000,0,0,0,0);
左端の値は右モータ、右隣の値は左モータで、正転逆転出力は32767~-32767で調節します。モーターが向かい合わせについているので、左のモータは-にします。 上の関数で信号を与えますが、それは一瞬の事です。走らせるにはそのまま待機させなければいけません。そのための関数が下の関数です。
Wait(1000);
たとえばWait(1)だと、1m秒(=1/1000秒)そのまま待機します。
アナログ入力
光センサとアナログ入力について

ビュートローバーには赤外線距離センサがついてきます。距離センサなので、今回の使用方法は邪道ですね。
受光素子と発光素子が並んでついています。発光素子が発した赤外線が、床を反射して受光素子に入ってきます。このときの光の量で距離を判断しています。(量というのはだいぶアバウトですが。)
ビュートローバーでは、帰ってきた光の量をAdRead関数で0~1023までの1024段階(10bit)で入手できます。センサ入力はアナログ(連続)で、それをデジタル(離散)に変換しています。このとき、プルアップという方法をとっているので、センサの感度に対して光が最小以下のとき1023,最大以上のとき0になります。
ちなみにプルアップについて
マイコンにセンサから信号が来ないときはどうなるでしょうか。この時、人間からは何レベルか解りませんし、マイコンに取っては不安定な信号になります。これはマイコンにとってとても良くない状態なので、何も入力されていないときには回路的に1023レベルか0レベルに決定できるようにしたのがプルアップ/プルダウンです。
コード
アナログ入力取得する関数が予め定義されていますので、それを使用します。
AdRead(1);
入力(引数)はチャンネル(0~7 = 1~8)で、出力(戻り値)はA/D 変換の値(0~1023)です。
試験的にアナログ入力情報を取得してLEDを光らせます。
while(1){
Rightdata = AdRead(0);
Leftdata = AdRead(1);
if(Rightdata< 500){
LED(1); //緑のLED点灯
Wait(500); //1000msec待つ
}
if(Leftdata< 500){
LED(2);
Wait(500); //オレンジのLED点灯
}
else{
LED(0);
}
}
左センサが感知 | 右センサが感知 | 左LEDが点灯 | 右LEDが点灯 |
---|---|---|---|
O | O | O | O |
O | X | O | X |
X | O | X | O |
X | X | X | X |
Border以上: 反射がない/黒=>光る
Border以下: 反射がある/白=>光らない
このボーダーは自分で設定する事が出来ます。 50にすると、センサと床の距離が同じなままで白黒を判別できました。私の手元に青いテープしかなかったのでうまく調整します。
プログラム

機体がラインにまたがり、センサがラインの両端に来るような状況を考えています。
作成したコードです。後半で解説しています。簡単なコードなのでかなり改良の余地があります(^^ゞ
使用するセンサの質や数、配置によってコードが変わってくるでしょうが、今回は製品を使用するので誤差は小さめかと思います。
#ifdef __cplusplus
extern "C" {
void abort(void);
#endif
void main(void);
#ifdef __cplusplus
}
#endif
/*インクルード***********************************************************/
#include<36064s.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include "vs-wrc003lv.h"
/*グローバル変数***********************************************************/
int Leftdata;
int Rightdata;
int Borderr = 50;
int Borderl = 55;
/*メイン関数***********************************************************/
void main(void)
{
//制御周期の設定[単位:Hz 範囲:30.0~]
const BYTE MainCycle = 60;
Init((BYTE)MainCycle); //CPUの初期設定
//ループ
while(1){
Rightdata = AdRead(0);
Leftdata = AdRead(1);
if(Rightdata > Borderr){
LED(1); //緑のLED点灯
Mtr_Run_lv(-10000,-10000,0,0,0,0);
Wait(100); //100msec待つ
}
if(Leftdata>Borderl){
LED(2);
Mtr_Run_lv(10000,10000,0,0,0,0);
Wait(100); //オレンジのLED点灯
}
else{
Mtr_Run_lv(0,0,0,0,0,0);//停止
Wait(100);
LED(0);
Mtr_Run_lv(-10000,10000,0,0,0,0);//前進
Wait(100);
}
}
}
#ifdef __cplusplus
void abort(void)
{
}
#endif
アルゴリズム
コードを実行する時、処理は上から順に行われますので、私がやったコードの実行手順は以下のようになっています(たぶん)。

これを実行すると、下のように動作すると思います。センサは白に反応するので注意してください。
状態 | 左センサ | 右センサ | 機体動作 |
---|---|---|---|
持つ | X | X | LED左右交互に点滅 |
線の上 | O | O | LED消灯、前進 |
右に脱線 | O | X | 左朱LED点灯、反時計回り |
左に脱線 | X | O | 右緑LED点灯、時計回り |
ライントレースの動作
実際に走らせてみたところ、完走です。 センサのボーダーの値はそれぞれの機体で走らせてみて調整してください。動画は諸事情によりありません。

雑記
紹介したコードの場合、手に持っている時にもモーターが左右交互に回転しようとしますので、効率が悪いです。 また、機体進行方向に対して水平なラインに出会ったときにも、左右交互に回転しようとしてしまい、脱出出来ません。
ロボットで勉強してみようという方がいらっしゃいましたら、コードを改良したりセンサを増やしてみたりして、様々な場合に対応できるように改良してみると楽しいのではないでしょうか。
参考
関連商品紹介