Rev 2102 | Rev 2104 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2102 | Rev 2103 | ||
---|---|---|---|
1 | #include <stdlib.h> |
1 | #include <stdlib.h> |
2 | #include <avr/io.h> |
2 | #include <avr/io.h> |
3 | #include "eeprom.h" |
3 | #include "eeprom.h" |
4 | #include "flight.h" |
4 | #include "flight.h" |
5 | #include "output.h" |
5 | #include "output.h" |
6 | 6 | ||
7 | // Necessary for external control and motor test |
7 | // Necessary for external control and motor test |
8 | #include "uart0.h" |
8 | #include "uart0.h" |
9 | 9 | ||
10 | #include "timer2.h" |
10 | #include "timer2.h" |
- | 11 | #include "analog.h" |
|
11 | #include "attitude.h" |
12 | #include "attitude.h" |
12 | #include "controlMixer.h" |
13 | #include "controlMixer.h" |
13 | 14 | ||
14 | #define CHECK_MIN_MAX(value, min, max) {if(value < min) value = min; else if(value > max) value = max;} |
15 | #define CHECK_MIN_MAX(value, min, max) {if(value < min) value = min; else if(value > max) value = max;} |
15 | 16 | ||
16 | /* |
17 | /* |
17 | * target-directions integrals. |
18 | * target-directions integrals. |
18 | */ |
19 | */ |
19 | int32_t target[3]; |
20 | int32_t target[3]; |
20 | 21 | ||
21 | /* |
22 | /* |
22 | * Error integrals. |
23 | * Error integrals. |
23 | */ |
24 | */ |
24 | int32_t error[3]; |
25 | int32_t error[3]; |
25 | 26 | ||
26 | uint8_t pFactor[3]; |
27 | uint8_t pFactor[3]; |
27 | uint8_t dFactor[3]; |
28 | uint8_t dFactor[3]; |
28 | uint8_t iFactor[3]; |
29 | uint8_t iFactor[3]; |
29 | uint8_t reverse[3]; |
30 | uint8_t reverse[3]; |
30 | int32_t IPart[3] = { 0, 0, 0 }; |
31 | int32_t IPart[3] = { 0, 0, 0 }; |
31 | 32 | ||
32 | int16_t controlServos[MAX_CONTROL_SERVOS]; |
33 | int16_t controlServos[MAX_CONTROL_SERVOS]; |
33 | 34 | ||
34 | /************************************************************************/ |
35 | /************************************************************************/ |
35 | /* Neutral Readings */ |
36 | /* Neutral Readings */ |
36 | /************************************************************************/ |
37 | /************************************************************************/ |
37 | #define CONTROL_CONFIG_SCALE 10 |
38 | #define CONTROL_CONFIG_SCALE 10 |
38 | 39 | ||
39 | void flight_setGround(void) { |
40 | void flight_setGround(void) { |
40 | IPart[PITCH] = IPart[ROLL] = IPart[YAW] = 0; |
41 | IPart[PITCH] = IPart[ROLL] = IPart[YAW] = 0; |
41 | target[PITCH] = attitude[PITCH]; |
42 | target[PITCH] = attitude[PITCH]; |
42 | target[ROLL] = attitude[ROLL]; |
43 | target[ROLL] = attitude[ROLL]; |
43 | target[YAW] = attitude[YAW]; |
44 | target[YAW] = attitude[YAW]; |
44 | } |
45 | } |
45 | 46 | ||
46 | // this should be followed by a call to switchToFlightMode!! |
47 | // this should be followed by a call to switchToFlightMode!! |
47 | void updateFlightParametersToFlightMode(uint8_t flightMode) { |
48 | void flight_updateFlightParametersToFlightMode(uint8_t flightMode) { |
48 | debugOut.analog[15] = flightMode; |
49 | debugOut.analog[16] = flightMode; |
49 | 50 | ||
50 | reverse[CONTROL_ELEVATOR] = staticParams.controlServosReverse |
51 | reverse[PITCH] = staticParams.controlServosReverse |
51 | & CONTROL_SERVO_REVERSE_ELEVATOR; |
52 | & CONTROL_SERVO_REVERSE_ELEVATOR; |
52 | reverse[CONTROL_AILERONS] = staticParams.controlServosReverse |
53 | reverse[ROLL] = staticParams.controlServosReverse |
53 | & CONTROL_SERVO_REVERSE_AILERONS; |
54 | & CONTROL_SERVO_REVERSE_AILERONS; |
54 | reverse[CONTROL_RUDDER] = staticParams.controlServosReverse |
55 | reverse[YAW] = staticParams.controlServosReverse |
55 | & CONTROL_SERVO_REVERSE_RUDDER; |
56 | & CONTROL_SERVO_REVERSE_RUDDER; |
56 | 57 | ||
57 | for (uint8_t i = 0; i < 3; i++) { |
58 | for (uint8_t i = 0; i < 3; i++) { |
58 | if (flightMode == FLIGHT_MODE_MANUAL) { |
59 | if (flightMode == FLIGHT_MODE_MANUAL) { |
59 | pFactor[i] = 0; |
60 | pFactor[i] = 0; |
60 | dFactor[i] = 0; |
61 | dFactor[i] = 0; |
61 | } else if(flightMode == FLIGHT_MODE_RATE || flightMode == FLIGHT_MODE_ANGLES) { |
62 | } else if(flightMode == FLIGHT_MODE_RATE || flightMode == FLIGHT_MODE_ANGLES) { |
62 | pFactor[i] = staticParams.gyroPID[i].P; |
63 | pFactor[i] = staticParams.gyroPID[i].P; |
63 | dFactor[i] = staticParams.gyroPID[i].D; |
64 | dFactor[i] = staticParams.gyroPID[i].D; |
64 | } |
65 | } |
65 | 66 | ||
66 | if (flightMode == FLIGHT_MODE_ANGLES) { |
67 | if (flightMode == FLIGHT_MODE_ANGLES) { |
67 | iFactor[i] = staticParams.gyroPID[i].I; |
68 | iFactor[i] = staticParams.gyroPID[i].I; |
68 | } else if(flightMode == FLIGHT_MODE_RATE || flightMode == FLIGHT_MODE_MANUAL) { |
69 | } else if(flightMode == FLIGHT_MODE_RATE || flightMode == FLIGHT_MODE_MANUAL) { |
69 | iFactor[i] = 0; |
70 | iFactor[i] = 0; |
70 | } |
71 | } |
71 | } |
72 | } |
72 | } |
73 | } |
73 | 74 | ||
74 | /************************************************************************/ |
75 | /************************************************************************/ |
75 | /* Main Flight Control */ |
76 | /* Main Flight Control */ |
76 | /************************************************************************/ |
77 | /************************************************************************/ |
77 | void flight_control(void) { |
78 | void flight_control(void) { |
78 | // Mixer Fractions that are combined for Motor Control |
79 | // Mixer Fractions that are combined for Motor Control |
79 | int16_t throttleTerm, term[3]; |
80 | int16_t term[4]; |
80 | 81 | ||
81 | // PID controller variables |
82 | // PID controller variables |
82 | int16_t PDPart[3]; |
83 | int16_t PDPart[3]; |
83 | 84 | ||
84 | static int8_t debugDataTimer = 1; |
85 | static int8_t debugDataTimer = 1; |
85 | 86 | ||
86 | // High resolution motor values for smoothing of PID motor outputs |
87 | // High resolution motor values for smoothing of PID motor outputs |
87 | // static int16_t outputFilters[MAX_OUTPUTS]; |
88 | // static int16_t outputFilters[MAX_OUTPUTS]; |
88 | 89 | ||
89 | uint8_t axis; |
90 | uint8_t axis; |
90 | 91 | ||
91 | // TODO: Check modern version. |
92 | // TODO: Check modern version. |
92 | // calculateFlightAttitude(); |
93 | // calculateFlightAttitude(); |
93 | // TODO: Check modern version. |
94 | // TODO: Check modern version. |
94 | // controlMixer_update(); |
95 | // controlMixer_update(); |
95 | throttleTerm = controls[CONTROL_THROTTLE]; |
96 | term[CONTROL_THROTTLE] = controls[CONTROL_THROTTLE]; |
96 | 97 | ||
97 | // These params are just left the same in all modes. In MANUAL and RATE the results are ignored anyway. |
98 | // These params are just left the same in all modes. In MANUAL and RATE the results are ignored anyway. |
98 | target[PITCH] += controls[CONTROL_ELEVATOR] * staticParams.stickIElevator; |
99 | target[PITCH] += (controls[CONTROL_ELEVATOR] * staticParams.stickIElevator) >> 6; |
99 | target[ROLL] += controls[CONTROL_AILERONS] * staticParams.stickIAilerons; |
100 | target[ROLL] += (controls[CONTROL_AILERONS] * staticParams.stickIAilerons) >> 6; |
100 | target[YAW] += controls[CONTROL_RUDDER] * staticParams.stickIRudder; |
101 | target[YAW] += (controls[CONTROL_RUDDER] * staticParams.stickIRudder) >> 6; |
101 | 102 | ||
102 | for (axis = PITCH; axis <= YAW; axis++) { |
103 | for (axis = PITCH; axis <= YAW; axis++) { |
103 | if (target[axis] > OVER180) { |
104 | if (target[axis] > OVER180) { |
104 | target[axis] -= OVER360; |
105 | target[axis] -= OVER360; |
105 | } else if (attitude[axis] <= -OVER180) { |
106 | } else if (target[axis] <= -OVER180) { |
106 | attitude[axis] += OVER360; |
107 | target[axis] += OVER360; |
107 | } |
108 | } |
108 | 109 | ||
109 | if (reverse[axis]) |
110 | if (reverse[axis]) |
110 | error[axis] = attitude[axis] + target[axis]; |
111 | error[axis] = attitude[axis] + target[axis]; |
111 | else |
112 | else |
112 | error[axis] = attitude[axis] - target[axis]; |
113 | error[axis] = attitude[axis] - target[axis]; |
113 | if (error[axis] > OVER180) { |
114 | if (error[axis] > OVER180) { |
114 | error[axis] -= OVER360; |
115 | error[axis] -= OVER360; |
115 | } else if (error[axis] <= -OVER180) { |
116 | } else if (error[axis] <= -OVER180) { |
116 | error[axis] += OVER360; |
117 | error[axis] += OVER360; |
117 | } |
118 | } |
118 | 119 | ||
119 | /************************************************************************/ |
120 | /************************************************************************/ |
120 | /* Calculate control feedback from angle (gyro integral) */ |
121 | /* Calculate control feedback from angle (gyro integral) */ |
121 | /* and angular velocity (gyro signal) */ |
122 | /* and angular velocity (gyro signal) */ |
122 | /************************************************************************/ |
123 | /************************************************************************/ |
123 | PDPart[axis] = (((int32_t) rate_PID[axis] * pFactor[axis]) >> 6) |
124 | PDPart[axis] = (((int32_t) gyro_PID[axis] * pFactor[axis]) >> 6) |
124 | + ((differential[axis] * (int16_t) dFactor[axis]) >> 4); |
125 | + ((gyroD[axis] * (int16_t) dFactor[axis]) >> 4); |
125 | if (reverse[axis]) |
126 | if (reverse[axis]) |
126 | PDPart[axis] = -PDPart[axis]; |
127 | PDPart[axis] = -PDPart[axis]; |
127 | 128 | ||
128 | int16_t anglePart = (error[axis] * iFactor[axis]) >> 10; |
129 | int16_t anglePart = (error[axis] * iFactor[axis]) >> 10; |
129 | if (reverse[axis]) |
130 | if (reverse[axis]) |
130 | PDPart[axis] += anglePart; |
131 | PDPart[axis] += anglePart; |
131 | else |
132 | else |
132 | PDPart[axis] -= anglePart; |
133 | PDPart[axis] -= anglePart; |
133 | 134 | ||
134 | // Add I parts here... these are integrated errors. |
135 | // Add I parts here... these are integrated errors. |
135 | // When an error wraps, actually its I part should be negated or something... |
136 | // When an error wraps, actually its I part should be negated or something... |
136 | 137 | ||
137 | term[axis] = controls[axis] + PDPart[axis] + IPart[axis]; |
138 | term[axis] = controls[axis] + PDPart[axis] + IPart[axis]; |
138 | } |
139 | } |
139 | 140 | ||
140 | debugOut.analog[12] = term[PITCH]; |
141 | debugOut.analog[12] = term[PITCH]; |
141 | debugOut.analog[13] = term[ROLL]; |
142 | debugOut.analog[13] = term[ROLL]; |
142 | debugOut.analog[14] = throttleTerm; |
143 | debugOut.analog[14] = term[YAW]; |
143 | debugOut.analog[15] = term[YAW]; |
144 | debugOut.analog[15] = term[THROTTLE]; |
144 | 145 | ||
145 | for (uint8_t i = 0; i < MAX_CONTROL_SERVOS; i++) { |
146 | for (uint8_t i = 0; i < MAX_CONTROL_SERVOS; i++) { |
146 | int16_t tmp; |
147 | int16_t tmp; |
147 | if (servoTestActive) { |
148 | if (servoTestActive) { |
148 | controlServos[i] = ((int16_t) servoTest[i] - 128) * 4; |
149 | controlServos[i] = ((int16_t) servoTest[i] - 128) * 4; |
149 | } else { |
150 | } else { |
150 | // Follow the normal order of servos: Ailerons, elevator, throttle, rudder. |
151 | // Follow the normal order of servos: Ailerons, elevator, throttle, rudder. |
151 | switch (i) { |
152 | switch (i) { |
152 | case 0: |
153 | case 0: |
153 | tmp = term[ROLL]; |
154 | tmp = term[ROLL]; |
154 | break; |
155 | break; |
155 | case 1: |
156 | case 1: |
156 | tmp = term[PITCH]; |
157 | tmp = term[PITCH]; |
157 | break; |
158 | break; |
158 | case 2: |
159 | case 2: |
159 | tmp = throttleTerm; |
160 | tmp = term[THROTTLE]; |
160 | break; |
161 | break; |
161 | case 3: |
162 | case 3: |
162 | tmp = term[YAW]; |
163 | tmp = term[YAW]; |
163 | break; |
164 | break; |
164 | default: |
165 | default: |
165 | tmp = 0; |
166 | tmp = 0; |
166 | } |
167 | } |
167 | // These are all signed and in the same units as the RC stuff in rc.c. |
168 | // These are all signed and in the same units as the RC stuff in rc.c. |
168 | controlServos[i] = tmp; |
169 | controlServos[i] = tmp; |
169 | } |
170 | } |
170 | } |
171 | } |
171 | 172 | ||
172 | calculateControlServoValues; |
173 | calculateControlServoValues(); |
173 | 174 | ||
174 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
175 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
175 | // Debugging |
176 | // Debugging |
176 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
177 | // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
177 | if (!(--debugDataTimer)) { |
178 | if (!(--debugDataTimer)) { |
178 | debugDataTimer = 24; // update debug outputs at 488 / 24 = 20.3 Hz. |
179 | debugDataTimer = 24; // update debug outputs at 488 / 24 = 20.3 Hz. |
179 | debugOut.analog[0] = rate_PID[PITCH]; // in 0.1 deg |
180 | debugOut.analog[0] = gyro_PID[PITCH]; // in 0.1 deg |
180 | debugOut.analog[1] = rate_PID[ROLL]; // in 0.1 deg |
181 | debugOut.analog[1] = gyro_PID[ROLL]; // in 0.1 deg |
181 | debugOut.analog[2] = rate_PID[YAW]; |
182 | debugOut.analog[2] = gyro_PID[YAW]; |
182 | 183 | ||
183 | debugOut.analog[3] = attitude[PITCH] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
184 | debugOut.analog[3] = attitude[PITCH] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
184 | debugOut.analog[4] = attitude[ROLL] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
185 | debugOut.analog[4] = attitude[ROLL] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
185 | debugOut.analog[5] = attitude[YAW] / (GYRO_DEG_FACTOR / 10); |
186 | debugOut.analog[5] = attitude[YAW] / (GYRO_DEG_FACTOR / 10); |
186 | 187 | ||
187 | debugOut.analog[6] = target[PITCH] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
188 | debugOut.analog[6] = target[PITCH] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
188 | debugOut.analog[7] = target[ROLL] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
189 | debugOut.analog[7] = target[ROLL] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
189 | debugOut.analog[8] = target[YAW] / (GYRO_DEG_FACTOR / 10); |
190 | debugOut.analog[8] = target[YAW] / (GYRO_DEG_FACTOR / 10); |
190 | 191 | ||
191 | debugOut.analog[9] = error[PITCH] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
192 | debugOut.analog[9] = error[PITCH] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
192 | debugOut.analog[10] = error[ROLL] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
193 | debugOut.analog[10] = error[ROLL] / (GYRO_DEG_FACTOR / 10); // in 0.1 deg |
193 | debugOut.analog[11] = error[YAW] / (GYRO_DEG_FACTOR / 10); |
194 | debugOut.analog[11] = error[YAW] / (GYRO_DEG_FACTOR / 10); |
194 | 195 | ||
195 | debugOut.analog[12] = term[PITCH]; |
196 | debugOut.analog[12] = term[PITCH]; |
196 | debugOut.analog[13] = term[ROLL]; |
197 | debugOut.analog[13] = term[ROLL]; |
197 | debugOut.analog[14] = term[YAW]; |
198 | debugOut.analog[14] = term[YAW]; |
198 | 199 | ||
199 | //DebugOut.Analog[18] = (10 * controlIntegrals[CONTROL_ELEVATOR]) / GYRO_DEG_FACTOR_PITCHROLL; // in 0.1 deg |
200 | //DebugOut.Analog[18] = (10 * controlIntegrals[CONTROL_ELEVATOR]) / GYRO_DEG_FACTOR_PITCHROLL; // in 0.1 deg |
200 | //DebugOut.Analog[19] = (10 * controlIntegrals[CONTROL_AILERONS]) / GYRO_DEG_FACTOR_PITCHROLL; // in 0.1 deg |
201 | //DebugOut.Analog[19] = (10 * controlIntegrals[CONTROL_AILERONS]) / GYRO_DEG_FACTOR_PITCHROLL; // in 0.1 deg |
201 | //debugOut.analog[22] = (10 * IPart[PITCH]) / GYRO_DEG_FACTOR; // in 0.1 deg |
202 | //debugOut.analog[22] = (10 * IPart[PITCH]) / GYRO_DEG_FACTOR; // in 0.1 deg |
202 | //debugOut.analog[23] = (10 * IPart[ROLL]) / GYRO_DEG_FACTOR; // in 0.1 deg |
203 | //debugOut.analog[23] = (10 * IPart[ROLL]) / GYRO_DEG_FACTOR; // in 0.1 deg |
203 | } |
204 | } |
204 | } |
205 | } |
205 | 206 |