Subversion Repositories FlightCtrl

Compare Revisions

Ignore whitespace Rev 2014 → Rev 2015

/branches/dongfang_FC_rewrite/analog.c
84,10 → 84,8
* the offsets with the DAC.
*/
volatile uint16_t sensorInputs[8];
volatile int16_t rawGyroSum[3];
volatile int16_t acc[3];
volatile int16_t filteredAcc[3] = { 0,0,0 };
// volatile int32_t stronglyFilteredAcc[3] = { 0,0,0 };
int16_t acc[3];
int16_t filteredAcc[3] = { 0,0,0 };
 
/*
* These 4 exported variables are zero-offset. The "PID" ones are used
94,10 → 92,10
* in the attitude control as rotation rates. The "ATT" ones are for
* integration to angles.
*/
volatile int16_t gyro_PID[2];
volatile int16_t gyro_ATT[2];
volatile int16_t gyroD[2];
volatile int16_t yawGyro;
int16_t gyro_PID[2];
int16_t gyro_ATT[2];
int16_t gyroD[2];
int16_t yawGyro;
 
/*
* Offset values. These are the raw gyro and acc. meter sums when the copter is
110,10 → 108,57
sensorOffset_t gyroAmplifierOffset;
 
/*
* This allows some experimentation with the gyro filters.
* Should be replaced by #define's later on...
* In the MK coordinate system, nose-down is positive and left-roll is positive.
* If a sensor is used in an orientation where one but not both of the axes has
* an opposite sign, PR_ORIENTATION_REVERSED is set to 1 (true).
* Transform:
* pitch <- pp*pitch + pr*roll
* roll <- rp*pitch + rr*roll
* Not reversed, GYRO_QUADRANT:
* 0: pp=1, pr=0, rp=0, rr=1 // 0 degrees
* 1: pp=1, pr=-1,rp=1, rr=1 // +45 degrees
* 2: pp=0, pr=-1,rp=1, rr=0 // +90 degrees
* 3: pp=-1,pr=-1,rp=1, rr=1 // +135 degrees
* 4: pp=-1,pr=0, rp=0, rr=-1 // +180 degrees
* 5: pp=-1,pr=1, rp=-1,rr=-1 // +225 degrees
* 6: pp=0, pr=1, rp=-1,rr=0 // +270 degrees
* 7: pp=1, pr=1, rp=-1,rr=1 // +315 degrees
* Reversed, GYRO_QUADRANT:
* 0: pp=-1,pr=0, rp=0, rr=1 // 0 degrees with pitch reversed
* 1: pp=-1,pr=-1,rp=-1,rr=1 // +45 degrees with pitch reversed
* 2: pp=0, pr=-1,rp=-1,rr=0 // +90 degrees with pitch reversed
* 3: pp=1, pr=-1,rp=-1,rr=1 // +135 degrees with pitch reversed
* 4: pp=1, pr=0, rp=0, rr=-1 // +180 degrees with pitch reversed
* 5: pp=1, pr=1, rp=1, rr=-1 // +225 degrees with pitch reversed
* 6: pp=0, pr=1, rp=1, rr=0 // +270 degrees with pitch reversed
* 7: pp=-1,pr=1, rp=1, rr=1 // +315 degrees with pitch reversed
*/
 
void rotate(int16_t* result, uint8_t quadrant, uint8_t reverse) {
static const int8_t rotationTab[] = {1,1,0,-1,-1,-1,0,1};
// Pitch to Pitch part
int8_t xx = (reverse & 1) ? rotationTab[(quadrant+4)%8] : rotationTab[quadrant];
// Roll to Pitch part
int8_t xy = rotationTab[(quadrant+2)%8];
// Pitch to Roll part
int8_t yx = reverse ? rotationTab[(quadrant+2)%8] : rotationTab[(quadrant+6)%8];
// Roll to Roll part
int8_t yy = rotationTab[quadrant];
 
int16_t xIn = result[0];
result[0] = xx*result[0] + xy*result[1];
result[1] = yx*xIn + yy*result[1];
if (quadrant & 1) {
// A rotation was used above, where the factors were too large by sqrt(2).
// So, we multiply by 2^n/sqt(2) and right shift n bits, as to divide by sqrt(2).
// A suitable value for n: Sample is 11 bits. After transformation it is the sum
// of 2 11 bit numbers, so 12 bits. We have 4 bits left...
result[0] = (result[0]*11) >> 4;
result[1] = (result[1]*11) >> 4;
}
}
 
