Subversion Repositories FlightCtrl

Rev

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

Rev 1645 Rev 1646
Line 70... Line 70...
70
 * Here are those for the gyros and the acc. meters. They are not zero-offset.
70
 * Here are those for the gyros and the acc. meters. They are not zero-offset.
71
 * They are exported in the analog.h file - but please do not use them! The only
71
 * They are exported in the analog.h file - but please do not use them! The only
72
 * reason for the export is that the ENC-03_FC1.3 modules needs them for calibrating
72
 * reason for the export is that the ENC-03_FC1.3 modules needs them for calibrating
73
 * the offsets with the DAC.
73
 * the offsets with the DAC.
74
 */
74
 */
75
volatile int16_t rawGyroSum[2], rawYawGyroSum;
75
volatile int16_t rawGyroSum[3];
76
volatile int16_t acc[2] = {0,0}, ZAcc = 0;
76
volatile int16_t acc[3];
77
volatile int16_t filteredAcc[2] = {0,0};
77
volatile int16_t filteredAcc[2]={0,0};
Line 78... Line 78...
78
 
78
 
79
/*
79
/*
80
 * These 4 exported variables are zero-offset. The "PID" ones are used
80
 * These 4 exported variables are zero-offset. The "PID" ones are used
81
 * in the attitude control as rotation rates. The "ATT" ones are for
81
 * in the attitude control as rotation rates. The "ATT" ones are for
82
 * integration to angles.
82
 * integration to angles.
83
 */
83
 */
84
volatile int16_t gyro_PID[2];
84
volatile int16_t gyro_PID[2];
85
volatile int16_t gyro_ATT[2];
85
volatile int16_t gyro_ATT[2];
86
volatile int16_t gyroD[2];
86
volatile int16_t gyroD[2];
Line 87... Line 87...
87
volatile int16_t yawGyro = 0;
87
volatile int16_t yawGyro;
88
 
88
 
89
/*
89
/*
90
 * Offset values. These are the raw gyro and acc. meter sums when the copter is
90
 * Offset values. These are the raw gyro and acc. meter sums when the copter is
91
 * standing still. They are used for adjusting the gyro and acc. meter values
91
 * standing still. They are used for adjusting the gyro and acc. meter values
92
 * to be centered on zero.
92
 * to be centered on zero.
-
 
93
 */
-
 
94
volatile int16_t gyroOffset[3] = {
-
 
95
        512 * GYRO_SUMMATION_FACTOR_PITCHROLL,
-
 
96
        512 * GYRO_SUMMATION_FACTOR_PITCHROLL,
-
 
97
        512 * GYRO_SUMMATION_FACTOR_YAW
93
 */
98
};
-
 
99
 
-
 
100
volatile int16_t accOffset[3] = {
-
 
101
        512 * ACC_SUMMATION_FACTOR_PITCHROLL,
-
 
102
        512 * ACC_SUMMATION_FACTOR_PITCHROLL,
Line 94... Line 103...
94
volatile int16_t gyroOffset[2], yawGyroOffset;
103
        512 * ACC_SUMMATION_FACTOR_Z
95
volatile int16_t accOffset[2], ZAccOffset;
104
};
96
 
105
 
97
/*
106
/*
98
 * This allows some experimentation with the gyro filters.
107
 * This allows some experimentation with the gyro filters.
99
 * Should be replaced by #define's later on...
108
 * Should be replaced by #define's later on...
100
 */
109
 */
101
volatile uint8_t GYROS_FIRSTORDERFILTER;
110
volatile uint8_t GYROS_PID_FILTER;
Line 102... Line 111...
102
volatile uint8_t GYROS_SECONDORDERFILTER;
111
volatile uint8_t GYROS_ATT_FILTER;
103
volatile uint8_t GYROS_DFILTER;
112
volatile uint8_t GYROS_D_FILTER;
104
volatile uint8_t ACC_FILTER;
113
volatile uint8_t ACC_FILTER;
Line 251... Line 260...
251
   * Actually we don't need this "switch". We could do all the sampling into the
260
   * Actually we don't need this "switch". We could do all the sampling into the
252
   * sensorInputs array first, and all the processing after the last sample.
261
   * sensorInputs array first, and all the processing after the last sample.
253
   */
262
   */
