Subversion Repositories FlightCtrl

Rev

Rev 2096 | Rev 2102 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2096 Rev 2099
Line 5... Line 5...
5
 
5
 
6
#include "analog.h"
6
#include "analog.h"
7
#include "attitude.h"
7
#include "attitude.h"
8
#include "sensors.h"
8
#include "sensors.h"
9
#include "printf_P.h"
-
 
Line 10... Line 9...
10
#include "mk3mag.h"
9
#include "printf_P.h"
11
 
10
 
Line 12... Line 11...
12
// for Delay functions
11
// for Delay functions
Line 30... Line 29...
30
 * They are exported in the analog.h file - but please do not use them! The only
29
 * They are exported in the analog.h file - but please do not use them! The only
31
 * reason for the export is that the ENC-03_FC1.3 modules needs them for calibrating
30
 * reason for the export is that the ENC-03_FC1.3 modules needs them for calibrating
32
 * the offsets with the DAC.
31
 * the offsets with the DAC.
33
 */
32
 */
34
volatile uint16_t sensorInputs[8];
33
volatile uint16_t sensorInputs[8];
35
int16_t acc[3];
34
//int16_t acc[3];
36
int16_t filteredAcc[3] = { 0,0,0 };
35
//int16_t filteredAcc[3] = { 0,0,0 };
Line 37... Line 36...
37
 
36
 
38
/*
37
/*
39
 * These 4 exported variables are zero-offset. The "PID" ones are used
38
 * These 4 exported variables are zero-offset. The "PID" ones are used
40
 * in the attitude control as rotation rates. The "ATT" ones are for
39
 * in the attitude control as rotation rates. The "ATT" ones are for
41
 * integration to angles.
40
 * integration to angles.
42
 */
41
 */
43
int16_t gyro_PID[2];
42
int16_t gyro_PID[3];
44
int16_t gyro_ATT[2];
43
int16_t gyro_ATT[3];
45
int16_t gyroD[2];
44
int16_t gyroD[3];
46
int16_t gyroDWindow[2][GYRO_D_WINDOW_LENGTH];
45
int16_t gyroDWindow[2][GYRO_D_WINDOW_LENGTH];
47
uint8_t gyroDWindowIdx = 0;
-
 
48
int16_t yawGyro;
-
 
49
int16_t magneticHeading;
-
 
50
 
-
 
51
int32_t groundPressure;
46
uint8_t gyroDWindowIdx = 0;
52
int16_t dHeight;
-
 
53
 
47
int16_t dHeight;
Line 54... Line 48...
54
uint32_t gyroActivity;
48
uint32_t gyroActivity;
55
 
49
 
56
/*
50
/*
Line 88... Line 82...
88
 * 5: pp=1, pr=1, rp=1, rr=-1 // +225 degrees with pitch reversed
82
 * 5: pp=1, pr=1, rp=1, rr=-1 // +225 degrees with pitch reversed
89
 * 6: pp=0, pr=1, rp=1, rr=0  // +270 degrees with pitch reversed
83
 * 6: pp=0, pr=1, rp=1, rr=0  // +270 degrees with pitch reversed
90
 * 7: pp=-1,pr=1, rp=1, rr=1  // +315 degrees with pitch reversed
84
 * 7: pp=-1,pr=1, rp=1, rr=1  // +315 degrees with pitch reversed
91
 */
85
 */
Line 92... Line 86...
92
 
86
 
93
void rotate(int16_t* result, uint8_t quadrant, uint8_t reverse) {
87
void rotate(int16_t* result, uint8_t quadrant, uint8_t reversePR, uint8_t reverseYaw) {
94
  static const int8_t rotationTab[] = {1,1,0,-1,-1,-1,0,1};
88
  static const int8_t rotationTab[] = {1,1,0,-1,-1,-1,0,1};
95
  // Pitch to Pitch part
89
  // Pitch to Pitch part
96
  int8_t xx = reverse ? rotationTab[(quadrant+4)%8] : rotationTab[quadrant];
90
  int8_t xx = reversePR ? rotationTab[(quadrant+4)%8] : rotationTab[quadrant];
97
  // Roll to Pitch part
91
  // Roll to Pitch part
98
  int8_t xy = rotationTab[(quadrant+2)%8];
92
  int8_t xy = rotationTab[(quadrant+2)%8];
99
  // Pitch to Roll part
93
  // Pitch to Roll part
100
  int8_t yx = reverse ? rotationTab[(quadrant+2)%8] : rotationTab[(quadrant+6)%8];
94
  int8_t yx = reversePR ? rotationTab[(quadrant+2)%8] : rotationTab[(quadrant+6)%8];
101
  // Roll to Roll part
95
  // Roll to Roll part
Line 102... Line 96...
102
  int8_t yy = rotationTab[quadrant];
96
  int8_t yy = rotationTab[quadrant];
103
 
97
 
Line 111... Line 105...
111
        // A suitable value for n: Sample is 11 bits. After transformation it is the sum
105
        // A suitable value for n: Sample is 11 bits. After transformation it is the sum
112
        // of 2 11 bit numbers, so 12 bits. We have 4 bits left...
106
        // of 2 11 bit numbers, so 12 bits. We have 4 bits left...
113
        result[0] = (result[0]*11) >> 4;
107
        result[0] = (result[0]*11) >> 4;
114
        result[1] = (result[1]*11) >> 4;
108
        result[1] = (result[1]*11) >> 4;
115
  }
109
  }
