- 追加された行はこの色です。
- 削除された行はこの色です。
[[ロボティクス入門ゼミ]]
#contents
*課題 ライントレースロボット [#oa7cbaec]
黒い線をなぞって周回するロボットを製作する。
&br; ・交差点が2箇所以上
&br; ・急なヘアピンカーブが1箇所以上
&br; ・直角に曲がるコーナー(クランク)が1箇所以上
&br; ・黒い線の幅は15〜20mm程度
#ref(2012a/A5/ITY/M2/photo/無題.png,wrap)
上記の写真は私たちA5のコース。下半分はなだらかなコースでだが、上半分がヘアピンや、半径が小さいカーブが多いために少し難しいコースになってしまった。
*製作過程 [#r3faba28]
h24/6/4〜6/29 [[2012a/A5/ITY/M2/photo]]
#ref(2012a/A5/ITY/M2/photo/.JPG,wrap)
h24/6/1〜6/29 [[2012a/A5/ITY/M2/photo]]
#ref(2012a/A5/ITY/M2/photo/CIMG1577.JPG,wrap)
・アナログセンサ1個、タッチセンサ2個使用
#ref(2012a/A5/ITY/M2/photo/無題5.png,wrap)
**車体部分 [#y9face06]
#ref(2012a/A5/ITY/M2/photo/CIMG1578.JPG,wrap)
前回は重心が高くて走行に支障が出たので今回は低重心、コンパクトを目指した。
#ref(2012a/A5/ITY/M2/photo/CIMG1582.JPG,wrap)
センサの位置をできるだけ車体に近づけた
***工夫したところ [#r33af6c3]
・低重心、コンパクト化
**結果 [#qb252fa7]
**プログラム [#e469798e]
**プログラム [#mf2ad5b3]
#ref(2012a/A5/ITY/M2/photo/無題2.png,wrap)
#ref(2012a/A5/ITY/M2/photo/無題3.png,wrap)
#ref(2012a/A5/ITY/M2/photo/無題6.png,wrap)
/* 2012/6/22 ITY */
/* 2012a_robo tore-su6 */
/*-------------------------------------------------------------------
別名定義
-------------------------------------------------------------------*/
#define PWM 80 // PWM(力の大きさ)
#define PWM_D 15 // PWM(力の大きさ)
#define DIF 6 // 差
#define ON 1 // オン
#define OFF 0 // オフ
#define TRUN_AC 320 // 90度の回転角度
#define DEFF_RC 180 // 超信地旋回までの時間
#define DEFF_LC 100 // 超信地旋回までの時間
/*-------------------------------------------------------------------
関数宣言
-------------------------------------------------------------------*/
void TURN_R(); // 90度ターン
void TURN_L(); // 90度ターン
void MODULATE(); // しきい値調整用の関数
/*-------------------------------------------------------------------
グローバル変数
-------------------------------------------------------------------*/
int s1_touch,s2_touch,br_light,wh_light; // タッチセンサ
/*-------------------------------------------------------------------
メインルーチン
-------------------------------------------------------------------*/
task main()
{
SetSensorLight(IN_4); // アナログセンサの宣言
SetSensorTouch(IN_2); // タッチセンサの宣言
SetSensorTouch(IN_1); // タッチセンサの宣言
int s_light,diff,abs_diff,aspect,s_avg,r_count,l_count,num_c; // 変数宣言
num_c=0,s_light=0,r_count=0,l_count=0; // 変数の初期化
MODULATE(); // しきい値調整用の関数
s_avg = (br_light+wh_light)/2; // 白と黒の平均値を取る
OnFwd(OUT_AC,80); // コースに入るために前進
Wait(400); // 0.4秒間前進
TURN_R(); // 右に90度旋回
while(true){ // ライントレース開始
num_c++; // クランク用のカウンタを回す
s_light = Sensor(IN_4); // アナログセンサの値を取得
if((s_light < (s_avg + DIF)) && (s_light > (s_avg - DIF))){ // センサの値が平均値の差(DIF)に入っているとき
OnFwd(OUT_AC,PWM); // 両方のモータを正転させる
}
else{ // センサの値が平均値の差(DIF)に入っていないとき
abs_diff = abs(s_light - s_avg); // 今のセンサの値と平均値を比較する
diff = PWM_D + (50 - abs_diff) + (abs(l_count-r_count)*0.1);// PWM=(初期速度)+(上で比較した値)+(センサが復帰するまでの時間*0.1)
if(diff > 100)diff = 100; // PWMが100を超えないようにする
if(s_light < s_avg){ // センサの値が平均値より小さい時(黒)
OnFwd(OUT_C,diff); // Cのモータを正転
if(l_count > DEFF_RC) OnRev(OUT_A,diff/2); // 復帰モードに入った時、Aのモータを後転(超信地旋回)
else Off(OUT_A); // 復帰モードに入るまで、Aのモータを停止
l_count++; // lのカウンタ開始
r_count=0; // rのカウンタのクリア
}
else if(s_light > s_avg){ // センサの値が平均値より小さい時(白)
OnFwd(OUT_A,diff); // Aのモータを正転
if(r_count > DEFF_RC) OnRev(OUT_C,diff/2); // 復帰モードに入った時、Cのモータを後転(超信地旋回)
else Off(OUT_C); // 復帰モードに入るまで、Cのモータを停止
r_count++; // rのカウンタ開始
l_count=0; // lのカウンタのクリア
}
}
Wait(1); // 1ms周期でメインルーチンを回す
if(num_c > 20000){ // クランク前にトレースする向きの変更
Off(OUT_AC); // ACのモータの停止
OnFwd(OUT_A,diff); // ACのモータの正転
Wait(400); // 0.4秒待つ
}
while(num_c > 20000){ // 向きの変更後トレース開始
s_light = Sensor(IN_4); // 以下は上のプログラムの左右を変更したもの
if((s_light < (s_avg + DIF)) && (s_light > (s_avg - DIF))){
OnFwd(OUT_AC,PWM);
}
else{
abs_diff = abs(s_light - s_avg);
diff = PWM_D + (50 - abs_diff) + (abs(l_count-r_count)*0.2);
if(diff > 100)diff = 100;
if(s_light < s_avg){
OnFwd(OUT_A,diff);
if(l_count > DEFF_LC) OnRev(OUT_C,diff/2);
else Off(OUT_C);
l_count++;
r_count=0;
}
else if(s_light > s_avg){
OnFwd(OUT_C,diff);
if(r_count > DEFF_LC) OnRev(OUT_A,diff/2);
else Off(OUT_A);
r_count++;
l_count=0;
}
}
}
}
}
/*-------------------------------------------------------------------
サブルーチン
-------------------------------------------------------------------*/
void TURN_R() // 90度ターン
{
int tako_a=0,tako_c=0; // 変数宣言
ResetScreen(); // LCDの初期化
OnFwdSyncEx(OUT_AC,40,-100,RESET_NONE); // 左右ACのモータを回す
while((tako_a < TRUN_AC) && (tako_c < TRUN_AC)){ // 90度回転していないとき
tako_a = abs(MotorTachoCount(OUT_A)); // タコメータからモータAの値を取得
tako_c = abs(MotorTachoCount(OUT_C)); // タコメータからモータBの値を取得
NumOut(10,48,tako_a,0); // LCDにタコメータ(A)の値を表示
NumOut(10,40,tako_c,0); // LCDにタコメータ(A)の値を表示
}
Off(OUT_AC); // モータの停止
}
void MODULATE() // しきい値の調整用
{
int t_count; // 変数宣言
s1_touch=0,s2_touch=0,t_count=0, // 変数の初期化
br_light=10,wh_light=60;
while(s2_touch == OFF){
s1_touch = Sensor(IN_2); // タッチセンサの値を取得
s2_touch = Sensor(IN_1); // タッチセンサの値を取得
NumOut(10,60,s1_touch,0); // LCDにタッチセンサの値を表示
NumOut(10,40,s2_touch,0); // LCDにタッチセンサの値を表示
NumOut(30,60,br_light,0); // LCDに黒のしきい値を表示
NumOut(30,40,wh_light,0); // LCDに白のしきい値を表示
if(s1_touch == OFF){ // スイッチ1が押されていないとき
t_count = 0; // カウンタの初期化
Off(OUT_AC); // モータの停止
}
else if(s1_touch == ON){ // スイッチ1が押されているとき
if(t_count < 1000){ // 1秒間押されているか判定
t_count++; // カウンタをまわす
br_light = Sensor(IN_4); // 黒いラインの明るさを取得
}
else { // 1以上押されているとき
wh_light = Sensor(IN_4); // 白い部分の明るさを取得
}
}
}
}
***工夫したところ [#f9d5e0c8]
*反省・感想 [#caeac12f]
#ref(2012a/A5/ITY/M2/photo/無題1.png,wrap)
#ref(2012a/A5/ITY/M2/photo/無題4.png,wrap)