254
  switch(state++) {
263
  switch(state++) {
255
  case 7: // Z acc      
264
  case 7: // Z acc      
256
#ifdef ACC_REVERSE_ZAXIS
265
  if (ACC_REVERSED[Z])
257
    ZAcc = -ZAccOffset - sensorInputs[AD_ACC_Z];
266
    acc[Z] = accOffset[Z] - sensorInputs[AD_ACC_Z];
258
#else
267
  else
259
    ZAcc = sensorInputs[AD_ACC_Z] - ZAccOffset;
268
    acc[Z] = sensorInputs[AD_ACC_Z] - accOffset[Z];
260
#endif
-
 
261
    break;
269
  break;
Line 262... Line 270...
262
   
270
   
263
  case 10: // yaw gyro
271
  case 10: // yaw gyro
264
    rawYawGyroSum = sensorInputs[AD_GYRO_YAW];
272
    rawGyroSum[YAW] = sensorInputs[AD_GYRO_YAW];
265
#ifdef GYRO_REVERSE_YAW
273
    if (GYRO_REVERSED[YAW])
266
    yawGyro = rawYawGyroSum - yawGyroOffset;
274
      yawGyro = gyroOffset[YAW] - sensorInputs[AD_GYRO_YAW];
267
#else
275
    else
268
    yawGyro = yawGyroOffset - rawYawGyroSum; // negative is "default" (FC 1.0-1.3).
-
 
269
#endif
276
      yawGyro = sensorInputs[AD_GYRO_YAW] - gyroOffset[YAW];
Line 270... Line 277...
270
    break;
277
    break;
271
   
278
   
272
  case 11: // pitch axis acc.
279
  case 11: // pitch axis acc.
273
#ifdef ACC_REVERSE_PITCHAXIS
280
    if (ACC_REVERSED[PITCH])
274
    acc[PITCH] = -accOffset[PITCH] - sensorInputs[AD_ACC_PITCH];
281
      acc[PITCH] = accOffset[PITCH] - sensorInputs[AD_ACC_PITCH];
275
#else
-
 
276
    acc[PITCH] = sensorInputs[AD_ACC_PITCH] - accOffset[PITCH];
-
 
Line -... Line 282...
-
 
282
    else
277
#endif
283
      acc[PITCH] = sensorInputs[AD_ACC_PITCH] - accOffset[PITCH];
278
    filteredAcc[PITCH] = (filteredAcc[PITCH] * (ACC_FILTER-1) + acc[PITCH]) / ACC_FILTER;
284
 
Line 279... Line 285...
279
 
285
    filteredAcc[PITCH] = (filteredAcc[PITCH] * (ACC_FILTER-1) + acc[PITCH]) / ACC_FILTER;
280
    measureNoise(acc[PITCH], &accNoisePeak[PITCH], 1);
286
    measureNoise(acc[PITCH], &accNoisePeak[PITCH], 1);
281
    break;
287
    break;
282
   
288
   
283
  case 12: // roll axis acc.
289
  case 12: // roll axis acc.
284
#ifdef ACC_REVERSE_ROLLAXIS
-
 
285
    acc[ROLL] = sensorInputs[AD_ACC_ROLL] - accOffset[ROLL];
290
    if (ACC_REVERSED[ROLL])
286
#else
291
      acc[ROLL] = accOffset[ROLL] - sensorInputs[AD_ACC_ROLL];
287
    acc[ROLL] = -accOffset[ROLL] - sensorInputs[AD_ACC_ROLL];
292
    else
Line 288... Line 293...
288
#endif
293
      acc[ROLL] = sensorInputs[AD_ACC_ROLL] - accOffset[ROLL];
Line 312... Line 317...
312
      OCR0A = range;
317
      OCR0A = range;
313
    } else {
318
    } else {
314
      filteredAirPressure = filterAirPressure(getAbsPressure(rawAirPressure));
319
      filteredAirPressure = filterAirPressure(getAbsPressure(rawAirPressure));
315
    }
320
    }
Line 316... Line 321...
316
   
321
   
317
    DebugOut.Analog[12] = range;
322
    DebugOut.Analog[13] = range;
318
    DebugOut.Analog[13] = rawAirPressure;
323
    DebugOut.Analog[14] = rawAirPressure;
319
    DebugOut.Analog[14] = filteredAirPressure;
324
    DebugOut.Analog[15] = filteredAirPressure;
Line 320... Line 325...
320
    break;
325
    break;
321
 
326
 
322
  case 14:
327
  case 14:
Line 338... Line 343...
338
        tempGyro = (tempGyro - SENSOR_MAX_PITCHROLL) * EXTRAPOLATION_SLOPE + SENSOR_MAX_PITCHROLL;