-
 
110
 
-
 
111
  if (reverseYaw)
-
 
112
    result[3] =-result[3];
116
}
113
}
Line 117... Line 114...
117
 
114
 
118
/*
115
/*
119
 * Air pressure
116
 * Airspeed
120
 */
-
 
121
volatile uint8_t rangewidth = 105;
-
 
122
 
-
 
123
// Direct from sensor, irrespective of range.
-
 
124
// volatile uint16_t rawAirPressure;
-
 
125
 
-
 
126
// Value of 2 samples, with range.
117
 */
Line 127... Line 118...
127
uint16_t simpleAirPressure;
118
uint16_t simpleAirPressure;
128
 
119
 
129
// Value of AIRPRESSURE_OVERSAMPLING samples, with range, filtered.
-
 
130
int32_t filteredAirPressure;
-
 
131
 
-
 
132
#define MAX_D_AIRPRESSURE_WINDOW_LENGTH 32
-
 
133
//int32_t lastFilteredAirPressure;
-
 
Line 134... Line 120...
134
int16_t dAirPressureWindow[MAX_D_AIRPRESSURE_WINDOW_LENGTH];
120
// Value of AIRPRESSURE_OVERSAMPLING samples, with range, filtered.
135
uint8_t dWindowPtr = 0;
121
// int32_t filteredAirPressure;
136
 
122
 
137
#define MAX_AIRPRESSURE_WINDOW_LENGTH 32
123
#define MAX_AIRPRESSURE_WINDOW_LENGTH 32
Line 143... Line 129...
143
int32_t airPressureSum;
129
int32_t airPressureSum;
Line 144... Line 130...
144
 
130
 
145
// The number of samples summed into airPressureSum so far.
131
// The number of samples summed into airPressureSum so far.
Line -... Line 132...
-
 
132
uint8_t pressureMeasurementCount;
146
uint8_t pressureMeasurementCount;
133
 
147
 
134
 
148
/*
135
/*
149
 * Battery voltage, in units of: 1k/11k / 3V * 1024 = 31.03 per volt.
136
 * Battery voltage, in units of: 1k/11k / 3V * 1024 = 31.03 per volt.
150
 * That is divided by 3 below, for a final 10.34 per volt.
137
 * That is divided by 3 below, for a final 10.34 per volt.
Line 159... Line 146...
159
 
146
 
160
/*
147
/*
161
 * Experiment: Measuring vibration-induced sensor noise.
148
 * Experiment: Measuring vibration-induced sensor noise.
162
 */
149
 */
163
uint16_t gyroNoisePeak[3];
-
 
Line 164... Line 150...
164
uint16_t accNoisePeak[3];
150
uint16_t gyroNoisePeak[3];
165
 
151
 
Line 166... Line 152...
166
volatile uint8_t adState;
152
volatile uint8_t adState;
Line 187... Line 173...
187
 * The acc. sensor is sampled even if not used - or installed
173
 * The acc. sensor is sampled even if not used - or installed
188
 * at all. The cost is not significant.
174
 * at all. The cost is not significant.
189
 */
175
 */
Line 190... Line 176...
190
 
176
 
