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 | */ |