Subversion Repositories FlightCtrl

Rev

Rev 2164 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1612 dongfang 1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include <avr/pgmspace.h>
2092 - 4
#include <stdlib.h>
2189 - 5
#include <stdio.h>
1864 - 6
 
1612 dongfang 7
#include "analog.h"
8
#include "sensors.h"
2189 - 9
// for Delay functions used in calibration.
1612 dongfang 10
#include "timer0.h"
11
// For reading and writing acc. meter offsets.
12
#include "eeprom.h"
2189 - 13
#include "debug.h"
1612 dongfang 14
 
1952 - 15
// set ADC enable & ADC Start Conversion & ADC Interrupt Enable bit
16
#define startADC() (ADCSRA |= (1<<ADEN)|(1<<ADSC)|(1<<ADIE))
17
 
2189 - 18
// TODO: Off to PROGMEM .
1969 - 19
const char* recal = ", recalibration needed.";
20
 
1854 - 21
/*
2189 - 22
 * Gyro and accelerometer values for attitude computation.
23
 * Unfiltered (this is unnecessary as noise should get absorbed in DCM).
24
 * Normalized to rad/s.
25
 * Data flow: ADCs (1 iteration) --> samplingADCData --offsetting-->  gyro_attitude_tmp
26
 * --rotation-->
27
 * [filtering] --> gyro_attitude.
28
 * Altimeter is also considered part of the "long" attitude loop.
1612 dongfang 29
 */
2189 - 30
Vector3f gyro_attitude;
31
Vector3f accel;
1612 dongfang 32
 
33
/*
2189 - 34
 * This stuff is for the aircraft control thread. It runs in unprocessed integers.
35
 * (well some sort of scaling will be required).
36
 * Data flow: ADCs (1 iteration) -> samplingADCData -> [offsetting and rotation] ->
37
 * [filtering] --> gyro_control
1612 dongfang 38
 */
2189 - 39
int16_t gyro_control[3];
2015 - 40
int16_t gyroD[2];
2086 - 41
int16_t gyroDWindow[2][GYRO_D_WINDOW_LENGTH];
2189 - 42
uint8_t gyroDWindowIdx;
1612 dongfang 43
 
2189 - 44
/*
45
 * Air pressure. TODO: Might as well convert to floats / well known units.
46
 */
2033 - 47
int32_t groundPressure;
2086 - 48
int16_t dHeight;
2033 - 49
 
1612 dongfang 50
/*
51
 * Offset values. These are the raw gyro and acc. meter sums when the copter is
52
 * standing still. They are used for adjusting the gyro and acc. meter values
1645 - 53
 * to be centered on zero.
1612 dongfang 54
 */
1969 - 55
sensorOffset_t gyroOffset;
2189 - 56
sensorOffset_t accelOffset;
1969 - 57
sensorOffset_t gyroAmplifierOffset;
1960 - 58
 
1612 dongfang 59
/*
2189 - 60
 * Redo this to that quadrant 0 is normal with an FC2.x.
1612 dongfang 61
 */
2015 - 62
void rotate(int16_t* result, uint8_t quadrant, uint8_t reverse) {
2189 - 63
    static const int8_t rotationTab[] = { 1, 1, 0, -1, -1, -1, 0, 1 };
64
    // Pitch to Pitch part
65
    int8_t xx = reverse ? rotationTab[(quadrant + 4) & 7] : rotationTab[quadrant]; // 1
66
    // Roll to Pitch part
67
    int8_t xy = rotationTab[(quadrant + 2) & 7]; // -1
68
    // Pitch to Roll part
69
    int8_t yx = reverse ? rotationTab[(quadrant + 2) & 7] : rotationTab[(quadrant + 6) & 7]; // -1  
70
    // Roll to Roll part
71
    int8_t yy = rotationTab[quadrant]; // -1
2015 - 72
 
2189 - 73
    int16_t xIn = result[0];
74
    int32_t tmp0, tmp1;
75
 
76
    tmp0 = xx * xIn + xy * result[1];
77
    tmp1 = yx * xIn + yy * result[1];
78
 
79
    if (quadrant & 1) {
80
        tmp0 = (tmp0 * 181L) >> 8;
81
        tmp1 = (tmp1 * 181L) >> 8;
82
    }
83
 
84
    result[0] = (int16_t) tmp0;
85
    result[1] = (int16_t) tmp1;
2015 - 86
}
2019 - 87
 
1645 - 88
/*
1775 - 89
 * Air pressure
1645 - 90
 */
1970 - 91
volatile uint8_t rangewidth = 105;
1612 dongfang 92
 
1775 - 93
// Direct from sensor, irrespective of range.
94
 