191
const uint8_t channelsForStates[] PROGMEM = {
177
const uint8_t channelsForStates[] PROGMEM = {
-
 
178
  AD_GYRO_PITCH,
-
 
179
  AD_GYRO_ROLL,
-
 
180
  AD_GYRO_YAW,
192
  AD_GYRO_PITCH, AD_GYRO_ROLL, AD_GYRO_YAW,
181
 
-
 
182
  AD_AIRPRESSURE,
-
 
183
 
-
 
184
  AD_GYRO_PITCH,
-
 
185
  AD_GYRO_ROLL,
Line -... Line 186...
-
 
186
  AD_GYRO_YAW,
-
 
187
 
193
  AD_ACC_PITCH, AD_ACC_ROLL, AD_AIRPRESSURE,
188
  AD_UBAT,
194
 
189
 
-
 
190
  AD_GYRO_PITCH,
Line 195... Line -...
195
  AD_GYRO_PITCH, AD_GYRO_ROLL, AD_ACC_Z, // at 8, measure Z acc.
-
 
196
  AD_GYRO_PITCH, AD_GYRO_ROLL, AD_GYRO_YAW, // at 11, finish yaw gyro
-
 
197
 
191
  AD_GYRO_ROLL,
Line 198... Line 192...
198
  AD_ACC_PITCH,   // at 12, finish pitch axis acc.
192
  AD_GYRO_YAW,
199
  AD_ACC_ROLL,    // at 13, finish roll axis acc.
193
 
200
  AD_AIRPRESSURE, // at 14, finish air pressure.
194
  AD_AIRPRESSURE,
201
 
195
 
Line 202... Line 196...
202
  AD_GYRO_PITCH,  // at 15, finish pitch gyro
196
  AD_GYRO_PITCH,
203
  AD_GYRO_ROLL,   // at 16, finish roll gyro
197
  AD_GYRO_ROLL,
Line 242... Line 236...
242
 
236
 
243
uint16_t rawGyroValue(uint8_t axis) {
237
uint16_t rawGyroValue(uint8_t axis) {
244
        return sensorInputs[AD_GYRO_PITCH-axis];
238
        return sensorInputs[AD_GYRO_PITCH-axis];
Line -... Line 239...
-
 
239
}
245
}
240
 
246
 
241
/*
247
uint16_t rawAccValue(uint8_t axis) {
242
uint16_t rawAccValue(uint8_t axis) {
-
 
243
        return sensorInputs[AD_ACC_PITCH-axis];
Line 248... Line 244...
248
        return sensorInputs[AD_ACC_PITCH-axis];
244
}
249
}
245
*/
250
 
246
 
251
void measureNoise(const int16_t sensor,
247
void measureNoise(const int16_t sensor,
Line 264... Line 260...
264
/*
260
/*
265
 * Min.: 0
261
 * Min.: 0
266
 * Max: About 106 * 240 + 2047 = 27487; it is OK with just a 16 bit type.
262
 * Max: About 106 * 240 + 2047 = 27487; it is OK with just a 16 bit type.
267
 */
263
 */
268
uint16_t getSimplePressure(int advalue) {
264
uint16_t getSimplePressure(int advalue) {
269
        uint16_t result = (uint16_t) OCR0A * (uint16_t) rangewidth + advalue;
-
 
270
        result += (acc[Z] * (staticParams.airpressureAccZCorrection-128)) >> 10;
-
 
271
        return result;
265
        return advalue;
272
}
266
}
Line 273... Line 267...
273
 
267
 
274
void startAnalogConversionCycle(void) {
268
void startAnalogConversionCycle(void) {
Line 303... Line 297...
303
    analogDataReady = 1;
297
    analogDataReady = 1;
304
    // do not restart ADC converter. 
298
    // do not restart ADC converter. 
305
  }
299
  }
306
}
300
}
Line -... Line 301...
-
 
301
 
307
 
302
/*
308
void measureGyroActivity(int16_t newValue) {
303
void measureGyroActivity(int16_t newValue) {
309
  gyroActivity += (uint32_t)((int32_t)newValue * newValue);
304
  gyroActivity += (uint32_t)((int32_t)newValue * newValue);
Line 310... Line 305...
310
}
305
}
Line 316... Line 311...
316
    cnt = 0;
311
    cnt = 0;
317
    gyroActivity *= (uint32_t)((1L<<GADAMPING)-1);
312
    gyroActivity *= (uint32_t)((1L<<GADAMPING)-1);
318
    gyroActivity >>= GADAMPING;
313
    gyroActivity >>= GADAMPING;
319
  }
314
  }
320
}
315
}
321
/*
-
 
322
void dampenGyroActivity(void) {
-
 
323
  if (gyroActivity >= 2000) {
-
 
324
    gyroActivity -= 2000;
-
 
325
  }
-
 
326
}
-
 
327
*/
316
*/
Line 328... Line 317...
328
 
317
 
329
void analog_updateGyros(void) {
318
void analog_updateGyros(void) {
330
  // for various filters...
319
  // for various filters...
Line 331... Line 320...
331
  int16_t tempOffsetGyro[2], tempGyro;
320
  int16_t tempOffsetGyro[3], tempGyro;
332
 
321
 
333
  debugOut.digital[0] &= ~DEBUG_SENSORLIMIT;
322
  debugOut.digital[0] &= ~DEBUG_SENSORLIMIT;
334
  for (uint8_t axis=0; axis<2; axis++) {
323
  for (uint8_t axis=0; axis<3; axis++) {
335
    tempGyro = rawGyroValue(axis);
324
    tempGyro = rawGyroValue(axis);
336
    /*
325
    /*
337
     * Process the gyro data for the PID controller.
326
     * Process the gyro data for the PID controller.
338
     */
327
     */
Line 339... Line 328...
339
    // 1) Extrapolate: Near the ends of the range, we boost the input significantly. This simulates a
328
    // 1) Extrapolate: Near the ends of the range, we boost the input significantly. This simulates a
340
    //    gyro with a wider range, and helps counter saturation at full control.
329
    //    gyro with a wider range, and helps counter saturation at full control.
341
   
330
   
342
    if (staticParams.bitConfig & CFG_GYRO_SATURATION_PREVENTION) {
331
    if (staticParams.bitConfig & CFG_GYRO_SATURATION_PREVENTION) {
343
      if (tempGyro < SENSOR_MIN_PITCHROLL) {
332
      if (tempGyro < SENSOR_MIN) {
344
                debugOut.digital[0] |= DEBUG_SENSORLIMIT;
333
                debugOut.digital[0] |= DEBUG_SENSORLIMIT;
345
                tempGyro = tempGyro * EXTRAPOLATION_SLOPE - EXTRAPOLATION_LIMIT;
334
                tempGyro = tempGyro * EXTRAPOLATION_SLOPE - EXTRAPOLATION_LIMIT;
346
      } else if (tempGyro > SENSOR_MAX_PITCHROLL) {
335
      } else if (tempGyro > SENSOR_MAX) {
347
                debugOut.digital[0] |= DEBUG_SENSORLIMIT;
336
                debugOut.digital[0] |= DEBUG_SENSORLIMIT;
Line 348... Line 337...
348
                tempGyro = (tempGyro - SENSOR_MAX_PITCHROLL) * EXTRAPOLATION_SLOPE + SENSOR_MAX_PITCHROLL;
337
                tempGyro = (tempGyro - SENSOR_MAX) * EXTRAPOLATION_SLOPE + SENSOR_MAX;
349
      }
338
      }
350
    }
339
    }
Line 351... Line 340...
351
 
340
 
352
    // 2) Apply sign and offset, scale before filtering.
341
    // 2) Apply sign and offset, scale before filtering.
Line 353... Line 342...
353
    tempOffsetGyro[axis] = (tempGyro - gyroOffset.offsets[axis]) * GYRO_FACTOR_PITCHROLL;
342
    tempOffsetGyro[axis] = (tempGyro - gyroOffset.offsets[axis]);
354
  }
343
  }
355
 
344
 
Line 356... Line 345...
356
  // 2.1: Transform axes.
345
  // 2.1: Transform axes.
357
  rotate(tempOffsetGyro, IMUConfig.gyroQuadrant, IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_PR);
346
  rotate(tempOffsetGyro, IMUConfig.gyroQuadrant, IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_PR, IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_YAW);
Line 372... Line 361...
372
 
361
 
373
    // 6) Done.
362
    // 6) Done.
Line 374... Line 363...
374
    gyro_PID[axis] = tempOffsetGyro[axis];
363
    gyro_PID[axis] = tempOffsetGyro[axis];
375
 
364
 
376
    // Prepare tempOffsetGyro for next calculation below...
365
    // Prepare tempOffsetGyro for next calculation below...
Line 377... Line 366...
377
    tempOffsetGyro[axis] = (rawGyroValue(axis) - gyroOffset.offsets[axis]) * GYRO_FACTOR_PITCHROLL;
366
    tempOffsetGyro[axis] = (rawGyroValue(axis) - gyroOffset.offsets[axis]);
378
  }
367
  }
379
 
368
 
380
  /*
369
  /*
381
   * Now process the data for attitude angles.
-
 
382
   */
-
 
383
   rotate(tempOffsetGyro, IMUConfig.gyroQuadrant, IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_PR);
-
 
384
 
-
 
385
   dampenGyroActivity();
-
 
386
   gyro_ATT[PITCH] = tempOffsetGyro[PITCH];
-
 
387
   gyro_ATT[ROLL] = tempOffsetGyro[ROLL];
-
 
388
 
-
 
389
   /*
-
 
390
   measureGyroActivity(tempOffsetGyro[PITCH]);
-
 
391
   measureGyroActivity(tempOffsetGyro[ROLL]);
-
 
Line 392... Line -...
392
   */
-
 
393
   measureGyroActivity(gyroD[PITCH]);
-
 
394
   measureGyroActivity(gyroD[ROLL]);
-
 
395
 
-
 
396
   // We measure activity of yaw by plain gyro value and not d/dt, because:
-
 
397
   // - There is no drift correction anyway
-
 
398
   // - Effect of steady circular flight would vanish (it should have effect).
-
 
399
   // int16_t diff = yawGyro;
-
 
400
   // Yaw gyro.
-
 
401
  if (IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_YAW)
-
 
402
    yawGyro = gyroOffset.offsets[YAW] - sensorInputs[AD_GYRO_YAW];
370
   * Now process the data for attitude angles.
403
  else
371
   */
404
    yawGyro = sensorInputs[AD_GYRO_YAW] - gyroOffset.offsets[YAW];
-
 
405
 
372
  rotate(tempOffsetGyro, IMUConfig.gyroQuadrant, IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_PR, IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_YAW);
Line -... Line 373...
-
 
373
 
406
  // diff -= yawGyro;
374
  // dampenGyroActivity();
-
 
375
  gyro_ATT[PITCH] = tempOffsetGyro[PITCH];
407
  // gyroD[YAW] -= gyroDWindow[YAW][gyroDWindowIdx];
376
  gyro_ATT[ROLL] = tempOffsetGyro[ROLL];
-
 
377
 
Line 408... Line 378...
408
  // gyroD[YAW] += diff;
378
  /*
409
  // gyroDWindow[YAW][gyroDWindowIdx] = diff;
379
  measureGyroActivity(gyroD[PITCH]);
410
 
380
  measureGyroActivity(gyroD[ROLL]);
411
  // gyroActivity += (uint32_t)(abs(yawGyro)* IMUConfig.yawRateFactor);
381
  measureGyroActivity(yawGyro);
Line 412... Line -...
412
  measureGyroActivity(yawGyro);
-
 
413
 
-
 
414
  if (++gyroDWindowIdx >= IMUConfig.gyroDWindowLength) {
-
 
415
      gyroDWindowIdx = 0;
-
 
416
  }
-
 
417
}
-
 
418
 
-
 
419
void analog_updateAccelerometers(void) {
-
 
420
  // Pitch and roll axis accelerations.
-
 
421
  for (uint8_t axis=0; axis<2; axis++) {
-
 
422
    acc[axis] = rawAccValue(axis) - accOffset.offsets[axis];
-
 
423
  }
-
 
424
 
-
 
425
  rotate(acc, IMUConfig.accQuadrant, IMUConfig.imuReversedFlags & IMU_REVERSE_ACC_XY);
-
 
426
  for(uint8_t axis=0; axis<3; axis++) {
-
 
427
    filteredAcc[axis] = (filteredAcc[axis] * (IMUConfig.accFilterConstant - 1) + acc[axis]) / IMUConfig.accFilterConstant;
-
 
428
    measureNoise(acc[axis], &accNoisePeak[axis], 1);
-
 
429
  }
-
 
430
 
-
 
431
  // Z acc.
-
 
432
  if (IMUConfig.imuReversedFlags & 8)
-
 
433
    acc[Z] = accOffset.offsets[Z] - sensorInputs[AD_ACC_Z];
382
  */
434
  else
-
 
435
    acc[Z] = sensorInputs[AD_ACC_Z] - accOffset.offsets[Z];
-
 
436
 
-
 
437
  // debugOut.analog[29] = acc[Z];
-
 
438
}
-
 
439
 
-
 
440
void analog_updateAirPressure(void) {
-
 
441
  static uint16_t pressureAutorangingWait = 25;
-
 
442
  uint16_t rawAirPressure;
383
 
443
  int16_t newrange;
-
 
444
  // air pressure
-
 
445
  if (pressureAutorangingWait) {
-
 
446
    //A range switch was done recently. Wait for steadying.
-
 
447
    pressureAutorangingWait--;
-
 
448
  } else {
-
 
449
    rawAirPressure = sensorInputs[AD_AIRPRESSURE];
-
 
450
    if (rawAirPressure < MIN_RAWPRESSURE) {
-
 
451
      // value is too low, so decrease voltage on the op amp minus input, making the value higher.
-
 
452
      newrange = OCR0A - (MAX_RAWPRESSURE - MIN_RAWPRESSURE) / (rangewidth * 4); // 4; // (MAX_RAWPRESSURE - rawAirPressure) / (rangewidth * 2) + 1;
-
 
453
      if (newrange > MIN_RANGES_EXTRAPOLATION) {
-
 
454
        pressureAutorangingWait = (OCR0A - newrange) * AUTORANGE_WAIT_FACTOR; // = OCRA0 - OCRA0 +
-
 
455
        OCR0A = newrange;
-
 
456
      } else {
-
 
457
        if (OCR0A) {
-
 
458
          OCR0A--;
-
 
459
          pressureAutorangingWait = AUTORANGE_WAIT_FACTOR;
-
 
460
        }
-
 
461
      }
-
 
462
    } else if (rawAirPressure > MAX_RAWPRESSURE) {
-
 
463
      // value is too high, so increase voltage on the op amp minus input, making the value lower.
-
 
464
      // If near the end, make a limited increase
-
 
465
      newrange = OCR0A + (MAX_RAWPRESSURE - MIN_RAWPRESSURE) / (rangewidth * 4); // 4;  // (rawAirPressure - MIN_RAWPRESSURE) / (rangewidth * 2) - 1;
-
 
466
      if (newrange < MAX_RANGES_EXTRAPOLATION) {
-
 
467
        pressureAutorangingWait = (newrange - OCR0A) * AUTORANGE_WAIT_FACTOR;
-
 
468
        OCR0A = newrange;
-
 
469
      } else {
-
 
470
        if (OCR0A < 254) {
-
 
471
          OCR0A++;
-
 
472
          pressureAutorangingWait = AUTORANGE_WAIT_FACTOR;
-
 
473
        }
-
 
474
      }
-
 
475
    }
-
 
476
   
-
 
477
    // Even if the sample is off-range, use it.
-
 
478
    simpleAirPressure = getSimplePressure(rawAirPressure);
-
 
479
    debugOut.analog[6] = rawAirPressure;
-
 
480
    debugOut.analog[7] = simpleAirPressure;
-
 
481
   
-
 
482
    if (simpleAirPressure < MIN_RANGES_EXTRAPOLATION * rangewidth) {
-
 
483
      // Danger: pressure near lower end of range. If the measurement saturates, the
-
 
484
      // copter may climb uncontrolledly... Simulate a drastic reduction in pressure.
-
 
485
      debugOut.digital[1] |= DEBUG_SENSORLIMIT;
-
 
486
      airPressureSum += (int16_t) MIN_RANGES_EXTRAPOLATION * rangewidth
-
 
487
        + (simpleAirPressure - (int16_t) MIN_RANGES_EXTRAPOLATION
-
 
488
           * rangewidth) * PRESSURE_EXTRAPOLATION_COEFF;
-
 
489
    } else if (simpleAirPressure > MAX_RANGES_EXTRAPOLATION * rangewidth) {
-
 
490
      // Danger: pressure near upper end of range. If the measurement saturates, the
-
 
491
      // copter may descend uncontrolledly... Simulate a drastic increase in pressure.
-
 
492
      debugOut.digital[1] |= DEBUG_SENSORLIMIT;
-
 
493
      airPressureSum += (int16_t) MAX_RANGES_EXTRAPOLATION * rangewidth
-
 
494
        + (simpleAirPressure - (int16_t) MAX_RANGES_EXTRAPOLATION
384
  if (++gyroDWindowIdx >= IMUConfig.gyroDWindowLength) {
495
           * rangewidth) * PRESSURE_EXTRAPOLATION_COEFF;
-
 
496
    } else {
-
 
497
      // normal case.
-
 
498
      // If AIRPRESSURE_OVERSAMPLING is an odd number we only want to add half the double sample.
-
 
499
      // The 2 cases above (end of range) are ignored for this.
-
 
500
      debugOut.digital[1] &= ~DEBUG_SENSORLIMIT;
-
 
501
          airPressureSum += simpleAirPressure;
-
 
502
    }
-
 
503
   
-
 
504
    // 2 samples were added.
-
 
505
    pressureMeasurementCount += 2;
-
 
506
    // Assumption here: AIRPRESSURE_OVERSAMPLING is even (well we all know it's 14 haha...)
-
 
507
    if (pressureMeasurementCount == AIRPRESSURE_OVERSAMPLING) {
-
 
508
 
-
 
509
      // The best oversampling count is 14.5. We add a quarter of the double ADC value to get the final half.
-
 
510
      airPressureSum += simpleAirPressure >> 2;
-
 
511
 
-
 
512
      uint32_t lastFilteredAirPressure = filteredAirPressure;
-
 
513
 
-
 
514
      if (!staticParams.airpressureWindowLength) {
-
 
515
          filteredAirPressure = (filteredAirPressure * (staticParams.airpressureFilterConstant - 1)
-
 
516
                          + airPressureSum + staticParams.airpressureFilterConstant / 2) / staticParams.airpressureFilterConstant;
-
 
517
      } else {
-
 
518
          // use windowed.
-
 
519
          windowedAirPressure += simpleAirPressure;
-
 
520
          windowedAirPressure -= airPressureWindow[windowPtr];
-
 
521
          airPressureWindow[windowPtr++] = simpleAirPressure;
-
 
522
          if (windowPtr >= staticParams.airpressureWindowLength) windowPtr = 0;
-
 
523
          filteredAirPressure = windowedAirPressure / staticParams.airpressureWindowLength;
-
 
524
      }
-
 
525
 
-
 
526
      // positive diff of pressure
-
 
527
      int16_t diff = filteredAirPressure - lastFilteredAirPressure;
-
 
528
      // is a negative diff of height.
-
 
529
      dHeight -= diff;
-
 
530
      // remove old sample (fifo) from window.
385
      gyroDWindowIdx = 0;
Line 531... Line 386...
531
      dHeight += dAirPressureWindow[dWindowPtr];
386
  }
532
      dAirPressureWindow[dWindowPtr++] = diff;
387
}
533
      if (dWindowPtr >= staticParams.airpressureDWindowLength) dWindowPtr = 0;
388
 
534
      pressureMeasurementCount = airPressureSum = 0;
389
void analog_updateAirPressure(void) {
535
    }
390
  uint16_t rawAirPressure = sensorInputs[AD_AIRPRESSURE];
Line 536... Line 391...
536
  }
391
  simpleAirPressure = rawAirPressure;
537
}
392
}
538
 
