- #include <I2Cdev.h>
- #include <MPU6050.h>
- #include <Wire.h>
- //=============mpu6050 declarations===========
- MPU6050 accelgyro;
- static double Gx_offset = -1.46;//soldered as LENGBEI
- static double Gy_offset = -0.07;
- static double Ax_offset = -0.21;
- static double Ay_offset = -1.7;
- int16_t ax,ay,az;
- int16_t gx,gy,gz;//raw data from sensors
- double aax,aay,aaz,ggx,ggy,ggz;
- double Ax,Ay,Az;//单位 g(9.8m/s^2)
- double Gx,Gy,Gz;//单位 °/s
- //=================mesure declarations=============
- double estima_X = 0.2;
- double estima_Y = 0.2;
- double es_GX;
- double es_GY;
- double fusion_angle_Y;
- double fusion_angle_X;
- double now_error_X, last_error_X, error_diff_X, error_int_X;
- double now_error_Y, last_error_Y, error_diff_Y, error_int_Y;
- double Angel_accX,Angel_accY,Angel_accZ;
-
- //===============control & accuracy declarations========
- double basic_power = 5; // z acc balancing, need calibration each time
- double rot_power_X, rot_power_Y;
- double orientX=0;
- double orientY=0;
- long tic_1,tic_2,tic_3, duration;
- int time_span_milli =20;
- float time_span =0.02;
- int moterPins[4];
- int moterPowers[4];
-
- void set_Motors(){
- pinMode(11,OUTPUT);
- pinMode(10,OUTPUT);
- pinMode(9,OUTPUT);
- pinMode(6,OUTPUT);
- analogWrite(10, 0);
- analogWrite(6, 0);
- analogWrite(11,0);
- analogWrite(9, 0);
- delay(100);
- }
- void setup()
- {
- Wire.begin();
- Serial.begin(9600);
- set_Motors();
- accelgyro.initialize();
- delay(100);
- autoCalibration();
- delay(100);
- }
- void autoCalibration(){
- Gx_offset=0.0;
- Gy_offset=0.0;
- double sum_1 =0;
- double sum_2 =0;
- double sum_3 =0;
- double sum_4 =0;
- for (int i=0; i<500; i++){
- accelgyro.getMotion6(&ax,&ay,&az,&gx,&gy,&gz);
- ggx=gx/131.00;
- ggy=gy/131.00;
- Ax=ax/16384.00;
- Ay=ay/16384.00;
- Az=az/16384.00;
- Angel_accX =atan(Ay/sqrt(Ax*Ax+Az*Az))*180/3.14 ;
- Angel_accY =-atan(Ax/sqrt(Az*Az+Ay*Ay))*180/3.14;
- sum_1 = sum_1 + ggx;
- sum_2 = sum_2 + ggy;
- sum_3 = sum_3 + Angel_accX;
- sum_4 = sum_4 + Angel_accY;
- delay(1);
- }
- Gx_offset = sum_1/500;
- Gy_offset = sum_2/500;
- Ax_offset = sum_3/500;
- Ay_offset = sum_4/500;
- // Serial.print("Gx_offset= ");
- // Serial.print(sum_1/1000);
- // Serial.print(" Gy_offset= ");
- // Serial.println(sum_2/1000);
- }
-
- void loop()
- {
- tic_1=millis();
- int emer_stat = 0;
- //------------------------command tests-----------------------------------
- while (Serial.available()>=1){
- char datatype = Serial.read();
- if (datatype == 'S'){
- digitalWrite(13, HIGH);
- delay(1);
- digitalWrite(13, LOW);
- delay(1);
- }else if(datatype == 'M'){
- orientX=0;
- orientY=0;
- }else if(datatype == 'z'){
- orientX=0;
- }else if(datatype == 'y'){
- orientY=0;
- }else if(datatype == 'L'){
- basic_power = basic_power+10;
- }else if(datatype == 'R'){
- basic_power = basic_power-10;
- }else if(datatype == 'P'){
- basic_power = basic_power+1;
- }else if(datatype == 'K'){
- basic_power = basic_power-1;
- }else if(datatype == 'Q'){
- if (orientX <=18){
- orientX=orientX+2;
- }
- }else if(datatype == 'W'){
- if (orientX >= -18){
- orientX=orientX-2;
- digitalWrite(13, HIGH);
- }
- }else if(datatype == 'D'){
- if (orientY <= 18){
- orientY=orientY+2;
- }
- }else if(datatype == 'G'){
- if (orientY >=-18){
- orientY=orientY-2;
- }
- }else if (datatype == 'V'){
- int value = Serial.parseInt();
- if ((value<=255)&&(value>=0)){
- basic_power = value;
- }
- }else if (datatype == 'X'){
- }else if (datatype == 'Y'){
-
- }else if (datatype == 'j'){
- orientY = 10;
- }else if (datatype == 'k'){
- orientY = 5;
- }else if (datatype == 'l'){
- orientY = -5;
- }else if (datatype == 'm'){
- orientY = -10;
- }else if (datatype == 'n'){
- orientX = -5;
- }else if (datatype == 'o'){
- orientX = 5;
- }else if (datatype == 'p'){
- orientX = 10;
- }else if (datatype == 'y'){
- orientY = 0;
- }else if (datatype == 'z'){
- orientX = 0;
- }
- }
-
- //--------------------------do NOT touch-----------------------------------------
-
-
- // obtaining and filtering Acc angles
- accelgyro.getMotion6(&ax,&ay,&az,&gx,&gy,&gz);
- Ax=ax/16384.00;
- Ay=ay/16384.00;
- Az=az/16384.00;
- Angel_accX =atan(Ay/sqrt(Ax*Ax+Az*Az))*180/3.14 -Ax_offset; //offset
- Angel_accY =-atan(Ax/sqrt(Az*Az+Ay*Ay))*180/3.14 -Ay_offset; //offset
- estima_X = estima_cal(estima_X, Angel_accX, 0.2);
- estima_Y = estima_cal(estima_Y, Angel_accY, 0.2);
- // Serial.print("estima_X=");
- // Serial.print(estima_X);
- // Serial.print("estima_Y=");
- // Serial.println(estima_Y);
-
- // obtaining Gyro angles without filter simply because I'm lasy
- ggx=gx/131.00;
- ggy=gy/131.00;
- ggz=gz/131.00;
- Gx=Gx+(ggx-Gx_offset)*time_span;
- Gy=Gy+(ggy-Gy_offset)*time_span;
- autoCorrection();
- // Serial.print("Gx=");
- // Serial.print(Gx);
- // Serial.print(" Gy=");
- // Serial.println(Gy);
- //fusion angles by combining 40% last observe + 30% Acc + 30% Gyro
-
- fusion_angle_X = update_Estimat(fusion_angle_X, estima_X, Gx );
- fusion_angle_Y = update_Estimat(fusion_angle_Y, estima_Y, Gy );
- // Serial.print("fusion_X=");
- // Serial.print(fusion_angle_X);
- // Serial.print("fusion_Y=");
- // Serial.println(fusion_angle_Y);
-
- // if (fusion_angle_Y>=80){
- // digitalWrite(13, HIGH);
- // delay(1);
- // digitalWrite(13, LOW);
- // delay(1);
- // }
-
- //---------------------------------PID's----------------------------------------
- uodate_error(orientX, orientY ,fusion_angle_X, fusion_angle_Y);
-
- double command_Y_raw = PID_control(now_error_Y, error_diff_Y, error_int_Y);
- double command_X_raw = PID_control(now_error_X, error_diff_X, error_int_X);
- int command_X = int (command_X_raw);
- int command_Y = int (command_Y_raw);
-
- moterPowers[1] =basic_power + command_X;
- moterPowers[0] =basic_power - command_X;
- moterPowers[3] =basic_power + command_Y;
- moterPowers[2] =basic_power - command_Y;
-
- emergency_STOP(emer_stat);
- //---------------------------------fuzzy's----------------------------------------
- // int command_X = fussy_command (fusion_angle_X);
- // int command_Y = fussy_command (fusion_angle_Y);
- // moterPowers[0] =basic_power + command_X + int(orientX);
- // moterPowers[1] =basic_power - command_X - int(orientX);
- // moterPowers[2] =basic_power + command_Y + int(orientY);
- // moterPowers[3] =basic_power - command_Y - int(orientY);
- //----------------------executing state for time_span_milli------------------------
- for (int i=0; i<=3; i++){
- if (moterPowers[i]< 0){
- moterPowers[i] = 0;
- }else if (moterPowers[i] >255){
- moterPowers[i] = 255;
- }
- }
-
- // Serial.print("po 10 = ");
- // Serial.print(moterPowers[0]);
- // Serial.print(" po 6 = ");
- // Serial.print(moterPowers[1]);
- // Serial.print(" po 11 = ");
- // Serial.print(moterPowers[2]);
- // Serial.print(" po 9 = ");
- // Serial.println(moterPowers[3]);
-
- analogWrite(10, moterPowers[0]);
- analogWrite(6, moterPowers[1]);
- analogWrite(11, moterPowers[2]);
- analogWrite(9, moterPowers[3]);
- tic_2=millis();
- duration = tic_2 - tic_1;
- if(duration > time_span_milli){
- duration=0;
- }
- //Serial.println(time_span_milli - duration);
- delay (time_span_milli - duration);
-
- }
- //--------------------------accesory functions----------------------------------------
- double estima_cal (double estima, double metron, double KG){
- double result1 = estima + KG*(metron - estima);
- return result1;
- }
- double PID_control(double error, double error_diff, double error_int ){
- double P=0.7;
- double D=0.2;
- double I=0;
- double command = P*error + I*error_int + D*error_diff;
- return command;
- }
- void uodate_error(double consigne_X, double consigne_Y, double mesure_X, double mesure_Y){
- now_error_X = consigne_X - mesure_X;
- now_error_Y = consigne_Y - mesure_Y;
- error_diff_X = (now_error_X - last_error_X)/time_span;
- error_diff_Y = (now_error_Y - last_error_Y)/time_span;
- error_int_X = error_int_X + now_error_X*time_span;
- error_int_Y = error_int_Y + now_error_Y*time_span;
- last_error_X =now_error_X;
- last_error_Y =now_error_Y;
- }
- double update_Estimat(double estimate, double metron_1, double metron_2){
- double temp = 0.4* estimate + 0.3*metron_1 + 0.3*metron_2;
- return temp;
- }
- void emergency_STOP(int choice){
- if (choice == 0){
- //do nothing
- }else if(choice == 1){
- //brutal descending
- basic_power =5;
- // moterPowers[1] =5;
- // moterPowers[2] =5;
- // moterPowers[3] =5;
- }else if(choice == 2){
- //douce descending
- moterPowers[0] = moterPowers[0]-10;
- moterPowers[1] = moterPowers[1]-10;
- moterPowers[2] = moterPowers[2]-10;
- moterPowers[3] = moterPowers[3]-10;
- }
- }
- double PorportionDet(double limA, double limB, double outA, double outB, double x){
- double a = (x - limB) / (limA-limB);
- double result = a*outA + (1-a)*outB;
- return result;
- }
- int fussy_command(double input){
- double PWM_command;
- if (input>=45 ){
- PWM_command = 30;
- }else if(input<45 & input>=25 ){
- PWM_command = PorportionDet(45, 25, 30, 10, input );
- }else if(input<25 & input>=5){
- PWM_command = PorportionDet(25, 5, 10, 3, input );
- }else if(input<5 & input>=-5){
- PWM_command = PorportionDet(5, -5, 3, -3, input );
- }else if(input<-5 &input>=-25){
- PWM_command = PorportionDet(-5, -25, -3, -10, input );
- }else if(input<-25 & input>=-45){
- PWM_command = PorportionDet(-25, -45, -10, -30, input );
- }else if(input<-45){
- PWM_command =-30;
- }
- int regu_pwm =int(PWM_command);
- return regu_pwm;
- }
- void autoCorrection (){
- if ( Angel_accX > -1.3 & Angel_accX < 1.3 ){
- Gx=Angel_accX /2;
- }
- if ( Angel_accY > -1.3 & Angel_accY < 1.3 ){
- Gy=Angel_accY /2;
- }
- }
复制代码
除了PID不太稳定,其他还好 |