Added one task
Dependencies: mbed
main.cpp
- Committer:
- PicYusuke
- Date:
- 2017-05-26
- Revision:
- 0:fb4269aa5fb4
File content as of revision 0:fb4269aa5fb4:
#include "mbed.h" #include "gpio.h" #include "robot.h" #include "GP2Y0E03.h" #include "MCP3208.h" #include "L3GD20.h" #define ERROR (-1) #define SUCCESS 0 //#define L3GD20_TEST //#define GP2Y0E03_TEST //#define MCP3208_TEST //#define LBR127_TEST /*---------RCサーボ制御用--------*/ float servo_pulse = 0.001f; //RCサーボパルス幅[s] uint32_t servo_state = 0; //サーボピン状態 /*-----------------------------*/ /*-----------------ラインセンサ--------------------*/ float line_pos[2] = {0.0f, 0.0f}; uint32_t intersection = 0; //交差点検知 /*------------------------------------------------*/ /*---------状態変数----------*/ float v_tr = 0.0f; //並進方向電圧, unit: V float theta = 0.0f; //姿勢角, unit: degree float omega_d = 0.0f; //目標角速度, unit: degree/s /*--------------------------*/ /*-----------------------------*/ float ts = 0.001f; //制御周期 uint32_t sequence = 0; //タスク管理変数 uint32_t error_seq = 0xFF; //エラーを起こしているタスク番号 int32_t (*Task_Fptr[10])(void); //タスク管理用関数ポインタ /*-----------------------------*/ /*-----制御器-----*/ PID_Struct trace_pid; //ライントレース用 PID_Struct gyro_pid; //ジャイロによるオドメトリ用 PID_Struct manual_control; //手動モータ制御用 PID_Struct *current_pid_ptr; //現在接続されている制御器 /*----------------*/ /*---------各タスク関数--------*/ //ロボットの動作をシーケンシャルに記述する //各タスク関数内ではフィードバック制御則へのアクセス原則禁止 int32_t Task0(void); int32_t Task1(void); int32_t Task2(void); int32_t Task3(void); int32_t Task4(void); int32_t Task5(void); int32_t Task6(void); int32_t Task7(void); int32_t Task8(void); int32_t Task9(void); /*---------------------------*/ void Turn_90deg(int32_t); void Turn_180deg(int32_t); void Accelerate(float); void Decelerate(); void Stop(); int main() { uint32_t i; /*Peripheral initialization*/ //GPIO_Init(); SPI_Init(); /*-----各種デバイス初期化----*/ L3GD20_Init(); MCP3208_Init(); /*-------------------------*/ /*------フィードバックコントローラ-------*/ PID_Struct_Init(&trace_pid, 1.1, 20.0, 0.0); //PID_Struct_Init(&gyro_pid, 0.015, 0.0, 0.0); PID_Struct_Init(&gyro_pid, 0.02, 0.0, 0.0); current_pid_ptr = &manual_control; /*-----------------------------------*/ TIM_Init(); //タイマスタート /*-------------------------*/ /*-----関数ポインタ設定------*/ Task_Fptr[0] = Task0; Task_Fptr[1] = Task1; Task_Fptr[2] = Task2; Task_Fptr[3] = Task3; Task_Fptr[4] = Task4; Task_Fptr[5] = Task5; Task_Fptr[6] = Task6; Task_Fptr[7] = Task7; Task_Fptr[8] = Task8; Task_Fptr[9] = Task9; /*-------------------------*/ while(1) { if(Task_Fptr[sequence]() == ERROR) //タスク呼び出し, エラーチェック { error_seq = sequence; //エラーを起こしているタスク番号を取得 } sequence ++; /* if(sequence == 1) { sequence = 3; } */ } } int32_t Task0(void) { /* if() { return ERROR; } */ servo_pulse = 0.0021f; //アームを折りたたむ wait(0.5f); /*-----最下点までリフトを移動-----*/ Put_Vm_Lift(-0.8f); //リフト下降 wait(2.0f); Put_Vm_Lift(0.0f); //リフト停止 /*-----------------------------*/ /*----リフトのリポジショニング----*/ Put_Vm_Lift(1.0f); //リフト上昇(どん兵衛用) wait(0.8f); Put_Vm_Lift(0.0f); //リフト停止 /*-----------------------------*/ /*--------------------スタート待機-----------------------*/ while(ain_cup > 0.5f) //カップ検出センサが反応するまで待機 { printf("cup = %f\n", (float)ain_cup); } servo_pulse = 0.001f; //アームを展開 wait(0.3f); /*-----------------------------------------------------*/ /* while(1) { HAL_Delay(10); printf("pos = %f\n", line_pos[0]); } */ return 0; } int32_t Task1(void) { uint32_t i; float v = 0.0f; /* if() { return ERROR; } */ /*-------------------ライントレース--------------------*/ current_pid_ptr = &trace_pid; //制御器変更 Accelerate(2.0f); //加速 for(i = 0; i < 2; i ++) //1-2回目の交差点はスキップ { while(!intersection) //一回目の交差点検出はスキップ { printf("running...\n"); } while(intersection) //一回目の交差点通過を待つ { printf("running...\n"); } } /*-----------------------------------------------------*/ return 0; } int32_t Task2(void) //3本目の交差点を左折 { /* if() { return ERROR; } */ while(!intersection) //3回目の交差点検出まで直進 { printf("running...\n"); } while(intersection) //3回目の交差点通過を待つ { printf("running...\n"); } wait(0.4f); Stop(); //停止 Turn_90deg(1); //左90度旋回 return 0; } int32_t Task3(void) //横道を直進し、どん兵衛を回収、180度回転 { uint32_t i; float v = 0.0f; /* if() { return ERROR; } */ /*-------------------ライントレース--------------------*/ current_pid_ptr = &trace_pid; //制御器変更 Accelerate(1.0f); //加速 /*-----------------------------------------------------*/ #if 0 //本来はここでカップを検出するまで前進する wait(1.3f); #endif #if 1 while(ain_cup > 0.6f) //カップ検出まで前進 { printf("waiting...\n"); } wait(0.05f); Stop(); //停止 servo_pulse = 0.0021f; //カップ把持 wait(1.0f); Put_Vm_Lift(1.5f); //リフト上昇 wait(0.8f); Put_Vm_Lift(0.0f); //リフト停止 #endif current_pid_ptr = &trace_pid; //制御器変更 Accelerate(1.5f); //加速 wait(0.5f); Stop(); //停止 Turn_180deg(1); //左180度旋回 return 0; } int32_t Task4(void) //カップ回収後、メインストリートに戻る { uint32_t i; float v = 0.0f; /* if() { return ERROR; } */ /*-------------------ライントレース--------------------*/ current_pid_ptr = &trace_pid; //制御器変更 Accelerate(1.5f); //加速 /*-----------------------------------------------------*/ while(!intersection) //交差点検出まで直進 { printf("running...\n"); } while(intersection) //交差点通過を待つ { printf("running...\n"); } wait(0.6f); Stop(); Turn_90deg(1); //左90度旋回 return 0; } int32_t Task5(void) //カップ回収後のメインストリート走行+カップ棚置き { uint32_t i; float v = 0.0f; /* if() { return ERROR; } */ /*-------------------ライントレース--------------------*/ current_pid_ptr = &trace_pid; //制御器変更 Accelerate(2.0f); //加速 /*-----------------------------------------------------*/ while(ain_cup > 0.7f) //棚検出まで前進 { printf("waiting...\n"); } Stop(); servo_pulse = 0.001f; //カップ解放 wait(0.5f); /*----------ジャイロを使って後退--------------*/ current_pid_ptr = &gyro_pid; //制御器変更 Accelerate(-1.5f); //加速 wait(0.6f); Stop(); /*------------------------------------------*/ Turn_180deg(1); //左180度旋回 /*-----最下点までリフトを移動-----*/ Put_Vm_Lift(-0.8f); //リフト下降 wait(2.5f); Put_Vm_Lift(0.0f); //リフト停止 /*-----------------------------*/ /*----リフトのリポジショニング----*/ Put_Vm_Lift(1.0f); //リフト上昇(UFO用) wait(0.35f); Put_Vm_Lift(0.0f); //リフト停止 /*-----------------------------*/ return 0; } int32_t Task6(void) //4本目の交差点を棚側から左折 { uint32_t i; float v = 0; /* if() { return ERROR; } */ /*-------------------ライントレース--------------------*/ current_pid_ptr = &trace_pid; //制御器変更 Accelerate(1.5f); //加速 /*-----------------------------------------------------*/ while(!intersection) //交差点検出まで直進 { printf("running...\n"); } while(intersection) //交差点通過を待つ { printf("running...\n"); } wait(0.6f); Stop(); //停止 Turn_90deg(1); //左90度旋回 return 0; } int32_t Task7(void) //横道を直進し、UFOを回収、180度回転 { /*-------------------ライントレース--------------------*/ current_pid_ptr = &trace_pid; //制御器変更 Accelerate(1.0f); //加速 /*-----------------------------------------------------*/ while(ain_cup > 0.6f) //カップ検出まで前進 { printf("waiting...\n"); } wait(0.05f); Stop(); //停止 servo_pulse = 0.0021f; //カップ把持 wait(1.0f); Put_Vm_Lift(1.5f); //リフト上昇 wait(0.8f); Put_Vm_Lift(0.0f); //リフト停止 current_pid_ptr = &trace_pid; //制御器変更 Accelerate(1.5f); //加速 wait(0.5f); Stop(); //停止 Turn_180deg(1); //左180度旋回 } int32_t Task8(void) //棚左側にUFOを置くために、位置合わせ { uint32_t i; float v = 0; /* if() { return ERROR; } */ /*-------------------ライントレース--------------------*/ current_pid_ptr = &trace_pid; //制御器変更 Accelerate(1.5f); //加速 /*-----------------------------------------------------*/ /*---------------1回目の交差点-----------------*/ while(!intersection) //交差点検出まで直進 { printf("running...\n"); } while(intersection) //交差点通過を待つ { printf("running...\n"); } wait(2.5f); //棚左側とカップの位置を合わせるためのパラメータ /*--------------------------------------------*/ Stop(); Turn_90deg(-1); //右90度旋回 return 0; } int32_t Task9(void) //ジャイロを使って棚まで接近、UFOを置く { uint32_t i; float v = 0; /* if() { return ERROR; } */ /*----------ジャイロを使って前進--------------*/ current_pid_ptr = &gyro_pid; //制御器変更 Accelerate(1.5f); //加速 /*------------------------------------------*/ while(ain_cup > 0.7f) //棚検出まで前進 { printf("waiting...\n"); } Stop(); servo_pulse = 0.001f; //カップ解放 wait(0.5f); while(1) { printf("Tasks completed\n"); } return 0; } #if 0 int32_t Task8(void) //棚左側にUFOを置くために、位置合わせ { uint32_t i; float v = 0; /* if() { return ERROR; } */ /*-------------------ライントレース--------------------*/ current_pid_ptr = &trace_pid; //制御器変更 Accelerate(2.0f); //加速 for(i = 0; i < 3; i ++) //1-3回目の交差点はスキップ { while(!intersection) //一回目の交差点検出はスキップ { printf("running...\n"); } while(intersection) //一回目の交差点通過を待つ { printf("running...\n"); } } /*-----------------------------------------------------*/ /*---------------4回目の交差点-----------------*/ while(!intersection) //交差点検出まで直進 { printf("running...\n"); } while(intersection) //交差点通過を待つ { printf("running...\n"); } wait(1.5f); /*--------------------------------------------*/ Stop(); return 0; } int32_t Task9(void) { uint32_t i; float v = 0; /* if() { return ERROR; } */ while(1) { printf("Tasks completed\n"); } return 0; } #endif void Turn_90deg(int32_t dir) { uint32_t i; float v = 0.0f; float sign = 1.0f; if(dir == 1) //回転方向 { sign = 1.0f; } else if(dir == -1) { sign = -1.0f; } theta = 0.0f; //角度初期化 /*--------台形加速(角度)---------*/ for(i = 0; i < 10; i ++) { v += 0.15f; Put_Vm_L(-sign * v); //回転 Put_Vm_R(sign * v); wait(0.05f); } /*-----------------------------*/ if(dir == 1) { while(theta < 80.0f) { printf("Turning...\n"); } } else if(dir == -1) { while(theta > -80.0f) { printf("Turning...\n"); } } Put_Vm_L(0.0f); //停止 Put_Vm_R(0.0f); wait(0.5f); } void Turn_180deg(int32_t dir) { uint32_t i; float v = 0.0f; float sign = 1.0f; if(dir == 1) //回転方向 { sign = 1.0f; } else if(dir == -1) { sign = -1.0f; } theta = 0.0f; //角度初期化 /*--------台形加速(角度)---------*/ for(i = 0; i < 10; i ++) { v += 0.15f; Put_Vm_L(-sign * v); //回転 Put_Vm_R(sign * v); wait(0.05f); } /*-----------------------------*/ while(theta < 170.0f) { printf("Turning...\n"); } Put_Vm_L(0.0f); //停止 Put_Vm_R(0.0f); wait(0.5f); } void Accelerate(float v_desired) //v_desired[V]まで緩やかに加速 { uint32_t i; float v = 0.0f; float v_step = v_desired / 10.0f; //単位速度 for(i = 0; i < 10; i ++) { v += v_step; v_tr = v; wait(0.05f); } } void Decelerate() //緩やかに減速、停止 { uint32_t i; float v = 0.0f; float v_step = -v_tr / 10.0f; for(i = 0; i < 10; i ++) { v += v_step; v_tr = v; wait(0.05f); } v_tr = 0.0f; //確実に停止 wait(0.1f); } void Stop() //急激に減速、停止 { current_pid_ptr = &manual_control; //制御OFF Put_Vm_L(0.0f); Put_Vm_R(0.0f); wait(0.5f); } void Flip1_Callback() //RCサーボ制御用割り込み関数 { switch(servo_state) { case 0: flipper1.attach(&Flip1_Callback, servo_pulse); servo = 1; servo_state ++; break; case 1: flipper1.attach(&Flip1_Callback, 0.01f - servo_pulse); servo = 0; servo_state ++; break; default: servo_state = 0; break; } } void Flip2_Callback() //フィードバック制御用割り込み関数 { int32_t i; uint32_t adres_max = 0; uint32_t adres_min = 65535; uint32_t adres_mid = 0; int32_t pos_int = 0; float omega = 0.0f; //unit: deg/s float vm_L, vm_R; //unit: V /*-----------------センサ読み取り-----------------*/ //MCP3208_Read(0); MCP3208_Read(1); MCP3208_Read(2); MCP3208_Read(3); MCP3208_Read(4); MCP3208_Read(5); L3GD20_Read(); /*-----------------------------------------------*/ /*---------------最大最小値を求める----------------*/ for(i = 0; i < 5; i ++) { mcp3208.adres[i+1] = 4095 - mcp3208.adres[i+1]; //ADCの出力とラインの色に合わせて反転/非反転 if(adres_min > mcp3208.adres[i+1]) adres_min = mcp3208.adres[i+1]; if(adres_max < mcp3208.adres[i+1]) adres_max = mcp3208.adres[i+1]; } adres_mid = (adres_max + adres_min) / 2; /*-----------------------------------------------*/ if(adres_max - adres_min > 200) { line_pos[0] = 0.0f; for(i = 0; i < 5; i ++) { pos_int += (i+1)*(mcp3208.adres[i+1] - adres_min); } line_pos[0] = ((float)pos_int); line_pos[0] = line_pos[0] / (mcp3208.adres[1]+mcp3208.adres[2]+mcp3208.adres[3]+mcp3208.adres[4]+mcp3208.adres[5]-5*adres_min) - 3.0f; } else { line_pos[0] = 0.0f; } /*-------------------交差点検出-------------------*/ if((mcp3208.adres[1] > adres_mid) && (mcp3208.adres[5] > adres_mid)) { intersection = 1; } else if((mcp3208.adres[1] < adres_mid) && (mcp3208.adres[5] < adres_mid)) { intersection = 0; } /*-----------------------------------------------*/ /*---------------フィルタ----------------*/ /*--------------------------------------*/ /*-----------ジャイロ角速度取得-----------*/ omega = (float)l3gd20.z * 0.07f; theta += omega * ts; /*--------------------------------------*/ /*------------------制御則-----------------*/ if(current_pid_ptr == &trace_pid) //ライントレース { //vm_R = PD_Control(current_pid_ptr, omega, 10.0f * line_pos[0]); vm_R = PD_Control(current_pid_ptr, -line_pos[0], 0.0f); vm_L = -vm_R; vm_L += v_tr; vm_R += v_tr; } else if(current_pid_ptr == &gyro_pid) { vm_R = PD_Control(current_pid_ptr, omega, omega_d); vm_L = -vm_R; vm_L += v_tr; vm_R += v_tr; } else { vm_L = 0.0f; vm_R = 0.0f; } if(current_pid_ptr == &manual_control) { //手動でモータ電圧を管理している場合 } else { Put_Vm_L(vm_L); //モータへ電圧印加 Put_Vm_R(vm_R); } /*----------------------------------------*/ } void Flip3_Callback() { } void PinIntrrpt1_Callback() { } void PinIntrrpt2_Callback() { }