393
 
539
void analog_updateBatteryVoltage(void) {
394
void analog_updateBatteryVoltage(void) {
540
  // Battery. The measured value is: (V * 1k/11k)/3v * 1024 = 31.03 counts per volt (max. measurable is 33v).
395
  // Battery. The measured value is: (V * 1k/11k)/3v * 1024 = 31.03 counts per volt (max. measurable is 33v).
541
  // This is divided by 3 --> 10.34 counts per volt.
396
  // This is divided by 3 --> 10.34 counts per volt.
542
  UBat = (3 * UBat + sensorInputs[AD_UBAT] / 3) / 4;
397
  UBat = (3 * UBat + sensorInputs[AD_UBAT] / 3) / 4;
543
}
398
}
-
 
399
 
544
 
400
void analog_update(void) {
Line 545... Line 401...
545
void analog_update(void) {
401
  analog_updateGyros();
546
  analog_updateGyros();
402
  // analog_updateAccelerometers();
Line 547... Line 403...
547
  analog_updateAccelerometers();
403
  analog_updateAirPressure();
548
  analog_updateAirPressure();
404
  analog_updateBatteryVoltage();
549
  analog_updateBatteryVoltage();
405
#ifdef USE_MK3MAG
550
#ifdef USE_MK3MAG
406
  magneticHeading = volatileMagneticHeading;
551
  magneticHeading = volatileMagneticHeading;
407
#endif
552
#endif
408
 
-
 
409
}
553
}
410
 
