[[ロボティクス入門ゼミ]] #contents *課題 ライントレースロボット [#oa7cbaec] 黒い線をなぞって周回するロボットを製作する。 &br; ・交差点が2箇所以上 &br; ・急なヘアピンカーブが1箇所以上 &br; ・直角に曲がるコーナー(クランク)が1箇所以上 &br; ・黒い線の幅は15〜20mm程度 #ref(2012a/A5/ITY/M2/photo/無題.png,wrap) 上記の写真は私たちA5のコース。下半分はなだらかなコースでだが、上半分がヘアピンや、半径が小さいカーブが多いために少し難しいコースになってしまった。 *製作過程 [#r3faba28] 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] **プログラム [#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)