343
        tempGyro = (tempGyro - SENSOR_MAX_PITCHROLL) * EXTRAPOLATION_SLOPE + SENSOR_MAX_PITCHROLL;
339
      }
344
      }
340
    }
345
    }
Line 341... Line 346...
341
 
346
 
342
    // 2) Apply sign and offset, scale before filtering.
347
    // 2) Apply sign and offset, scale before filtering.
343
    if (GYROS_REVERSE[axis]) {
348
    if (GYRO_REVERSED[axis]) {
344
      tempOffsetGyro = (gyroOffset[axis] - tempGyro) * GYRO_FACTOR_PITCHROLL;
349
      tempOffsetGyro = (gyroOffset[axis] - tempGyro) * GYRO_FACTOR_PITCHROLL;
345
    } else {
350
    } else {
346
      tempOffsetGyro = (tempGyro - gyroOffset[axis]) * GYRO_FACTOR_PITCHROLL;
351
      tempOffsetGyro = (tempGyro - gyroOffset[axis]) * GYRO_FACTOR_PITCHROLL;
Line 347... Line 352...
347
    }
352
    }
348
 
353
 
Line 349... Line 354...
349
    // 3) Scale and filter.
354
    // 3) Scale and filter.
350
    tempOffsetGyro = (gyro_PID[axis] * (GYROS_PIDFILTER-1) + tempOffsetGyro) / GYROS_PIDFILTER;
355
    tempOffsetGyro = (gyro_PID[axis] * (GYROS_PID_FILTER-1) + tempOffsetGyro) / GYROS_PID_FILTER;
Line 351... Line 356...
351
 
356
 
352
    // 4) Measure noise.
357
    // 4) Measure noise.
Line 353... Line 358...
353
    measureNoise(tempOffsetGyro, &gyroNoisePeak[axis], GYRO_NOISE_MEASUREMENT_DAMPING);
358
    measureNoise(tempOffsetGyro, &gyroNoisePeak[axis], GYRO_NOISE_MEASUREMENT_DAMPING);
354
 
359
 
Line 355... Line 360...
355
    // 5) Differential measurement. 
360
    // 5) Differential measurement. 
356
    gyroD[axis] = (gyroD[axis] * (GYROS_DFILTER-1) + (tempOffsetGyro - gyro_PID[axis])) / GYROS_DFILTER;
361
    gyroD[axis] = (gyroD[axis] * (GYROS_D_FILTER-1) + (tempOffsetGyro - gyro_PID[axis])) / GYROS_D_FILTER;
357
 
362
 
358
    // 6) Done.
363
    // 6) Done.
Line 359... Line 364...
359
    gyro_PID[axis] = tempOffsetGyro;
364
    gyro_PID[axis] = tempOffsetGyro;
360
 
365
 
361
    /*
366
    /*
362
     * Now process the data for attitude angles.
367
     * Now process the data for attitude angles.
363
     */
368
     */
364
    tempGyro = rawGyroSum[axis];
369
    tempGyro = rawGyroSum[axis];
Line 365... Line 370...
365
   
370
   
366
    // 1) Apply sign and offset, scale before filtering.
371
    // 1) Apply sign and offset, scale before filtering.
367
    if (GYROS_REVERSE[axis]) {
372
    if (GYRO_REVERSED[axis]) {
Line 368... Line 373...
368
      tempOffsetGyro = (gyroOffset[axis] - tempGyro) * GYRO_FACTOR_PITCHROLL;
373
      tempOffsetGyro = (gyroOffset[axis] - tempGyro) * GYRO_FACTOR_PITCHROLL;
369
    } else {
374
    } else {
370
      tempOffsetGyro = (tempGyro - gyroOffset[axis]) * GYRO_FACTOR_PITCHROLL;
375
      tempOffsetGyro = (tempGyro - gyroOffset[axis]) * GYRO_FACTOR_PITCHROLL;
Line 398... Line 403...
398
  if(state) analog_start();
403
  if(state) analog_start();
399
}
404
}
Line 400... Line 405...
400
 
405
 