554
 
411
void analog_setNeutral() {
555
void analog_setNeutral() {
412
  gyro_init();
556
  gyro_init();
413
 
557
 
414
  if (gyroOffset_readFromEEProm()) {
-
 
415
    printf("gyro offsets invalid%s",recal);
Line 558... Line 416...
558
  if (gyroOffset_readFromEEProm()) {
416
    gyroOffset.offsets[PITCH] = gyroOffset.offsets[ROLL] = 512 * GYRO_OVERSAMPLING;
559
    printf("gyro offsets invalid%s",recal);
417
    gyroOffset.offsets[YAW] = 512 * GYRO_OVERSAMPLING;
560
    gyroOffset.offsets[PITCH] = gyroOffset.offsets[ROLL] = 512 * GYRO_OVERSAMPLING_PITCHROLL;
418
  }
561
    gyroOffset.offsets[YAW] = 512 * GYRO_OVERSAMPLING_YAW;
-
 
562
  }
419
 
563
 
420
  /*
564
  if (accOffset_readFromEEProm()) {
421
  if (accOffset_readFromEEProm()) {
565
    printf("acc. meter offsets invalid%s",recal);
422
    printf("acc. meter offsets invalid%s",recal);
566
    accOffset.offsets[PITCH] = accOffset.offsets[ROLL] = 512 * ACC_OVERSAMPLING_XY;
423
    accOffset.offsets[PITCH] = accOffset.offsets[ROLL] = 512 * ACC_OVERSAMPLING_XY;
Line 598... Line 455...
598
  }
455
  }
Line 599... Line 456...
599
 
456
 
600
  for (axis = PITCH; axis <= YAW; axis++) {
457
  for (axis = PITCH; axis <= YAW; axis++) {
Line 601... Line 458...
601
    gyroOffset.offsets[axis] = (offsets[axis] + GYRO_OFFSET_CYCLES / 2) / GYRO_OFFSET_CYCLES;
458
    gyroOffset.offsets[axis] = (offsets[axis] + GYRO_OFFSET_CYCLES / 2) / GYRO_OFFSET_CYCLES;
602
 
459
 
603
    int16_t min = (512-200) * (axis==YAW) ? GYRO_OVERSAMPLING_YAW : GYRO_OVERSAMPLING_PITCHROLL;
460
    int16_t min = (512-200) * GYRO_OVERSAMPLING;
604
    int16_t max = (512+200) * (axis==YAW) ? GYRO_OVERSAMPLING_YAW : GYRO_OVERSAMPLING_PITCHROLL;
461
    int16_t max = (512+200) * GYRO_OVERSAMPLING;
605
    if(gyroOffset.offsets[axis] < min || gyroOffset.offsets[axis] > max)
462
    if(gyroOffset.offsets[axis] < min || gyroOffset.offsets[axis] > max)
Line 606... Line 463...
606
      versionInfo.hardwareErrors[0] |= FC_ERROR0_GYRO_PITCH << axis;
463
      versionInfo.hardwareErrors[0] |= FC_ERROR0_GYRO_PITCH << axis;
607
  }
464
  }
608
 
465
 
609
  gyroOffset_writeToEEProm();  
-
 
610
  startAnalogConversionCycle();
-
 
611
}
-
 
612
 
-
 
613
/*
-
 
614
 * Find acc. offsets for a neutral reading, and write them to EEPROM.
-
 
615
 * Does not (!} update the local variables. This must be done with a
-
 
616
 * call to analog_calibrate() - this always (?) is done by the caller
-
 
617
 * anyway. There would be nothing wrong with updating the variables
-
 
618
 * directly from here, though.
-
 
619
 */
-
 
620
void analog_calibrateAcc(void) {
-
 
621
#define ACC_OFFSET_CYCLES 32
-
 
622
  uint8_t i, axis;
-
 
623
  int32_t offsets[3] = { 0, 0, 0 };
-
 
624
 
-
 
625
  for (i = 0; i < ACC_OFFSET_CYCLES; i++) {
-
 
626
    delay_ms_with_adc_measurement(10, 1);
-
 
627
    for (axis = PITCH; axis <= YAW; axis++) {
-
 
628
      offsets[axis] += rawAccValue(axis);
-
 
629
    }
-
 
630
  }
-
 
631
 
-
 
632
  for (axis = PITCH; axis <= YAW; axis++) {
-
 
633
    accOffset.offsets[axis] = (offsets[axis] + ACC_OFFSET_CYCLES / 2) / ACC_OFFSET_CYCLES;
-
 
634
    int16_t min,max;
-
 
635
    if (axis==Z) {
-
 
636
        if (IMUConfig.imuReversedFlags & IMU_REVERSE_ACC_Z) {
-
 
637
        // TODO: This assumes a sensitivity of +/- 2g.
-
 
638
                min = (256-200) * ACC_OVERSAMPLING_Z;
-
 
639
                        max = (256+200) * ACC_OVERSAMPLING_Z;
-
 
640
        } else {
-
 
641
        // TODO: This assumes a sensitivity of +/- 2g.
-
 
642
                min = (768-200) * ACC_OVERSAMPLING_Z;
-
 
643
                        max = (768+200) * ACC_OVERSAMPLING_Z;
-
 
644
        }
-
 
645
    } else {
-
 
646
        min = (512-200) * ACC_OVERSAMPLING_XY;
-
 
647
        max = (512+200) * ACC_OVERSAMPLING_XY;
-
 
648
    }
-
 
649
    if(gyroOffset.offsets[axis] < min || gyroOffset.offsets[axis] > max) {
-
 
650
      versionInfo.hardwareErrors[0] |= FC_ERROR0_ACC_X << axis;
-
 
651
    }
-
 
652
  }
-
 
653
 
-
 
654
  accOffset_writeToEEProm();
-
 
655
  startAnalogConversionCycle();
-
 
656
}
-
 
657
 
-
 
658
void analog_setGround() {
-
 
659
  groundPressure = filteredAirPressure;
-
 
660
}
-
 
661
 
-
 
662
int32_t analog_getHeight(void) {
-
 
663
  return groundPressure - filteredAirPressure;
-
 
664
}
-
 
665
 
-
 
666
int16_t analog_getDHeight(void) {
-
 
667
/*
-
 
668
        int16_t result = 0;
-
 
669
        for (int i=0; i<staticParams.airpressureDWindowLength; i++) {
-
 
670
                result -= dAirPressureWindow[i]; // minus pressure is plus height.
-
 
671
        }
-
 
672
  // dHeight = -dPressure, so here it is the old pressure minus the current, not opposite.
-
 
673
  return result;
-