123

Dependencies:   StationKeeping MPU9250 PID Servo mbed

Revision:
0:4fecb14ffbb8
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jul 25 09:11:26 2017 +0000
@@ -0,0 +1,1079 @@
+#include "mbed.h"
+#include "PID.h"
+#include "Servo.h"
+#include "MPU9250.h"
+
+//**************************** PID control para declaration ************************************//
+#define RATE  0.005
+#define Kp_1    1.1            //1.1
+#define Ki_1    0.18            //0.2
+#define Kd_1    0.001
+//**************************** Angle Sonsor para declaration ************************************//
+#define Kp 0.5f         // proportional gain governs rate of convergence to accelerometer/magnetometer
+#define Ki 0.0f//0.005f       // integral gain governs rate of convergence of gyroscope biases
+//**************************** pragram debug declaration ************************************//
+int index_times = 0;
+double RunTime =0,lastTime =0;
+int do_measure_index=0;
+int Arm_enable_index;
+DigitalOut Arm_interrupt(D9);
+
+double t_MeasureAngularVelocity=0.001;
+double t_PIDcontrol_velocity =0.001;
+double t_LQR_control = 0.005;
+double t_MeasureRobotAttitudeAngle = 0.005;
+double t_quadratureDecoder = 7;
+double t_TrajectoryTracking_control = 0.1;
+//**************************** Motor para declaration ************************************//
+double radius_ball = 0.15;
+double radius_robot = 0.105;
+double r_wheel = 0.05;
+//**************************** Motor declaration ************************************//
+//DigitalOut ExtInt(PB_7);
+DigitalOut Break_1(A5);//D15
+DigitalOut Break_2(A4);//D14
+DigitalOut Break_3(A3);//D8
+DigitalOut AR_1(D15);//A5
+DigitalOut AR_2(D14);//A4
+DigitalOut AR_3(D8);//A3
+DigitalOut CW_CCW_1(D7);
+DigitalOut CW_CCW_2(D6);
+DigitalOut CW_CCW_3(D5);
+Servo PWM_Motor_1(D2);
+Servo PWM_Motor_2(D3);
+Servo PWM_Motor_3(D4);
+int control_Brake,control_StopRun=0;
+int cw_ccw_1=0,cw_ccw_2=0,cw_ccw_3=0;
+//**************************** Measuremant of angular velocity declaration ************************************//
+double Angle_1 =0,Angle_2 =0,Angle_3 =0;
+double LastAngle_1 =0,LastAngle_2 =0,LastAngle_3 =0;
+double _1_SectionAngle=0,_1_LastSectionAngle,_1_LastSectionAngle_1,_1_LastSectionAngle_2,_1_LastSectionAngle_3,_1_LastSectionAngle_4;
+double _2_SectionAngle=0,_2_LastSectionAngle,_2_LastSectionAngle_1,_2_LastSectionAngle_2,_2_LastSectionAngle_3,_2_LastSectionAngle_4;
+double _3_SectionAngle=0,_3_LastSectionAngle,_3_LastSectionAngle_1,_3_LastSectionAngle_2,_3_LastSectionAngle_3,_3_LastSectionAngle_4;
+double Average_SectionAngle_1,Now_angularVelocity_1=0;
+double Average_SectionAngle_2,Now_angularVelocity_2=0;
+double Average_SectionAngle_3,Now_angularVelocity_3=0;
+double SectionTime =0;
+double NowTime_measureVelocity=0, LastTime_measureVelocity = 0;
+//**************************** PID control declaration ************************************//
+float Now_time_PID,Last_Time_PID;
+    //Command
+double Command_AngularVel_1=1,Command_AngularVel_2=1,Command_AngularVel_3=1;
+double command_AngularVel_1=1,command_AngularVel_2=1,command_AngularVel_3=1;
+    //Control
+double Control_motor_1,Control_motor_2,Control_motor_3;
+    //Control PWM value
+double Control_Motor_PWM_1,Control_Motor_PWM_2,Control_Motor_PWM_3;
+
+
+PID Motor_1 (&Now_angularVelocity_1, &Control_motor_1, &Command_AngularVel_1, Kp_1, Ki_1, Kd_1, DIRECT,&Now_time_PID,&Last_Time_PID);
+PID Motor_2 (&Now_angularVelocity_2, &Control_motor_2, &Command_AngularVel_2, Kp_1, Ki_1, Kd_1, DIRECT,&Now_time_PID,&Last_Time_PID);
+PID Motor_3 (&Now_angularVelocity_3, &Control_motor_3, &Command_AngularVel_3, Kp_1, Ki_1, Kd_1, DIRECT,&Now_time_PID,&Last_Time_PID);
+//****************************LQR_control declaration************************************//
+double Ka = 25;                //25.0
+double Kav = 10.7423;               //10.4423
+
+double Kt = 3.1 ;                   //3.1
+double Kt_y = 3.1;                    //3.98
+double Kv = 1.0;                    //1.0
+double Kv_y = 1.0;                    //1.1
+
+double Kz = 0.05;                   //0.05
+double Kii = 0.15;                  //0.2
+
+double KI_xy = 0.0085;                //0.02
+double KI_xy_y = 0.0085;                //0.025
+
+double Roll_offset = 2.1;          //2.88       4.0
+double Pitch_offset = 1.85;        //-0.05       2.1
+double Diff_Roll,Diff_Pitch,Diff_Yaw;
+double Integ_Roll,Integ_Pitch;
+double Integ_x,Integ_y;
+double Roll_last,Pitch_last;
+double Vx=0,Vy=0,Wz=0;
+double d_x=0,d_y=0;
+double u_x=0,u_y=0;
+double Point_x;
+double x_now,y_now;
+double x_pre_1,y_pre_1;
+double ax_now,ay_now;
+double ax_pre_1,ay_pre_1;
+double ax_pre_2,ay_pre_2;
+double Vx_pre_1,Vy_pre_1;
+double Diff_x,Diff_y;
+double Diff_x_pre,Diff_y_pre;
+double dot_diff_x,dot_diff_y;
+//****************************Trajectory Tracking declaration************************************//
+double x_trajectory,y_trajectory;
+//****************************Encoder declaration************************************//
+DigitalIn phaseA_1( PC_3 );
+DigitalIn phaseB_1( PC_2 );
+DigitalIn phaseA_2( PH_1 );
+DigitalIn phaseB_2( PB_7 );
+DigitalIn phaseA_3( PA_15 );
+DigitalIn phaseB_3( PA_14 );
+int encoderClickCount_1=0,previousEncoderState_1=0; 
+int encoderClickCount_2=0,previousEncoderState_2=0;
+int encoderClickCount_3=0,previousEncoderState_3=0;
+
+//****************************Angle Sensor declaration************************************//
+float Times[10] = {0,0,0,0,0,0,0,0,0,0};
+float control_frequency = 800;//PPM_FREQU;         // frequency for the main loop in Hz
+int counter = 0;
+int divider = 20;
+float dt;                       // time for entire loop
+float dt_sensors;               // time only to read sensors
+float q0 = 1, q1 = 0, q2 = 0, q3 = 0;
+float q0_A = 1, q1_A = 0, q2_A = 0, q3_A = 0;
+float exInt = 0, eyInt = 0, ezInt = 0;
+float OX = 0, OY = 0, OZ = 0;
+float Roll_pre_1,Roll_pre_2,Roll_pre_3,Roll_pre_4;
+float Pitch_pre_1,Pitch_pre_2,Pitch_pre_3,Pitch_pre_4;
+float Mag_x_pre,Mag_y_pre,Mag_z_pre;
+float Mag_x_pre_L,Mag_y_pre_L,Mag_z_pre_L;
+float Mag_x_pre_LL,Mag_y_pre_LL,Mag_z_pre_LL;
+float Mag_x_pre_LLL,Mag_y_pre_LLL,Mag_z_pre_LLL;
+float Mag_x_ave,Mag_y_ave,Mag_x_total,Mag_y_total;
+float Cal_Mag_x_pre_LL,Cal_Mag_x_pre_L,Cal_Mag_x_pre,Cal_Mag_x;
+float GYRO_z_pre,GYRO_z_pre_L,GYRO_z_pre_LL,GYRO_z_pre_LLL;
+float GYRO_z_total,GYRO_z_offset,Global_GYRO_z;
+float Global_mag_vector_angle,Yaw_pre;
+float Global_mag_x_vector_angle,Mag_x_vector_angle;
+float Global_mag_y_vector_angle,Mag_y_vector_angle;
+int Count_mag_check=0;
+float angle[3];
+float Roll,Pitch,Yaw;
+float calibrated_values[3],magCalibrationp[3];
+float v_index[3];
+float dest1,dest2;
+int f=0;
+int j=0;
+int k=0;
+int g=0;
+int count1=0,count2=0,count3=0,count4=0,count5=0,count6=0,count7=0,count8=0,count9=0,count11=0,count12=0,count14=0;
+int Rot_index;
+float mRes = 10.*4912./32760.0;
+
+int AngleFilter_counter = 0;
+float Roll_total = 0,Pitch_total = 0;
+
+SPI spi(SPI_MOSI, SPI_MISO, SPI_SCK);
+mpu9250_spi imu(spi,SPI_CS);   //define the mpu9250 object
+//****************************Timer declaration************************************//
+Timer NowTime;
+//**************************** Filter_IMUupdate ************************************//
+//**************************** Filter_IMUupdate ************************************//
+//**************************** Filter_IMUupdate ************************************//
+//**************************** Filter_IMUupdate ************************************//
+//**************************** Filter_IMUupdate ************************************//
+void Filter_IMUupdate(float halfT, float gx, float gy, float gz, float ax, float ay, float az) {
+    float norm;
+    float vx, vy, vz;
+    float ex, ey, ez;         
+    
+    // normalise the measurements
+    norm = sqrt(ax*ax + ay*ay + az*az);
+    if(norm == 0.0f) return;   
+    ax /= norm;
+    ay /= norm;
+    az /= norm;      
+    
+    // estimated direction of gravity
+    vx = 2*(q1*q3 - q0*q2);
+    vy = 2*(q0*q1 + q2*q3);
+    vz = q0*q0 - q1*q1 - q2*q2 + q3*q3;
+    
+    // error is sum of cross product between reference direction of field and direction measured by sensor
+    ex = (ay*vz - az*vy);
+    ey = (az*vx - ax*vz);
+    ez = (ax*vy - ay*vx);
+    
+    // integral error scaled integral gain
+    exInt += ex*Ki;
+    eyInt += ey*Ki;
+    ezInt += ez*Ki;
+    
+    // adjusted gyroscope measurements
+    gx += Kp*ex + exInt;
+    gy += Kp*ey + eyInt;
+    gz += Kp*ez + ezInt;
+    
+    // integrate quaternion rate and normalise
+    float q0o = q0; // he did the MATLAB to C error by not thinking of the beginning vector elements already being changed for the calculation of the rest!
+    float q1o = q1;
+    float q2o = q2;
+    float q3o = q3;
+    q0 += (-q1o*gx - q2o*gy - q3o*gz)*halfT;
+    q1 += (q0o*gx + q2o*gz - q3o*gy)*halfT;
+    q2 += (q0o*gy - q1o*gz + q3o*gx)*halfT;
+    q3 += (q0o*gz + q1o*gy - q2o*gx)*halfT;  
+    
+    // normalise quaternion
+    norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
+    q0 = q0 / norm;
+    q1 = q1 / norm;
+    q2 = q2 / norm;
+    q3 = q3 / norm;
+}
+//**************************** Filter_compute ************************************//
+//**************************** Filter_compute ************************************//
+//**************************** Filter_compute ************************************//
+//**************************** Filter_compute ************************************//
+//**************************** Filter_compute ************************************//
+void Filter_compute(float dt, const float * Gyro_data, const float * Acc_data, const float * Comp_data)
+{
+    // IMU/AHRS
+
+    float d_Gyro_angle[3];
+    void get_Acc_angle(const float * Acc_data);
+     // IMU/AHRS (from http://www.x-io.co.uk/open-source-imu-and-ahrs-algorithms/)   
+    float radGyro[3],Gyro_cal_data; // Gyro in radians per second
+    
+    for(int i=0; i<3; i++)
+        radGyro[i] = Gyro_data[i] * 3.14159/ 180;
+        
+        Filter_IMUupdate(dt/2, radGyro[0], radGyro[1], radGyro[2], Acc_data[0], Acc_data[1], Acc_data[2]);
+        //IMU_AHRSupdate(dt/2, radGyro[0], radGyro[1], radGyro[2], Acc_data[0], Acc_data[1], Acc_data[2], Comp_data[0], Comp_data[1], Comp_data[2]);
+        
+        float rangle[3]; // calculate angles in radians from quternion output, formula from Wiki (http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles)
+        
+        rangle[0] = atan2(2*q0*q1 + 2*q2*q3, 1 - 2*(q1*q1 + q2*q2));
+        rangle[1] = asin (2*q0*q2 - 2*q3*q1);
+        rangle[2] = atan2(2*q0_A*q3_A + 2*q1_A*q2_A, 1 - 2*(q2_A*q2_A + q3_A*q3_A));            // Z-axis
+        
+        
+        for(int i=0; i<2; i++){  // angle in degree
+            angle[i] = rangle[i] * 180 / 3.14159;
+        }
+        /*Roll=angle[0]*0.2 + Roll_pre_1*0.2 + Roll_pre_2*0.2 +Roll_pre_3*0.2 + Roll_pre_4*0.2;
+        Roll_pre_4 = Roll_pre_3;
+        Roll_pre_3 = Roll_pre_2;
+        Roll_pre_2 = Roll_pre_1;
+        Roll_pre_1 = Roll;
+    
+        Pitch=angle[1]*0.2 + Pitch_pre_1*0.2 + Pitch_pre_2*0.2 + Pitch_pre_3*0.2 + Pitch_pre_4*0.2;
+        Pitch_pre_4 = Pitch_pre_3;
+        Pitch_pre_3 = Pitch_pre_2;
+        Pitch_pre_2 = Pitch_pre_1;
+        Pitch_pre_1 = Pitch;*/
+
+        Roll_total += angle[0];
+        Pitch_total += angle[1];
+        AngleFilter_counter++;
+        
+        if( AngleFilter_counter > 1 ){                        // The average of the attitude angle for 100 times.
+            Roll = Roll_total / AngleFilter_counter;
+            Pitch = Pitch_total / AngleFilter_counter;
+            AngleFilter_counter = 0;
+            Roll_total = 0;
+            Pitch_total = 0;
+            Roll -= Roll_offset;
+            Pitch -= Pitch_offset;
+        }
+        
+//**************************************************Gyro_data[2]  filter      start
+        float GYRO_z=0;
+
+        GYRO_z=Gyro_data[2]*0.15 + GYRO_z_pre*0.20 + GYRO_z_pre_L*0.20 + GYRO_z_pre_LL*0.25 + GYRO_z_pre_LLL*0.20;
+        if( count4==1 ){
+            GYRO_z_pre_L=GYRO_z_pre;
+            
+            count4=0;
+        }
+        if( count5==2 ){
+            GYRO_z_pre_LL=GYRO_z_pre_L;
+            
+            count5=0;
+        }
+        if( count6==3 ){
+            GYRO_z_pre_LLL=GYRO_z_pre_LL;
+            
+            count6=0;
+        }
+        
+       
+        
+        count4++;
+        count5++;
+        count6++;
+        GYRO_z_pre=Gyro_data[2];
+        Global_GYRO_z=GYRO_z;
+       /*printf("     GYRO_z:%10.3f     ,count8:%10d   \n", 
+            GYRO_z,
+            count8
+            );*/
+        if((count8>5)&&(count8<=2005)){
+            GYRO_z_total+=GYRO_z;
+        }
+        if( count8==2005 ){
+            GYRO_z_offset=GYRO_z_total/2000;
+           /* printf("     GYRO_z_offset:%10.5f    \n ", 
+            GYRO_z_offset
+            );*/
+            GYRO_z_total=0;
+            count8=0;
+        }
+
+        count8++;
+//**************************************************Gyro_data[2]'s average  filter   :     answer=GYRO_Z is roughly = 0.74956
+
+//************************************************** calculate Yaw
+    if( (count11==35) ){
+        if( abs(Yaw_pre-Yaw)<1 ){
+            Yaw_pre=Yaw_pre;
+        }else{
+            Yaw_pre=Yaw;
+        }
+        count11=0;
+    }
+    count11++;
+        
+    if( count12>=20 ){
+        Yaw += (Gyro_data[2]-0.74936) *dt; 
+    }
+    count12++;
+    //pc.printf("     Yaw:%10.5f     ", 
+            //Yaw
+    // );
+}
+//**************************** Mag_Complentary_Filter ************************************//
+//**************************** Mag_Complentary_Filter ************************************//
+//**************************** Mag_Complentary_Filter ************************************//
+//**************************** Mag_Complentary_Filter ************************************//
+//**************************** Mag_Complentary_Filter ************************************//
+void Mag_Complentary_Filter(float dt, const float * Comp_data)
+{
+        float Mag_x=0,Mag_y=0,Mag_z=0;
+        Mag_x=Comp_data[0]*0.15 + Mag_x_pre*0.20 + Mag_x_pre_L*0.20 + Mag_x_pre_LL*0.25 + Mag_x_pre_LLL*0.20;
+        Mag_y=Comp_data[1]*0.15 + Mag_y_pre*0.20 + Mag_y_pre_L*0.20 + Mag_y_pre_LL*0.25 + Mag_y_pre_LLL*0.20;
+        Mag_z=Comp_data[2]*0.15 + Mag_z_pre*0.20 + Mag_z_pre_L*0.20 + Mag_z_pre_LL*0.25 + Mag_z_pre_LLL*0.20;
+        
+        
+        if( count1==1 ){
+            Mag_x_pre_L=Mag_x_pre;
+            Mag_y_pre_L=Mag_y_pre;
+            Mag_z_pre_L=Mag_z_pre;
+            Cal_Mag_x_pre=Cal_Mag_x;
+            
+            count1=0;
+        }
+        if( count2==2 ){
+            Mag_x_pre_LL=Mag_x_pre_L;
+            Mag_y_pre_LL=Mag_y_pre_L;
+            Mag_z_pre_LL=Mag_z_pre_L;
+            Cal_Mag_x_pre_L=Cal_Mag_x_pre;
+            
+            count2=0;
+        }
+        if( count7==3 ){
+            Mag_x_pre_LLL=Mag_x_pre_LL;
+            Mag_y_pre_LLL=Mag_y_pre_LL;
+            Mag_z_pre_LLL=Mag_z_pre_LL;
+            Cal_Mag_x_pre_LL=Cal_Mag_x_pre_L;
+        
+            count7=0;
+        }
+
+        
+        count1++;
+        count2++;
+        count7++;
+        Mag_x_pre=Comp_data[0];
+        Mag_y_pre=Comp_data[1];
+        Mag_z_pre=Comp_data[2];
+        if( count14>4 ){ 
+            Cal_Mag_x=Mag_x;             
+        }
+        count14++;
+        
+        
+//*************************************Mag_ave calculate
+        if(count3<=20){
+            Mag_x_total+=Mag_x;
+            Mag_y_total+=Mag_y;
+        }
+        if( count3==20){
+            Mag_x_ave=Mag_x_total/21;
+            Mag_y_ave=Mag_y_total/21;
+            /*pc.printf("     Mag_x_ave:%10.5f    ,Mag_y_ave:%10.5f     ", 
+            Mag_x_ave,
+            Mag_y_ave
+            );*/
+            Mag_x_total=0;
+            Mag_y_total=0;
+            count3=0;
+            
+            
+        }
+        count3++;
+        
+//********************************ROT_check  start
+
+        float v_length,v_length_ave,MagVector_angle;
+        v_length=sqrt( Mag_x*Mag_x + Mag_y*Mag_y );
+        v_length_ave=sqrt( Mag_x_ave*Mag_x_ave + Mag_y_ave*Mag_y_ave );
+        
+        MagVector_angle=acos(( Mag_x*Mag_x_ave + Mag_y*Mag_y_ave )/(v_length*v_length_ave))*57.3;
+        
+        if( count9==3 ){
+            Global_mag_vector_angle=MagVector_angle;
+            count9=0;
+        }
+        count9++;
+        
+        
+        if( (abs(Global_mag_vector_angle-MagVector_angle)<5) && (abs(Global_GYRO_z)<5) ){
+            Count_mag_check++;
+            
+        }else{ Count_mag_check=0; }
+        
+        if( Count_mag_check==30 ){
+            Yaw=Yaw_pre;
+            Count_mag_check=0;
+        }
+        float ABS_CHECK=abs(Global_mag_vector_angle-MagVector_angle);
+//********************************Theta_check  end
+        /*pc.printf("ABS_CHECK:%10.3f,Cal_Mag_x_pre_LL:%10.3f,Mag_x:%10.3f,Count_mag_check:%10d ,Yaw_pre:%10.3f,Yaw_filter:%10.3f    ", 
+            ABS_CHECK,
+            Cal_Mag_x_pre_LL,
+            Mag_x,
+            Count_mag_check,
+            Yaw_pre,
+            Yaw
+            );*/
+
+}
+//****************************Motor_run************************************//
+//****************************Motor_run************************************//
+//****************************Motor_run************************************//
+//****************************Motor_run************************************//
+//****************************Motor_run************************************//
+int Motor_run(double control_value_PWM_1,double control_value_PWM_2,double control_value_PWM_3,int control_CW_CCW_1,int control_CW_CCW_2,int control_CW_CCW_3,int control_brake ,int control_stopRun){
+    
+    Break_1 = 0;
+    Break_2 = 0;
+    Break_3 = 0;
+    //Brake = 1;
+    /*CW_CCW_1 = 1;
+    CW_CCW_2 = 1;
+    CW_CCW_3 = 1;*/
+    
+    CW_CCW_1 = control_CW_CCW_1;
+    CW_CCW_2 = control_CW_CCW_2;
+    CW_CCW_3 = control_CW_CCW_3;
+    double Control_value_PWM_1 = 1-control_value_PWM_1;
+    double Control_value_PWM_2 = 1-control_value_PWM_2;
+    double Control_value_PWM_3 = 1-control_value_PWM_3;
+    //printf("Control_value_PWM_2: %f\n",Control_value_PWM_2);
+    //printf("Control_value_PWM_3: %f\n",Control_value_PWM_3);
+    //PWM_Motor_1.write(Control_value_PWM_1);
+    /*control_CW_CCW_1 = 0;
+    control_CW_CCW_2 = 0;
+    control_CW_CCW_3 = 0;
+    AR_1 = 1;
+    AR_2 = 1;
+    AR_3 = 1;
+    CW_CCW_1 = 1;
+    CW_CCW_2 = 1;
+    CW_CCW_3 = 1;
+    PWM_Motor_1.write(0.75);
+    PWM_Motor_2.write(0.75);
+    PWM_Motor_3.write(0.75);*/
+    //wait_ms(0.5);
+    PWM_Motor_1.write(Control_value_PWM_1);
+    PWM_Motor_2.write(Control_value_PWM_2);
+    PWM_Motor_3.write(Control_value_PWM_3);
+
+}
+//****************************quadratureDecoder_1************************************//
+//****************************quadratureDecoder_1************************************//
+//****************************quadratureDecoder_1************************************//
+//****************************quadratureDecoder_1************************************//
+//****************************quadratureDecoder_1************************************//
+void quadratureDecoder_1( void )
+{
+  int  currentEncoderState_1 = (phaseB_1.read() << 1) + phaseA_1.read(); 
+  
+//****************************  1  ************************************//
+    if( currentEncoderState_1 == previousEncoderState_1 )
+    {
+        return;
+    }
+    
+    switch( previousEncoderState_1 )
+    {
+        case 0:
+            if( currentEncoderState_1 == 2 )
+            {
+                encoderClickCount_1--;
+                
+            }
+            else if( currentEncoderState_1 == 1 )
+            {
+                encoderClickCount_1++;
+                
+            }
+            break;
+            
+        case 1:
+            if( currentEncoderState_1 == 0 )
+            {        
+                encoderClickCount_1--;
+                
+            }
+            else if( currentEncoderState_1 == 3 )
+            {
+                encoderClickCount_1++;
+                
+            }
+            break;
+            
+        case 2:
+            if( currentEncoderState_1 == 3 )
+            {
+                encoderClickCount_1--;
+                
+            }
+            else if( currentEncoderState_1 == 0 )
+            {
+                encoderClickCount_1++;
+                
+            }
+            break;
+            
+        case 3:
+            if( currentEncoderState_1 == 1 )
+            {
+                encoderClickCount_1--;
+                
+            }
+            else if( currentEncoderState_1 == 2 )
+            {
+                encoderClickCount_1++;
+                
+            }
+            break;
+
+        default:
+            break;
+    }
+    previousEncoderState_1 = currentEncoderState_1;
+
+}
+void quadratureDecoder_2( void )
+{
+  int  currentEncoderState_2 = (phaseB_2.read() << 1) + phaseA_2.read(); 
+
+//****************************  2  ************************************//
+    if( currentEncoderState_2 == previousEncoderState_2 )
+    {
+        return;
+    }
+    
+    switch( previousEncoderState_2 )
+    {
+        case 0:
+            if( currentEncoderState_2 == 2 )
+            {
+                encoderClickCount_2--;
+                
+            }
+            else if( currentEncoderState_2 == 1 )
+            {
+                encoderClickCount_2++;
+                
+            }
+            break;
+            
+        case 1:
+            if( currentEncoderState_2 == 0 )
+            {        
+                encoderClickCount_2--;
+                
+            }
+            else if( currentEncoderState_2 == 3 )
+            {
+                encoderClickCount_2++;
+                
+            }
+            break;
+            
+        case 2:
+            if( currentEncoderState_2 == 3 )
+            {
+                encoderClickCount_2--;
+                
+            }
+            else if( currentEncoderState_2 == 0 )
+            {
+                encoderClickCount_2++;
+                
+            }
+            break;
+            
+        case 3:
+            if( currentEncoderState_2 == 1 )
+            {
+                encoderClickCount_2--;
+                
+            }
+            else if( currentEncoderState_2 == 2 )
+            {
+                encoderClickCount_2++;
+                
+            }
+            break;
+
+        default:
+            break;
+    }
+    previousEncoderState_2 = currentEncoderState_2;
+}
+void quadratureDecoder_3( void )
+{
+  int  currentEncoderState_3 = (phaseB_3.read() << 1) + phaseA_3.read(); 
+  
+//****************************  3  ************************************//
+    if( currentEncoderState_3 == previousEncoderState_3 )
+    {
+        return;
+    }
+    
+    switch( previousEncoderState_3 )
+    {
+        case 0:
+            if( currentEncoderState_3 == 2 )
+            {
+                encoderClickCount_3--;
+                
+            }
+            else if( currentEncoderState_3 == 1 )
+            {
+                encoderClickCount_3++;
+                
+            }
+            break;
+            
+        case 1:
+            if( currentEncoderState_3 == 0 )
+            {        
+                encoderClickCount_3--;
+                
+            }
+            else if( currentEncoderState_3 == 3 )
+            {
+                encoderClickCount_3++;
+                
+            }
+            break;
+            
+        case 2:
+            if( currentEncoderState_3 == 3 )
+            {
+                encoderClickCount_3--;
+                
+            }
+            else if( currentEncoderState_3 == 0 )
+            {
+                encoderClickCount_3++;
+                
+            }
+            break;
+            
+        case 3:
+            if( currentEncoderState_3 == 1 )
+            {
+                encoderClickCount_3--;
+                
+            }
+            else if( currentEncoderState_3 == 2 )
+            {
+                encoderClickCount_3++;
+                
+            }
+            break;
+
+        default:
+            break;
+    }
+    previousEncoderState_3 = currentEncoderState_3;
+
+}
+//****************************getAngular************************************//
+//****************************getAngular************************************//
+//****************************getAngular************************************//
+//****************************getAngular************************************//
+//****************************getAngular************************************//
+void getAngular( void )
+{
+    Angle_1 = (encoderClickCount_1*0.1499)/5; 
+    Angle_2 = (encoderClickCount_2*0.1499)/5; 
+    Angle_3 = (encoderClickCount_3*0.1499)/5; 
+
+    
+    _1_SectionAngle = Angle_1 - LastAngle_1;
+    _2_SectionAngle = Angle_2 - LastAngle_2;
+    _3_SectionAngle = Angle_3 - LastAngle_3;
+    Average_SectionAngle_1 = (_1_SectionAngle*0.3 + _1_LastSectionAngle*0.3 + _1_LastSectionAngle_1*0.1 + _1_LastSectionAngle_2*0.1 + _1_LastSectionAngle_3*0.1 + _1_LastSectionAngle_4*0.1)/1;
+    Average_SectionAngle_2 = (_2_SectionAngle*0.3 + _2_LastSectionAngle*0.3 + _2_LastSectionAngle_1*0.1 + _2_LastSectionAngle_2*0.1 + _2_LastSectionAngle_3*0.1 + _2_LastSectionAngle_4*0.1)/1;
+    Average_SectionAngle_3 = (_3_SectionAngle*0.3 + _3_LastSectionAngle*0.3 + _3_LastSectionAngle_1*0.1 + _3_LastSectionAngle_2*0.1 + _3_LastSectionAngle_3*0.1 + _3_LastSectionAngle_4*0.1)/1;
+    NowTime_measureVelocity = NowTime.read();
+    SectionTime = NowTime_measureVelocity - LastTime_measureVelocity;
+    Now_angularVelocity_1 = abs(Average_SectionAngle_1/(SectionTime));
+    Now_angularVelocity_2 = abs(Average_SectionAngle_2/(SectionTime));
+    Now_angularVelocity_3 = abs(Average_SectionAngle_3/(SectionTime));
+    
+    
+    LastTime_measureVelocity = NowTime_measureVelocity;
+    LastAngle_1 = Angle_1;
+    _1_LastSectionAngle_4 = _1_LastSectionAngle_3;
+    _1_LastSectionAngle_3 = _1_LastSectionAngle_2;
+    _1_LastSectionAngle_2 = _1_LastSectionAngle_1;
+    _1_LastSectionAngle_1 = _1_LastSectionAngle;
+    _1_LastSectionAngle = _1_SectionAngle;
+    LastAngle_2 = Angle_2;
+    _2_LastSectionAngle_4 = _2_LastSectionAngle_3;
+    _2_LastSectionAngle_3 = _2_LastSectionAngle_2;
+    _2_LastSectionAngle_2 = _2_LastSectionAngle_1;
+    _2_LastSectionAngle_1 = _2_LastSectionAngle;
+    _2_LastSectionAngle = _2_SectionAngle;
+    LastAngle_3 = Angle_3;
+    _3_LastSectionAngle_4 = _3_LastSectionAngle_3;
+    _3_LastSectionAngle_3 = _3_LastSectionAngle_2;
+    _3_LastSectionAngle_2 = _3_LastSectionAngle_1;
+    _3_LastSectionAngle_1 = _3_LastSectionAngle;
+    _3_LastSectionAngle = _3_SectionAngle;
+}
+//****************************PWM_commmand_transformation************************************//
+//****************************PWM_commmand_transformation************************************//
+//****************************PWM_commmand_transformation************************************//
+//****************************PWM_commmand_transformation************************************//
+//****************************PWM_commmand_transformation************************************//
+double PWM_commmand_transformation( double  Control_AngVel_Value ){
+    double Control_PWM_Value = 0;
+    //double control_CW_CCW = 0;
+    //printf("*********************Control_AngVel_Value:%.3f\n",Control_AngVel_Value);
+    if( Control_AngVel_Value > 0 ){
+        Control_AngVel_Value = Control_AngVel_Value;
+        //control_CW_CCW = 0;
+        
+    }else if( Control_AngVel_Value < 0 ){
+        Control_AngVel_Value = -Control_AngVel_Value;
+        //control_CW_CCW = 1;
+        
+    }
+    if( Control_AngVel_Value > 325){
+        if( Control_AngVel_Value < 466 ){
+            if( Control_AngVel_Value < 393 ){
+                Control_PWM_Value =  Control_AngVel_Value/651.6   ;   //0.5~0.6
+            }else {
+                Control_PWM_Value =  Control_AngVel_Value/658.8;   //0.6~0.7
+            }
+        }else{
+            if( Control_AngVel_Value < 523 ){
+               Control_PWM_Value =  Control_AngVel_Value/658.39; //0.7~0.8
+            }else{
+                if( Control_AngVel_Value < 588 ){
+                  Control_PWM_Value =  Control_AngVel_Value/652.36;  //0.8~0.9
+                }else{
+                  Control_PWM_Value =  Control_AngVel_Value/655.11;  //0.9~1
+                }
+            }
+        }
+    }else if( Control_AngVel_Value < 325){
+        if( Control_AngVel_Value < 40 ){
+           Control_PWM_Value =  Control_AngVel_Value/533.3; //0~0.075
+        }else{
+            if( Control_AngVel_Value < 59 ){
+               Control_PWM_Value =  Control_AngVel_Value/560.65; //0.1~0.15
+            }else{
+                if( Control_AngVel_Value < 131 ){
+                  Control_PWM_Value =  Control_AngVel_Value/638.3;  //0.15~0.2
+                }else{
+                    if( Control_AngVel_Value < 197 ){
+                       Control_PWM_Value =  Control_AngVel_Value/651.6; //0.2~0.3
+                    }else{
+                        if( Control_AngVel_Value < 263 ){
+                            Control_PWM_Value =  Control_AngVel_Value/654.16; //0.3~0.4
+                        }else{
+                            Control_PWM_Value =  Control_AngVel_Value/652.5; //0.4~0.5
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return Control_PWM_Value;
+}
+//****************************PIDcontrol_compute_velocity************************************//
+//****************************PIDcontrol_compute_velocity************************************//
+//****************************PIDcontrol_compute_velocity************************************//
+//****************************PIDcontrol_compute_velocity************************************//
+//****************************PIDcontrol_compute_velocity************************************//
+void PIDcontrol_compute_velocity(void){
+    if(command_AngularVel_1 >= 0){
+        cw_ccw_1 = 0;
+        Command_AngularVel_1 = command_AngularVel_1;
+    }else{
+        cw_ccw_1 = 1;
+        Command_AngularVel_1 = -command_AngularVel_1;
+    }
+    if(command_AngularVel_2 >= 0){
+        cw_ccw_2 = 0;
+        Command_AngularVel_2 = command_AngularVel_2;
+    }else{
+        cw_ccw_2 = 1;
+        Command_AngularVel_2 = -command_AngularVel_2;
+    }
+    if(command_AngularVel_3 >= 0){
+        cw_ccw_3 = 0;
+        Command_AngularVel_3 = command_AngularVel_3;
+    }else{
+        cw_ccw_3 = 1;
+        Command_AngularVel_3 = -command_AngularVel_3;
+    }
+    Now_time_PID=NowTime.read();
+    Motor_1.Compute(&Now_time_PID);
+    Motor_2.Compute(&Now_time_PID);
+    Motor_3.Compute(&Now_time_PID);
+    Control_Motor_PWM_1 = PWM_commmand_transformation(Control_motor_1);
+    Control_Motor_PWM_2 = PWM_commmand_transformation(Control_motor_2);
+    Control_Motor_PWM_3 = PWM_commmand_transformation(Control_motor_3);
+    //Control_Motor_PWM_1 = PWM_commmand_transformation(Command_AngularVel_1);
+    //Control_Motor_PWM_2 = PWM_commmand_transformation(Command_AngularVel_2);
+    //Control_Motor_PWM_3 = PWM_commmand_transformation(Command_AngularVel_3);
+    //printf("Command_AngularVel_2: %f\n",Command_AngularVel_2);
+    //printf("Control_motor_2: %f\n",Control_motor_2);
+    
+}
+//****************************Compute_point************************************//
+//****************************Compute_point************************************//
+//****************************Compute_point************************************//
+//****************************Compute_point************************************//
+//****************************Compute_point************************************//
+void LQR_control_compute(void){
+    //Now_point_x = (angle/57.295)*3;
+    //Now_point_x = Angle_1;
+    /*if( Roll > 0.5 ){
+        d_x = Roll*0.01745*radius_ball;
+        Vx = d_x/0.001;
+    }else{
+        Vx = 0;
+    }
+    if(Pitch > 0.5){
+        d_y = Pitch*0.01745*radius_ball;
+        Vy = d_y/0.001;
+    }else{
+        Vy = 0;
+    }
+    if( Yaw > 0 ){
+        Wz = 0;
+    }else{
+        Wz = 0;
+    }*/
+    Diff_Roll = (Roll - Roll_last);
+    Diff_Pitch = (Pitch - Pitch_last);
+    Integ_Roll += Roll;
+    //printf("Diff_Roll:%.3f\n",Diff_Roll);
+    Integ_Pitch +=  Pitch;
+    Roll_last = Roll;
+    Pitch_last = Pitch;
+    
+    //Diff_Roll =0;
+    //Roll -= 2.45;
+    //Pitch -=2.5;
+    Diff_x = x_now - x_trajectory;
+    Diff_y = y_now - y_trajectory;
+    dot_diff_x = Diff_x - Diff_x_pre;
+    dot_diff_y = Diff_y - Diff_y_pre;
+    Integ_x += Diff_x;
+    Integ_y += Diff_y;
+    
+    //x_pre_1 = x_now;
+    //y_pre_1 = y_now;
+    Diff_x_pre = Diff_x;
+    Diff_y_pre = Diff_y;
+    
+    u_x = Ka*(Roll)+(Integ_Roll*Kii) + Kav*Diff_Roll + Kt*Diff_x + Kv*dot_diff_x + KI_xy*Integ_x;
+    //u_x = Ka*(Roll)+(Integ_Roll*Kii) + Kav*Diff_Roll - Kt*(10) - Kv*0;
+    u_y = Ka*(Pitch)+(Integ_Pitch*Kii) + Kav*Diff_Pitch + Kt_y*Diff_y + Kv_y*dot_diff_y + KI_xy_y*Integ_y;
+    //u_y = Ka*(Pitch)+(Integ_Pitch*Kii) + Kav*Diff_Pitch - Kt*0 - Kv*0;
+    if(u_x > 100 ){u_x = 100;}else if(u_x < -100){u_x = -100;}
+    if(u_y > 100 ){u_y = 100;}else if(u_y < -100){u_y = -100;}
+    Vx = u_x;
+    Vy = u_y;
+    Wz = -Yaw;
+    
+    command_AngularVel_1 = (1/radius_ball)*(-Vy*(-0.5)+Kz*Wz);
+    command_AngularVel_2 = (1/radius_ball)*((0.866*Vx+0.5*Vy)*(-0.5)+Kz*Wz);
+    command_AngularVel_3 = (1/radius_ball)*((-0.866*Vx+0.5*Vy)*(-0.5)+Kz*Wz);
+    //printf("Command_AngularVel_2: %f\n",Command_AngularVel_2);
+    //printf("Command_AngularVel_3: %f\n",Command_AngularVel_3);
+    
+    /*ax_now = Vx - Vx_pre_1;
+    ay_now = Vy - Vy_pre_1;
+    ax_pre_2 = ax_pre_1;
+    ax_pre_1 = ax_now;
+    ay_pre_2 = ay_pre_1;
+    ay_pre_1 = ay_now;
+    Vx_pre_1 = Vx;
+    Vy_pre_1 = Vy;*/
+    
+}
+void MeasureRobotAttitudeAngle(void){
+    dt = t_MeasureRobotAttitudeAngle;
+    imu.read_all();
+    Mag_Complentary_Filter(dt,imu.Magnetometer);
+    Filter_compute(dt, imu.gyroscope_data, imu.accelerometer_data, imu.Magnetometer);
+    /*x_now = x_pre_1 + (1/(dt*dt))*(ax_now-2*ax_pre_1+ax_pre_2);
+    y_now = y_pre_1 + (1/(dt*dt))*(ay_now-2*ay_pre_1+ay_pre_2);
+    x_pre_1 = x_now;
+    y_pre_1 = y_now;*/
+    x_now = -((2*r_wheel)/3)*(-1.732*(-Angle_2+Angle_3));
+    y_now = ((2*r_wheel)/3)*((-2*Angle_1+Angle_2+Angle_3)/(-1));
+    do_measure_index++;
+}
+void Trajectory_generator(void){
+    double t_trajectory = NowTime.read();
+    
+    if( RunTime>=0 &&( RunTime<=10) ){
+    //x_trajectory = t_trajectory * (0.5);
+        x_trajectory = 0;
+        y_trajectory = 0;
+        Arm_enable_index = 0;
+    }else if( RunTime>=10  ){
+        x_trajectory = 0;
+        y_trajectory = 0;
+        Arm_enable_index = 1;
+    }
+}
+void Check_Arm_interrupt( double x_Now, double y_Now, double X_trajectory, double Y_trajectory){
+    if( sqrt((x_Now-X_trajectory)*(x_Now-X_trajectory)+(y_Now-Y_trajectory)*(y_Now-Y_trajectory)) < 5 ){
+        if( Arm_enable_index == 1 ){
+            Arm_interrupt = 1;
+            //Roll_offset = 2.0; 
+            //Pitch_offset = 2.5;
+        }
+    }
+}
+//****************************main function************************************//
+int main() {
+    Serial pc( USBTX, USBRX );
+    pc.baud(460800);
+//****************************Angle Sensor initialization************************************//    
+    if(imu.init(1,BITS_DLPF_CFG_188HZ)){  //INIT the mpu9250
+        //pc.printf("\nCouldn't initialize MPU9250 via SPI!");
+    }    
+    //pc.printf("\nWHOAMI=0x%2x\n",imu.whoami()); //output the I2C address to know if SPI is working, it should be 104
+    imu.whoami();
+    //wait(1);    
+    //pc.printf("Gyro_scale=%u\n",imu.set_gyro_scale(BITS_FS_2000DPS));    //Set full scale range for gyros
+    imu.set_gyro_scale(BITS_FS_2000DPS);
+    //wait(1);  
+    //pc.printf("Acc_scale=%u\n",imu.set_acc_scale(BITS_FS_16G));          //Set full scale range for accs
+    imu.set_acc_scale(BITS_FS_16G);
+    //wait(1);
+    //pc.printf("AK8963 WHIAM=0x%2x\n",imu.AK8963_whoami());
+    imu.AK8963_whoami();
+    //wait(0.1);  
+    imu.AK8963_calib_Magnetometer();
+//****************************Motor driver declare************************************//    
+    //ExtInt = 0;            //number high, voltage high.
+    AR_1 = 1;
+    AR_2 = 1;
+    AR_3 = 1;
+    control_Brake = 1;        //1:Run   0:Stop
+//**************************** PWM ************************************//
+    PWM_Motor_1.calibrate(0.02, 0*0.02, 1*0.02);
+    PWM_Motor_2.calibrate(0.02, 0*0.02, 1*0.02);
+    PWM_Motor_3.calibrate(0.02, 0*0.02, 1*0.02);
+//**************************** Encoder ************************************//
+    phaseA_1.mode( PullUp );
+    phaseB_1.mode( PullUp );
+    phaseA_2.mode( PullUp );
+    phaseB_2.mode( PullUp );
+    phaseA_3.mode( PullUp );
+    phaseB_3.mode( PullUp );
+//**************************** Ticker ************************************//
+    Ticker Sample_Motor_encoder_1;                                // create a timer to sample the encoder.
+    Ticker Sample_Motor_encoder_2;                                // create a timer to sample the encoder.
+    Ticker Sample_Motor_encoder_3;                                // create a timer to sample the encoder.
+    Ticker Sample_robotAngleSonsor;                                // create a timer to sample the robot attitude.
+    Ticker MeasureAngularVelocity;                      // create a timer to measure the motor angular velocity.
+    Ticker PIDcontrol_velocity;                         // create a timer to do the motor angular velocity PID control.
+    Ticker LQR_control;                                 // create a timer to do the position control.
+    Ticker TrajectoryTracking_control;                  // create a timer to do the TrajectoryTracking_control.
+
+//**************************** Create the motor encoder sampler. ************************************//
+    Sample_Motor_encoder_1.attach_us( &quadratureDecoder_1, t_quadratureDecoder ); 
+    Sample_Motor_encoder_2.attach_us( &quadratureDecoder_2, t_quadratureDecoder ); 
+    Sample_Motor_encoder_3.attach_us( &quadratureDecoder_3, t_quadratureDecoder ); 
+//**************************** Create the motor encoder sampler. ************************************//
+    Sample_robotAngleSonsor.attach( &MeasureRobotAttitudeAngle, t_MeasureRobotAttitudeAngle ); 
+//**************************** Create the motor angular velocity measurement. ************************************//
+    MeasureAngularVelocity.attach( &getAngular, t_MeasureAngularVelocity ); 
+//**************************** Create the motor angular velocity PID control. ************************************//
+    PIDcontrol_velocity.attach( &PIDcontrol_compute_velocity, t_PIDcontrol_velocity );
+//**************************** Create the robot LQR control. ************************************//
+    LQR_control.attach( &LQR_control_compute, t_LQR_control );
+//**************************** Create the motor posistion control. ************************************//
+    TrajectoryTracking_control.attach( &Trajectory_generator, t_TrajectoryTracking_control );
+//**************************** Motor settlement ************************************//
+    Motor_1.SetMode(AUTOMATIC);
+    Motor_2.SetMode(AUTOMATIC);
+    Motor_3.SetMode(AUTOMATIC);
+
+
+    Command_AngularVel_1 = 0;
+    Command_AngularVel_2 = 0;
+    Command_AngularVel_3 = 0;
+//**************************** Timers start ************************************//
+    NowTime.start();
+
+    while( 1 ){ 
+            
+            RunTime = NowTime.read();
+   
+            if( (RunTime-lastTime) > 0.1  ){
+                index_times++;
+                lastTime = RunTime;
+            }
+            
+            if( index_times >= 0.1 ){
+               /* pc.printf("  Now_angularVelocity_1 : %.3f ",Now_angularVelocity_1);
+                pc.printf("  Now_angularVelocity_2 : %.3f ",Now_angularVelocity_2);
+                pc.printf("  Now_angularVelocity_3 : %.3f\n ",Now_angularVelocity_3);
+                pc.printf("  Vx : %.3f ",Vx);
+                pc.printf("  Vy : %.3f ",Vy);
+                //pc.printf(", Vy : %.3f ",Vy);
+                pc.printf(", Command_AngularVel_1 : %.3f ",Command_AngularVel_1);
+                pc.printf(", Command_AngularVel_2 : %.3f ",Command_AngularVel_2);
+                pc.printf(", Command_AngularVel_3 : %.3f \n",Command_AngularVel_3);*/
+                
+                /*pc.printf("x_now: %.3f   , y_now: %.3f , x_trajectory: %f   , u_y: %f ",x_now,y_now,x_trajectory,u_y);
+                pc.printf(" Roll : %10.3f, Pitch : %10.3f, Yaw : %10.3f   \n", 
+                            Roll,
+                            Pitch,
+                            Yaw
+                            );*/
+                pc.printf(" %.3f   ,  %.3f , %.3f   , %.3f ",x_now,y_now,x_trajectory,y_trajectory);
+                pc.printf(",  %10.3f,  %10.3f,  %10.3f , %10.3f   \n", 
+                            Roll,
+                            Pitch,
+                            Yaw,
+                            RunTime
+                            );
+                //pc.printf(",Control_motor_1 : %.3f ",Control_motor_1);
+                //pc.printf(", %.3f  ", Command_gularVel_1);
+                
+                /*pc.printf(", %.3f ",Control_motor_1);*/
+                //pc.printf(",  %.3f\n ",Now_angularVelocity_1);
+                index_times = 0;
+            }
+    Motor_run(Control_Motor_PWM_1,Control_Motor_PWM_2,Control_Motor_PWM_3,cw_ccw_1,cw_ccw_2,cw_ccw_3,control_Brake,control_StopRun);
+    
+    Check_Arm_interrupt(x_now,y_now,x_trajectory,y_trajectory);
+            
+    //wait(0.1);
+    }
+}