最終調整
Dependencies: mbed AQM0802 CRotaryEncoder TB6612FNG
Diff: main.cpp
- Revision:
- 30:14615f9ff467
- Parent:
- 29:01b7f40ec029
- Child:
- 31:fe9ae7992246
--- a/main.cpp Mon Nov 25 05:58:11 2019 +0000 +++ b/main.cpp Tue Nov 26 02:49:20 2019 +0000 @@ -1,74 +1,15 @@ -//LCD表示系を一新した -//1行目に走行モード、機体状態、記憶マーカ数を表示 -//2行目にDefault_Speedの値を表示する。 +/******************************************************** + +**********************************************************/ ////ライントレースサンプル #include "mbed.h" #include "CRotaryEncoder.h" #include "TB6612.h" #include "AQM0802.h" - - -//☆★☆★各種パラメータ調整箇所☆★☆★☆★ -#define DEFAULT_SPEED 750 //1走目の基本速度 -#define LOW_SPEED 750 //2走目の低速速度[mm/sec] -#define MEDIUM_SPEED 850 //2走目の低速速度[mm/sec] -#define HIGH_SPEED 1100 //2走目の低速速度[mm/sec] -#define DEFAULT_HIGH_SPEED 900 //3走目の低速速度[mm/sec] -#define STOP_DISTANCE 100000 //停止距離200000[um]⇒20[cm] -#define TURN_POWER 0.6 //コースアウト時の旋回力 -#define PULSE_TO_UM 28 //エンコーダ1パルス当たりのタイヤ移動距離[um] -#define INTERRUPT_TIME 1000 //割りこみ周期[us] -#define DEFAULT_GRAY 0.2f //フォトリフレクタデジタル入力の閾値 - //シリアル通信でSensor_Digital値を確認し調整する。 -#define MARKER_WIDTH 10000 //マーカ幅[um](ビニルテープ幅19000[um]以内) - //コースの傷によってマーカ誤検知する場合は値を大きくする。 -#define CROSS_JUDGE 4 //ラインセンサいくつ以上白線検知で交差点認識するか設定。 - -#define HIGH_SPEED_SECTION 1.25f //最高速度の左右回転差の上限倍率 -#define MIDIUM_SPEED_SECTION 2.0f //中間速度の左右回転差の上限倍率 -#define LOW_SPEED_SECTION 4.0f //最低速度の左右回転差の上限倍率 - - -//モータ速度のゲイン関連(むやみに調整しない) -#define M_KP 0.002f //P(比例)制御成分 -#define M_KD 0.001f //D(微分)制御成分 - -//フォトリフレクタのゲイン(外側に行くにつれ値を何倍させたいか調整する。) -#define S_K1 1.0f //float演算させる値には必ずfを付ける -#define S_K2 2.0f //2倍 -#define S_K3 3.0f //4倍 - - -//ラインセンサ各種制御成分 -#define S_KP_DEFAULT 1.0f //ラインセンサ比例成分。大きいほど曲がりやすい -#define S_KP_HIGH 1.0f -#define S_KP_MEDIUM 1.0f -#define S_KP_LOW 1.0f -#define S_KP_DEFAULT_HIGH 1.0f - -#define S_KD_DEFAULT 1.0f //ラインセンサ微分成分。大きいほど急なラインずれに強くなる。 -#define S_KD_HIGH 1.0f -#define S_KD_MEDIUM 1.0f -#define S_KD_LOW 1.0f -#define S_KD_DEFAULT_HIGH 0.7f -//////////☆★☆★☆★☆★☆★////////////// - - - -//スイッチ状態の定義 -#define PUSH 0 //スイッチ押したときの状態 -#define PULL 1 //スイッチ離したときの状態 -//機体状態の定義 -#define STOP 0x80 //機体停止状態 -#define RUN_START 0x40 //スタートマーカ通過 -#define RUN_COURSE_LOUT 0x20 //左コースアウト状態 -#define RUN_COURSE_CENTER 0x18 //ライン中央走行状態 -#define RUN_COURSE_ROUT 0x04 //右コースアウト状態 -#define SECOND_RUN 0x02 //機体停止状態 -#define TUARD_RUN 0x01 //機体設定モード - +#include "tuning.h" +#include "flag.h" //デジタル入力オブジェクト定義 DigitalIn push_sw(D13); @@ -108,6 +49,8 @@ long long int Enc_Count_A=0,Enc_Count_B=0; //エンコーダパルス数。現在速度推定に使用する。 long long int Enc_A_Rotate=0,Enc_B_Rotate=0; //エンコーダパルス数。停止時の機体速度調整に使用。 long long int Stop_Distance=STOP_DISTANCE; //ストップ時の徐行→停止に使う +long long int Next_Marker_Distance=200000; //加減速走行時のマーカ間の距離を格納 +long long int Recent_Distance=0; //加減速走行時の次のマーカまでの距離を格納 /////↓エンコーダパルス数。コース記憶時のエンコーダパルスの蓄積に使用する。 long long int Memory_Enc_Count_A=0,Memory_Enc_Count_B=0; char MemoryA_Str[5]; //LCD表示用。左モータの走行距離格納 @@ -117,16 +60,14 @@ ////↓左右タイヤの走行距離格納。1走目のコース記憶処理に使用する。マーカ通過ごとにリセット。 long long int Distance_memory_A=0, Distance_memory_B=0; -long int S_Kp=S_KP_DEFAULT;////センサP成分 -long int S_Kd=S_KD_DEFAULT;////センサD成分 +long int S_Kp=S_KP_LOW;////センサP成分 +long int S_Kd=S_KD_LOW;////センサD成分 long long int Marker_Run_Distance=0; long int Speed_A=0, Speed_B=0; //機体の現在速度を格納 -long int Default_Speed = DEFAULT_SPEED; //1走目の標準速度 long int Low_Speed = LOW_SPEED; //2走目以降の低速 long int Medium_Speed = MEDIUM_SPEED; //2走目以降の中速 long int High_Speed = HIGH_SPEED; //2走目以降の高速 -long int Default_High_Speed = DEFAULT_HIGH_SPEED;//3走目の高速 char Speed_Str[5]; //LCD速度表示用文字列 long int Target_Speed_A=0,Target_Speed_B=0; //目標速度 long int Motor_A_Diff[2]={0,0}; //過去の速度偏差と現在の速度偏差を格納 @@ -146,22 +87,37 @@ int SG_Flag=0; //スタート・ゴールセンサがマーカを検知したことを示すフラグ int SG_Cnt=0; //スタート・ゴールセンサのマーカ通過数 int Cross_Flag=0; //交差点を通過したことを示すフラグ -long int Imaginary_Speed=0; //曲率演算にて求めた2走目以降の仮想走行速度 + +int Imaginary_Speed=0; //曲率演算にて求めた2走目以降の仮想走行速度 +int Next_Imaginary_Speed=0; long long int course_data[100][3]; //コース情報の記憶用配列マーカ数は行数分まで対応し、 //列情報は左タイヤ走行距離、右タイヤ走行距離、演算で求めた2走目走行速度を格納する。 int Row=0; //行情報を格納。マーカ通過ごとに加算し、走行終了後リセットされる。 int Marker_Cnt=0; +int Cross_Cnt=0; +int Disp_Cross_Cnt=0; void sensor_analog_read(){//ラインセンサの情報取得処理。 - S1_Data=s1.read(); - S2_Data=s2.read(); - S3_Data=s3.read(); - S4_Data=s4.read(); - S5_Data=s5.read(); - S6_Data=s6.read(); - S7_Data=s7.read(); - S8_Data=s8.read(); + if((Sensor_Digital&0x18)||(Cross_Flag==1)){//センサ中央検知もしくは交差点検知のとき + S1_Data=s1.read(); + S2_Data=0; //交差点通過中は急旋回しないようにする。 + S3_Data=s3.read()/S_K2; //交差点通過中は急カーブを控える + S4_Data=s4.read(); + S5_Data=s5.read(); + S6_Data=s6.read()/S_K2; //交差点通過中は急カーブを控える + S7_Data=0; //交差点通過中は急旋回しないようにする。 + S8_Data=s8.read(); + }else if(Cross_Flag==0){ + S1_Data=s1.read(); + S2_Data=s2.read(); + S3_Data=s3.read(); + S4_Data=s4.read(); + S5_Data=s5.read(); + S6_Data=s6.read(); + S7_Data=s7.read(); + S8_Data=s8.read(); + } } //8つのフォトリフレクタの入力を8ビットのデジタルパターンに変換。センサの状態をデジタルパターンで @@ -209,13 +165,13 @@ //機体がライン中央に位置するとき if(Sensor_Digital&RUN_COURSE_CENTER )Machine_Status|=RUN_COURSE_CENTER; else Machine_Status &= 0xE7;//ライン中央情報のマスク - if((Sensor_Digital==0x00)&&(Old_Sensor_Digital==0x40)){//左センサコースアウト時 + if((Sensor_Digital==0x00)&&(Old_Sensor_Digital==0x40)&&(Cross_Flag==0)){//左センサコースアウト時 Machine_Status|=RUN_COURSE_LOUT;//左コースアウト状態のビットをセット }else if((Machine_Status&RUN_COURSE_LOUT)&&(Sensor_Digital&RUN_COURSE_CENTER)){ //左コースアウト状態かつ機体がライン中央に復帰したとき Machine_Status &= 0xDF;//左コースアウト情報のみマスク } - if((Sensor_Digital==0x00)&&(Old_Sensor_Digital==0x02)){//右センサコースアウト時 + if((Sensor_Digital==0x00)&&(Old_Sensor_Digital==0x02)&&(Cross_Flag==0)){//右センサコースアウト時 Machine_Status|=RUN_COURSE_ROUT;//右コースアウト状態のビットをセット }else if((Machine_Status&RUN_COURSE_ROUT)&&(Sensor_Digital&RUN_COURSE_CENTER)){ //右コースアウト状態かつ機体がライン中央に復帰したとき @@ -238,11 +194,11 @@ if((((course_data[Row][0])>=(course_data[Row][1]*1.0f))&&((course_data[Row][0])<(course_data[Row][1]*HIGH_SPEED_SECTION))) || (((course_data[Row][0])>=(course_data[Row][1]*1.0f))&&((course_data[Row][0])<(course_data[Row][1]*HIGH_SPEED_SECTION)))){ Imaginary_Speed=High_Speed;//高速とする。 - }else if((((course_data[Row][0])>=(course_data[Row][1]*HIGH_SPEED_SECTION))&&((course_data[Row][0])<(course_data[Row][1]*MIDIUM_SPEED_SECTION))) - || (((course_data[Row][0])>=(course_data[Row][1]*HIGH_SPEED_SECTION))&&((course_data[Row][0])<(course_data[Row][1]*MIDIUM_SPEED_SECTION)))){ + }else if((((course_data[Row][0])>=(course_data[Row][1]*HIGH_SPEED_SECTION))&&((course_data[Row][0])<(course_data[Row][1]*MEDIUM_SPEED_SECTION))) + || (((course_data[Row][0])>=(course_data[Row][1]*HIGH_SPEED_SECTION))&&((course_data[Row][0])<(course_data[Row][1]*MEDIUM_SPEED_SECTION)))){ Imaginary_Speed=Medium_Speed;//中カーブは中速とする。 - }else if((((course_data[Row][0])>=(course_data[Row][1]*MIDIUM_SPEED_SECTION))&&((course_data[Row][0])<(course_data[Row][1]*LOW_SPEED_SECTION))) - || (((course_data[Row][0])>=(course_data[Row][1]*MIDIUM_SPEED_SECTION))&&((course_data[Row][0])<(course_data[Row][1]*LOW_SPEED_SECTION)))){ + }else if((((course_data[Row][0])>=(course_data[Row][1]*MEDIUM_SPEED_SECTION))&&((course_data[Row][0])<(course_data[Row][1]*LOW_SPEED_SECTION))) + || (((course_data[Row][0])>=(course_data[Row][1]*MEDIUM_SPEED_SECTION))&&((course_data[Row][0])<(course_data[Row][1]*LOW_SPEED_SECTION)))){ Imaginary_Speed=Low_Speed;//低速 } else{ @@ -251,38 +207,75 @@ course_data[Row][2]=Imaginary_Speed; //仮想の演算速度を格納 Memory_Enc_Count_A=0; //マーカ間の左タイヤエンコーダパルス数のクリア Memory_Enc_Count_B=0; //マーカ間の右タイヤエンコーダパルス数のクリア - Row++; //次のコース情報へ - + Row++; //次のコース情報へ } //2走目の加減速走行に使用。1走目で演算したマーカ間の仮想速度を機体目標速度に設定する。 -void second_speed_control(){ - if(course_data[Row][2]==Default_Speed){//標準速度区間のとき - S_Kp=S_KP_DEFAULT; - S_Kd=S_KD_DEFAULT; - }else if(course_data[Row][2]==Low_Speed){//低速走行区間のとき +void second_speed_control(void){ + Memory_Enc_Count_A=0; + Memory_Enc_Count_B=0; + + ++Row; + Next_Marker_Distance=(course_data[Row][0]+course_data[Row][1])/2; //次のマーカまでの距離を算出 + Next_Imaginary_Speed=course_data[Row+1][2]; //次のマーカ通過後の速度情報を取得 + if(course_data[Row+1][2]<Low_Speed){//登録されていない速度データだったとき + Next_Imaginary_Speed=Low_Speed; //標準速度にしておく + }else if(course_data[Row+1][2]>High_Speed){ + Next_Imaginary_Speed=High_Speed; // + } + + if(course_data[Row][2]==Low_Speed){ //標準速度区間のとき S_Kp=S_KP_LOW; - S_Kd=S_KD_LOW; + S_Kd=S_KD_LOW; }else if(course_data[Row][2]==Medium_Speed){//中速走行区間のとき S_Kp=S_KP_MEDIUM; S_Kd=S_KD_MEDIUM; - }else if(course_data[Row][2]==High_Speed){//高速走行区間のとき + }else if(course_data[Row][2]==High_Speed){ //高速走行区間のとき S_Kp=S_KP_HIGH; S_Kd=S_KD_HIGH; }else{// - S_Kp=S_KP_DEFAULT_HIGH; - S_Kd=S_KD_DEFAULT_HIGH; + S_Kp=S_KP_LOW; + S_Kd=S_KD_LOW; + } + + if(course_data[Row][2]<Low_Speed){//登録されていない速度データだったとき + Target_Speed_A=Low_Speed;//安全のため標準速度にしておく + Target_Speed_B=Low_Speed; + }else if(course_data[Row][2]>High_Speed){ + Target_Speed_A=High_Speed; + Target_Speed_B=High_Speed; + }else{ + Target_Speed_A=course_data[Row][2];//記憶走行で演算した仮想速度を使う + Target_Speed_B=course_data[Row][2]; + } +} +void second_breaking(){ + Recent_Distance=Next_Marker_Distance + -(((Memory_Enc_Count_A*PULSE_TO_UM)+(Memory_Enc_Count_B*PULSE_TO_UM))/2); + + //現在速度がハイスピードで次のコースが急カーブであり、残り距離が---だったとき + if((course_data[Row][2]==High_Speed)&&(Next_Imaginary_Speed==Low_Speed) + &&(Recent_Distance<HL_BREAK_DISANCE)){ + Target_Speed_A=Low_Speed; + Target_Speed_B=Low_Speed; + } + //現在速度がハイスピードで次のコースが中カーブであり、残り距離が---だったとき + else if((course_data[Row][2]==High_Speed)&&(Next_Imaginary_Speed==Medium_Speed) + &&(Recent_Distance<HM_BREAK_DISANCE)){ + Target_Speed_A=Medium_Speed; + Target_Speed_B=Medium_Speed; + } + //現在速度が中間速度で次のコースが急カーブであり、残り距離が---だったとき + else if((course_data[Row][2]==High_Speed)&&(Next_Imaginary_Speed==Low_Speed) + &&(Recent_Distance<ML_BREAK_DISANCE)){ + Target_Speed_A=Low_Speed; + Target_Speed_B=Low_Speed; } - Target_Speed_A=course_data[Row][2];//記憶走行で演算した仮想速度を使う - Target_Speed_B=course_data[Row][2]; - Row++; //次のコース情報へ } - /////LCD表示用関数。機体の現在状態を表示する。 void display_print(void){ - char lcd_top_str[8],lcd_low_str[8]; //lcd表示用配列を用意 各行分 - char stop_or_go; //機体停止状態'-'か走行状態'G'を格納 + char lcd_top_str[9],lcd_low_str[9]; //lcd表示用配列を用意 各行分 //////表示クリア lcd.locate(0,0); lcd.print(" "); @@ -290,28 +283,19 @@ lcd.print(" "); ////////0行目の表示////////////////////////////// - if(Machine_Status&STOP){ //機体停止状態のとき - stop_or_go='-'; - }else if(!(Machine_Status&STOP)){ //機体走行状態のとき - stop_or_go='G'; - } - sprintf(lcd_top_str,"%d:%c %03d",Sw_Cnt,stop_or_go,Marker_Cnt);//0行の表示文字の整理 + sprintf(lcd_top_str,"%d:%d:%03d",Sw_Cnt,Disp_Cross_Cnt,Marker_Cnt);//0行の表示文字の整理 lcd.locate(0,0); //表示位置を0行目にセット lcd.print(lcd_top_str); //表示 ////////1行目の表示///////////////////////////// - if(Sw_Cnt<=2){ //1走目か2走目のとき - sprintf(lcd_low_str,"SPD:%04d",Default_Speed); //1行の表示文字の整理 - }else sprintf(lcd_low_str,"SPD:%04d",Default_High_Speed); //3走目のとき + sprintf(lcd_low_str,"SPD:%04d",Low_Speed); //1行の表示文字の整理 lcd.locate(0,1); //表示位置を1行目にセット lcd.print(lcd_low_str); //表示 } - //タイマ割り込み1[ms]周期 -void timer_interrupt(){ - +void timer_interrupt(){ //ラインセンサ情報取得 sensor_analog_read(); sensor_digital_read(); @@ -320,13 +304,11 @@ Machine_Status_Set(); //交差点の認識 - if(Sensor_Cnt>=CROSS_JUDGE )Cross_Flag=1;//ラインセンサ4つ以上検知状態の時は交差点を示す。 - + if((Sensor_Cnt>=CROSS_JUDGE)||(Sensor_Digital==0x42))Cross_Flag=1;//ラインセンサ4つ以上検知状態の時は交差点を示す。 //エンコーダパルス数の取得 Enc_Count_A=encoder_a.Get(); Enc_Count_B=-encoder_b.Get(); - //各種マーカの検知 Old_Marker_Pass_Flag=Marker_Pass_Flag;//過去のフラグを退避 if(Sensor_Digital&0x81){ //マーカセンサ検知時 @@ -335,12 +317,11 @@ if(Sensor_Digital&0x01)SG_Flag=1; //スタートゴールセンサの検知 if((Corner_Flag==1)&&(SG_Flag==1));//交差点通過中。何もしない }else Marker_Pass_Flag=0;//マーカ通過終了 - //マーカ通過後、マーカ種類判別 if((Old_Marker_Pass_Flag==1)&&(Marker_Pass_Flag==0)){//マーカ通過後 if(Marker_Run_Distance>MARKER_WIDTH){ //マーカ幅がもっともらしいとき - if(Cross_Flag==1); //交差点の時は何もしない + if((SG_Flag==1)&&(Corner_Flag==1)&&(Cross_Flag==1))Cross_Cnt++; //交差点数の更新 else if((SG_Flag==1)&&(SG_Cnt==0)){ //ゴールスタートマーカの時⇒1回目 SG_Cnt=1; if(Sw_Cnt==1){ //1走目のとき @@ -348,17 +329,19 @@ }else if(Sw_Cnt==2){ //2走目のとき second_speed_control(); //記憶情報から目標速度を設定する処理 }else{//3走目は定速で高速走行 - Target_Speed_A=Default_High_Speed; - Target_Speed_B=Default_High_Speed; + Target_Speed_A=Low_Speed; + Target_Speed_B=Low_Speed; } }else if((SG_Flag==1)&&(SG_Cnt==1)){//ゴールスタートマーカの時⇒2回目 - Marker_Cnt=Row; //マーカカウント数をLCD表示用に退避させる + Marker_Cnt=Row; //マーカカウント数をLCD表示用に退避させる + Disp_Cross_Cnt=Cross_Cnt; //ディスプレイ表示用に交差点数を退避させる if(Sw_Cnt==1){ corner_curvature(); //曲率に応じた速度推定処理 }else if(Sw_Cnt==2){ //2走目のとき 何もしない }else; //3走目のとき 何もしない Machine_Status|=STOP; //機体停止状態へ - Row=0; //コース記憶用配列の行情報[通過マーカ情報]の初期化 + Row=0; //コース記憶用配列の行情報[通過マーカ情報]の初期化 + Cross_Cnt=0; SG_Cnt=0; //スタート・ゴールマーカ情報のリセット }else if(Corner_Flag==1){ //コーナマーカの時 if(Sw_Cnt==1){ //1走目のとき @@ -366,8 +349,8 @@ }else if(Sw_Cnt==2){ //2走目のとき second_speed_control(); //記憶情報から目標速度を設定する処理 へ }else{//3走目は定速で高速走行 - Target_Speed_A=Default_High_Speed; - Target_Speed_B=Default_High_Speed; + Target_Speed_A=Low_Speed; + Target_Speed_B=Low_Speed; } } }else;//マーカではなく、誤検知だった場合。何もしない @@ -427,11 +410,7 @@ }else if(Machine_Status&RUN_COURSE_ROUT){ //右端センサ振り切れた時 motor_a=-(TURN_POWER); //右旋回 motor_b=-(-TURN_POWER); - }else if(Cross_Flag==1){//交差点通過中 - motor_a=-0.3;//交差点なので控えめの速度で直進 - motor_b=-0.3; - } - else{ + }else{ motor_a=-Motor_A_Pwm; motor_b=-Motor_B_Pwm; } @@ -465,7 +444,9 @@ //////コース記憶に使用するエンコーダパルス数の蓄積処理 Memory_Enc_Count_A+=Enc_Count_A; Memory_Enc_Count_B+=Enc_Count_B; - + + + if(Sw_Cnt==2)second_breaking(); //2走目の場合はブレーキングシステムを使用する。 //割込み終了時の各種パラメータリセット処理 //エンコーダ関連情報のリセット encoder_a.Set(0);//エンコーダクラスのパルス数情報のリセット @@ -487,8 +468,7 @@ display_print(); //LCDに現在の機体状態を表示 if(Machine_Status&STOP){//機体停止状態の時 - if(Sw_Cnt<=2)Default_Speed=DEFAULT_SPEED+(Enc_B_Rotate/16); //1,2走目標準速度調整 - else if(Sw_Cnt>2)Default_High_Speed=DEFAULT_HIGH_SPEED+(Enc_B_Rotate/16); //3走目 + Low_Speed=LOW_SPEED+(Enc_B_Rotate/8); //標準速度調整 } if((Old_Sw_Ptn==PULL)&&(Sw_Ptn==PUSH)){//スイッチが押された瞬間 @@ -506,20 +486,21 @@ SG_Cnt=0; //スタート・ゴールマーカ情報のリセット Marker_Run_Distance=0;//マーカ通過距離情報リセット if(Sw_Cnt==1){ //1走目のとき - S_Kp=S_KP_DEFAULT; - S_Kd=S_KD_DEFAULT; - Target_Speed_A=Default_Speed; - Target_Speed_B=Default_Speed; + S_Kp=S_KP_LOW; + S_Kd=S_KD_LOW; + Target_Speed_A=Low_Speed; + Target_Speed_B=Low_Speed; }else if(Sw_Cnt==2){ //2走目のとき - S_Kp=S_KP_DEFAULT; - S_Kd=S_KD_DEFAULT; - second_speed_control(); //記憶情報から目標速度を設定する処理 + S_Kp=S_KP_LOW; + S_Kd=S_KD_LOW; + Target_Speed_A=Low_Speed; + Target_Speed_B=Low_Speed; } else{ //3走目以降のとき S_Kp=S_KP_DEFAULT_HIGH; S_Kd=S_KD_DEFAULT_HIGH; - Target_Speed_A=Default_High_Speed; - Target_Speed_B=Default_High_Speed; + Target_Speed_A=Low_Speed; + Target_Speed_B=Low_Speed; } Stop_Distance=0; Machine_Status&=0x7F;//ストップ状態解除 @@ -530,6 +511,7 @@ SG_Flag=0; Cross_Flag=0; Row=0; //コース記憶用配列の行情報[通過マーカ情報]の初期化 + Cross_Cnt=0; SG_Cnt=0; //スタート・ゴールマーカ情報のリセット Marker_Run_Distance=0;//マーカ通過距離情報リセット Machine_Status |= STOP;//機体停止状態にする。