95
// Value of 2 samples, with range.
2015 - 96
uint16_t simpleAirPressure;
1775 - 97
 
2019 - 98
// Value of AIRPRESSURE_OVERSAMPLING samples, with range, filtered.
2015 - 99
int32_t filteredAirPressure;
1775 - 100
 
2073 - 101
#define MAX_D_AIRPRESSURE_WINDOW_LENGTH 32
2071 - 102
//int32_t lastFilteredAirPressure;
103
int16_t dAirPressureWindow[MAX_D_AIRPRESSURE_WINDOW_LENGTH];
2073 - 104
uint8_t dWindowPtr = 0;
2071 - 105
 
2036 - 106
#define MAX_AIRPRESSURE_WINDOW_LENGTH 32
2026 - 107
int16_t airPressureWindow[MAX_AIRPRESSURE_WINDOW_LENGTH];
108
int32_t windowedAirPressure;
2073 - 109
uint8_t windowPtr = 0;
2026 - 110
 
1775 - 111
// Partial sum of AIRPRESSURE_SUMMATION_FACTOR samples.
2015 - 112
int32_t airPressureSum;
1775 - 113
 
114
// The number of samples summed into airPressureSum so far.
2189 - 115
uint8_t pressureSumCount;
1775 - 116
 
1612 dongfang 117
/*
1854 - 118
 * Battery voltage, in units of: 1k/11k / 3V * 1024 = 31.03 per volt.
1612 dongfang 119
 * That is divided by 3 below, for a final 10.34 per volt.
120
 * So the initial value of 100 is for 9.7 volts.
121
 */
2015 - 122
int16_t UBat = 100;
1612 dongfang 123
 
124
/*
125
 * Control and status.
126
 */
2189 - 127
volatile uint16_t samplingADCData[8];
128
volatile uint16_t attitudeADCData[8];
1612 dongfang 129
 
2189 - 130
volatile uint8_t analog_controlDataStatus = CONTROL_SENSOR_DATA_READY;
131
volatile uint8_t analog_attitudeDataStatus = ATTITUDE_SENSOR_NO_DATA;
132
// Number of ADC iterations done for current attitude loop.
133
volatile uint8_t attitudeSumCount;
1612 dongfang 134
 
2189 - 135
volatile uint8_t ADCSampleCount;
1987 - 136
volatile uint8_t adChannel;
1986 - 137
 
1612 dongfang 138
 
2189 - 139
const uint8_t channelsForStates[] PROGMEM = {
140
    AD_GYRO_X,
141
    AD_GYRO_Y,
142
    AD_GYRO_Z,
1612 dongfang 143
 
2189 - 144
    AD_ACCEL_X,
145
    AD_ACCEL_Y,
1612 dongfang 146
 
2189 - 147
    AD_GYRO_X,
148
    AD_GYRO_Y,
149
    //AD_GYRO_Z,
150
 
151
    AD_ACCEL_Z,
152
    AD_AIRPRESSURE,
153
 
154
    AD_GYRO_X,
155
    AD_GYRO_Y,
156
    AD_GYRO_Z,
157
 
158
    AD_ACCEL_X,
159
    AD_ACCEL_Y,
160
 
161
    AD_GYRO_X,
162
    AD_GYRO_Y,
163
    //AD_GYRO_Z,
164
 
165
    //AD_ACCEL_Z,
166
    //AD_AIRPRESSURE,
167
 
168
    AD_GYRO_X,
169
    AD_GYRO_Y,
170
    AD_GYRO_Z,
171
 
172
    AD_ACCEL_X,
173
    AD_ACCEL_Y,
174
 
175
    AD_GYRO_X,
176
    AD_GYRO_Y,
177
    //AD_GYRO_Z,
178
 
179
    AD_ACCEL_Z,
180
    AD_AIRPRESSURE,
181
 
182
    AD_GYRO_Y,
183
    AD_GYRO_X,
184
    AD_GYRO_Z,
185
 
186
    AD_ACCEL_X,
187
    AD_ACCEL_Y,
188
 
189
    AD_GYRO_X,
190
    AD_GYRO_Y,
191
    // AD_GYRO_Z,
192
 
193
    //AD_ACCEL_Z,
194
    //AD_AIRPRESSURE,
195
    AD_UBAT
1870 - 196
};
1612 dongfang 197
 
198
// Feature removed. Could be reintroduced later - but should work for all gyro types then.
199
// uint8_t GyroDefectPitch = 0, GyroDefectRoll = 0, GyroDefectYaw = 0;
200
 
