Rev 2142 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1910 | - | 1 | #include <stdlib.h> |
2 | #include <avr/io.h> |
||
3 | #include "eeprom.h" |
||
4 | #include "flight.h" |
||
5 | #include "output.h" |
||
6 | |||
7 | // Necessary for external control and motor test |
||
8 | #include "uart0.h" |
||
9 | #include "timer2.h" |
||
2103 | - | 10 | #include "analog.h" |
1910 | - | 11 | #include "attitude.h" |
12 | #include "controlMixer.h" |
||
2104 | - | 13 | #include "configuration.h" |
1910 | - | 14 | |
15 | #define CHECK_MIN_MAX(value, min, max) {if(value < min) value = min; else if(value > max) value = max;} |
||
16 | |||
17 | /* |
||
2099 | - | 18 | * target-directions integrals. |
1910 | - | 19 | */ |
2099 | - | 20 | int32_t target[3]; |
1910 | - | 21 | |
2099 | - | 22 | /* |
23 | * Error integrals. |
||
24 | */ |
||
1910 | - | 25 | |
2104 | - | 26 | int32_t maxError[3]; |
2099 | - | 27 | int32_t IPart[3] = { 0, 0, 0 }; |
2104 | - | 28 | PID_t airspeedPID[3]; |
1910 | - | 29 | |
2104 | - | 30 | int16_t controlServos[NUM_CONTROL_SERVOS]; |
1910 | - | 31 | |
32 | /************************************************************************/ |
||
33 | /* Neutral Readings */ |
||
34 | /************************************************************************/ |
||
35 | #define CONTROL_CONFIG_SCALE 10 |
||
36 | |||
2099 | - | 37 | void flight_setGround(void) { |
2102 | - | 38 | IPart[PITCH] = IPart[ROLL] = IPart[YAW] = 0; |
39 | target[PITCH] = attitude[PITCH]; |
||
40 | target[ROLL] = attitude[ROLL]; |
||
41 | target[YAW] = attitude[YAW]; |
||
1910 | - | 42 | } |
43 | |||
2104 | - | 44 | void flight_updateFlightParametersToFlightMode(void) { |
45 | debugOut.analog[16] = currentFlightMode; |
||
1910 | - | 46 | |
2104 | - | 47 | // At a switch to angles, we want to kill errors first. |
48 | // This should be triggered only once per mode change! |
||
49 | if (currentFlightMode == FLIGHT_MODE_ANGLES) { |
||
50 | target[PITCH] = attitude[PITCH]; |
||
51 | target[ROLL] = attitude[ROLL]; |
||
52 | target[YAW] = attitude[YAW]; |
||
53 | } |
||
1910 | - | 54 | |
2104 | - | 55 | for (uint8_t axis=0; axis<3; axis++) { |
56 | maxError[axis] = (int32_t)staticParams.gyroPID[axis].iMax * GYRO_DEG_FACTOR; |
||
57 | } |
||
58 | } |
||
2102 | - | 59 | |
2143 | - | 60 | // min = 10 max = 12, speed = 11 shold make 50/50 cycle. |
61 | void updateAirspeedIndicatorLEDs(void) { |
||
62 | static uint8_t flashPrescaler = 0; |
||
63 | static uint8_t flashCnt = 0; |
||
64 | |||
65 | flashPrescaler++; |
||
66 | if (flashPrescaler == 10) { |
||
67 | flashPrescaler = 0; |
||
68 | |||
69 | if (airspeedVelocity <= staticParams.minFlashAirspeed) { |
||
70 | debugOut.digital[0] &= ~DEBUG_AIRSPEED; |
||
71 | debugOut.digital[1] &= ~DEBUG_AIRSPEED; |
||
72 | return; |
||
73 | } |
||
74 | if (airspeedVelocity >= staticParams.maxFlashAirspeed) { |
||
75 | debugOut.digital[0] |= DEBUG_AIRSPEED; |
||
76 | debugOut.digital[1] |= DEBUG_AIRSPEED; |
||
77 | return; |
||
78 | } |
||
79 | |||
80 | uint8_t span = staticParams.maxFlashAirspeed - staticParams.minFlashAirspeed; // is 2 |
||
81 | uint8_t speed = airspeedVelocity - staticParams.minFlashAirspeed; // is 1 |
||
82 | |||
83 | if (flashCnt > speed) { |
||
84 | debugOut.digital[0] &= ~DEBUG_AIRSPEED; |
||
85 | debugOut.digital[1] &= ~DEBUG_AIRSPEED; |
||
86 | } else { |
||
87 | debugOut.digital[0] |= DEBUG_AIRSPEED; |
||
88 | debugOut.digital[1] |= DEBUG_AIRSPEED; |
||
89 | } |
||
90 | |||
91 | flashCnt++; |
||
92 | if (flashCnt >= span) flashCnt = 0; |
||
93 | } |
||
94 | } |
||
95 | |||
2104 | - | 96 | // Normal at airspeed = 10. |
97 | uint8_t calcAirspeedPID(uint8_t pid) { |
||
2119 | - | 98 | if (!(staticParams.bitConfig & CFG_USE_AIRSPEED_PID)) { |
2104 | - | 99 | return pid; |
2102 | - | 100 | } |
2104 | - | 101 | |
2106 | - | 102 | uint16_t result = (pid * 10) / airspeedVelocity; |
2104 | - | 103 | |
2106 | - | 104 | if (result > 240 || airspeedVelocity == 0) { |
2104 | - | 105 | result = 240; |
106 | } |
||
107 | |||
108 | return result; |
||
1910 | - | 109 | } |
110 | |||
2104 | - | 111 | void setAirspeedPIDs(void) { |
112 | for (uint8_t axis = 0; axis<3; axis++) { |
||
113 | airspeedPID[axis].P = calcAirspeedPID(dynamicParams.gyroPID[axis].P); |
||
114 | airspeedPID[axis].I = calcAirspeedPID(dynamicParams.gyroPID[axis].I); // Should this be??? |
||
115 | airspeedPID[axis].D = dynamicParams.gyroPID[axis].D; |
||
116 | } |
||
117 | } |
||
118 | |||
1910 | - | 119 | /************************************************************************/ |
120 | /* Main Flight Control */ |
||
121 | /************************************************************************/ |
||
122 | void flight_control(void) { |
||
2102 | - | 123 | // Mixer Fractions that are combined for Motor Control |
2103 | - | 124 | int16_t term[4]; |
2099 | - | 125 | |
2102 | - | 126 | // PID controller variables |
127 | int16_t PDPart[3]; |
||
1910 | - | 128 | |
2102 | - | 129 | static int8_t debugDataTimer = 1; |
1910 | - | 130 | |
2102 | - | 131 | // High resolution motor values for smoothing of PID motor outputs |
132 | // static int16_t outputFilters[MAX_OUTPUTS]; |
||
1910 | - | 133 | |
2102 | - | 134 | uint8_t axis; |
1910 | - | 135 | |
2104 | - | 136 | setAirspeedPIDs(); |
137 | |||
2103 | - | 138 | term[CONTROL_THROTTLE] = controls[CONTROL_THROTTLE]; |
1910 | - | 139 | |
2102 | - | 140 | // These params are just left the same in all modes. In MANUAL and RATE the results are ignored anyway. |
2122 | - | 141 | int32_t tmp; |
1910 | - | 142 | |
2122 | - | 143 | tmp = ((int32_t)controls[CONTROL_ELEVATOR] * staticParams.stickIElevator) >> LOG_STICK_SCALE; |
2142 | - | 144 | if (staticParams.servos[PITCH].reverse) target[PITCH] += tmp; else target[PITCH] -= tmp; |
2122 | - | 145 | |
146 | tmp = ((int32_t)controls[CONTROL_AILERONS] * staticParams.stickIAilerons) >> LOG_STICK_SCALE; |
||
2142 | - | 147 | if (staticParams.servos[ROLL].reverse) target[ROLL] += tmp; else target[ROLL] -= tmp; |
2122 | - | 148 | |
149 | tmp = ((int32_t)controls[CONTROL_RUDDER] * staticParams.stickIRudder) >> LOG_STICK_SCALE; |
||
2142 | - | 150 | if (staticParams.servos[YAW].reverse) target[YAW] += tmp; else target[YAW] -= tmp; |
2122 | - | 151 | |
2102 | - | 152 | for (axis = PITCH; axis <= YAW; axis++) { |
153 | if (target[axis] > OVER180) { |
||
154 | target[axis] -= OVER360; |
||
2103 | - | 155 | } else if (target[axis] <= -OVER180) { |
2104 | - | 156 | target[axis] += OVER360; |
2102 | - | 157 | } |
1910 | - | 158 | |
2135 | - | 159 | int32_t error = attitude[axis] - target[axis]; |
2129 | - | 160 | |
2131 | - | 161 | #define ROTATETARGET 1 |
162 | // #define TRUNCATEERROR 1 |
||
163 | |||
2132 | - | 164 | #ifdef ROTATETARGET |
2135 | - | 165 | //if(abs(error) > OVER180) { // doesnt work!!! |
166 | if(error > OVER180 || error < -OVER180) { |
||
2131 | - | 167 | // The shortest way from attitude to target crosses -180. |
168 | // Well there are 2 possibilities: A is >0 and T is < 0, that makes E a (too) large positive number. It should be wrapped to negative. |
||
169 | // Or A is <0 and T is >0, that makes E a (too) large negative number. It should be wrapped to positive. |
||
2135 | - | 170 | if (error > 0) { |
171 | if (error < OVER360 - maxError[axis]) { |
||
2131 | - | 172 | // too much err. |
2135 | - | 173 | error = -maxError[axis]; |
2131 | - | 174 | target[axis] = attitude[axis] + maxError[axis]; |
2132 | - | 175 | if (target[axis] > OVER180) target[axis] -= OVER360; |
2131 | - | 176 | } else { |
177 | // Normal case, we just need to correct for the wrap. Error will be negative. |
||
2135 | - | 178 | error -= OVER360; |
2131 | - | 179 | } |
180 | } else { |
||
2135 | - | 181 | if (error > maxError[axis] - OVER360) { |
2131 | - | 182 | // too much err. |
2135 | - | 183 | error = maxError[axis]; |
2131 | - | 184 | target[axis] = attitude[axis] - maxError[axis]; |
2132 | - | 185 | if (target[axis] < -OVER180) target[axis] += OVER360; |
2131 | - | 186 | } else { |
187 | // Normal case, we just need to correct for the wrap. Error will be negative. |
||
2135 | - | 188 | error += OVER360; |
2131 | - | 189 | } |
190 | } |
||
191 | } else { |
||
192 | // Simple case, linear range. |
||
2135 | - | 193 | if (error > maxError[axis]) { |
194 | error = maxError[axis]; |
||
2131 | - | 195 | target[axis] = attitude[axis] - maxError[axis]; |
2135 | - | 196 | } else if (error < -maxError[axis]) { |
197 | error = -maxError[axis]; |
||
2131 | - | 198 | target[axis] = attitude[axis] + maxError[axis]; |
199 | } |
||
2129 | - | 200 | } |
2131 | - | 201 | #endif |
2132 | - | 202 | #ifdef TUNCATEERROR |
2135 | - | 203 | if (error > maxError[axis]) { |
204 | error = maxError[axis]; |
||
205 | } else if (error < -maxError[axis]) { |
||
206 | error = -maxError[axis]; |
||
2118 | - | 207 | } else { |
2129 | - | 208 | // update I parts here for angles mode. I parts in rate mode is something different. |
2102 | - | 209 | } |
2131 | - | 210 | #endif |
1910 | - | 211 | |
2135 | - | 212 | debugOut.analog[9+axis] = error / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
213 | |||
2102 | - | 214 | /************************************************************************/ |
215 | /* Calculate control feedback from angle (gyro integral) */ |
||
216 | /* and angular velocity (gyro signal) */ |
||
217 | /************************************************************************/ |
||
2119 | - | 218 | if (currentFlightMode == FLIGHT_MODE_ANGLES || currentFlightMode == FLIGHT_MODE_RATE) { |
2122 | - | 219 | PDPart[axis] = +(((int32_t) gyro_PID[axis] * (int32_t) airspeedPID[axis].P) >> LOG_P_SCALE) |
2119 | - | 220 | + (((int16_t)gyroD[axis] * (int16_t) airspeedPID[axis].D) >> LOG_D_SCALE); |
2104 | - | 221 | } else { |
222 | PDPart[axis] = 0; |
||
223 | } |
||
1910 | - | 224 | |
2104 | - | 225 | if (currentFlightMode == FLIGHT_MODE_ANGLES) { |
2135 | - | 226 | int16_t anglePart = (int32_t)(error * (int32_t) airspeedPID[axis].I) >> LOG_I_SCALE; |
2122 | - | 227 | PDPart[axis] += anglePart; |
2104 | - | 228 | } |
2118 | - | 229 | |
2102 | - | 230 | // Add I parts here... these are integrated errors. |
2142 | - | 231 | if (staticParams.servos[axis].reverse) |
2122 | - | 232 | term[axis] = controls[axis] - PDPart[axis]; // + IPart[axis]; |
233 | else |
||
234 | term[axis] = controls[axis] + PDPart[axis]; // + IPart[axis]; |
||
2102 | - | 235 | } |
1910 | - | 236 | |
2104 | - | 237 | for (uint8_t i = 0; i < NUM_CONTROL_SERVOS; i++) { |
2102 | - | 238 | int16_t tmp; |
239 | if (servoTestActive) { |
||
2119 | - | 240 | controlServos[i] = ((int16_t) servoTest[i] - 128) * 8; |
2102 | - | 241 | } else { |
242 | // Follow the normal order of servos: Ailerons, elevator, throttle, rudder. |
||
243 | switch (i) { |
||
244 | case 0: |
||
245 | tmp = term[ROLL]; |
||
246 | break; |
||
247 | case 1: |
||
248 | tmp = term[PITCH]; |
||
249 | break; |
||
250 | case 2: |
||
2103 | - | 251 | tmp = term[THROTTLE]; |
2102 | - | 252 | break; |
253 | case 3: |
||
254 | tmp = term[YAW]; |
||
255 | break; |
||
256 | default: |
||
257 | tmp = 0; |
||
258 | } |
||
259 | // These are all signed and in the same units as the RC stuff in rc.c. |
||
260 | controlServos[i] = tmp; |
||
261 | } |
||
262 | } |
||
1910 | - | 263 | |
2103 | - | 264 | calculateControlServoValues(); |
1910 | - | 265 | |
2102 | - | 266 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
267 | // Debugging |
||
268 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
||
269 | if (!(--debugDataTimer)) { |
||
270 | debugDataTimer = 24; // update debug outputs at 488 / 24 = 20.3 Hz. |
||
2103 | - | 271 | debugOut.analog[0] = gyro_PID[PITCH]; // in 0.1 deg |
272 | debugOut.analog[1] = gyro_PID[ROLL]; // in 0.1 deg |
||
273 | debugOut.analog[2] = gyro_PID[YAW]; |
||
1910 | - | 274 | |
2102 | - | 275 | debugOut.analog[3] = attitude[PITCH] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
276 | debugOut.analog[4] = attitude[ROLL] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
||
277 | debugOut.analog[5] = attitude[YAW] / (GYRO_DEG_FACTOR / 10); |
||
2099 | - | 278 | |
2102 | - | 279 | debugOut.analog[6] = target[PITCH] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
280 | debugOut.analog[7] = target[ROLL] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
||
281 | debugOut.analog[8] = target[YAW] / (GYRO_DEG_FACTOR / 10); |
||
282 | |||
283 | debugOut.analog[12] = term[PITCH]; |
||
284 | debugOut.analog[13] = term[ROLL]; |
||
285 | debugOut.analog[14] = term[YAW]; |
||
2142 | - | 286 | debugOut.analog[15] = term[THROTTLE]; |
2102 | - | 287 | } |
1910 | - | 288 | } |