Quadcopter software. Flying - Contact me for more details or a copy of the PC ground station code

Dependencies:   ConfigFile PID PPM MODSERIAL mbed-rtos mbed MaxbotixDriver TinyGPS filter

Committer:
joe4465
Date:
Fri May 16 14:22:18 2014 +0000
Revision:
2:b3b771c8f7d1
Parent:
1:045edcf091f3
Child:
3:82665e39f1ea
second commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
joe4465 0:0010a5abcc31 1 #include "mbed.h"
joe4465 0:0010a5abcc31 2 #include "rtos.h"
joe4465 0:0010a5abcc31 3 #include "hardware.h"
joe4465 0:0010a5abcc31 4
joe4465 0:0010a5abcc31 5 //Declarations
joe4465 0:0010a5abcc31 6 float Constrain(const float in, const float min, const float max);
joe4465 0:0010a5abcc31 7 float map(float x, float in_min, float in_max, float out_min, float out_max);
joe4465 0:0010a5abcc31 8 void GetAttitude();
joe4465 0:0010a5abcc31 9 void Task500Hz(void const *n);
joe4465 0:0010a5abcc31 10 void Task10Hz();
joe4465 0:0010a5abcc31 11
joe4465 0:0010a5abcc31 12 //Variables
joe4465 0:0010a5abcc31 13 float _gyroRate[3] ={}; // Yaw, Pitch, Roll
joe4465 2:b3b771c8f7d1 14 float _ypr[3] = {0,0,0}; // Yaw, pitch, roll
joe4465 0:0010a5abcc31 15 float _yawTarget = 0;
joe4465 0:0010a5abcc31 16 int _notFlying = 0;
joe4465 0:0010a5abcc31 17 float _altitude = 0;
joe4465 0:0010a5abcc31 18 int _10HzIterator = 0;
joe4465 2:b3b771c8f7d1 19 float _ratePIDControllerOutputs[3] = {0,0,0}; //Yaw, pitch, roll
joe4465 2:b3b771c8f7d1 20 float _stabPIDControllerOutputs[3] = {0,0,0}; //Yaw, pitch, roll
joe4465 2:b3b771c8f7d1 21 float _motorPower [4] = {0,0,0,0};
joe4465 2:b3b771c8f7d1 22
joe4465 0:0010a5abcc31 23
joe4465 1:045edcf091f3 24 //Timers
joe4465 1:045edcf091f3 25 RtosTimer *_updateTimer;
joe4465 1:045edcf091f3 26
joe4465 0:0010a5abcc31 27 // A thread to monitor the serial ports
joe4465 0:0010a5abcc31 28 void FlightControllerThread(void const *args)
joe4465 0:0010a5abcc31 29 {
joe4465 1:045edcf091f3 30 //Update Timer
joe4465 0:0010a5abcc31 31 _updateTimer = new RtosTimer(Task500Hz, osTimerPeriodic, (void *)0);
joe4465 0:0010a5abcc31 32 int updateTime = (1.0 / UPDATE_FREQUENCY) * 1000;
joe4465 0:0010a5abcc31 33 _updateTimer->start(updateTime);
joe4465 0:0010a5abcc31 34
joe4465 0:0010a5abcc31 35 // Wait here forever
joe4465 0:0010a5abcc31 36 Thread::wait(osWaitForever);
joe4465 0:0010a5abcc31 37 }
joe4465 0:0010a5abcc31 38
joe4465 0:0010a5abcc31 39 //Constrains value to between min and max
joe4465 0:0010a5abcc31 40 float Constrain(const float in, const float min, const float max)
joe4465 0:0010a5abcc31 41 {
joe4465 0:0010a5abcc31 42 float out = in;
joe4465 0:0010a5abcc31 43 out = out > max ? max : out;
joe4465 0:0010a5abcc31 44 out = out < min ? min : out;
joe4465 0:0010a5abcc31 45 return out;
joe4465 0:0010a5abcc31 46 }
joe4465 0:0010a5abcc31 47
joe4465 0:0010a5abcc31 48 //Maps input to output
joe4465 0:0010a5abcc31 49 float map(float x, float in_min, float in_max, float out_min, float out_max)
joe4465 0:0010a5abcc31 50 {
joe4465 0:0010a5abcc31 51 return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
joe4465 0:0010a5abcc31 52 }
joe4465 0:0010a5abcc31 53
joe4465 0:0010a5abcc31 54 //Zeros values
joe4465 0:0010a5abcc31 55 void GetAttitude()
joe4465 0:0010a5abcc31 56 {
joe4465 1:045edcf091f3 57 //Take off zero values to account for any angle inbetween the PCB level and ground
joe4465 0:0010a5abcc31 58 _ypr[1] = _ypr[1] - _zeroValues[1];
joe4465 0:0010a5abcc31 59 _ypr[2] = _ypr[2] - _zeroValues[2];
joe4465 0:0010a5abcc31 60
joe4465 0:0010a5abcc31 61 //Swap pitch and roll because IMU is mounted at a right angle to the board
joe4465 0:0010a5abcc31 62 float pitch = _ypr[2];
joe4465 0:0010a5abcc31 63 float roll = _ypr[1];
joe4465 0:0010a5abcc31 64 _ypr[1] = pitch;
joe4465 0:0010a5abcc31 65 _ypr[2] = roll;
joe4465 0:0010a5abcc31 66 }
joe4465 0:0010a5abcc31 67
joe4465 0:0010a5abcc31 68 void Task500Hz(void const *n)
joe4465 0:0010a5abcc31 69 {
joe4465 1:045edcf091f3 70 _10HzIterator++;
joe4465 1:045edcf091f3 71 if(_10HzIterator % 50 == 0)
joe4465 0:0010a5abcc31 72 {
joe4465 1:045edcf091f3 73 Task10Hz();
joe4465 0:0010a5abcc31 74 }
joe4465 0:0010a5abcc31 75
joe4465 0:0010a5abcc31 76 //Get IMU data
joe4465 0:0010a5abcc31 77 _freeIMU.getYawPitchRoll(_ypr);
joe4465 0:0010a5abcc31 78 _freeIMU.getRate(_gyroRate);
joe4465 0:0010a5abcc31 79 GetAttitude();
joe4465 0:0010a5abcc31 80
joe4465 0:0010a5abcc31 81 //Rate mode
joe4465 0:0010a5abcc31 82 if(_rate == true && _stab == false)
joe4465 0:0010a5abcc31 83 {
joe4465 0:0010a5abcc31 84 //Update rate PID process value with gyro rate
joe4465 0:0010a5abcc31 85 _yawRatePIDController->setProcessValue(_gyroRate[0]);
joe4465 0:0010a5abcc31 86 _pitchRatePIDController->setProcessValue(_gyroRate[1]);
joe4465 0:0010a5abcc31 87 _rollRatePIDController->setProcessValue(_gyroRate[2]);
joe4465 0:0010a5abcc31 88
joe4465 0:0010a5abcc31 89 //Update rate PID set point with desired rate from RC
joe4465 1:045edcf091f3 90 _yawRatePIDController->setSetPoint(_rcMappedCommands[0]);
joe4465 1:045edcf091f3 91 _pitchRatePIDController->setSetPoint(_rcMappedCommands[1]);
joe4465 1:045edcf091f3 92 _rollRatePIDController->setSetPoint(_rcMappedCommands[2]);
joe4465 0:0010a5abcc31 93
joe4465 0:0010a5abcc31 94 //Compute rate PID outputs
joe4465 0:0010a5abcc31 95 _ratePIDControllerOutputs[0] = _yawRatePIDController->compute();
joe4465 1:045edcf091f3 96 _ratePIDControllerOutputs[1] = _pitchRatePIDController->compute();
joe4465 0:0010a5abcc31 97 _ratePIDControllerOutputs[2] = _rollRatePIDController->compute();
joe4465 0:0010a5abcc31 98 }
joe4465 0:0010a5abcc31 99 //Stability mode
joe4465 0:0010a5abcc31 100 else
joe4465 0:0010a5abcc31 101 {
joe4465 0:0010a5abcc31 102 //Update stab PID process value with ypr
joe4465 0:0010a5abcc31 103 _yawStabPIDController->setProcessValue(_ypr[0]);
joe4465 0:0010a5abcc31 104 _pitchStabPIDController->setProcessValue(_ypr[1]);
joe4465 0:0010a5abcc31 105 _rollStabPIDController->setProcessValue(_ypr[2]);
joe4465 0:0010a5abcc31 106
joe4465 0:0010a5abcc31 107 //Update stab PID set point with desired angle from RC
joe4465 0:0010a5abcc31 108 _yawStabPIDController->setSetPoint(_yawTarget);
joe4465 1:045edcf091f3 109 _pitchStabPIDController->setSetPoint(_rcMappedCommands[1]);
joe4465 1:045edcf091f3 110 _rollStabPIDController->setSetPoint(_rcMappedCommands[2]);
joe4465 0:0010a5abcc31 111
joe4465 0:0010a5abcc31 112 //Compute stab PID outputs
joe4465 0:0010a5abcc31 113 _stabPIDControllerOutputs[0] = _yawStabPIDController->compute();
joe4465 1:045edcf091f3 114 _stabPIDControllerOutputs[1] = _pitchStabPIDController->compute();
joe4465 0:0010a5abcc31 115 _stabPIDControllerOutputs[2] = _rollStabPIDController->compute();
joe4465 0:0010a5abcc31 116
joe4465 1:045edcf091f3 117 //If pilot commanding yaw
joe4465 1:045edcf091f3 118 if(abs(_rcMappedCommands[0]) > 0)
joe4465 0:0010a5abcc31 119 {
joe4465 1:045edcf091f3 120 _stabPIDControllerOutputs[0] = _rcMappedCommands[0]; //Feed to rate PID (overwriting stab PID output)
joe4465 0:0010a5abcc31 121 _yawTarget = _ypr[0];
joe4465 0:0010a5abcc31 122 }
joe4465 0:0010a5abcc31 123
joe4465 0:0010a5abcc31 124 //Update rate PID process value with gyro rate
joe4465 0:0010a5abcc31 125 _yawRatePIDController->setProcessValue(_gyroRate[0]);
joe4465 0:0010a5abcc31 126 _pitchRatePIDController->setProcessValue(_gyroRate[1]);
joe4465 0:0010a5abcc31 127 _rollRatePIDController->setProcessValue(_gyroRate[2]);
joe4465 0:0010a5abcc31 128
joe4465 0:0010a5abcc31 129 //Update rate PID set point with desired rate from stab PID
joe4465 0:0010a5abcc31 130 _yawRatePIDController->setSetPoint(_stabPIDControllerOutputs[0]);
joe4465 0:0010a5abcc31 131 _pitchRatePIDController->setSetPoint(_stabPIDControllerOutputs[1]);
joe4465 0:0010a5abcc31 132 _rollRatePIDController->setSetPoint(_stabPIDControllerOutputs[2]);
joe4465 0:0010a5abcc31 133
joe4465 0:0010a5abcc31 134 //Compute rate PID outputs
joe4465 0:0010a5abcc31 135 _ratePIDControllerOutputs[0] = _yawRatePIDController->compute();
joe4465 0:0010a5abcc31 136 _ratePIDControllerOutputs[1] = _pitchRatePIDController->compute();
joe4465 0:0010a5abcc31 137 _ratePIDControllerOutputs[2] = _rollRatePIDController->compute();
joe4465 0:0010a5abcc31 138 }
joe4465 0:0010a5abcc31 139
joe4465 0:0010a5abcc31 140 //Testing
joe4465 1:045edcf091f3 141 _ratePIDControllerOutputs[0] = 0; // yaw
joe4465 0:0010a5abcc31 142 //_ratePIDControllerOutputs[1] = 0; // pitch
joe4465 1:045edcf091f3 143 _ratePIDControllerOutputs[2] = 0; // roll
joe4465 0:0010a5abcc31 144
joe4465 0:0010a5abcc31 145 //Calculate motor power if flying
joe4465 1:045edcf091f3 146 if(_rcMappedCommands[3] > 0.1 && _armed == true)
joe4465 0:0010a5abcc31 147 {
joe4465 0:0010a5abcc31 148 //Constrain motor power to 1, this means at max throttle there is no overhead for stabilising
joe4465 1:045edcf091f3 149 _motorPower[0] = Constrain((_rcMappedCommands[3] + _ratePIDControllerOutputs[1] - _ratePIDControllerOutputs[2] + _ratePIDControllerOutputs[0]), 0.0, 1.0);
joe4465 1:045edcf091f3 150 _motorPower[1] = Constrain((_rcMappedCommands[3] + _ratePIDControllerOutputs[1] + _ratePIDControllerOutputs[2] - _ratePIDControllerOutputs[0]), 0.0, 1.0);
joe4465 1:045edcf091f3 151 _motorPower[2] = Constrain((_rcMappedCommands[3] - _ratePIDControllerOutputs[1] + _ratePIDControllerOutputs[2] + _ratePIDControllerOutputs[0]), 0.0, 1.0);
joe4465 1:045edcf091f3 152 _motorPower[3] = Constrain((_rcMappedCommands[3] - _ratePIDControllerOutputs[1] - _ratePIDControllerOutputs[2] - _ratePIDControllerOutputs[0]), 0.0, 1.0);
joe4465 0:0010a5abcc31 153
joe4465 0:0010a5abcc31 154
joe4465 0:0010a5abcc31 155 //Map 0-1 value to actual pwm pulsewidth 1060 - 1860
joe4465 1:045edcf091f3 156 _motorPower[0] = map(_motorPower[0], 0.0, 1.0, MOTORS_MIN, 1500); //Reduced to 1500 to limit power for testing
joe4465 1:045edcf091f3 157 _motorPower[1] = map(_motorPower[1], 0.0, 1.0, MOTORS_MIN, 1500);
joe4465 1:045edcf091f3 158 _motorPower[2] = map(_motorPower[2], 0.0, 1.0, MOTORS_MIN, 1500);
joe4465 1:045edcf091f3 159 _motorPower[3] = map(_motorPower[3], 0.0, 1.0, MOTORS_MIN, 1500);
joe4465 0:0010a5abcc31 160 }
joe4465 0:0010a5abcc31 161
joe4465 0:0010a5abcc31 162 //Not flying
joe4465 0:0010a5abcc31 163 else if(_armed == true)
joe4465 0:0010a5abcc31 164 {
joe4465 1:045edcf091f3 165 _yawTarget = _ypr[0];
joe4465 1:045edcf091f3 166
joe4465 0:0010a5abcc31 167 //Set motors to armed state
joe4465 0:0010a5abcc31 168 _motorPower[0] = MOTORS_ARMED;
joe4465 0:0010a5abcc31 169 _motorPower[1] = MOTORS_ARMED;
joe4465 0:0010a5abcc31 170 _motorPower[2] = MOTORS_ARMED;
joe4465 0:0010a5abcc31 171 _motorPower[3] = MOTORS_ARMED;
joe4465 0:0010a5abcc31 172
joe4465 0:0010a5abcc31 173 _notFlying ++;
joe4465 0:0010a5abcc31 174 if(_notFlying > 500) //Not flying for 1 second
joe4465 0:0010a5abcc31 175 {
joe4465 0:0010a5abcc31 176 //Reset iteratior
joe4465 0:0010a5abcc31 177 _notFlying = 0;
joe4465 0:0010a5abcc31 178
joe4465 0:0010a5abcc31 179 //Reset I
joe4465 0:0010a5abcc31 180 _yawRatePIDController->reset();
joe4465 0:0010a5abcc31 181 _pitchRatePIDController->reset();
joe4465 0:0010a5abcc31 182 _rollRatePIDController->reset();
joe4465 0:0010a5abcc31 183 _yawStabPIDController->reset();
joe4465 0:0010a5abcc31 184 _pitchStabPIDController->reset();
joe4465 0:0010a5abcc31 185 _rollStabPIDController->reset();
joe4465 0:0010a5abcc31 186 }
joe4465 0:0010a5abcc31 187 }
joe4465 0:0010a5abcc31 188 else
joe4465 0:0010a5abcc31 189 {
joe4465 0:0010a5abcc31 190 //Disable Motors
joe4465 0:0010a5abcc31 191 _motorPower[0] = MOTORS_OFF;
joe4465 0:0010a5abcc31 192 _motorPower[1] = MOTORS_OFF;
joe4465 0:0010a5abcc31 193 _motorPower[2] = MOTORS_OFF;
joe4465 0:0010a5abcc31 194 _motorPower[3] = MOTORS_OFF;
joe4465 0:0010a5abcc31 195 }
joe4465 0:0010a5abcc31 196
joe4465 0:0010a5abcc31 197 //Set motor power
joe4465 0:0010a5abcc31 198 _motor1.pulsewidth_us(_motorPower[0]);
joe4465 0:0010a5abcc31 199 _motor2.pulsewidth_us(_motorPower[1]);
joe4465 0:0010a5abcc31 200 _motor3.pulsewidth_us(_motorPower[2]);
joe4465 0:0010a5abcc31 201 _motor4.pulsewidth_us(_motorPower[3]);
joe4465 0:0010a5abcc31 202 }
joe4465 0:0010a5abcc31 203
joe4465 0:0010a5abcc31 204 //Print data
joe4465 0:0010a5abcc31 205 void Task10Hz()
joe4465 0:0010a5abcc31 206 {
joe4465 0:0010a5abcc31 207 int batt = 0;
joe4465 0:0010a5abcc31 208 _wirelessSerial.printf("<%1.6f:%1.6f:%1.6f:%1.6f:%1.6f:%1.6f:%1.6f:%d:%1.6f:%1.6f:%1.6f:%1.6f:%1.6f:%1.6f:%d:%d:%d:%d:%1.6f:%1.6f:%1.6f:%1.2f:%1.2f:%1.2f:%1.2f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f:%1.8f>",
joe4465 1:045edcf091f3 209 _motorPower[0], _motorPower[1], _motorPower[2], _motorPower[3], _ypr[0], _ypr[1], _ypr[2], batt, _ratePIDControllerOutputs[0], _ratePIDControllerOutputs[1], _ratePIDControllerOutputs[2], _stabPIDControllerOutputs[0], _stabPIDControllerOutputs[1], _stabPIDControllerOutputs[2], _armed, _initialised, _rate, _stab, _gyroRate[0], _gyroRate[1], _gyroRate[2], _rcMappedCommands[0], _rcMappedCommands[1], _rcMappedCommands[2], _rcMappedCommands[3], _yawRatePIDControllerP, _yawRatePIDControllerI, _yawRatePIDControllerD, _pitchRatePIDControllerP, _pitchRatePIDControllerI, _pitchRatePIDControllerD, _rollRatePIDControllerP, _rollRatePIDControllerI, _rollRatePIDControllerD, _yawStabPIDControllerP, _yawStabPIDControllerI, _yawStabPIDControllerD, _pitchStabPIDControllerP, _pitchStabPIDControllerI, _pitchStabPIDControllerD, _rollStabPIDControllerP, _rollStabPIDControllerI, _rollStabPIDControllerD);
joe4465 0:0010a5abcc31 210 }