201
void analog_init(void) {
2189 - 202
    uint8_t sreg = SREG;
203
    // disable all interrupts before reconfiguration
204
    cli();
1612 dongfang 205
 
2189 - 206
    //ADC0 ... ADC7 is connected to PortA pin 0 ... 7
207
    DDRA = 0x00;
208
    PORTA = 0x00;
209
    // Digital Input Disable Register 0
210
    // Disable digital input buffer for analog adc_channel pins
211
    DIDR0 = 0xFF;
212
    // external reference, adjust data to the right
213
    ADMUX &= ~((1 << REFS1) | (1 << REFS0) | (1 << ADLAR));
214
    // set muxer to ADC adc_channel 0 (0 to 7 is a valid choice)
215
    ADMUX = (ADMUX & 0xE0);
216
    //Set ADC Control and Status Register A
217
    //Auto Trigger Enable, Prescaler Select Bits to Division Factor 128, i.e. ADC clock = SYSCKL/128 = 156.25 kHz
218
    ADCSRA = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
219
    //Set ADC Control and Status Register B
220
    //Trigger Source to Free Running Mode
221
    ADCSRB &= ~((1 << ADTS2) | (1 << ADTS1) | (1 << ADTS0));
1952 - 222
 
2189 - 223
    for (uint8_t i = 0; i < MAX_AIRPRESSURE_WINDOW_LENGTH; i++) {
224
        airPressureWindow[i] = 0;
225
    }
226
 
2036 - 227
    windowedAirPressure = 0;
2026 - 228
 
2189 - 229
    startADCCycle();
1952 - 230
 
2189 - 231
    // restore global interrupt flags
232
    SREG = sreg;
1612 dongfang 233
}
234
 
2189 - 235
// Convert axis number (X, Y, Z to ADC channel mapping (1, 2, 0)
236
uint16_t gyroValue(uint8_t axis, volatile uint16_t dataArray[]) {
237
    switch (axis) {
238
    case X:
239
        return dataArray[AD_GYRO_X];
240
    case Y:
241
        return dataArray[AD_GYRO_Y];
242
    case Z:
243
        return dataArray[AD_GYRO_Z];
244
    default:
245
        return 0; // should never happen.
246
    }
2015 - 247
}
248
 
2189 - 249
uint16_t gyroValueForFC13DACCalibration(uint8_t axis) {
250
    return gyroValue(axis, samplingADCData);
2015 - 251
}
252
 
2189 - 253
// Convert axis number (X, Y, Z to ADC channel mapping (6, 7, 5)
254
uint16_t accValue(uint8_t axis, volatile uint16_t dataArray[]) {
255
    switch (axis) {
256
    case X:
257
        return dataArray[AD_ACCEL_X];
258
    case Y:
259
        return dataArray[AD_ACCEL_Y];
260
    case Z:
261
        return dataArray[AD_ACCEL_Z];
262
    default:
263
        return 0; // should never happen.
264
    }
1612 dongfang 265
}
266
 
1796 - 267
/*
268
 * Min.: 0
269
 * Max: About 106 * 240 + 2047 = 27487; it is OK with just a 16 bit type.
270
 */
1775 - 271
uint16_t getSimplePressure(int advalue) {
2189 - 272
    uint16_t result = (uint16_t) OCR0A * /*(uint16_t)*/ rangewidth + advalue;
273
    result += (/*accel.z*/0 * (staticParams.airpressureAccZCorrection - 128)) >> 10;
274
    return result;
1634 - 275
}
276
 
2189 - 277
void startADCCycle(void) {
278
    for (uint8_t i=0; i<8; i++) {
279
        samplingADCData[i] = 0;
280
    }
281
    ADCSampleCount = 0;
282
    adChannel = AD_GYRO_X;
283
    ADMUX = (ADMUX & 0xE0) | adChannel;
284
    analog_controlDataStatus = CONTROL_SENSOR_SAMPLING_DATA;
285
    J4HIGH;
286
    startADC();
1952 - 287
}
288
 
1645 - 289
/*****************************************************
1854 - 290
 * Interrupt Service Routine for ADC
2189 - 291
 * Runs at 12 kHz. When all states are processed
292
 * further conversions are stopped.
1645 - 293
 *****************************************************/
2189 - 294
ISR( ADC_vect) {
295
    samplingADCData[adChannel] += ADC;
296
    // set up for next state.
297
    ADCSampleCount++;
298
    if (ADCSampleCount < sizeof(channelsForStates)) {
299
        adChannel = pgm_read_byte(&channelsForStates[ADCSampleCount]);
300
        // set adc muxer to next adChannel
301
        ADMUX = (ADMUX & 0xE0) | adChannel;
302
        // after full cycle stop further interrupts
303
        startADC();
304
    } else {
305
        J4LOW;
306
        analog_controlDataStatus = CONTROL_SENSOR_DATA_READY;
307
        // do not restart ADC converter.
308
    }
1952 - 309
}
1612 dongfang 310
 
