2.タッチセンサの使用 TOPへ 4.ロータリーエンコーダの使用

3.ライトセンサの使用


次にライトセンサについて解説します。 このセンサは光を測定することで表面の色を判別したり、周囲の明るさを知ることができます。
この項を学習する前に今一度、ライトセンサの測定や応答について復習しておきましょう。


1.ライトセンサの取り付け

ロボットは1.で作ったものを引き継ぎます。今回はライトセンサを路面側に向けるように作りましょう。
ここでは、ロボット組立て図のp32〜34に記載されたものを用います。この時、前回取り付けたバンパーは外して下さい
light1.jpg(7856 byte) light2.jpg(30013 byte)
今回はライトセンサを入力ポート3に接続します。


2.ライントレース

ここでは黒いラインに沿って走行するライントレースロボットのプログラムを作成します。
次のプログラムを作成してください。ここではファイル名をlight1.cとします。
light1.c
#include "nxtlib.h"

#define WHITE 40
#define BLACK 30
#define TURN_SPEED 20

task main(){
	SetSensorLight(S3,Active);
	while(true){
		motor[motorB] = 100;
		motor[motorC] = TURN_SPEED;
		while(SensorValue(S3) > WHITE){
			wait1Msec(1);
		}

		motor[motorB] = TURN_SPEED;
		motor[motorC] = 100;
		while(SensorValue(S3) < BLACK){
			wait1Msec(1);
		}
	}
}

このプログラムを動かすときは黒いライン上から始めてください。
新しく使用したAPIの解説をします。

SetSensorLight(S3,Active)
入力ポート3にライトセンサをアクティブモード(投光照明をONにするモード)で設定します。
第1の引数は入力ポートを記述します。指定方法は、タッチセンサの場合と同じです。
第2の引数はライトセンサのモードを指定します。今回はアクティブモードで設定しました。 パッシブモード(投光照明をOFFにするモード)の場合は、Passiveと記述してください。
このAPIは nxtlib.h に記述されています。

ライトセンサの場合は、SensorValue()で得られる値は0〜100となっています。
このプログラムは黒のライン上では左に曲がり、白いところでは右に曲がります。 白や黒の基準はプログラムの最初に定義した『WHITE』、『BLACK』の値によって決まります。
従って、実際のコースの状況や周りの照明、センサと地面の間の距離によって正しく判別できない可能性があります。 このような場合は、NXTコンソールにより実際の値を測定してそれぞれの値を書き換えましょう。
また、曲がる量が大き過ぎたり小さいような場合には、『TURN_SPEED』の値を変えることでそれを調整できます。


3.ライントレースの改良

ここでは先ほどのライントレースロボットを改造し、タッチセンサを用いて障害物に衝突すると停止するロボットを作ります。
まず、次のバンパーを作成してください。
light_plus.png(81078 byte)

【作り方】
 light2-01.png(6700 byte)  light3-01.png(5710 byte)
 light2-02.png(7148 byte)  light3-02.png(6141 byte)
 light2-03.png(8294 byte)  light2-06.png(10467 byte)
 light2-04.png(10608 byte)  light2-07.png(10636 byte)
 light2-05.png(10445 byte)

今回はタッチセンサを入力ポート1に、ライトセンサを入力ポート3に接続します。

次にプログラムを作成します。タッチセンサを判別しながらライントレースを行うには、上のような方法ではうまくいきません。
ここでは、一定時間ごとにタッチセンサの状態を判別し、押されていれば停止を、押されていなければライトセンサの値から適した動作をする ことで実現させます。
それでは次のプログラムを作成してください。ここでは light2.c とします。なお、light2.h と light2.c は同じディレクトリに保存してください。
light2.h
#include "nxtlib.h"

#define FWD_POWER 75
#define TRN_POWER 5

#define TOUCH S1
#define LIGHT S3

#define RIGHT motorB
#define LEFT motorC

#define CHECK_TIME 10
#define COLOR_WHITE 40


void init_sensor(){
	SetSensorLight(LIGHT,Active);
	SetSensorTouch(TOUCH);
}

void turn_right(){
	motor[RIGHT] = TRN_POWER;
	motor[LEFT] = FWD_POWER;
}

void turn_left(){
	motor[RIGHT] = FWD_POWER;
	motor[LEFT] = TRN_POWER;
}

void stop(){
	motor[RIGHT] = 0;
	motor[LEFT] = 0;
	StopAllTasks();
}

light2.c
#include "light2.h"

task main(){
	init_sensor();

	while(true){

		if(SensorValue(TOUCH) == 1){
			stop();
		}else if(SensorValue(LIGHT) > COLOR_WHITE){
			turn_right();
		}else{
			turn_left();
		}
		wait1Msec(CHECK_TIME);
	}
}

このプログラムではロボットの初期位置が黒いライン上でなくてもライントレースを行います。
また、ロボットが障害物に衝突すると、ライントレースを止めて停止すると思います。
それでは新しく用いたAPIの解説を行います。

StopAllTasks()
全てのタスクを終了させる命令です。タスクを全て終了させるとプログラムは停止します。 このAPIには引数は不要なので、()まで含めて一つのAPIとして覚えておくと良いでしょう。
なお、タスクについては10.マルチタスクで学習します。

さらに今回は関数の定義とヘッダのインクルードを行いました。ご覧の通り、これらの記述はC言語とほとんど同じです。
インクルードするヘッダは、コンパイルするプログラムと同じフォルダに置く必要があります。
このようにプログラムを作成するとプログラムそのものが見やすくなり、また編集も簡単に行えます。


4.課題

3.で作成したプログラムをさらに改良し、「ライントレースを行いながら、タッチセンサが押されたらその障害物を回避する」プログラムを作成しなさい。



2.タッチセンサの使用 TOPへ 4.ロータリーエンコーダの使用