Subversion Repositories FlightCtrl

Rev

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

Rev 1646 Rev 1775
Line 111... Line 111...
111
volatile uint8_t GYROS_ATT_FILTER;
111
volatile uint8_t GYROS_ATT_FILTER;
112
volatile uint8_t GYROS_D_FILTER;
112
volatile uint8_t GYROS_D_FILTER;
113
volatile uint8_t ACC_FILTER;
113
volatile uint8_t ACC_FILTER;
Line 114... Line 114...
114
 
114
 
115
/*
115
/*
116
 * Air pressure measurement.
116
 * Air pressure
117
 */
117
 */
-
 
118
volatile uint8_t rangewidth = 106;
118
#define MIN_RAWPRESSURE 200
119
 
119
#define MAX_RAWPRESSURE (1023-MIN_RAWPRESSURE)
120
// Direct from sensor, irrespective of range.
-
 
121
// volatile uint16_t rawAirPressure;
-
 
122
 
120
volatile uint8_t rangewidth = 53;
123
// Value of 2 samples, with range.
-
 
124
volatile uint16_t simpleAirPressure;
-
 
125
 
121
volatile uint16_t rawAirPressure;
126
// Value of AIRPRESSURE_SUMMATION_FACTOR samples, with range, filtered.
-
 
127
volatile int32_t filteredAirPressure;
-
 
128
 
-
 
129
// Partial sum of AIRPRESSURE_SUMMATION_FACTOR samples.
-
 
130
volatile int32_t airPressureSum;
-
 
131
 
-
 
132
// The number of samples summed into airPressureSum so far.
Line 122... Line 133...
122
volatile uint16_t filteredAirPressure;
133
volatile uint8_t pressureMeasurementCount;
123
 
134
 
124
/*
135
/*
125
 * 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.
Line 167... Line 178...
167
  AD_GYRO_ROLL,
178
  AD_GYRO_ROLL,
168
  AD_GYRO_YAW,
179
  AD_GYRO_YAW,
Line 169... Line 180...
169
 
180
 
170
  AD_ACC_PITCH,
181
  AD_ACC_PITCH,
171
  AD_ACC_ROLL,
182
  AD_ACC_ROLL,
Line 172... Line 183...
172
  // AD_AIRPRESSURE,
183
  AD_AIRPRESSURE,
173
 
184
 
174
  AD_GYRO_PITCH,
185
  AD_GYRO_PITCH,
Line 175... Line 186...
175
  AD_GYRO_ROLL,
186
  AD_GYRO_ROLL,
176
  AD_ACC_Z,       // at 7, measure Z acc.
187
  AD_ACC_Z,       // at 8, measure Z acc.
177
 
188
 
Line 178... Line 189...
178
  AD_GYRO_PITCH,
189
  AD_GYRO_PITCH,
179
  AD_GYRO_ROLL,
190
  AD_GYRO_ROLL,
180
  AD_GYRO_YAW,    // at 10, finish yaw gyro
191
  AD_GYRO_YAW,    // at 11, finish yaw gyro
181
 
192
 
182
  AD_ACC_PITCH,   // at 11, finish pitch axis acc.
193
  AD_ACC_PITCH,   // at 12, finish pitch axis acc.
183
  AD_ACC_ROLL,    // at 12, finish roll axis acc.
194
  AD_ACC_ROLL,    // at 13, finish roll axis acc.
184
  AD_AIRPRESSURE, // at 13, finish air pressure.
195
  AD_AIRPRESSURE, // at 14, finish air pressure.
185
 
196
 
Line 186... Line 197...
186
  AD_GYRO_PITCH,  // at 14, finish pitch gyro
197
  AD_GYRO_PITCH,  // at 15, finish pitch gyro
187
  AD_GYRO_ROLL,   // at 15, finish roll gyro
198
  AD_GYRO_ROLL,   // at 16, finish roll gyro
Line 228... Line 239...
228
  } else {
239
  } else {
229
    *noiseMeasurement = 0;
240
    *noiseMeasurement = 0;
230
  }
241
  }
231
}
242
}
Line 232... Line 243...
232
 
243
 
233
uint16_t getAbsPressure(int advalue) {
244
uint16_t getSimplePressure(int advalue) {
234
  return (uint16_t)OCR0A * (uint16_t)rangewidth + advalue;
245
  return (uint16_t)OCR0A * (uint16_t)rangewidth + advalue;
Line 235... Line -...
235
}
-
 
236
 
-
 
237
uint16_t filterAirPressure(uint16_t rawpressure) {
-
 
238
  return rawpressure;
-
 
239
}
246
}
240
 
247
 
241
/*****************************************************
248
/*****************************************************
242
 * Interrupt Service Routine for ADC            
249
 * Interrupt Service Routine for ADC            
243
 * Runs at 312.5 kHz or 3.2 µs. When all states are
250
 * Runs at 312.5 kHz or 3.2 µs. When all states are
244
 * processed the interrupt is disabled and further
251
 * processed the interrupt is disabled and further
245
 * AD conversions are stopped.
252
 * AD conversions are stopped.
246
 *****************************************************/