2189 - 311
/*
312
 * Used in calibration only!
313
 * Wait the specified number of millis, and then run a full sensor ADC cycle.
314
 */
315
void waitADCCycle(uint16_t delay) {
316
    delay_ms(delay);
317
    startADCCycle();
318
    while(analog_controlDataStatus != CONTROL_SENSOR_DATA_READY)
319
        ;
2055 - 320
}
321
 
2189 - 322
void analog_updateControlData(void) {
323
    /*
324
     * 1) Near-saturation boost (dont bother with Z)
325
     * 2) Offset
326
     * 3) Rotation
327
     * 4) Filter
328
     * 5) Extract gyroD (should this be without near-saturation boost really? Ignore issue)
329
     */
2160 - 330
 
2189 - 331
    int16_t tempOffsetGyro[2];
332
    int16_t tempGyro;
333
 
334
    for (uint8_t axis=X; axis<=Y; axis++) {
335
        tempGyro = gyroValue(axis, samplingADCData);
336
        //debugOut.analog[3 + axis] = tempGyro;
337
        //debugOut.analog[3 + 2] = gyroValue(Z, samplingADCData);
2160 - 338
 
2189 - 339
        /*
340
         * Process the gyro data for the PID controller.
341
         */
342
        // 1) Extrapolate: Near the ends of the range, we boost the input significantly. This simulates a
343
        //    gyro with a wider range, and helps counter saturation at full control.
344
        //    There is hardly any reason to bother extrapolating yaw.
2055 - 345
 
2189 - 346
        if (staticParams.bitConfig & CFG_GYRO_SATURATION_PREVENTION) {
347
            if (tempGyro < SENSOR_MIN_XY) {
348
                debugOut.digital[0] |= DEBUG_SENSORLIMIT;
349
                tempGyro = tempGyro * EXTRAPOLATION_SLOPE - EXTRAPOLATION_LIMIT;
350
            } else if (tempGyro > SENSOR_MAX_XY) {
351
                debugOut.digital[0] |= DEBUG_SENSORLIMIT;
352
                tempGyro = (tempGyro - SENSOR_MAX_XY) * EXTRAPOLATION_SLOPE + SENSOR_MAX_XY;
353
            }
354
        }
355
 
356
        // 2) Apply offset (rotation will take care of signs).
357
        tempOffsetGyro[axis] = tempGyro - gyroOffset.offsets[axis];
1952 - 358
    }
2015 - 359
 
2189 - 360
    // 2.1: Transform axes.
361
    rotate(tempOffsetGyro, IMUConfig.gyroQuadrant, IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_XY);
2015 - 362
 
2189 - 363
    for (uint8_t axis=X; axis<=Y; axis++) {
364
        // Filter. There is no filter for Z and no need for one.
365
 
366
      tempGyro = (gyro_control[axis] * (IMUConfig.gyroPIDFilterConstant - 1) + tempOffsetGyro[axis]) / IMUConfig.gyroPIDFilterConstant;
367
        // 5) Differential measurement.
368
        int16_t diff = tempGyro - gyro_control[axis];
369
        gyroD[axis] -= gyroDWindow[axis][gyroDWindowIdx];
370
        gyroD[axis] += diff;
371
        gyroDWindow[axis][gyroDWindowIdx] = diff;
2015 - 372
 
2189 - 373
        // 6) Done.
374
        gyro_control[axis] = tempGyro;
375
    }
2015 - 376
 
2189 - 377
    if (++gyroDWindowIdx >= IMUConfig.gyroDWindowLength) {
378
        gyroDWindowIdx = 0;
379
    }
380
 
381
    if (IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_Z)
382
      tempGyro = gyroOffset.offsets[Z] - gyroValue(Z, samplingADCData);
383
    else
384
      tempGyro = gyroValue(Z, samplingADCData) - gyroOffset.offsets[Z];
2015 - 385
 
2189 - 386
    gyro_control[Z] = tempGyro;
387
 
388
    startADCCycle();
389
}
2015 - 390
 
2189 - 391
/*
392
 * The uint16s can take a max. of 1<<16-10) = 64 samples summed.
393
 * Assuming a max oversampling count of 8 for the control loop, this is 8 control loop iterations
394
 * summed. After 8 are reached, we just throw away all further data. This (that the attitude loop
395
 * is more than 8 times slower than the control loop) should not happen anyway so there is no waste.
396
 */
397
#define MAX_OVEROVERSAMPLING_COUNT 8
2015 - 398
 
