ドローン用計測制御基板の作り方 vol.1 ハードウェア編 p.32掲載 オートパイロットの基本機能
Dependencies: mbed MPU6050_alter SDFileSystem
main.cpp
- Committer:
- Joeatsumi
- Date:
- 2019-12-30
- Revision:
- 0:ff469cc9ac07
File content as of revision 0:ff469cc9ac07:
//================================================== //Auto pilot(prototype) // //MPU board: mbed LPC1768 //Multiplexer TC74HC157AP //Accelerometer +Gyro sensor : GY-521 //2019/11/17 A.Toda //================================================== #include "mbed.h" #include "MPU6050.h" #include "SDFileSystem.h" //================================================== #define RAD_TO_DEG 57.2957795f // 180 / π #define MAX_MEAN_COUNTER 100 #define ACC_X 1.3//offset of x-axi accelerometer #define THRESHOLD_PWM 0.0015 #define SERVO_PERIOD 0.020 //================================================== //Port Setting SDFileSystem sd(p5, p6, p7, p8, "sd");//pins for sd slot MPU6050 mpu(p9, p10); //Accelerometer + Gyro //(SDA,SCLK) DigitalIn logging_terminater(p16); InterruptIn reading_port(p18); DigitalOut mux_switch(p19); PwmOut ELE(p21); Serial pc(USBTX, USBRX); //UART //Pointer of sd card FILE *fp; //================================================== //Accelerometer and gyro data //================================================== double acc[3]; //variables for accelerometer double gyro[3]; //variables for gyro double offset_gyro_x=0.0; double offset_gyro_y=0.0; double sum_gyro_x=0.0; double sum_gyro_y=0.0; double threshold_acc,threshold_acc_ini; //================================================== //Atitude data //================================================== double roll_and_pitch_acc[2];//atitude from acceleromter double roll_and_pitch[2];//atitude from gyro and acceleromter //================================================== //Timer valiables //================================================== Timer ch_time;//timer for calculate pulse width Timer passed_time;//timer for calculate atitude double measured_pre_pulse=0.0; double measured_pulse=0.0; double time_new; double time_old; double pulse_width_ele,deflection_ele; //================================================= //Functions for rising and falind edge interrution //================================================= //rise edge void rising_edge(){ ch_time.reset();//reset timer counter measured_pre_pulse=ch_time.read(); } //falling edge void falling_edge(){ measured_pre_pulse=(ch_time.read()-measured_pre_pulse); //pc.printf("The pulse width=%f\r\n",measured_pre_pulse); if(measured_pre_pulse>THRESHOLD_PWM){ mux_switch=1; }else{ mux_switch=0; } } //terminate logging void end_of_log(){ //flipper.detach(); fclose(fp);//close "Atitude_angles.csv" pc.printf("Logging was terminated."); } //================================================== //Gyro and accelerometer functions //================================================== //get data void aquisition_sensor_values(double *a,double *g){ float ac[3],gy[3]; mpu.getAccelero(ac);//get acceleration (Accelerometer) //x_axis acc[0] //y_axis acc[1] //z_axis acc[2] mpu.getGyro(gy); //get rate of angle(Gyro) //x_axis gyro[0] //y_axis gyro[1] //z_axis gyro[2] //Invertion for direction of Accelerometer axis ac[0]*=(-1.0); ac[0]+=ACC_X; ac[2]*=(-1.0); //Unit convertion of rate of angle(radian to degree) gy[0]*=RAD_TO_DEG; gy[0]*=(-1.0); gy[1]*=RAD_TO_DEG; gy[2]*=RAD_TO_DEG; gy[2]*=(-1.0); for(int i=0;i<3;i++){ a[i]=double(ac[i]); g[i]=double(gy[i]); } g[0]-=offset_gyro_x;//offset rejection g[1]-=offset_gyro_y;//offset rejection return; } //calculate offset of gyro void offset_calculation_for_gyro(){ //Accelerometer and gyro setting mpu.setAcceleroRange(0);//acceleration range is +-2G mpu.setGyroRange(1);//gyro rate is +-500degree per second(dps) //calculate offset of gyro for(int mean_counter=0; mean_counter<MAX_MEAN_COUNTER ;mean_counter++){ aquisition_sensor_values(acc,gyro); sum_gyro_x+=gyro[0]; sum_gyro_y+=gyro[1]; wait(0.01); } offset_gyro_x=sum_gyro_x/MAX_MEAN_COUNTER; offset_gyro_y=sum_gyro_y/MAX_MEAN_COUNTER; return; } //atitude calculation from acceleromter void atitude_estimation_from_accelerometer(double *a,double *roll_and_pitch){ roll_and_pitch[0] = atan(a[1]/a[2])*RAD_TO_DEG;//roll roll_and_pitch[1] = atan(a[0]/sqrt( (a[1]*a[1]+a[2]*a[2]) ) )*RAD_TO_DEG;//pitch return; } //atitude calculation void atitude_update(){ aquisition_sensor_values(acc,gyro); roll_and_pitch[0]+=gyro[0]*(time_new-time_old); roll_and_pitch[1]+=gyro[1]*(time_new-time_old); threshold_acc=sqrt(acc[0]*acc[0]+acc[1]*acc[1]+acc[2]*acc[2]); if((threshold_acc>=0.9*threshold_acc_ini) &&(threshold_acc<=1.1*threshold_acc_ini)){ atitude_estimation_from_accelerometer(acc,roll_and_pitch_acc); roll_and_pitch[0] = 0.98*roll_and_pitch[0] + 0.02*roll_and_pitch_acc[0]; roll_and_pitch[1] = 0.98*roll_and_pitch[1] + 0.02*roll_and_pitch_acc[1]; }else{} //pc.printf("roll=%f pitch=%f\r\n",roll_and_pitch[0],roll_and_pitch[1]); fprintf(fp, "%f,%f,%f\r\n",time_new,roll_and_pitch[0],roll_and_pitch[1]); return; } double deflection_of_ele(double pitch){ double add_deflection=(pitch*6.0/1000.0)/1000.0; return add_deflection; } //================================================== //Main //================================================== int main() { //UART initialization pc.baud(115200); //define servo period ELE.period(SERVO_PERIOD); // servo requires a 20ms period pulse_width_ele=0.0015; //timer starts ch_time.start(); passed_time.start(); time_old=0.0; //declare interrupitons reading_port.rise(rising_edge); reading_port.fall(falling_edge); mux_switch=0;//set circit as manual mode //gyro and accelerometer initialization offset_calculation_for_gyro(); //determine initilal atitude aquisition_sensor_values(acc,gyro); atitude_estimation_from_accelerometer(acc,roll_and_pitch); threshold_acc_ini=sqrt(acc[0]*acc[0]+acc[1]*acc[1]+acc[2]*acc[2]); //create folder(sd) in sd card mkdir("/sd", 0777); //create "Atitude_angles.csv" in folder(sd) fp = fopen("/sd/Atitude_angles.csv", "w"); if(fp == NULL) { error("Could not open file for write\n"); } //Logging starts pc.printf("Logging starts."); //while while(1){ if(logging_terminater==1){ end_of_log(); }else{} time_new=passed_time.read(); atitude_update(); time_old=time_new; //determine deflectionangle of elevator /* ここから先でサーボの操舵角を姿勢角に応じて変化させる。関数deflection_of_ele はpitch角に応じてサーボのパルス幅を返す関数である。 もし制御則を自ら実装できるのであれば、姿勢角や角速度を引数としてサーボパルス幅を 戻り値とする関数を作成し、機体を理論的に制御する事が可能である。 */ deflection_ele=deflection_of_ele(roll_and_pitch[1]); ELE.pulsewidth(THRESHOLD_PWM+deflection_ele); pc.printf("%f,%f\r\n",THRESHOLD_PWM+deflection_ele,roll_and_pitch[1]); wait(0.002); }//while ends }//main ends