1.ライントレース(2値化走行制御) TOPへ 3.ライントレース(PD制御走行)

2.ライントレース(P制御走行)


※この章を学習するにはⅡ.基礎編1〜7までを習得することが必要です。

前章までのライントレースは、常にロボットが旋回しているため、ジグザグに走行してしまい、あまり速くは走れませんでした。
今回はそれを改良し、速く、安定した走りを実現しましょう。
ロボットは基本的にこれまでのものを引き続き使います。


1.比例制御

これまでのプログラムでは、色の閾値より暗いとき、明るいとき、で旋回方向を指定していました。
しかし、光センサが色の目標付近(この場合は白黒中間値)を読み取っているとき、ロボットを大きく旋回する必要はありません。
そこで、左右のモータの駆動力の差(旋回値)を、光センサ値の目標値(この場合は白黒の中間値)からのずれに比例して大きくなるようにして走行させます(図)。

pseigyo2.png(9799 byte)

このような制御を比例制御(P制御)といいます。
次のプログラムをコンパイルして、NXTにダウンロードしてください。

trace_p.c
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"

#define PORT_LIGHT NXT_PORT_S3	/* 入出力ポートの定義 */
#define PORT_TOUCH NXT_PORT_S2
#define L_MOTOR NXT_PORT_B
#define R_MOTOR NXT_PORT_C

#define BLACK 700
#define WHITE 500

DeclareTask(Task1);				/* Task1を宣言 */

void ecrobot_device_initialize(){		/* OSEK起動時の処理 */
	nxt_motor_set_speed(L_MOTOR,0,1);
	nxt_motor_set_speed(R_MOTOR,0,1);
	ecrobot_set_light_sensor_active(PORT_LIGHT);
}

void ecrobot_device_terminate(){		/* OSEK終了時の処理 */
	nxt_motor_set_speed(L_MOTOR,0,1);
	nxt_motor_set_speed(R_MOTOR,0,1);
	ecrobot_set_light_sensor_inactive(PORT_LIGHT);
}

void user_1ms_isr_type2(void){}


void sound_beep(){			/* ビープ音を鳴らすユーザ関数 */
	ecrobot_sound_tone(600, 2, 80);
	systick_wait_ms(20);
	ecrobot_sound_tone(500, 5, 80);
	systick_wait_ms(50);
}


TASK(Task1)
{
	int speed = 70;			// SPEED値
	float Kp = 0.4;		// Pゲイン変数
	int black,white,gray;		// 色変数 
	
	float turn;			
 	float turn_prev;
	int turn_flag, turn_count;

	black = BLACK;
	white = WHITE;
	gray = (black + white) / 2;

	while(1){

		while(ecrobot_get_touch_sensor(PORT_TOUCH) == 0){		/* TSが押されるまでループする*/
			display_goto_xy(0, 1);
			display_string("PUSH START");
			display_update();
		}
		display_clear(1);
		systick_wait_ms(500); 	/* wait 500msec */

		turn_prev = 0.0;
		turn_flag = 0;
		turn_count = 0;

		while(ecrobot_get_touch_sensor(PORT_TOUCH) == 0){ 	//TSが押されるまでループする

			// P制御による旋回
			turn = Kp * (ecrobot_get_light_sensor(PORT_LIGHT) - gray);
			nxt_motor_set_speed(L_MOTOR,speed-turn,1);
			nxt_motor_set_speed(R_MOTOR,speed+turn,1);

			// TURN値が減少に転じたときにカウントする
			if( turn < turn_prev && turn_flag == 1 ){
				turn_count++;
				//ecrobot_sound_tone(440, 10, 100);
				display_goto_xy(0, 3);
				display_string("TURN COUNT  ");
				display_int(turn_count,0);
				display_update();
				turn_flag = 0;
			}
			// TURN値が負で上昇しているとき TURN_FLAG を1とする
			if( (turn < 0) && (turn > turn_prev) ){
				turn_flag = 1;
			}

			turn_prev = turn;

			systick_wait_ms(10); /* wait 10msec*/
		}

		//停止
		nxt_motor_set_speed(L_MOTOR,0,1);
		nxt_motor_set_speed(R_MOTOR,0,1);
		systick_wait_ms(1000);		/* 1秒待つ */
	}

	TerminateTask();					/* 処理終了 */
}

このプログラムを実行しても、ロボットはジグザグに走ってしまうかもしれません。しかし、前の閾値で制御していたものよりも、ロボットの振れは緩やかになっているはずです。
速度と比例ゲインを適切に設定すれば、かなり安定して走れるようになります。
比例ゲインを大きくしすぎると、ロボットが曲がりすぎるので不安定になります。
逆に小さくしすぎると、振れは小さくなりますが、カーブなどが曲がりきれなくなります。
適切な比例ゲインと速度は、コースやロボットによって異なるので、試験走行をして適切な値を探りましょう。

このプログラムはスタートから停止までのジグザクの回数(turn_countの値)をLCDに表時するようにしています。 限界感度法で PID ゲインを決定する際にはジグザクの周期(振動周期)を与える必要がありますが、それを求めるときこの値を利用することが出来ます。


2.課題

1.BLACK, WHITE の値を適切に設定し、サンプルプログラムを実行し、動作を確認せよ。
2.ロボットが速く・安定してコースを周回できるように、速度およびPゲイン(Kp)を調節せよ。
3.一番早かったときのラップタイムを記録せよ。


1.ライントレース(2値化走行制御) TOPへ 3.ライントレース(PD制御走行)