2189 - 399
void analog_sumAttitudeData(void) {
400
    // From when this procedure completes, there is attitude data available.
401
    if (analog_attitudeDataStatus == ATTITUDE_SENSOR_NO_DATA)
402
        analog_attitudeDataStatus = ATTITUDE_SENSOR_DATA_READY;
2086 - 403
 
2015 - 404
 
2189 - 405
    if (analog_attitudeDataStatus == ATTITUDE_SENSOR_DATA_READY && attitudeSumCount < MAX_OVEROVERSAMPLING_COUNT) {
406
        for (uint8_t i = 0; i < 8; i++) {
407
            attitudeADCData[i] += samplingADCData[i];
408
        }
409
        attitudeSumCount++;
410
        debugOut.analog[24] = attitudeSumCount;
411
    }
412
}
2017 - 413
 
2189 - 414
void clearAttitudeData(void) {
415
    for (uint8_t i = 0; i < 8; i++) {
416
        attitudeADCData[i] = 0;
417
    }
418
    attitudeSumCount = 0;
419
    analog_attitudeDataStatus = ATTITUDE_SENSOR_NO_DATA;
420
}
2089 - 421
 
2189 - 422
void updateAttitudeVectors(void) {
423
    /*
424
     int16_t gyro_attitude_tmp[3];
425
     Vector3f gyro_attitude;
426
     Vector3f accel;
427
     */
2089 - 428
 
2189 - 429
    int16_t tmpSensor[3];
2095 - 430
 
2189 - 431
    // prevent gyro_attitude_tmp and attitudeSumCount from being updated.
432
    // TODO: This only prevents interrupts from starting. Well its good enough really?
433
    analog_attitudeDataStatus = ATTITUDE_SENSOR_READING_DATA;
2095 - 434
 
2189 - 435
    tmpSensor[X] = gyroValue(X, attitudeADCData) - gyroOffset.offsets[X] * attitudeSumCount;
436
    tmpSensor[Y] = gyroValue(Y, attitudeADCData) - gyroOffset.offsets[Y] * attitudeSumCount;
1775 - 437
 
2189 - 438
    rotate(tmpSensor, IMUConfig.gyroQuadrant, IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_XY);
2015 - 439
 
2189 - 440
    if (IMUConfig.imuReversedFlags & IMU_REVERSE_GYRO_Z)
441
        tmpSensor[Z] = gyroOffset.offsets[Z] * attitudeSumCount - gyroValue(Z, attitudeADCData);
442
    else
443
        tmpSensor[Z] = gyroValue(Z, attitudeADCData) - gyroOffset.offsets[Z] * attitudeSumCount;
2015 - 444
 
2189 - 445
    gyro_attitude.x = ((float) tmpSensor[X]) / (GYRO_RATE_FACTOR_XY * attitudeSumCount);
446
    gyro_attitude.y = ((float) tmpSensor[Y]) / (GYRO_RATE_FACTOR_XY * attitudeSumCount);
447
    gyro_attitude.z = ((float) tmpSensor[Z]) / (GYRO_RATE_FACTOR_Z  * attitudeSumCount);
2069 - 448
 
2189 - 449
    // Done with gyros. Now accelerometer:
450
    tmpSensor[X] = accValue(X, attitudeADCData) - accelOffset.offsets[X] * attitudeSumCount;
451
    tmpSensor[Y] = accValue(Y, attitudeADCData) - accelOffset.offsets[Y] * attitudeSumCount;
452
 
453
    rotate(tmpSensor, IMUConfig.accQuadrant, IMUConfig.imuReversedFlags & IMU_REVERSE_ACCEL_XY);
454
 
455
    // Z acc.
456
    if (IMUConfig.imuReversedFlags & IMU_REVERSE_ACCEL_Z)
457
        tmpSensor[Z] = accelOffset.offsets[Z] * attitudeSumCount - accValue(Z, attitudeADCData);
458
    else
459
        tmpSensor[Z] = accValue(Z, attitudeADCData) - accelOffset.offsets[Z] * attitudeSumCount;
460
 
461
    // Blarh!!! We just skip acc filtering. There are trillions of samples already.
462
    accel.x = (float)tmpSensor[X] / (ACCEL_FACTOR_XY * attitudeSumCount); // (accel.x + (float)tmpSensor[X] / (ACCEL_FACTOR_XY * attitudeSumCount)) / 2.0;
463
    accel.y = (float)tmpSensor[Y] / (ACCEL_FACTOR_XY * attitudeSumCount); // (accel.y + (float)tmpSensor[Y] / (ACCEL_FACTOR_XY * attitudeSumCount)) / 2.0;
464
    accel.z = (float)tmpSensor[Z] / (ACCEL_FACTOR_Z  * attitudeSumCount); // (accel.z + (float)tmpSensor[Z] / (ACCEL_FACTOR_Z  * attitudeSumCount)) / 2.0;
465
 
466
    for (uint8_t i=0; i<3; i++) {
467
      debugOut.analog[3 + i] = (int16_t)(gyro_attitude[i] * 100);
468
      debugOut.analog[6 + i] = (int16_t)(accel[i] * 100);
469
    }
1952 - 470
}
1645 - 471
 
