Rev 1970 | Rev 2018 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1612 | dongfang | 1 | #ifndef _ANALOG_H |
2 | #define _ANALOG_H |
||
3 | #include <inttypes.h> |
||
1965 | - | 4 | #include "configuration.h" |
1612 | dongfang | 5 | |
6 | /* |
||
1645 | - | 7 | * How much low pass filtering to apply for gyro_PID. |
1612 | dongfang | 8 | * 0=illegal, 1=no filtering, 2=50% last value + 50% new value, 3=67% last value + 33 % new value etc... |
9 | * Temporarily replaced by userparam-configurable variable. |
||
10 | */ |
||
1646 | - | 11 | // #define GYROS_PID_FILTER 1 |
1612 | dongfang | 12 | |
13 | /* |
||
1645 | - | 14 | * How much low pass filtering to apply for gyro_ATT. |
1612 | dongfang | 15 | * 0=illegal, 1=no filtering, 2=50% last value + 50% new value, 3=67% last value + 33 % new value etc... |
16 | * Temporarily replaced by userparam-configurable variable. |
||
17 | */ |
||
1646 | - | 18 | // #define GYROS_ATT_FILTER 1 |
1612 | dongfang | 19 | |
20 | // Temporarily replaced by userparam-configurable variable. |
||
1646 | - | 21 | // #define ACC_FILTER 4 |
1612 | dongfang | 22 | |
23 | /* |
||
1821 | - | 24 | About setting constants for different gyros: |
25 | Main parameters are positive directions and voltage/angular speed gain. |
||
26 | The "Positive direction" is the rotation direction around an axis where |
||
27 | the corresponding gyro outputs a voltage > the no-rotation voltage. |
||
28 | A gyro is considered, in this code, to be "forward" if its positive |
||
29 | direction is: |
||
30 | - Nose down for pitch |
||
31 | - Left hand side down for roll |
||
32 | - Clockwise seen from above for yaw. |
||
33 | Declare the GYRO_REVERSE_YAW, GYRO_REVERSE_ROLL and |
||
34 | GYRO_REVERSE_PITCH #define's if the respective gyros are reverse. |
||
35 | |||
36 | Setting gyro gain correctly: All sensor measurements in analog.c take |
||
37 | place in a cycle, each cycle comprising all sensors. Some sensors are |
||
38 | sampled more than ones, and the results added. The pitch and roll gyros |
||
39 | are sampled 4 times and the yaw gyro 2 times in the original H&I V0.74 |
||
40 | code. |
||
41 | In the H&I code, the results for pitch and roll are multiplied by 2 (FC1.0) |
||
42 | or 4 (other versions), offset to zero, low pass filtered and then assigned |
||
43 | to the "HiResXXXX" and "AdWertXXXXFilter" variables, where XXXX is nick or |
||
44 | roll. |
||
45 | So: |
||
46 | |||
47 | gyro = V * (ADCValue1 + ADCValue2 + ADCValue3 + ADCValue4), |
||
48 | where V is 2 for FC1.0 and 4 for all others. |
||
49 | |||
50 | Assuming constant ADCValue, in the H&I code: |
||
1612 | dongfang | 51 | |
1821 | - | 52 | gyro = I * ADCValue. |
1612 | dongfang | 53 | |
1821 | - | 54 | where I is 8 for FC1.0 and 16 for all others. |
1612 | dongfang | 55 | |
1821 | - | 56 | The relation between rotation rate and ADCValue: |
57 | ADCValue [units] = |
||
58 | rotational speed [deg/s] * |
||
59 | gyro sensitivity [V / deg/s] * |
||
60 | amplifier gain [units] * |
||
61 | 1024 [units] / |
||
62 | 3V full range [V] |
||
1612 | dongfang | 63 | |
1821 | - | 64 | or: H is the number of steps the ADC value changes with, |
65 | for a 1 deg/s change in rotational velocity: |
||
66 | H = ADCValue [units] / rotation rate [deg/s] = |
||
67 | gyro sensitivity [V / deg/s] * |
||
68 | amplifier gain [units] * |
||
69 | 1024 [units] / |
||
70 | 3V full range [V] |
||
1612 | dongfang | 71 | |
1821 | - | 72 | Examples: |
73 | FC1.3 has 0.67 mV/deg/s gyros and amplifiers with a gain of 5.7: |
||
74 | H = 0.00067 V / deg / s * 5.7 * 1024 / 3V = 1.304 units/(deg/s). |
||
75 | FC2.0 has 6*(3/5) mV/deg/s gyros (they are ratiometric) and no amplifiers: |
||
76 | H = 0.006 V / deg / s * 1 * 1024 * 3V / (3V * 5V) = 1.2288 units/(deg/s). |
||
77 | My InvenSense copter has 2mV/deg/s gyros and no amplifiers: |
||
78 | H = 0.002 V / deg / s * 1 * 1024 / 3V = 0.6827 units/(deg/s) |
||
79 | (only about half as sensitive as V1.3. But it will take about twice the |
||
80 | rotation rate!) |
||
1612 | dongfang | 81 | |
1821 | - | 82 | All together: gyro = I * H * rotation rate [units / (deg/s)]. |
83 | */ |
||
1612 | dongfang | 84 | |
85 | /* |
||
86 | * A factor that the raw gyro values are multiplied by, |
||
1645 | - | 87 | * before being filtered and passed to the attitude module. |
1612 | dongfang | 88 | * A value of 1 would cause a little bit of loss of precision in the |
89 | * filtering (on the other hand the values are so noisy in flight that |
||
90 | * it will not really matter - but when testing on the desk it might be |
||
91 | * noticeable). 4 is fine for the default filtering. |
||
1645 | - | 92 | * Experiment: Set it to 1. |
1612 | dongfang | 93 | */ |
1874 | - | 94 | #define GYRO_FACTOR_PITCHROLL 1 |
1612 | dongfang | 95 | |
96 | /* |
||
97 | * How many samples are summed in one ADC loop, for pitch&roll and yaw, |
||
98 | * respectively. This is = the number of occurences of each channel in the |
||
99 | * channelsForStates array in analog.c. |
||
100 | */ |
||
101 | #define GYRO_SUMMATION_FACTOR_PITCHROLL 4 |
||
102 | #define GYRO_SUMMATION_FACTOR_YAW 2 |
||
103 | |||
1646 | - | 104 | #define ACC_SUMMATION_FACTOR_PITCHROLL 2 |
105 | #define ACC_SUMMATION_FACTOR_Z 1 |
||
106 | |||
1612 | dongfang | 107 | /* |
1821 | - | 108 | Integration: |
109 | The HiResXXXX values are divided by 8 (in H&I firmware) before integration. |
||
110 | In the Killagreg rewrite of the H&I firmware, the factor 8 is called |
||
111 | HIRES_GYRO_AMPLIFY. In this code, it is called HIRES_GYRO_INTEGRATION_FACTOR, |
||
112 | and care has been taken that all other constants (gyro to degree factor, and |
||
113 | 180 degree flip-over detection limits) are corrected to it. Because the |
||
114 | division by the constant takes place in the flight attitude code, the |
||
115 | constant is there. |
||
1612 | dongfang | 116 | |
1821 | - | 117 | The control loop executes every 2ms, and for each iteration |
118 | gyro_ATT[PITCH/ROLL] is added to gyroIntegral[PITCH/ROLL]. |
||
119 | Assuming a constant rotation rate v and a zero initial gyroIntegral |
||
120 | (for this explanation), we get: |
||
1612 | dongfang | 121 | |
1821 | - | 122 | gyroIntegral = |
123 | N * gyro / HIRES_GYRO_INTEGRATION_FACTOR = |
||
124 | N * I * H * v / HIRES_GYRO_INTEGRATION_FACTOR |
||
1612 | dongfang | 125 | |
1821 | - | 126 | where N is the number of summations; N = t/2ms. |
1612 | dongfang | 127 | |
1821 | - | 128 | For one degree of rotation: t*v = 1: |
1612 | dongfang | 129 | |
1821 | - | 130 | gyroIntegralXXXX = t/2ms * I * H * 1/t = INTEGRATION_FREQUENCY * I * H / HIRES_GYRO_INTEGRATION_FACTOR. |
1612 | dongfang | 131 | |
1821 | - | 132 | This number (INTEGRATION_FREQUENCY * I * H) is the integral-to-degree factor. |
133 | |||
134 | Examples: |
||
135 | FC1.3: I=2, H=1.304, HIRES_GYRO_INTEGRATION_FACTOR=8 --> integralDegreeFactor = 1304 |
||
136 | FC2.0: I=2, H=2.048, HIRES_GYRO_INTEGRATION_FACTOR=13 --> integralDegreeFactor = 1260 |
||
137 | My InvenSense copter: HIRES_GYRO_INTEGRATION_FACTOR=4, H=0.6827 --> integralDegreeFactor = 1365 |
||
138 | */ |
||
139 | |||
1612 | dongfang | 140 | /* |
1645 | - | 141 | * The value of gyro[PITCH/ROLL] for one deg/s = The hardware factor H * the number of samples * multiplier factor. |
1612 | dongfang | 142 | * Will be about 10 or so for InvenSense, and about 33 for ADXRS610. |
143 | */ |
||
144 | #define GYRO_RATE_FACTOR_PITCHROLL (GYRO_HW_FACTOR * GYRO_SUMMATION_FACTOR_PITCHROLL * GYRO_FACTOR_PITCHROLL) |
||
145 | #define GYRO_RATE_FACTOR_YAW (GYRO_HW_FACTOR * GYRO_SUMMATION_FACTOR_YAW) |
||
146 | |||
147 | /* |
||
1645 | - | 148 | * Gyro saturation prevention. |
149 | */ |
||
150 | // How far from the end of its range a gyro is considered near-saturated. |
||
151 | #define SENSOR_MIN_PITCHROLL 32 |
||
152 | // Other end of the range (calculated) |
||
153 | #define SENSOR_MAX_PITCHROLL (GYRO_SUMMATION_FACTOR_PITCHROLL * 1023 - SENSOR_MIN_PITCHROLL) |
||
154 | // Max. boost to add "virtually" to gyro signal at total saturation. |
||
155 | #define EXTRAPOLATION_LIMIT 2500 |
||
156 | // Slope of the boost (calculated) |
||
157 | #define EXTRAPOLATION_SLOPE (EXTRAPOLATION_LIMIT/SENSOR_MIN_PITCHROLL) |
||
158 | |||
159 | /* |
||
1612 | dongfang | 160 | * This value is subtracted from the gyro noise measurement in each iteration, |
161 | * making it return towards zero. |
||
162 | */ |
||
163 | #define GYRO_NOISE_MEASUREMENT_DAMPING 5 |
||
164 | |||
1645 | - | 165 | #define PITCH 0 |
166 | #define ROLL 1 |
||
1646 | - | 167 | #define YAW 2 |
168 | #define Z 2 |
||
1612 | dongfang | 169 | /* |
170 | * The values that this module outputs |
||
1645 | - | 171 | * These first 2 exported arrays are zero-offset. The "PID" ones are used |
172 | * in the attitude control as rotation rates. The "ATT" ones are for |
||
173 | * integration to angles. For the same axis, the PID and ATT variables |
||
174 | * generally have about the same values. There are just some differences |
||
175 | * in filtering, and when a gyro becomes near saturated. |
||
176 | * Maybe this distinction is not really necessary. |
||
1612 | dongfang | 177 | */ |
1645 | - | 178 | extern volatile int16_t gyro_PID[2]; |
179 | extern volatile int16_t gyro_ATT[2]; |
||
180 | extern volatile int16_t gyroD[2]; |
||
1775 | - | 181 | extern volatile int16_t yawGyro; |
1612 | dongfang | 182 | extern volatile uint16_t ADCycleCount; |
183 | extern volatile int16_t UBat; |
||
184 | |||
1775 | - | 185 | // 1:11 voltage divider, 1024 counts per 3V, and result is divided by 3. |
1869 | - | 186 | #define UBAT_AT_5V (int16_t)((5.0 * (1.0/11.0)) * 1024 / (3.0 * 3)) |
1775 | - | 187 | |
1969 | - | 188 | extern sensorOffset_t gyroOffset; |
189 | extern sensorOffset_t accOffset; |
||
190 | extern sensorOffset_t gyroAmplifierOffset; |
||
1960 | - | 191 | |
1612 | dongfang | 192 | /* |
193 | * This is not really for external use - but the ENC-03 gyro modules needs it. |
||
194 | */ |
||
1646 | - | 195 | extern volatile int16_t rawGyroSum[3]; |
1612 | dongfang | 196 | |
197 | /* |
||
1645 | - | 198 | * The acceleration values that this module outputs. They are zero based. |
1612 | dongfang | 199 | */ |
1646 | - | 200 | extern volatile int16_t acc[3]; |
1979 | - | 201 | extern volatile int16_t filteredAcc[3]; |
1872 | - | 202 | // extern volatile int32_t stronglyFilteredAcc[3]; |
1612 | dongfang | 203 | |
204 | /* |
||
1775 | - | 205 | * Diagnostics: Gyro noise level because of motor vibrations. The variables |
206 | * only really reflect the noise level when the copter stands still but with |
||
207 | * its motors running. |
||
208 | */ |
||
1979 | - | 209 | extern volatile uint16_t gyroNoisePeak[3]; |
210 | extern volatile uint16_t accNoisePeak[3]; |
||
1775 | - | 211 | |
212 | /* |
||
213 | * Air pressure. |
||
1961 | - | 214 | * The sensor has a sensitivity of 45 mV/kPa. |
1970 | - | 215 | * An approximate p(h) formula is = p(h[m])[kPa] = p_0 - 11.95 * 10^-3 * h |
216 | * p(h[m])[kPa] = 101.3 - 11.95 * 10^-3 * h |
||
217 | * 11.95 * 10^-3 * h = 101.3 - p[kPa] |
||
218 | * h = (101.3 - p[kPa])/0.01195 |
||
219 | * That is: dV = -45 mV * 11.95 * 10^-3 dh = -0.53775 mV / m. |
||
220 | * That is, with 38.02 * 1.024 / 3 steps per mV: -7 steps / m |
||
221 | |||
222 | Display pressures |
||
223 | 4165 mV-->1084.7 |
||
224 | 4090 mV-->1602.4 517.7 |
||
225 | 3877 mV-->3107.8 1503.4 |
||
226 | |||
227 | 4165 mV-->1419.1 |
||
228 | 3503 mV-->208.1 |
||
229 | Diff.: 1211.0 |
||
230 | |||
231 | Calculated Vout = 5V(.009P-0.095) --> 5V .009P = Vout + 5V 0.095 --> P = (Vout + 5V 0.095)/(5V 0.009) |
||
232 | 4165 mV = 5V(0.009P-0.095) P = 103.11 kPa h = -151.4m |
||
233 | 4090 mV = 5V(0.009P-0.095) P = 101.44 kPa h = -11.7m 139.7m |
||
234 | 3877 mV = 5V(0.009P-0.095) P = 96.7 kPa h = 385m 396.7m |
||
235 | |||
236 | 4165 mV = 5V(0.009P-0.095) P = 103.11 kPa h = -151.4m |
||
237 | 3503 mV = 5V(0.009P-0.095) P = 88.4 kPa h = 384m Diff: 1079.5m |
||
238 | Pressure at sea level: 101.3 kPa. voltage: 5V * (0.009P-0.095) = 4.0835V |
||
239 | This is OCR2 = 143.15 at 1.5V in --> simple pressure = |
||
240 | */ |
||
241 | |||
242 | #define AIRPRESSURE_SUMMATION_FACTOR 14 |
||
1775 | - | 243 | #define AIRPRESSURE_FILTER 8 |
244 | // Minimum A/D value before a range change is performed. |
||
245 | #define MIN_RAWPRESSURE (200 * 2) |
||
246 | // Maximum A/D value before a range change is performed. |
||
247 | #define MAX_RAWPRESSURE (1023 * 2 - MIN_RAWPRESSURE) |
||
248 | |||
1796 | - | 249 | #define MIN_RANGES_EXTRAPOLATION 15 |
250 | #define MAX_RANGES_EXTRAPOLATION 240 |
||
1775 | - | 251 | |
252 | #define PRESSURE_EXTRAPOLATION_COEFF 25L |
||
253 | #define AUTORANGE_WAIT_FACTOR 1 |
||
254 | |||
1970 | - | 255 | #define ABS_ALTITUDE_OFFSET 108205 |
256 | |||
1775 | - | 257 | extern volatile uint16_t simpleAirPressure; |
258 | /* |
||
259 | * At saturation, the filteredAirPressure may actually be (simulated) negative. |
||
260 | */ |
||
261 | extern volatile int32_t filteredAirPressure; |
||
262 | |||
263 | /* |
||
1612 | dongfang | 264 | * Flag: Interrupt handler has done all A/D conversion and processing. |
265 | */ |
||
266 | extern volatile uint8_t analogDataReady; |
||
267 | |||
268 | void analog_init(void); |
||
269 | |||
1952 | - | 270 | /* |
271 | * Start the conversion cycle. It will stop automatically. |
||
272 | */ |
||
273 | void startAnalogConversionCycle(void); |
||
1612 | dongfang | 274 | |
1952 | - | 275 | /* |
276 | * Process the sensor data to update the exported variables. Must be called after each measurement cycle and before the data is used. |
||
277 | */ |
||
1955 | - | 278 | void analog_update(void); |
1612 | dongfang | 279 | |
280 | /* |
||
1961 | - | 281 | * Read gyro and acc.meter calibration from EEPROM. |
1612 | dongfang | 282 | */ |
1961 | - | 283 | void analog_setNeutral(void); |
1612 | dongfang | 284 | |
285 | /* |
||
1961 | - | 286 | * Zero-offset gyros and write the calibration data to EEPROM. |
1612 | dongfang | 287 | */ |
1961 | - | 288 | void analog_calibrateGyros(void); |
289 | |||
290 | /* |
||
291 | * Zero-offset accelerometers and write the calibration data to EEPROM. |
||
292 | */ |
||
1612 | dongfang | 293 | void analog_calibrateAcc(void); |
294 | #endif //_ANALOG_H |