a quadcopter code
Dependencies: Pulse RangeFinder mbed
main.cpp
- Committer:
- Gendy
- Date:
- 2015-11-24
- Revision:
- 0:4a55d0a21ea9
File content as of revision 0:4a55d0a21ea9:
#include <math.h> #include "I2Cdev.h" #include "mbed.h" #include "MPU6050_6Axis_MotionApps20.h" #include "PID.h" #include "RangeFinder.h" #ifndef M_PI #define M_PI 3.1415 #endif #define OUTPUT_READABLE_YAWPITCHROLL #define OUTPUT_READABLE_QUATERNION #define OUTPUT_READABLE_ACCELGYRO ////// VARIABLES ////// ///ultrasonic variable/// float d=0; ////////////////// /// PID VARIABLES /// float KPRoll=5; float KIRoll=1; float KDRoll=0.5; float KPPitch=5; float KIPitch=1.1; float KDPitch=0.5;// float KPRPITCH=2; float KIRPITCH=0; float KDRPITCH=0.05; float KPRROLL=2; float KIRROLL=0; float KDRROLL=0.05; float KPHIGHT=5; float KIHIGHT=1; float KDHIGHT=0.1; float SetpointROLL=0; float RateRequired=0; float SetpointPITCH=0; float InputPITCH, OutputPITCH=0,RATEXinput=0,RATEXoutput=0,SetpointPitchrate=0,SetpointRollrate=0; float InputROLL, OutputROLL=0,RATEYinput=0,RATEYoutput=0; float Input_altitude,delta_trotle=0,Setpointaltitude=600; /// ESC VARIABLES /// float in_pulse=1200; // ranging from 0 to 1 /// MPU VARIABLES /// bool blinkState = false; bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) uint16_t fifoCount; // count of all bytes currently in FIFO uint8_t fifoBuffer[64]; // FIFO storage buffer Quaternion q; // [w, x, y, z] quaternion container VectorInt16 aa; // [x, y, z] accel sensor measurements VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements VectorFloat gravity; // [x, y, z] gravity vector float euler[3]; // [psi, theta, phi] Euler angle container float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector uint8_t teapotPacket[15] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n',0 }; float mean_yaw=0 ; //int16_t &ax, &ay, &az; int16_t gx, gy, gz; // CALIBRATION VARIABLES // float AngleYaw,pAngleYaw,AnglePitch,pAnglePitch,AngleRoll,pAngleRoll; float AngleOffset[3]; int16_t GyroOffset[3]; int16_t Rate_x,Rate_y,Rate_z,pgx,pgy,pgz; int start_flag=0; ////// INITIAL SETUP ////// ////// mbed setup /////// Serial pc(p13 ,p14); //xbee 13/14 /// PID SETUP /// PID PITCHPID(&InputPITCH, &OutputPITCH, &SetpointPITCH,KPPitch,KIPitch,KDPitch); PID PITCHPIDrate(&RATEYinput, &RATEYoutput,&SetpointPitchrate,KPRPITCH,KIRPITCH,KDRPITCH); PID ROLLPID(&InputROLL, &OutputROLL, &SetpointROLL,KPRoll,KIRoll,KDRoll); PID ROLLPIDrate(&RATEXinput, &RATEXoutput,&SetpointRollrate,KPRROLL,KIRROLL,KDRROLL); PID altitudecontroller(&Input_altitude, &delta_trotle, &Setpointaltitude,KPHIGHT,KIHIGHT,KDHIGHT); //PID altitudedampingcontroller(&Zvelocity, &trotle_damping,&Setpoint_Zdamping,KPDAMPING,KIDAMPING,KDDAMPING); //dont forget to declare the variables /// MPU SETUP /// MPU6050 mpu; volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high void dmpDataReady() { mpuInterrupt = true; } /// Motors SETUP /// PwmOut esc1(p21); PwmOut esc2(p22); PwmOut esc3(p23); PwmOut esc4(p24); ///ultrasonic setup//// RangeFinder rf(p20, 10, 5800.0, 100000); /////////////////////////// ////// FUNCTION DECLARATIONS ////// /*void mpu_code(); void send_data(); void calibration();*/ ////// FUNCTIONS ////// void mpu_code(){ mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); fifoCount = mpu.getFIFOCount(); if ((mpuIntStatus & 0x10) || fifoCount == 1024) { mpu.resetFIFO(); pc.printf("FIFO overflow!"); } else if (mpuIntStatus & 0x02) { while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); mpu.getFIFOBytes(fifoBuffer, packetSize); fifoCount -= packetSize; #ifdef OUTPUT_READABLE_QUATERNION mpu.dmpGetQuaternion(&q, fifoBuffer); /*pc.printf("%f",q.w); pc.printf(","); pc.printf("%f",q.x); pc.printf(","); pc.printf("%f",q.y); pc.printf(","); pc.printf("%f\n",q.z);*/ #endif #ifdef OUTPUT_READABLE_EULER mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetEuler(euler, &q); /* pc.printf("euler\t"); pc.printf("%f",euler[0] * 180/M_PI); pc.printf("\t"); pc.printf("%f",euler[1] * 180/M_PI); pc.printf("\t"); pc.printf("%f\n",euler[2] * 180/M_PI);*/ #endif #ifdef OUTPUT_READABLE_YAWPITCHROLL mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); #endif #ifdef OUTPUT_READABLE_ACCELGYRO mpu.getRotation(&gx, &gy, &gz); // mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); /*pc.printf("a/g:\t"); pc.printf(gx); pc.printf("\t"); pc.printf(gy); pc.printf("\t"); pc.printf(gz); pc.printf("\t"); pc.printf(gz);*/ #endif #ifdef OUTPUT_READABLE_REALACCEL mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); #endif #ifdef OUTPUT_READABLE_WORLDACCEL mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetAccel(&aa, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q); #endif #ifdef OUTPUT_TEAPOT teapotPacket[2] = fifoBuffer[0]; teapotPacket[3] = fifoBuffer[1]; teapotPacket[4] = fifoBuffer[4]; teapotPacket[5] = fifoBuffer[5]; teapotPacket[6] = fifoBuffer[8]; teapotPacket[7] = fifoBuffer[9]; teapotPacket[8] = fifoBuffer[12]; teapotPacket[9] = fifoBuffer[13]; for(int i=0;i<14;i++) { pc.putc(teapotPacket[i]); } teapotPacket[11]++; // packetCount, loops at 0xFF on purpose #endif } } void send_data(){ /////////// Pitch Final output calibration /////////////// int Final_output_x1 = 1100+OutputPITCH+delta_trotle-RATEYoutput; int Final_output_x2 = 1100-OutputPITCH+delta_trotle+RATEYoutput; float min=1050; if (Final_output_x1 < min){ Final_output_x1=min; } else if (Final_output_x2 <min){ Final_output_x2=min; } /////////// Roll Final output calibration /////////////// int Final_output_y1 = 1100+OutputROLL+delta_trotle+RATEXoutput; int Final_output_y2 = 1100-OutputROLL+delta_trotle-RATEXoutput; if (Final_output_y1 < min){ Final_output_y1=min; } else if (Final_output_y2 <min){ Final_output_y2=min; } //////////////// Altitude final output calibration///////// //////////////// FINALIZATION ///////////////// esc1.pulsewidth_us(Final_output_y2); esc2.pulsewidth_us(Final_output_x1); esc3.pulsewidth_us(Final_output_y1); esc4.pulsewidth_us(Final_output_x2); } void calibration(){ if(pc.readable()) { switch (pc.getc()) { case 'c': AngleOffset[0]=ypr[0]; AngleOffset[1]=ypr[1]; AngleOffset[2]=ypr[2]; GyroOffset[0]=gx; GyroOffset[1]=gy; GyroOffset[2]=gz; break; case 'x': start_flag=0; case 's': start_flag=1; } } } ////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////// int main() { esc1.period_ms(20); esc2.period_ms(20); esc3.period_ms(20); esc4.period_ms(20); #define D_SDA p9 #define D_SCL p10 I2C i2c(D_SDA, D_SCL); DigitalOut myled1(LED1); DigitalOut myled2(LED2); DigitalOut myled3(LED3); DigitalOut heartbeatLED(LED4); #define D_BAUDRATE 115200 pc.baud(D_BAUDRATE); pc.printf("Initializing I2C devices...\n"); mpu.initialize(); pc.printf("Testing device connections...\n"); bool mpu6050TestResult = mpu.testConnection(); if(mpu6050TestResult){ pc.printf("MPU6050 test passed \n"); } else{ pc.printf("MPU6050 test failed \n"); } pc.printf("\nSend any character to begin DMP programming and demo: "); while(!pc.readable()); pc.getc(); pc.printf("\n"); pc.printf("Initializing DMP...\n"); devStatus = mpu.dmpInitialize(); mpu.setXGyroOffset(-61); mpu.setYGyroOffset(-127); mpu.setZGyroOffset(19); mpu.setZAccelOffset(16282); if (devStatus == 0) { pc.printf("Enabling DMP...\n"); mpu.setDMPEnabled(true); pc.printf("Enabling interrupt detection (Arduino external interrupt 0)...\n"); mpuIntStatus = mpu.getIntStatus(); pc.printf("DMP ready! Waiting for first interrupt...\n"); dmpReady = true; packetSize = mpu.dmpGetFIFOPacketSize(); } else { pc.printf("DMP Initialization failed (code "); pc.printf("%u",devStatus); pc.printf(")\n"); } esc1.pulsewidth_us(in_pulse); esc2.pulsewidth_us(in_pulse); esc3.pulsewidth_us(in_pulse); esc4.pulsewidth_us(in_pulse); //pc.printf("i am entering the loop"); /////////////////////////////////////////// // PROGRAM LOOP // /////////////////////////////////////////// while(1) { // setting an old value for the readings to use it in the filter pAngleYaw = AngleYaw; pAnglePitch = AnglePitch; pAngleRoll= AngleRoll; pgx = Rate_x; pgy = Rate_y; pgz = Rate_z; mpu_code(); calibration(); //pc.printf("g"); AngleYaw = ypr[0] - AngleOffset[0]; // calibrating the readings AnglePitch=ypr[1] - AngleOffset[1]; AngleRoll=ypr[2] - AngleOffset[2]; Rate_x =gx - GyroOffset[0]; Rate_y =gy - GyroOffset[1]; Rate_z =gz - GyroOffset[2]; AngleYaw = 0.7 * pAngleYaw + 0.3 * AngleYaw; // low pass filter AnglePitch = 0.7 * pAnglePitch + 0.3 * AnglePitch; AngleRoll = 0.7 * pAngleRoll + 0.3 * AngleRoll; Rate_x = 0.6 * pgx + 0.4 * Rate_x; Rate_y = 0.6 * pgy + 0.4 * Rate_y; Rate_z = 0.6 * pgz + 0.4 * Rate_z; InputPITCH=AnglePitch * 180/M_PI; InputROLL=AngleRoll * 180/M_PI; RATEXinput=Rate_x; RATEYinput=Rate_y; ///// measure distance ultrasonic//////// /* d = rf.read_m(); if (d == -1.0) { printf("Timeout Error.\n"); } else if (d > 5.0) { // Seeed's sensor has a maximum range of 4m, it returns // something like 7m if the ultrasound pulse isn't reflected. pc.printf("No object within detection range.\n"); } else { pc.printf("p:%f r:%f \n\r",AnglePitch*180/M_PI,AngleRoll*180/M_PI); }*/ ////////////////////////// if (start_flag==1){ //PITCHPID.Compute(); //ROLLPID.Compute(); PITCHPIDrate.Compute(); ROLLPIDrate.Compute(); //altitudecontroller.Compute(); send_data(); } else{ esc1.pulsewidth_us(1000); esc2.pulsewidth_us(1000); esc3.pulsewidth_us(1000); esc4.pulsewidth_us(1000); start_flag=0; } //pc.printf("pitch:%f roll:%f\r\n",AnglePitch*180/M_PI,AngleRoll*180/M_PI); pc.printf("rate y:%d rate x:%d\r\n",Rate_y,Rate_x); blinkState = !blinkState; myled1 = blinkState; } }