/*
* Air pressure
*/
123,16 → 168,16
// volatile uint16_t rawAirPressure;
 
// Value of 2 samples, with range.
volatile uint16_t simpleAirPressure;
uint16_t simpleAirPressure;
 
// Value of AIRPRESSURE_SUMMATION_FACTOR samples, with range, filtered.
volatile int32_t filteredAirPressure;
int32_t filteredAirPressure;
 
// Partial sum of AIRPRESSURE_SUMMATION_FACTOR samples.
volatile int32_t airPressureSum;
int32_t airPressureSum;
 
// The number of samples summed into airPressureSum so far.
volatile uint8_t pressureMeasurementCount;
uint8_t pressureMeasurementCount;
 
/*
* Battery voltage, in units of: 1k/11k / 3V * 1024 = 31.03 per volt.
139,7 → 184,7
* That is divided by 3 below, for a final 10.34 per volt.
* So the initial value of 100 is for 9.7 volts.
*/
volatile int16_t UBat = 100;
int16_t UBat = 100;
 
/*
* Control and status.
150,8 → 195,8
/*
* Experiment: Measuring vibration-induced sensor noise.
*/
volatile uint16_t gyroNoisePeak[3];
volatile uint16_t accNoisePeak[3];
uint16_t gyroNoisePeak[3];
uint16_t accNoisePeak[3];
 
volatile uint8_t adState;
volatile uint8_t adChannel;
225,6 → 270,14
SREG = sreg;
}
 
uint16_t rawGyroValue(uint8_t axis) {
return sensorInputs[AD_GYRO_PITCH-axis];
}
 
uint16_t rawAccValue(uint8_t axis) {
return sensorInputs[AD_ACC_PITCH-axis];
}
 
