Subversion Repositories FlightCtrl

Rev

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
}