1952 - 472
void analog_updateAirPressure(void) {
2189 - 473
    static uint16_t pressureAutorangingWait = 25;
474
    uint16_t rawAirPressure;
475
    int16_t newrange;
476
    // air pressure
477
    if (pressureAutorangingWait) {
478
        //A range switch was done recently. Wait for steadying.
479
        pressureAutorangingWait--;
1952 - 480
    } else {
2189 - 481
        rawAirPressure = attitudeADCData[AD_AIRPRESSURE] / attitudeSumCount;
482
        if (rawAirPressure < MIN_RAWPRESSURE) {
483
            // value is too low, so decrease voltage on the op amp minus input, making the value higher.
484
            newrange = OCR0A - (MAX_RAWPRESSURE - MIN_RAWPRESSURE) / (rangewidth * 4);
485
            if (newrange > MIN_RANGES_EXTRAPOLATION) {
486
                pressureAutorangingWait = (OCR0A - newrange) * AUTORANGE_WAIT_FACTOR; // = OCRA0 - OCRA0 +
487
                OCR0A = newrange;
488
            } else {
489
                if (OCR0A) {
490
                    OCR0A--;
491
                    pressureAutorangingWait = AUTORANGE_WAIT_FACTOR;
492
                }
493
            }
494
        } else if (rawAirPressure > MAX_RAWPRESSURE) {
495
            // value is too high, so increase voltage on the op amp minus input, making the value lower.
496
            // If near the end, make a limited increase
497
            newrange = OCR0A + (MAX_RAWPRESSURE - MIN_RAWPRESSURE) / (rangewidth * 4);
498
            if (newrange < MAX_RANGES_EXTRAPOLATION) {
499
                pressureAutorangingWait = (newrange - OCR0A) * AUTORANGE_WAIT_FACTOR;
500
                OCR0A = newrange;
501
            } else {
502
                if (OCR0A < 254) {
503
                    OCR0A++;
504
                    pressureAutorangingWait = AUTORANGE_WAIT_FACTOR;
505
                }
506
            }
507
        }
2035 - 508
 
2189 - 509
        // Even if the sample is off-range, use it.
510
        simpleAirPressure = getSimplePressure(rawAirPressure);
511
 
512
        if (simpleAirPressure < (uint16_t)(MIN_RANGES_EXTRAPOLATION * rangewidth)) {
513
            // Danger: pressure near lower end of range. If the measurement saturates, the
514
            // copter may climb uncontrolledly... Simulate a drastic reduction in pressure.
515
            debugOut.digital[1] |= DEBUG_SENSORLIMIT;
516
            airPressureSum += (int16_t) MIN_RANGES_EXTRAPOLATION * rangewidth
517
                    + (simpleAirPressure - (int16_t) MIN_RANGES_EXTRAPOLATION
518
                            * rangewidth) * PRESSURE_EXTRAPOLATION_COEFF;
519
        } else if (simpleAirPressure > (uint16_t)(MAX_RANGES_EXTRAPOLATION * rangewidth)) {
520
            // Danger: pressure near upper end of range. If the measurement saturates, the
521
            // copter may descend uncontrolledly... Simulate a drastic increase in pressure.
522
            debugOut.digital[1] |= DEBUG_SENSORLIMIT;
523
            airPressureSum += (int16_t) MAX_RANGES_EXTRAPOLATION * rangewidth
524
                    + (simpleAirPressure - (int16_t) MAX_RANGES_EXTRAPOLATION
525
                            * rangewidth) * PRESSURE_EXTRAPOLATION_COEFF;
526
        } else {
527
            // normal case.
528
            // If AIRPRESSURE_OVERSAMPLING is an odd number we only want to add half the double sample.
529
            // The 2 cases above (end of range) are ignored for this.
530
            debugOut.digital[1] &= ~DEBUG_SENSORLIMIT;
531
            airPressureSum += simpleAirPressure;
532
        }
2035 - 533
 
2189 - 534
        // 2 samples were added.
535
        pressureSumCount += 2;
536
        // Assumption here: AIRPRESSURE_OVERSAMPLING is even (well we all know it's 28...)
537
        if (pressureSumCount == AIRPRESSURE_OVERSAMPLING) {
2035 - 538
 
2189 - 539
            // The best oversampling count is 14.5. We add a quarter of the double ADC value to get the final half.
540
            airPressureSum += simpleAirPressure >> 2;
2036 - 541
 
2189 - 542
            uint32_t lastFilteredAirPressure = filteredAirPressure;
543
 
544
            if (!staticParams.airpressureWindowLength) {
545
                filteredAirPressure = (filteredAirPressure
546
                        * (staticParams.airpressureFilterConstant - 1)
547
                        + airPressureSum
548
                        + staticParams.airpressureFilterConstant / 2)
549
                        / staticParams.airpressureFilterConstant;
550
            } else {
551
                // use windowed.
552
                windowedAirPressure += simpleAirPressure;
553
                windowedAirPressure -= airPressureWindow[windowPtr];
554
                airPressureWindow[windowPtr++] = simpleAirPressure;
555
                if (windowPtr >= staticParams.airpressureWindowLength)
556
                    windowPtr = 0;
557
                filteredAirPressure = windowedAirPressure / staticParams.airpressureWindowLength;
558
            }
559
 
560
            // positive diff of pressure
561
            int16_t diff = filteredAirPressure - lastFilteredAirPressure;
562
            // is a negative diff of height.
563
            dHeight -= diff;
564
            // remove old sample (fifo) from window.
565
            dHeight += dAirPressureWindow[dWindowPtr];
566
            dAirPressureWindow[dWindowPtr++] = diff;
567
            if (dWindowPtr >= staticParams.airpressureDWindowLength)
568
                dWindowPtr = 0;
569
            pressureSumCount = airPressureSum = 0;
570
        }
1952 - 571
    }
2189 - 572
 
573
    debugOut.analog[25] = simpleAirPressure;
574
    debugOut.analog[26] = OCR0A;
575
    debugOut.analog[27] = filteredAirPressure;
1952 - 576
}
1821 - 577
 