void measureNoise(const int16_t sensor,
volatile uint16_t* const noiseMeasurement, const uint8_t damping) {
if (sensor > (int16_t) (*noiseMeasurement)) {
282,12 → 335,12
 
void analog_updateGyros(void) {
// for various filters...
int16_t tempOffsetGyro, tempGyro;
int16_t tempOffsetGyro[2], tempGyro;
debugOut.digital[0] &= ~DEBUG_SENSORLIMIT;
for (uint8_t axis=0; axis<2; axis++) {
tempGyro = rawGyroSum[axis] = sensorInputs[AD_GYRO_PITCH-axis];
tempGyro = rawGyroValue(axis);
 
/*
* Process the gyro data for the PID controller.
*/
296,53 → 349,49
if (staticParams.bitConfig & CFG_GYRO_SATURATION_PREVENTION) {
if (tempGyro < SENSOR_MIN_PITCHROLL) {
debugOut.digital[0] |= DEBUG_SENSORLIMIT;
tempGyro = tempGyro * EXTRAPOLATION_SLOPE - EXTRAPOLATION_LIMIT;
debugOut.digital[0] |= DEBUG_SENSORLIMIT;
tempGyro = tempGyro * EXTRAPOLATION_SLOPE - EXTRAPOLATION_LIMIT;
} else if (tempGyro > SENSOR_MAX_PITCHROLL) {
debugOut.digital[0] |= DEBUG_SENSORLIMIT;
tempGyro = (tempGyro - SENSOR_MAX_PITCHROLL) * EXTRAPOLATION_SLOPE
+ SENSOR_MAX_PITCHROLL;
debugOut.digital[0] |= DEBUG_SENSORLIMIT;
tempGyro = (tempGyro - SENSOR_MAX_PITCHROLL) * EXTRAPOLATION_SLOPE + SENSOR_MAX_PITCHROLL;
}
}
 
// 2) Apply sign and offset, scale before filtering.
if (GYRO_REVERSED[axis]) {
tempOffsetGyro = (gyroOffset.offsets[axis] - tempGyro) * GYRO_FACTOR_PITCHROLL;
} else {
tempOffsetGyro = (tempGyro - gyroOffset.offsets[axis]) * GYRO_FACTOR_PITCHROLL;
}
// 3) Scale and filter.
tempOffsetGyro = (gyro_PID[axis] * (staticParams.gyroPIDFilterConstant - 1) + tempOffsetGyro) / staticParams.gyroPIDFilterConstant;
tempOffsetGyro[axis] = (tempGyro - gyroOffset.offsets[axis]) * GYRO_FACTOR_PITCHROLL;
}
 
// 2.1: Transform axes.
rotate(tempOffsetGyro, staticParams.gyroQuadrant, staticParams.imuReversedFlags & 1);
 
for (uint8_t axis=0; axis<2; axis++) {
// 3) Filter.
tempOffsetGyro[axis] = (gyro_PID[axis] * (staticParams.gyroPIDFilterConstant - 1) + tempOffsetGyro[axis]) / staticParams.gyroPIDFilterConstant;
 
// 4) Measure noise.
measureNoise(tempOffsetGyro, &gyroNoisePeak[axis], GYRO_NOISE_MEASUREMENT_DAMPING);
measureNoise(tempOffsetGyro[axis], &gyroNoisePeak[axis], GYRO_NOISE_MEASUREMENT_DAMPING);
 
// 5) Differential measurement.
gyroD[axis] = (gyroD[axis] * (staticParams.gyroDFilterConstant - 1) + (tempOffsetGyro - gyro_PID[axis])) / staticParams.gyroDFilterConstant;
gyroD[axis] = (gyroD[axis] * (staticParams.gyroDFilterConstant - 1) + (tempOffsetGyro[axis] - gyro_PID[axis])) / staticParams.gyroDFilterConstant;
 
// 6) Done.
gyro_PID[axis] = tempOffsetGyro;
/*
* Now process the data for attitude angles.
*/
tempGyro = rawGyroSum[axis];
// 1) Apply sign and offset, scale before filtering.
if (GYRO_REVERSED[axis]) {
tempOffsetGyro = (gyroOffset.offsets[axis] - tempGyro) * GYRO_FACTOR_PITCHROLL;
} else {
tempOffsetGyro = (tempGyro - gyroOffset.offsets[axis]) * GYRO_FACTOR_PITCHROLL;
}
// 2) Filter.
gyro_ATT[axis] = (gyro_ATT[axis] * (staticParams.gyroATTFilterConstant - 1) + tempOffsetGyro) / staticParams.gyroATTFilterConstant;
gyro_PID[axis] = tempOffsetGyro[axis];
 
// Prepare tempOffsetGyro for next calculation below...
tempOffsetGyro[axis] = (rawGyroValue(axis) - gyroOffset.offsets[axis]) * GYRO_FACTOR_PITCHROLL;
}
/*
* Now process the data for attitude angles.
*/
rotate(tempOffsetGyro, staticParams.gyroQuadrant, staticParams.imuReversedFlags & 1);
 
// 2) Filter. This should really be quite unnecessary. The integration should gobble up any noise anyway and the values are not used for anything else.
// gyro_ATT[PITCH] = (gyro_ATT[PITCH] * (staticParams.attitudeGyroFilter - 1) + tempOffsetGyro[PITCH]) / staticParams.attitudeGyroFilter;
// gyro_ATT[ROLL] = (gyro_ATT[ROLL] * (staticParams.attitudeGyroFilter - 1) + tempOffsetGyro[ROLL]) / staticParams.attitudeGyroFilter;
 
// Yaw gyro.
rawGyroSum[YAW] = sensorInputs[AD_GYRO_YAW];
if (GYRO_REVERSED[YAW])
if (staticParams.imuReversedFlags & 2)
yawGyro = gyroOffset.offsets[YAW] - sensorInputs[AD_GYRO_YAW];
else
yawGyro = sensorInputs[AD_GYRO_YAW] - gyroOffset.offsets[YAW];
349,24 → 398,23
}
 
void analog_updateAccelerometers(void) {
// Z acc.
if (ACC_REVERSED[Z])
acc[Z] = accOffset.offsets[Z] - sensorInputs[AD_ACC_Z];
else
acc[Z] = sensorInputs[AD_ACC_Z] - accOffset.offsets[Z];
 
// Pitch and roll axis accelerations.
for (uint8_t axis=0; axis<2; axis++) {
if (ACC_REVERSED[axis])
acc[axis] = accOffset.offsets[axis] - sensorInputs[AD_ACC_PITCH-axis];
else
acc[axis] = sensorInputs[AD_ACC_PITCH-axis] - accOffset.offsets[axis];
acc[axis] = rawAccValue(axis) - accOffset.offsets[axis];
}
for (uint8_t axis=0; axis<3; axis++) {
 
rotate(acc, staticParams.accQuadrant, staticParams.imuReversedFlags & 4);
 
for(uint8_t axis=0; axis<3; axis++) {
filteredAcc[axis] = (filteredAcc[axis] * (staticParams.accFilterConstant - 1) + acc[axis]) / staticParams.accFilterConstant;
measureNoise(acc[axis], &accNoisePeak[axis], 1);
}
 
// Z acc.
if (staticParams.imuReversedFlags & 8)
acc[Z] = accOffset.offsets[Z] - sensorInputs[AD_ACC_Z];
else
acc[Z] = sensorInputs[AD_ACC_Z] - accOffset.offsets[Z];
}
 
void analog_updateAirPressure(void) {
488,7 → 536,7
// Setting offset values has an influence in the analog.c ISR
// Therefore run measurement for 100ms to achive stable readings
delay_ms_with_adc_measurement(100);
delay_ms_with_adc_measurement(100, 0);
 
// Rough estimate. Hmm no nothing happens at calibration anyway.
// airPressureSum = simpleAirPressure * (AIRPRESSURE_SUMMATION_FACTOR/2);
503,9 → 551,9
// determine gyro bias by averaging (requires that the copter does not rotate around any axis!)
for (i = 0; i < GYRO_OFFSET_CYCLES; i++) {
delay_ms_with_adc_measurement(20);
delay_ms_with_adc_measurement(10, 1);
for (axis = PITCH; axis <= YAW; axis++) {
offsets[axis] += rawGyroSum[axis];
offsets[axis] += rawGyroValue(axis);
}
}
514,6 → 562,7
}
 
gyroOffset_writeToEEProm();
startAnalogConversionCycle();
}
 
/*
524,23 → 573,22
* directly from here, though.
*/
void analog_calibrateAcc(void) {
#define ACC_OFFSET_CYCLES 10
#define ACC_OFFSET_CYCLES 32
uint8_t i, axis;
int32_t deltaOffset[3] = { 0, 0, 0 };
int32_t offsets[3] = { 0, 0, 0 };
int16_t filteredDelta;
 
for (i = 0; i < ACC_OFFSET_CYCLES; i++) {
delay_ms_with_adc_measurement(10);
delay_ms_with_adc_measurement(10, 1);
for (axis = PITCH; axis <= YAW; axis++) {
deltaOffset[axis] += acc[axis];
offsets[axis] += rawAccValue(axis);
}
}
 
for (axis = PITCH; axis <= YAW; axis++) {
filteredDelta = (deltaOffset[axis] + ACC_OFFSET_CYCLES / 2)
/ ACC_OFFSET_CYCLES;
accOffset.offsets[axis] += ACC_REVERSED[axis] ? -filteredDelta : filteredDelta;
accOffset.offsets[axis] = (offsets[axis] + ACC_OFFSET_CYCLES / 2) / ACC_OFFSET_CYCLES;
}
 
accOffset_writeToEEProm();
accOffset_writeToEEProm();
startAnalogConversionCycle();
}