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
flightController.h
- Committer:
- joe4465
- Date:
- 2014-05-16
- Revision:
- 1:045edcf091f3
- Parent:
- 0:0010a5abcc31
- Child:
- 2:b3b771c8f7d1
File content as of revision 1:045edcf091f3:
#include "mbed.h" #include "rtos.h" #include "hardware.h" //Declarations float Constrain(const float in, const float min, const float max); float map(float x, float in_min, float in_max, float out_min, float out_max); void GetAttitude(); void Task500Hz(void const *n); void Task10Hz(); //Variables float _gyroRate[3] ={}; // Yaw, Pitch, Roll float _yawTarget = 0; int _notFlying = 0; float _altitude = 0; int _10HzIterator = 0; //Timers RtosTimer *_updateTimer; // A thread to monitor the serial ports void FlightControllerThread(void const *args) { //Update Timer _updateTimer = new RtosTimer(Task500Hz, osTimerPeriodic, (void *)0); int updateTime = (1.0 / UPDATE_FREQUENCY) * 1000; _updateTimer->start(updateTime); // Wait here forever Thread::wait(osWaitForever); } //Constrains value to between min and max float Constrain(const float in, const float min, const float max) { float out = in; out = out > max ? max : out; out = out < min ? min : out; return out; } //Maps input to output float map(float x, float in_min, float in_max, float out_min, float out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; } //Zeros values void GetAttitude() { //Take off zero values to account for any angle inbetween the PCB level and ground _ypr[1] = _ypr[1] - _zeroValues[1]; _ypr[2] = _ypr[2] - _zeroValues[2]; //Swap pitch and roll because IMU is mounted at a right angle to the board float pitch = _ypr[2]; float roll = _ypr[1]; _ypr[1] = pitch; _ypr[2] = roll; } void Task500Hz(void const *n) { _10HzIterator++; if(_10HzIterator % 50 == 0) { Task10Hz(); } //Get IMU data _freeIMU.getYawPitchRoll(_ypr); _freeIMU.getRate(_gyroRate); GetAttitude(); //Rate mode if(_rate == true && _stab == false) { //Update rate PID process value with gyro rate _yawRatePIDController->setProcessValue(_gyroRate[0]); _pitchRatePIDController->setProcessValue(_gyroRate[1]); _rollRatePIDController->setProcessValue(_gyroRate[2]); //Update rate PID set point with desired rate from RC _yawRatePIDController->setSetPoint(_rcMappedCommands[0]); _pitchRatePIDController->setSetPoint(_rcMappedCommands[1]); _rollRatePIDController->setSetPoint(_rcMappedCommands[2]); //Compute rate PID outputs _ratePIDControllerOutputs[0] = _yawRatePIDController->compute(); _ratePIDControllerOutputs[1] = _pitchRatePIDController->compute(); _ratePIDControllerOutputs[2] = _rollRatePIDController->compute(); } //Stability mode else { //Update stab PID process value with ypr _yawStabPIDController->setProcessValue(_ypr[0]); _pitchStabPIDController->setProcessValue(_ypr[1]); _rollStabPIDController->setProcessValue(_ypr[2]); //Update stab PID set point with desired angle from RC _yawStabPIDController->setSetPoint(_yawTarget); _pitchStabPIDController->setSetPoint(_rcMappedCommands[1]); _rollStabPIDController->setSetPoint(_rcMappedCommands[2]); //Compute stab PID outputs _stabPIDControllerOutputs[0] = _yawStabPIDController->compute(); _stabPIDControllerOutputs[1] = _pitchStabPIDController->compute(); _stabPIDControllerOutputs[2] = _rollStabPIDController->compute(); //If pilot commanding yaw if(abs(_rcMappedCommands[0]) > 0) { _stabPIDControllerOutputs[0] = _rcMappedCommands[0]; //Feed to rate PID (overwriting stab PID output) _yawTarget = _ypr[0]; } //Update rate PID process value with gyro rate _yawRatePIDController->setProcessValue(_gyroRate[0]); _pitchRatePIDController->setProcessValue(_gyroRate[1]); _rollRatePIDController->setProcessValue(_gyroRate[2]); //Update rate PID set point with desired rate from stab PID _yawRatePIDController->setSetPoint(_stabPIDControllerOutputs[0]); _pitchRatePIDController->setSetPoint(_stabPIDControllerOutputs[1]); _rollRatePIDController->setSetPoint(_stabPIDControllerOutputs[2]); //Compute rate PID outputs _ratePIDControllerOutputs[0] = _yawRatePIDController->compute(); _ratePIDControllerOutputs[1] = _pitchRatePIDController->compute(); _ratePIDControllerOutputs[2] = _rollRatePIDController->compute(); } //Testing _ratePIDControllerOutputs[0] = 0; // yaw //_ratePIDControllerOutputs[1] = 0; // pitch _ratePIDControllerOutputs[2] = 0; // roll //Calculate motor power if flying if(_rcMappedCommands[3] > 0.1 && _armed == true) { //Constrain motor power to 1, this means at max throttle there is no overhead for stabilising _motorPower[0] = Constrain((_rcMappedCommands[3] + _ratePIDControllerOutputs[1] - _ratePIDControllerOutputs[2] + _ratePIDControllerOutputs[0]), 0.0, 1.0); _motorPower[1] = Constrain((_rcMappedCommands[3] + _ratePIDControllerOutputs[1] + _ratePIDControllerOutputs[2] - _ratePIDControllerOutputs[0]), 0.0, 1.0); _motorPower[2] = Constrain((_rcMappedCommands[3] - _ratePIDControllerOutputs[1] + _ratePIDControllerOutputs[2] + _ratePIDControllerOutputs[0]), 0.0, 1.0); _motorPower[3] = Constrain((_rcMappedCommands[3] - _ratePIDControllerOutputs[1] - _ratePIDControllerOutputs[2] - _ratePIDControllerOutputs[0]), 0.0, 1.0); //Map 0-1 value to actual pwm pulsewidth 1060 - 1860 _motorPower[0] = map(_motorPower[0], 0.0, 1.0, MOTORS_MIN, 1500); //Reduced to 1500 to limit power for testing _motorPower[1] = map(_motorPower[1], 0.0, 1.0, MOTORS_MIN, 1500); _motorPower[2] = map(_motorPower[2], 0.0, 1.0, MOTORS_MIN, 1500); _motorPower[3] = map(_motorPower[3], 0.0, 1.0, MOTORS_MIN, 1500); } //Not flying else if(_armed == true) { _yawTarget = _ypr[0]; //Set motors to armed state _motorPower[0] = MOTORS_ARMED; _motorPower[1] = MOTORS_ARMED; _motorPower[2] = MOTORS_ARMED; _motorPower[3] = MOTORS_ARMED; _notFlying ++; if(_notFlying > 500) //Not flying for 1 second { //Reset iteratior _notFlying = 0; //Reset I _yawRatePIDController->reset(); _pitchRatePIDController->reset(); _rollRatePIDController->reset(); _yawStabPIDController->reset(); _pitchStabPIDController->reset(); _rollStabPIDController->reset(); } } else { //Disable Motors _motorPower[0] = MOTORS_OFF; _motorPower[1] = MOTORS_OFF; _motorPower[2] = MOTORS_OFF; _motorPower[3] = MOTORS_OFF; } //Set motor power _motor1.pulsewidth_us(_motorPower[0]); _motor2.pulsewidth_us(_motorPower[1]); _motor3.pulsewidth_us(_motorPower[2]); _motor4.pulsewidth_us(_motorPower[3]); } //Print data void Task10Hz() { int batt = 0; _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>", _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); }