1952 - 578
void analog_updateBatteryVoltage(void) {
2189 - 579
    // Battery. The measured value is: (V * 1k/11k)/3v * 1024 = 31.03 counts per volt (max. measurable is 33v).
580
    // This is divided by 3 --> 10.34 counts per volt.
581
    UBat = (3 * UBat + attitudeADCData[AD_UBAT] / 3) / 4;
1952 - 582
}
1821 - 583
 
2189 - 584
void analog_updateAttitudeData(void) {
585
    updateAttitudeVectors();
586
 
587
    // TODO: These are waaaay off by now.
588
    analog_updateAirPressure();
589
    analog_updateBatteryVoltage();
590
 
591
    clearAttitudeData();
1612 dongfang 592
}
593
 
1961 - 594
void analog_setNeutral() {
2189 - 595
    gyro_init();
1961 - 596
 
2189 - 597
    if (gyroOffset_readFromEEProm()) {
598
        printf("gyro offsets invalid%s", recal);
599
        gyroOffset.offsets[X] = gyroOffset.offsets[Y] = 512 * GYRO_OVERSAMPLING_XY;
600
        gyroOffset.offsets[Z] = 512 * GYRO_OVERSAMPLING_Z;
601
        // This will get the DACs for FC1.3 to offset to a reasonable value.
602
        gyro_calibrate();
603
    }
1961 - 604
 
2189 - 605
    if (accelOffset_readFromEEProm()) {
606
        printf("acc. meter offsets invalid%s", recal);
607
        accelOffset.offsets[X] = accelOffset.offsets[Y] = 512 * ACCEL_OVERSAMPLING_XY;
608
        accelOffset.offsets[Z] = 512 * ACCEL_OVERSAMPLING_Z;
609
        if (IMUConfig.imuReversedFlags & IMU_REVERSE_ACCEL_Z) {
610
            accelOffset.offsets[Z] -= ACCEL_G_FACTOR_Z;
611
        } else {
612
            accelOffset.offsets[Z] += ACCEL_G_FACTOR_Z;
613
        }
614
    }
615
 
616
    // Noise is relative to offset. So, reset noise measurements when changing offsets.
617
    for (uint8_t i=X; i<=Y; i++) {
618
        // gyroNoisePeak[i] = 0;
619
        gyroD[i] = 0;
620
        for (uint8_t j=0; j<GYRO_D_WINDOW_LENGTH; j++) {
621
            gyroDWindow[i][j] = 0;
622
        }
623
    }
624
    // Setting offset values has an influence in the analog.c ISR
625
    // Therefore run measurement for 100ms to achive stable readings
626
    waitADCCycle(100);
1961 - 627
}
628
 