253
 *****************************************************/
247
ISR(ADC_vect) {
254
ISR(ADC_vect) {
248
  static uint8_t ad_channel = AD_GYRO_PITCH, state = 0;
255
  static uint8_t ad_channel = AD_GYRO_PITCH, state = 0;
-
 
256
  static uint16_t sensorInputs[8] = {0,0,0,0,0,0,0,0};
249
  static uint16_t sensorInputs[8] = {0,0,0,0,0,0,0,0};
257
  static uint16_t pressureAutorangingWait = 25;
250
  static uint8_t pressure_wait = 10;
258
  uint16_t rawAirPressure;
Line 251... Line 259...
251
  uint8_t i, axis;
259
  uint8_t i, axis;
252
  int16_t range;
260
  int16_t newrange;
Line 253... Line 261...
253
 
261
 
Line 259... Line 267...
259
  /*
267
  /*
260
   * Actually we don't need this "switch". We could do all the sampling into the
268
   * Actually we don't need this "switch". We could do all the sampling into the
261
   * sensorInputs array first, and all the processing after the last sample.
269
   * sensorInputs array first, and all the processing after the last sample.
262
   */
270
   */
263
  switch(state++) {
271
  switch(state++) {
-
 
272
 
264
  case 7: // Z acc      
273
  case 8: // Z acc      
265
  if (ACC_REVERSED[Z])
274
  if (ACC_REVERSED[Z])
266
    acc[Z] = accOffset[Z] - sensorInputs[AD_ACC_Z];
275
    acc[Z] = accOffset[Z] - sensorInputs[AD_ACC_Z];
267
  else
276
  else
268
    acc[Z] = sensorInputs[AD_ACC_Z] - accOffset[Z];
277
    acc[Z] = sensorInputs[AD_ACC_Z] - accOffset[Z];
269
  break;
278
  break;
Line 270... Line 279...
270
   
279
   
271
  case 10: // yaw gyro
280
  case 11: // yaw gyro
272
    rawGyroSum[YAW] = sensorInputs[AD_GYRO_YAW];
281
    rawGyroSum[YAW] = sensorInputs[AD_GYRO_YAW];
273
    if (GYRO_REVERSED[YAW])
282
    if (GYRO_REVERSED[YAW])
274
      yawGyro = gyroOffset[YAW] - sensorInputs[AD_GYRO_YAW];
283
      yawGyro = gyroOffset[YAW] - sensorInputs[AD_GYRO_YAW];
275
    else
284
    else
276
      yawGyro = sensorInputs[AD_GYRO_YAW] - gyroOffset[YAW];
285
      yawGyro = sensorInputs[AD_GYRO_YAW] - gyroOffset[YAW];
Line 277... Line 286...
277
    break;
286
    break;
278
   
287
   
279
  case 11: // pitch axis acc.
288
  case 12: // pitch axis acc.
280
    if (ACC_REVERSED[PITCH])
289
    if (ACC_REVERSED[PITCH])
281
      acc[PITCH] = accOffset[PITCH] - sensorInputs[AD_ACC_PITCH];
290
      acc[PITCH] = accOffset[PITCH] - sensorInputs[AD_ACC_PITCH];
Line 282... Line 291...
282
    else
291
    else
283
      acc[PITCH] = sensorInputs[AD_ACC_PITCH] - accOffset[PITCH];
292
      acc[PITCH] = sensorInputs[AD_ACC_PITCH] - accOffset[PITCH];
284
 
293
 
Line 285... Line 294...
285
    filteredAcc[PITCH] = (filteredAcc[PITCH] * (ACC_FILTER-1) + acc[PITCH]) / ACC_FILTER;
294
    filteredAcc[PITCH] = (filteredAcc[PITCH] * (ACC_FILTER-1) + acc[PITCH]) / ACC_FILTER;
286
    measureNoise(acc[PITCH], &accNoisePeak[PITCH], 1);
295
    measureNoise(acc[PITCH], &accNoisePeak[PITCH], 1);
287
    break;
296
    break;
288
   
297
   
289
  case 12: // roll axis acc.
298
  case 13: // roll axis acc.
290
    if (ACC_REVERSED[ROLL])
299
    if (ACC_REVERSED[ROLL])
291
      acc[ROLL] = accOffset[ROLL] - sensorInputs[AD_ACC_ROLL];
300
      acc[ROLL] = accOffset[ROLL] - sensorInputs[AD_ACC_ROLL];
292
    else
301
    else
Line 293... Line 302...
293
      acc[ROLL] = sensorInputs[AD_ACC_ROLL] - accOffset[ROLL];
302
      acc[ROLL] = sensorInputs[AD_ACC_ROLL] - accOffset[ROLL];
294
    filteredAcc[ROLL] = (filteredAcc[ROLL] * (ACC_FILTER-1) + acc[ROLL]) / ACC_FILTER;
303
    filteredAcc[ROLL] = (filteredAcc[ROLL] * (ACC_FILTER-1) + acc[ROLL]) / ACC_FILTER;
295
    measureNoise(acc[ROLL], &accNoisePeak[ROLL], 1);
304
    measureNoise(acc[ROLL], &accNoisePeak[ROLL], 1);
296
    break;
305
    break;
297
 
306
 
298
  case 13: // air pressure
307
  case 14: // air pressure
299
    if (pressure_wait) {
-
 
300
      // A range switch was done recently. Wait for steadying.
308
    if (pressureAutorangingWait) {
301
      pressure_wait--;
309
      //A range switch was done recently. Wait for steadying.
302
      break;
310
      pressureAutorangingWait--;
303
    }
311
      break;
304
    range = OCR0A;
312
    }
305
    rawAirPressure = sensorInputs[AD_AIRPRESSURE];
313
    rawAirPressure = sensorInputs[AD_AIRPRESSURE];
306
    if (rawAirPressure < MIN_RAWPRESSURE) {
314
    if (rawAirPressure < MIN_RAWPRESSURE) {
-
 
315
      // value is too low, so decrease voltage on the op amp minus input, making the value higher.
-
 
316
      newrange = OCR0A - (MAX_RAWPRESSURE - rawAirPressure) / rangewidth - 1;
-
 
317
      if (newrange > MIN_RANGES_EXTRAPOLATION) {
-
 
318
        pressureAutorangingWait = (OCR0A - newrange) * AUTORANGE_WAIT_FACTOR;
-
 
319
        OCR0A = newrange;
-
 
320
      } else {
307
      // value is too low, so decrease voltage on the op amp minus input, making the value higher.
321
        if (OCR0A) {
308
      range -= (MAX_RAWPRESSURE - rawAirPressure) / rangewidth - 1;
322
          OCR0A--;
-
 
323
          pressureAutorangingWait = AUTORANGE_WAIT_FACTOR;
309
      if (range < 0) range = 0;
324
        }
310
      pressure_wait = (OCR0A - range) * 4;
325
      }
311
      OCR0A = range;
326
    } else if (rawAirPressure > MAX_RAWPRESSURE) {
312
    } else if (rawAirPressure > MAX_RAWPRESSURE) {
327
      // value is too high, so increase voltage on the op amp minus input, making the value lower.
-
 
328
      // If near the end, make a limited increase
-
 
329
      newrange = OCR0A + (rawAirPressure - MIN_RAWPRESSURE) / rangewidth - 1;
-
 
330
      if (newrange < MAX_RANGES_EXTRAPOLATION) {
-
 
331
      pressureAutorangingWait = (newrange - OCR0A) * AUTORANGE_WAIT_FACTOR;
-
 
332
      OCR0A = newrange;
-
 
333
      } else {
-
 
334
        if (OCR0A<254) {
-
 
335
          OCR0A++;
-
 
336
          pressureAutorangingWait = AUTORANGE_WAIT_FACTOR;
-
 
337
        }
-
 
338
      }
-
 
339
    }
-
 
340
 
-
 
341
    // Even if the sample is off-range, use it.
-
 
342
    simpleAirPressure = getSimplePressure(rawAirPressure);
-
 
343
    if (simpleAirPressure < MIN_RANGES_EXTRAPOLATION * rangewidth) {
-
 
344
      // Danger: pressure near lower end of range. If the measurement saturates, the 
-
 
345
      // copter may climb uncontrolled... Simulate a drastic reduction in pressure.
313
      // value is too high, so increase voltage on the op amp minus input, making the value lower.
346
      airPressureSum += (int16_t)MIN_RANGES_EXTRAPOLATION * rangewidth + (simpleAirPressure - (int32_t)MIN_RANGES_EXTRAPOLATION * rangewidth) * PRESSURE_EXTRAPOLATION_COEFF;
-
 
347
    } else if (simpleAirPressure > MAX_RANGES_EXTRAPOLATION * rangewidth) {
314
      range += (rawAirPressure - MIN_RAWPRESSURE) / rangewidth - 1;
348
      // Danger: pressure near upper end of range. If the measurement saturates, the 
315
      if (range > 254) range = 254;
349
      // copter may fall uncontrolled... Simulate a drastic increase in pressure.
Line -... Line 350...
-
 
350
      airPressureSum += (int16_t)MAX_RANGES_EXTRAPOLATION * rangewidth + (simpleAirPressure - (int32_t)MAX_RANGES_EXTRAPOLATION * rangewidth) * PRESSURE_EXTRAPOLATION_COEFF;
-
 
351
    } else {
-
 
352
      // normal case.
-
 
353
      airPressureSum += simpleAirPressure;
-
 
354
    }
-
 
355
   
-
 
356
    // 2 samples were added.
316
      pressure_wait = (range - OCR0A) * 4;
357
    pressureMeasurementCount += 2;
317
      OCR0A = range;
358
    if (pressureMeasurementCount == AIRPRESSURE_SUMMATION_FACTOR) {
318
    } else {
359
      filteredAirPressure = (filteredAirPressure * (AIRPRESSURE_FILTER-1) + airPressureSum + AIRPRESSURE_FILTER/2) / AIRPRESSURE_FILTER;
-
 
360
      pressureMeasurementCount = airPressureSum = 0;
319
      filteredAirPressure = filterAirPressure(getAbsPressure(rawAirPressure));
361
    }
Line 320... Line 362...
320
    }
362
 
321
   
363
    // DebugOut.Analog[14] = OCR0A;
322
    DebugOut.Analog[13] = range;
364
    // DebugOut.Analog[15] = simpleAirPressure;
323
    DebugOut.Analog[14] = rawAirPressure;
365
    DebugOut.Analog[11] = UBat;
324
    DebugOut.Analog[15] = filteredAirPressure;
366
    DebugOut.Analog[27] = acc[Z];
325
    break;
367
    break;
326
 
368
 
327
  case 14:
369
  case 15:
Line 377... Line 419...
377
   
419
   
378
    // 2) Filter.
420
    // 2) Filter.
379
    gyro_ATT[axis] = (gyro_ATT[axis] * (GYROS_ATT_FILTER-1) + tempOffsetGyro) / GYROS_ATT_FILTER;
421
    gyro_ATT[axis] = (gyro_ATT[axis] * (GYROS_ATT_FILTER-1) + tempOffsetGyro) / GYROS_ATT_FILTER;
Line 380... Line 422...
380
    break;
422
    break;
-
 
423
   
381
   
424
  case 17:
382
  case 16:
425
    // Battery. The measured value is: (V * 1k/11k)/3v * 1024 = 31.03 counts per volt (max. measurable is 33v).
383
    // battery
426
    // This is divided by 3 --> 10.34 counts per volt.
384
    UBat = (3 * UBat + sensorInputs[AD_UBAT] / 3) / 4;
427
    UBat = (3 * UBat + sensorInputs[AD_UBAT] / 3) / 4;
385
    analogDataReady = 1; // mark
428
    analogDataReady = 1; // mark
386
    ADCycleCount++;
429
    ADCycleCount++;
Line 405... Line 448...
405
 
448
 
406
void analog_calibrate(void) {
449
void analog_calibrate(void) {
407
#define GYRO_OFFSET_CYCLES 32
450
#define GYRO_OFFSET_CYCLES 32
408
  uint8_t i, axis;
451
  uint8_t i, axis;
409
  int32_t deltaOffsets[3] = {0,0,0};
-
 
Line 410... Line 452...
410
  int16_t filteredDelta;
452
  int32_t deltaOffsets[3] = {0,0,0};
411
 
453
 
412
  // Set the filters... to be removed again, once some good settings are found.
454
  // Set the filters... to be removed again, once some good settings are found.
413
  GYROS_PID_FILTER = (dynamicParams.UserParams[4]   & 0b00000011)       + 1;
455
  GYROS_PID_FILTER = (dynamicParams.UserParams[4]   & 0b00000011)       + 1;
Line 417... Line 459...
417
 
459
 
Line 418... Line 460...
418
  gyro_calibrate();
460
  gyro_calibrate();
419
 
461
 
420
  // determine gyro bias by averaging (requires that the copter does not rotate around any axis!)
462
  // determine gyro bias by averaging (requires that the copter does not rotate around any axis!)
421
  for(i=0; i < GYRO_OFFSET_CYCLES; i++) {
463
  for(i=0; i < GYRO_OFFSET_CYCLES; i++) {
422
    Delay_ms_Mess(10);
464
    Delay_ms_Mess(20);
423
    for (axis=0; axis<=YAW; axis++) {
465
    for (axis=PITCH; axis<=YAW; axis++) {
424
      deltaOffsets[axis] += rawGyroSum[axis] - gyroOffset[axis];
466
      deltaOffsets[axis] += rawGyroSum[axis];
Line 425... Line 467...
425
    }
467
    }
426
  }
468
  }
427
 
469
 
428
  for (axis=0; axis<=YAW; axis++) {
470
  for (axis=PITCH; axis<=YAW; axis++) {
Line 429... Line 471...
429
    filteredDelta = (deltaOffsets[axis] + GYRO_OFFSET_CYCLES / 2) / GYRO_OFFSET_CYCLES;
471
    gyroOffset[axis] =  (deltaOffsets[axis] + GYRO_OFFSET_CYCLES/2) / GYRO_OFFSET_CYCLES;
430
    gyroOffset[axis] += filteredDelta;
472
    DebugOut.Analog[20+axis] = gyroOffset[axis];
Line 431... Line 473...
431
  }
473
  }
432
 
474
 
433
  // Noise is relative to offset. So, reset noise measurements when changing offsets.
475
  // Noise is relative to offset. So, reset noise measurements when changing offsets.
Line -... Line 476...
-
 
476
  gyroNoisePeak[PITCH] = gyroNoisePeak[ROLL] = 0;
-
 
477
 
-
 
478
  accOffset[PITCH] = GetParamWord(PID_ACC_PITCH);
-
 
479
  accOffset[ROLL]  = GetParamWord(PID_ACC_ROLL);
-
 
480
  accOffset[Z]     = GetParamWord(PID_ACC_Z);
-
 
481
 
-
 
482
  // Rough estimate. Hmm no nothing happens at calibration anyway.
434
  gyroNoisePeak[PITCH] = gyroNoisePeak[ROLL] = 0;
483
  // airPressureSum = simpleAirPressure * (AIRPRESSURE_SUMMATION_FACTOR/2);
435
 
484
  // pressureMeasurementCount = 0;
Line 436... Line 485...
436
  accOffset[PITCH] = GetParamWord(PID_ACC_PITCH);
485
 
437
  accOffset[ROLL]  = GetParamWord(PID_ACC_ROLL);
486
  // Experiment!
Line 454... Line 503...
454
  int16_t filteredDelta;
503
  int16_t filteredDelta;
455
  // int16_t pressureDiff, savedRawAirPressure;
504
  // int16_t pressureDiff, savedRawAirPressure;
Line 456... Line 505...
456
 
505
 
457
  for(i=0; i < ACC_OFFSET_CYCLES; i++) {
506
  for(i=0; i < ACC_OFFSET_CYCLES; i++) {
458
    Delay_ms_Mess(10);
507
    Delay_ms_Mess(10);
459
    for (axis=0; axis<=YAW; axis++) {
508
    for (axis=PITCH; axis<=YAW; axis++) {
460
          deltaOffset[axis] += acc[axis];
509
      deltaOffset[axis] += acc[axis];
461
        }
510
    }
Line 462... Line 511...
462
  }
511
  }
463
 
512
 
464
  for (axis=0; axis<=YAW; axis++) {
513
  for (axis=PITCH; axis<=YAW; axis++) {
465
    filteredDelta = (deltaOffset[axis] + ACC_OFFSET_CYCLES / 2) / ACC_OFFSET_CYCLES;
514
    filteredDelta = (deltaOffset[axis] + ACC_OFFSET_CYCLES / 2) / ACC_OFFSET_CYCLES;
Line 466... Line 515...
466
    accOffset[axis] += ACC_REVERSED[axis] ? -filteredDelta : filteredDelta;
515
    accOffset[axis] += ACC_REVERSED[axis] ? -filteredDelta : filteredDelta;
Line 484... Line 533...
484
  // OCR0A += (rawAirPressure - 512) / rangewidth;
533
  // OCR0A += (rawAirPressure - 512) / rangewidth;
485
  // Delay_ms_Mess(500);
534
  // Delay_ms_Mess(500);
Line 486... Line 535...
486
 
535
 
487
  /*
536
  /*
488
    pressureDiff = 0;
537
    pressureDiff = 0;
Line 489... Line 538...
489
    DebugOut.Analog[16] = rawAirPressure;
538
    // DebugOut.Analog[16] = rawAirPressure;
490
 
539
 
491
    #define PRESSURE_CAL_CYCLE_COUNT 2
540
    #define PRESSURE_CAL_CYCLE_COUNT 2
492
    for (i=0; i<PRESSURE_CAL_CYCLE_COUNT; i++) {
541
    for (i=0; i<PRESSURE_CAL_CYCLE_COUNT; i++) {
Line 501... Line 550...
501
    Delay_ms_Mess(200);
550
    Delay_ms_Mess(200);
502
    // raw pressure will increase.
551
    // raw pressure will increase.
503
    pressureDiff += (rawAirPressure - savedRawAirPressure);
552
    pressureDiff += (rawAirPressure - savedRawAirPressure);
504
    }
553
    }
Line 505... Line 554...
505
 
554
 
506
    DebugOut.Analog[16] = rangewidth =
555
    // DebugOut.Analog[16] =
507
    (pressureDiff + PRESSURE_CAL_CYCLE_COUNT * 2 - 1) / (PRESSURE_CAL_CYCLE_COUNT * 2);
556
    rangewidth = (pressureDiff + PRESSURE_CAL_CYCLE_COUNT * 2 - 1) / (PRESSURE_CAL_CYCLE_COUNT * 2);
508
  */
557
  */