401
void analog_calibrate(void) {
406
void analog_calibrate(void) {
402
#define GYRO_OFFSET_CYCLES 32
407
#define GYRO_OFFSET_CYCLES 32
403
  uint8_t i;
408
  uint8_t i, axis;
-
 
409
  int32_t deltaOffsets[3] = {0,0,0};
Line 404... Line 410...
404
  int32_t _pitchOffset = 0, _rollOffset = 0, _yawOffset = 0;
410
  int16_t filteredDelta;
405
 
411
 
406
  // Set the filters... to be removed again, once some good settings are found.
412
  // Set the filters... to be removed again, once some good settings are found.
407
  GYROS_FIRSTORDERFILTER = (dynamicParams.UserParams[4]   & 0b00000011)       + 1;
413
  GYROS_PID_FILTER = (dynamicParams.UserParams[4]   & 0b00000011)       + 1;
408
  GYROS_SECONDORDERFILTER = ((dynamicParams.UserParams[4] & 0b00001100) >> 2) + 1;
414
  GYROS_ATT_FILTER = ((dynamicParams.UserParams[4]  & 0b00001100) >> 2) + 1;
409
  GYROS_DFILTER = ((dynamicParams.UserParams[4]           & 0b00110000) >> 4) + 1;
-
 
410
  ACC_FILTER = ((dynamicParams.UserParams[4]              & 0b11000000) >> 6) + 1;
-
 
Line 411... Line 415...
411
 
415
  GYROS_D_FILTER = ((dynamicParams.UserParams[4]    & 0b00110000) >> 4) + 1;
Line 412... Line 416...
412
  gyroOffset[PITCH] = gyroOffset[ROLL] = yawGyroOffset = 0;
416
  ACC_FILTER = ((dynamicParams.UserParams[4]        & 0b11000000) >> 6) + 1;
413
 
417
 
414
  gyro_calibrate();
418
  gyro_calibrate();
415
 
419
 
416
  // determine gyro bias by averaging (requires that the copter does not rotate around any axis!)
420
  // determine gyro bias by averaging (requires that the copter does not rotate around any axis!)
417
  for(i=0; i < GYRO_OFFSET_CYCLES; i++) {
421
  for(i=0; i < GYRO_OFFSET_CYCLES; i++) {
418
    Delay_ms_Mess(10);
422
    Delay_ms_Mess(10);
419
    _pitchOffset += rawGyroSum[PITCH];
423
    for (axis=0; axis<=YAW; axis++) {
420
    _rollOffset  += rawGyroSum[ROLL];
424
      deltaOffsets[axis] += rawGyroSum[axis] - gyroOffset[axis];
421
    _yawOffset   += rawYawGyroSum;
425
    }
422
  }
426
  }
423
 
427
 
424
  gyroOffset[PITCH] = (_pitchOffset + GYRO_OFFSET_CYCLES / 2) / GYRO_OFFSET_CYCLES;
-
 
425
  gyroOffset[ROLL] = (_rollOffset  + GYRO_OFFSET_CYCLES / 2) / GYRO_OFFSET_CYCLES;
-
 
426
  yawGyroOffset   = (_yawOffset   + GYRO_OFFSET_CYCLES / 2) / GYRO_OFFSET_CYCLES;
428
  for (axis=0; axis<=YAW; axis++) {
427
 
429
    filteredDelta = (deltaOffsets[axis] + GYRO_OFFSET_CYCLES / 2) / GYRO_OFFSET_CYCLES;
428
  gyro_PID[PITCH] = gyro_PID[ROLL] = 0;
-
 
429
  gyro_ATT[PITCH] = gyro_ATT[ROLL] = 0;
430
    gyroOffset[axis] += filteredDelta;
Line 430... Line 431...
430
 
431
  }
431
  // Noise is relative to offset. So, reset noise measurements when
432
 
432
  // changing offsets.
433
  // Noise is relative to offset. So, reset noise measurements when changing offsets.
-
 
434
  gyroNoisePeak[PITCH] = gyroNoisePeak[ROLL] = 0;
-
 
435
 
433
  gyroNoisePeak[PITCH] = gyroNoisePeak[ROLL] = 0;
436
  accOffset[PITCH] = GetParamWord(PID_ACC_PITCH);
Line 434... Line 437...
434
 
437
  accOffset[ROLL]  = GetParamWord(PID_ACC_ROLL);
435
  accOffset[PITCH] = (int16_t)GetParamWord(PID_ACC_PITCH);
438
  accOffset[Z]     = GetParamWord(PID_ACC_Z);
436
  accOffset[ROLL]  = (int16_t)GetParamWord(PID_ACC_ROLL);
439
 
Line 444... Line 447...
444
 * anyway. There would be nothing wrong with updating the variables
447
 * anyway. There would be nothing wrong with updating the variables
445
 * directly from here, though.
448
 * directly from here, though.
446
 */
449
 */
447
void analog_calibrateAcc(void) {
450
void analog_calibrateAcc(void) {
448
#define ACC_OFFSET_CYCLES 10
451
#define ACC_OFFSET_CYCLES 10
449
  uint8_t i;
452
  uint8_t i, axis;
450
  int32_t _pitchAxisOffset = 0, _rollAxisOffset = 0, _ZAxisOffset = 0;
453
  int32_t deltaOffset[3] = {0,0,0};
-
 
454
  int16_t filteredDelta;
451
  // int16_t pressureDiff, savedRawAirPressure;
455
  // int16_t pressureDiff, savedRawAirPressure;
452
 
-
 
453
  accOffset[PITCH] = accOffset[ROLL] = ZAccOffset = 0;
-
 
Line 454... Line 456...
454
 
456
 
455
  for(i=0; i < ACC_OFFSET_CYCLES; i++) {
457
  for(i=0; i < ACC_OFFSET_CYCLES; i++) {
456
    Delay_ms_Mess(10);
458
    Delay_ms_Mess(10);
457
    _pitchAxisOffset += acc[PITCH];
459
    for (axis=0; axis<=YAW; axis++) {
-
 
460
          deltaOffset[axis] += acc[axis];
-
 
461
        }
-
 
462
  }
458
    _rollAxisOffset  += acc[ROLL];
463
 
-
 
464
  for (axis=0; axis<=YAW; axis++) {
-
 
465
    filteredDelta = (deltaOffset[axis] + ACC_OFFSET_CYCLES / 2) / ACC_OFFSET_CYCLES;
459
    _ZAxisOffset += ZAcc;
466
    accOffset[axis] += ACC_REVERSED[axis] ? -filteredDelta : filteredDelta;
Line 460... Line 467...
460
  }
467
  }
461
 
468
 
462
  // Save ACC neutral settings to eeprom
469
  // Save ACC neutral settings to eeprom
463
  SetParamWord(PID_ACC_PITCH, (uint16_t)((_pitchAxisOffset + ACC_OFFSET_CYCLES / 2) / ACC_OFFSET_CYCLES));
470
  SetParamWord(PID_ACC_PITCH, accOffset[PITCH]);
Line 464... Line 471...
464
  SetParamWord(PID_ACC_ROLL, (uint16_t)((_rollAxisOffset  + ACC_OFFSET_CYCLES / 2) / ACC_OFFSET_CYCLES));
471
  SetParamWord(PID_ACC_ROLL,  accOffset[ROLL]);
465
  SetParamWord(PID_ACC_TOP,  (uint16_t)((_ZAxisOffset     + ACC_OFFSET_CYCLES / 2) / ACC_OFFSET_CYCLES));
472
  SetParamWord(PID_ACC_Z,     accOffset[Z]);
466
 
473
 
-
 
474
  // Noise is relative to offset. So, reset noise measurements when
467
  // Noise is relative to offset. So, reset noise measurements when
475
  // changing offsets.
468
  // changing offsets.
476
  accNoisePeak[PITCH] = accNoisePeak[ROLL] = 0;
469
  accNoisePeak[PITCH] = accNoisePeak[ROLL] = 0;
477
 
Line 470... Line 478...
470
  // Setting offset values has an influence in the analog.c ISR
478
  // Setting offset values has an influence in the analog.c ISR
471
  // Therefore run measurement for 100ms to achive stable readings
479
  // Therefore run measurement for 100ms to achive stable readings
472
  // Delay_ms_Mess(100);
480
  Delay_ms_Mess(100);
473
 
481
 
Line 493... Line 501...
493
    Delay_ms_Mess(200);
501
    Delay_ms_Mess(200);
494
    // raw pressure will increase.
502
    // raw pressure will increase.
495
    pressureDiff += (rawAirPressure - savedRawAirPressure);
503
    pressureDiff += (rawAirPressure - savedRawAirPressure);
496
    }
504
    }
Line 497... Line 505...
497
 
505
 
498
    DebugOut.Analog[15] = rangewidth =
506
    DebugOut.Analog[16] = rangewidth =
499
    (pressureDiff + PRESSURE_CAL_CYCLE_COUNT * 2 - 1) / (PRESSURE_CAL_CYCLE_COUNT * 2);
507
    (pressureDiff + PRESSURE_CAL_CYCLE_COUNT * 2 - 1) / (PRESSURE_CAL_CYCLE_COUNT * 2);
500
  */
508
  */