629
void analog_calibrateGyros(void) {
2189 - 630
#define GYRO_OFFSET_CYCLES 100
631
    uint8_t i, axis;
632
    int32_t offsets[3] = { 0, 0, 0 };
633
 
634
    flightControlStatus = BLOCKED_FOR_CALIBRATION;
635
    delay_ms(10);
636
 
637
    gyro_calibrate();
638
 
639
    // determine gyro bias by averaging (requires that the copter does not rotate around any axis!)
640
    for (i = 0; i < GYRO_OFFSET_CYCLES; i++) {
641
        waitADCCycle(5);
642
        for (axis=X; axis<=Z; axis++) {
643
            offsets[axis] += gyroValue(axis, samplingADCData);
644
        }
1952 - 645
    }
2018 - 646
 
2189 - 647
    for (axis=X; axis<=Z; axis++) {
648
        gyroOffset.offsets[axis] = (offsets[axis] + GYRO_OFFSET_CYCLES/2) / GYRO_OFFSET_CYCLES;
649
        int16_t min = (512 - 200) * (axis==Z) ? GYRO_OVERSAMPLING_Z : GYRO_OVERSAMPLING_XY;
650
        int16_t max = (512 + 200) * (axis==Z) ? GYRO_OVERSAMPLING_Z : GYRO_OVERSAMPLING_XY;
651
        if (gyroOffset.offsets[axis] < min || gyroOffset.offsets[axis] > max)
652
            versionInfo.hardwareErrors[0] |= FC_ERROR0_GYRO_X << axis;
653
    }
1961 - 654
 
2189 - 655
    gyroOffset_writeToEEProm();
656
    //startADCCycle();
1612 dongfang 657
}
658
 
659
/*
660
 * Find acc. offsets for a neutral reading, and write them to EEPROM.
661
 * Does not (!} update the local variables. This must be done with a
662
 * call to analog_calibrate() - this always (?) is done by the caller
663
 * anyway. There would be nothing wrong with updating the variables
664
 * directly from here, though.
665
 */
666
void analog_calibrateAcc(void) {
2189 - 667
#define ACCEL_OFFSET_CYCLES 100
668
    uint8_t i, axis;
669
    int32_t offsets[3] = { 0, 0, 0 };
2015 - 670
 
2189 - 671
    flightControlStatus = BLOCKED_FOR_CALIBRATION;
672
    delay_ms(10);
673
 
674
    for (i = 0; i < ACCEL_OFFSET_CYCLES; i++) {
675
        waitADCCycle(5);
676
        for (axis=X; axis<=Z; axis++) {
677
            offsets[axis] += accValue(axis, samplingADCData);
678
        }
1960 - 679
    }
2015 - 680
 
2189 - 681
    for (axis=X; axis<=Z; axis++) {
682
        accelOffset.offsets[axis] = (offsets[axis] + ACCEL_OFFSET_CYCLES / 2) / ACCEL_OFFSET_CYCLES;
683
        int16_t min, max;
684
        if (axis == Z) {
685
            if (IMUConfig.imuReversedFlags & IMU_REVERSE_ACCEL_Z) {
686
                // TODO: This assumes a sensitivity of +/- 2g.
687
                min = (256 - 200) * ACCEL_OVERSAMPLING_Z;
688
                max = (256 + 200) * ACCEL_OVERSAMPLING_Z;
689
            } else {
690
                // TODO: This assumes a sensitivity of +/- 2g.
691
                min = (768 - 200) * ACCEL_OVERSAMPLING_Z;
692
                max = (768 + 200) * ACCEL_OVERSAMPLING_Z;
693
            }
694
        } else {
695
            min = (512 - 200) * ACCEL_OVERSAMPLING_XY;
696
            max = (512 + 200) * ACCEL_OVERSAMPLING_XY;
697
        }
698
        if (gyroOffset.offsets[axis] < min || gyroOffset.offsets[axis] > max) {
699
            versionInfo.hardwareErrors[0] |= FC_ERROR0_ACCEL_X << axis;
700
        }
701
    }
702
 
703
    if (IMUConfig.imuReversedFlags & IMU_REVERSE_ACCEL_Z) {
704
        accelOffset.offsets[Z] -= ACCEL_G_FACTOR_Z;
2018 - 705
    } else {
2189 - 706
        accelOffset.offsets[Z] += ACCEL_G_FACTOR_Z;
2018 - 707
    }
1961 - 708
 
2189 - 709
    accelOffset_writeToEEProm();
710
    // startADCCycle();
1612 dongfang 711
}
2033 - 712
 
713
void analog_setGround() {
2189 - 714
    groundPressure = filteredAirPressure;
2033 - 715
}
716
 
717
int32_t analog_getHeight(void) {
2189 - 718
    int32_t height = groundPressure - filteredAirPressure;
719
    debugOut.analog[28] = height;
720
    return height;
2033 - 721
}
722
 
723
int16_t analog_getDHeight(void) {
2189 - 724
    return dHeight;
2033 - 725
}