2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
23 #include "build_config.h"
25 #include "common/axis.h"
27 #include "drivers/sensor.h"
29 #include "drivers/accgyro.h"
30 #include "drivers/accgyro_adxl345.h"
31 #include "drivers/accgyro_bma280.h"
32 #include "drivers/accgyro_l3g4200d.h"
33 #include "drivers/accgyro_mma845x.h"
34 #include "drivers/accgyro_mpu3050.h"
35 #include "drivers/accgyro_mpu6050.h"
36 #include "drivers/accgyro_l3gd20.h"
37 #include "drivers/accgyro_lsm303dlhc.h"
39 #include "drivers/bus_spi.h"
40 #include "drivers/accgyro_spi_mpu6000.h"
41 #include "drivers/accgyro_spi_mpu6500.h"
42 #include "drivers/gyro_sync.h"
44 #include "drivers/barometer.h"
45 #include "drivers/barometer_bmp085.h"
46 #include "drivers/barometer_bmp280.h"
47 #include "drivers/barometer_ms5611.h"
49 #include "drivers/compass.h"
50 #include "drivers/compass_hmc5883l.h"
51 #include "drivers/compass_ak8975.h"
53 #include "drivers/sonar_hcsr04.h"
55 #include "drivers/gpio.h"
56 #include "drivers/system.h"
58 #include "config/runtime_config.h"
60 #include "sensors/sensors.h"
61 #include "sensors/acceleration.h"
62 #include "sensors/barometer.h"
63 #include "sensors/gyro.h"
64 #include "sensors/compass.h"
65 #include "sensors/sonar.h"
66 #include "sensors/initialisation.h"
69 #include "hardware_revision.h"
72 extern float magneticDeclination
;
78 uint8_t detectedSensors
[MAX_SENSORS_TO_DETECT
] = { GYRO_NONE
, ACC_NONE
, BARO_NONE
, MAG_NONE
};
81 const mpu6050Config_t
*selectMPU6050Config(void)
84 // MPU_INT output on rev4 PB13
85 static const mpu6050Config_t nazeRev4MPU6050Config
= {
86 .gpioAPB2Peripherals
= RCC_APB2Periph_GPIOB
,
89 .exti_port_source
= GPIO_PortSourceGPIOB
,
90 .exti_line
= EXTI_Line13
,
91 .exti_pin_source
= GPIO_PinSource13
,
92 .exti_irqn
= EXTI15_10_IRQn
94 // MPU_INT output on rev5 hardware PC13
95 static const mpu6050Config_t nazeRev5MPU6050Config
= {
96 .gpioAPB2Peripherals
= RCC_APB2Periph_GPIOC
,
99 .exti_port_source
= GPIO_PortSourceGPIOC
,
100 .exti_line
= EXTI_Line13
,
101 .exti_pin_source
= GPIO_PinSource13
,
102 .exti_irqn
= EXTI15_10_IRQn
105 if (hardwareRevision
< NAZE32_REV5
) {
106 return &nazeRev4MPU6050Config
;
108 return &nazeRev5MPU6050Config
;
113 static const mpu6050Config_t spRacingF3MPU6050Config
= {
114 .gpioAHBPeripherals
= RCC_AHBPeriph_GPIOC
,
117 .exti_port_source
= EXTI_PortSourceGPIOC
,
118 .exti_pin_source
= EXTI_PinSource13
,
119 .exti_line
= EXTI_Line13
,
120 .exti_irqn
= EXTI15_10_IRQn
122 return &spRacingF3MPU6050Config
;
129 static void fakeGyroInit(void) {}
130 static void fakeGyroRead(int16_t *gyroADC
) {
131 memset(gyroADC
, 0, sizeof(int16_t[XYZ_AXIS_COUNT
]));
133 static void fakeGyroReadTemp(int16_t *tempData
) {
137 bool fakeGyroDetect(gyro_t
*gyro
, uint16_t lpf
)
140 gyro
->init
= fakeGyroInit
;
141 gyro
->read
= fakeGyroRead
;
142 gyro
->temperature
= fakeGyroReadTemp
;
148 static void fakeAccInit(void) {}
149 static void fakeAccRead(int16_t *accData
) {
150 memset(accData
, 0, sizeof(int16_t[XYZ_AXIS_COUNT
]));
153 bool fakeAccDetect(acc_t
*acc
)
155 acc
->init
= fakeAccInit
;
156 acc
->read
= fakeAccRead
;
157 acc
->revisionCode
= 0;
162 bool detectGyro(uint16_t gyroLpf
)
164 gyroSensor_e gyroHardware
= GYRO_DEFAULT
;
166 gyroAlign
= ALIGN_DEFAULT
;
168 switch(gyroHardware
) {
172 #ifdef USE_GYRO_MPU6050
173 if (mpu6050GyroDetect(selectMPU6050Config(), &gyro
, gyroLpf
)) {
174 #ifdef GYRO_MPU6050_ALIGN
175 gyroHardware
= GYRO_MPU6050
;
176 gyroAlign
= GYRO_MPU6050_ALIGN
;
183 #ifdef USE_GYRO_L3G4200D
184 if (l3g4200dDetect(&gyro
, gyroLpf
)) {
185 #ifdef GYRO_L3G4200D_ALIGN
186 gyroHardware
= GYRO_L3G4200D
;
187 gyroAlign
= GYRO_L3G4200D_ALIGN
;
195 #ifdef USE_GYRO_MPU3050
196 if (mpu3050Detect(&gyro
, gyroLpf
)) {
197 #ifdef GYRO_MPU3050_ALIGN
198 gyroHardware
= GYRO_MPU3050
;
199 gyroAlign
= GYRO_MPU3050_ALIGN
;
207 #ifdef USE_GYRO_L3GD20
208 if (l3gd20Detect(&gyro
, gyroLpf
)) {
209 #ifdef GYRO_L3GD20_ALIGN
210 gyroHardware
= GYRO_L3GD20
;
211 gyroAlign
= GYRO_L3GD20_ALIGN
;
218 case GYRO_SPI_MPU6000
:
219 #ifdef USE_GYRO_SPI_MPU6000
220 if (mpu6000SpiGyroDetect(&gyro
, gyroLpf
)) {
221 #ifdef GYRO_SPI_MPU6000_ALIGN
222 gyroHardware
= GYRO_SPI_MPU6000
;
223 gyroAlign
= GYRO_SPI_MPU6000_ALIGN
;
230 case GYRO_SPI_MPU6500
:
231 #ifdef USE_GYRO_SPI_MPU6500
232 #ifdef USE_HARDWARE_REVISION_DETECTION
236 if (hardwareRevision
== NAZE32_SP
&& mpu6500SpiGyroDetect(&gyro
, gyroLpf
)) {
237 #ifdef GYRO_SPI_MPU6500_ALIGN
238 gyroHardware
= GYRO_SPI_MPU6500
;
239 gyroAlign
= GYRO_SPI_MPU6500_ALIGN
;
244 if (mpu6500SpiGyroDetect(&gyro
, gyroLpf
)) {
245 #ifdef GYRO_SPI_MPU6500_ALIGN
246 gyroHardware
= GYRO_SPI_MPU6500
;
247 gyroAlign
= GYRO_SPI_MPU6500_ALIGN
;
257 if (fakeGyroDetect(&gyro
, gyroLpf
)) {
258 gyroHardware
= GYRO_FAKE
;
264 gyroHardware
= GYRO_NONE
;
267 if (gyroHardware
== GYRO_NONE
) {
271 detectedSensors
[SENSOR_INDEX_GYRO
] = gyroHardware
;
272 sensorsSet(SENSOR_GYRO
);
277 static void detectAcc(accelerationSensor_e accHardwareToUse
)
279 accelerationSensor_e accHardware
;
281 #ifdef USE_ACC_ADXL345
282 drv_adxl345_config_t acc_params
;
286 accAlign
= ALIGN_DEFAULT
;
288 switch (accHardwareToUse
) {
291 case ACC_ADXL345
: // ADXL345
292 #ifdef USE_ACC_ADXL345
293 acc_params
.useFifo
= false;
294 acc_params
.dataRate
= 800; // unused currently
296 if (hardwareRevision
< NAZE32_REV5
&& adxl345Detect(&acc_params
, &acc
)) {
298 if (adxl345Detect(&acc_params
, &acc
)) {
300 #ifdef ACC_ADXL345_ALIGN
301 accAlign
= ACC_ADXL345_ALIGN
;
303 accHardware
= ACC_ADXL345
;
309 #ifdef USE_ACC_LSM303DLHC
310 if (lsm303dlhcAccDetect(&acc
)) {
311 #ifdef ACC_LSM303DLHC_ALIGN
312 accAlign
= ACC_LSM303DLHC_ALIGN
;
314 accHardware
= ACC_LSM303DLHC
;
319 case ACC_MPU6050
: // MPU6050
320 #ifdef USE_ACC_MPU6050
321 if (mpu6050AccDetect(selectMPU6050Config(), &acc
)) {
322 #ifdef ACC_MPU6050_ALIGN
323 accAlign
= ACC_MPU6050_ALIGN
;
325 accHardware
= ACC_MPU6050
;
330 case ACC_MMA8452
: // MMA8452
331 #ifdef USE_ACC_MMA8452
333 // Not supported with this frequency
334 if (hardwareRevision
< NAZE32_REV5
&& mma8452Detect(&acc
)) {
336 if (mma8452Detect(&acc
)) {
338 #ifdef ACC_MMA8452_ALIGN
339 accAlign
= ACC_MMA8452_ALIGN
;
341 accHardware
= ACC_MMA8452
;
346 case ACC_BMA280
: // BMA280
347 #ifdef USE_ACC_BMA280
348 if (bma280Detect(&acc
)) {
349 #ifdef ACC_BMA280_ALIGN
350 accAlign
= ACC_BMA280_ALIGN
;
352 accHardware
= ACC_BMA280
;
357 case ACC_SPI_MPU6000
:
358 #ifdef USE_ACC_SPI_MPU6000
359 if (mpu6000SpiAccDetect(&acc
)) {
360 #ifdef ACC_SPI_MPU6000_ALIGN
361 accAlign
= ACC_SPI_MPU6000_ALIGN
;
363 accHardware
= ACC_SPI_MPU6000
;
368 case ACC_SPI_MPU6500
:
369 #ifdef USE_ACC_SPI_MPU6500
371 if (hardwareRevision
== NAZE32_SP
&& mpu6500SpiAccDetect(&acc
)) {
373 if (mpu6500SpiAccDetect(&acc
)) {
375 #ifdef ACC_SPI_MPU6500_ALIGN
376 accAlign
= ACC_SPI_MPU6500_ALIGN
;
378 accHardware
= ACC_SPI_MPU6500
;
385 if (fakeAccDetect(&acc
)) {
386 accHardware
= ACC_FAKE
;
391 case ACC_NONE
: // disable ACC
392 accHardware
= ACC_NONE
;
397 // Found anything? Check if error or ACC is really missing.
398 if (accHardware
== ACC_NONE
&& accHardwareToUse
!= ACC_DEFAULT
&& accHardwareToUse
!= ACC_NONE
) {
399 // Nothing was found and we have a forced sensor that isn't present.
400 accHardwareToUse
= ACC_DEFAULT
;
405 if (accHardware
== ACC_NONE
) {
409 detectedSensors
[SENSOR_INDEX_ACC
] = accHardware
;
410 sensorsSet(SENSOR_ACC
);
413 static void detectBaro(baroSensor_e baroHardwareToUse
)
416 // Detect what pressure sensors are available. baro->update() is set to sensor-specific update function
418 baroSensor_e baroHardware
= baroHardwareToUse
;
420 #ifdef USE_BARO_BMP085
422 const bmp085Config_t
*bmp085Config
= NULL
;
424 #if defined(BARO_XCLR_GPIO) && defined(BARO_EOC_GPIO)
425 static const bmp085Config_t defaultBMP085Config
= {
426 .gpioAPB2Peripherals
= BARO_APB2_PERIPHERALS
,
427 .xclrGpioPin
= BARO_XCLR_PIN
,
428 .xclrGpioPort
= BARO_XCLR_GPIO
,
429 .eocGpioPin
= BARO_EOC_PIN
,
430 .eocGpioPort
= BARO_EOC_GPIO
432 bmp085Config
= &defaultBMP085Config
;
436 if (hardwareRevision
== NAZE32
) {
437 bmp085Disable(bmp085Config
);
443 switch (baroHardware
) {
448 #ifdef USE_BARO_MS5611
449 if (ms5611Detect(&baro
)) {
450 baroHardware
= BARO_MS5611
;
456 #ifdef USE_BARO_BMP085
457 if (bmp085Detect(bmp085Config
, &baro
)) {
458 baroHardware
= BARO_BMP085
;
464 #ifdef USE_BARO_BMP280
465 if (bmp280Detect(&baro
)) {
466 baroHardware
= BARO_BMP280
;
471 baroHardware
= BARO_NONE
;
475 if (baroHardware
== BARO_NONE
) {
479 detectedSensors
[SENSOR_INDEX_BARO
] = baroHardware
;
480 sensorsSet(SENSOR_BARO
);
484 static void detectMag(magSensor_e magHardwareToUse
)
486 magSensor_e magHardware
;
488 #ifdef USE_MAG_HMC5883
489 const hmc5883Config_t
*hmc5883Config
= 0;
492 static const hmc5883Config_t nazeHmc5883Config_v1_v4
= {
493 .gpioAPB2Peripherals
= RCC_APB2Periph_GPIOB
,
497 /* Disabled for v4 needs more work.
498 .exti_port_source = GPIO_PortSourceGPIOB,
499 .exti_pin_source = GPIO_PinSource12,
500 .exti_line = EXTI_Line12,
501 .exti_irqn = EXTI15_10_IRQn
504 static const hmc5883Config_t nazeHmc5883Config_v5
= {
505 .gpioAPB2Peripherals
= RCC_APB2Periph_GPIOC
,
508 .exti_port_source
= GPIO_PortSourceGPIOC
,
509 .exti_line
= EXTI_Line14
,
510 .exti_pin_source
= GPIO_PinSource14
,
511 .exti_irqn
= EXTI15_10_IRQn
513 if (hardwareRevision
< NAZE32_REV5
) {
514 hmc5883Config
= &nazeHmc5883Config_v1_v4
;
516 hmc5883Config
= &nazeHmc5883Config_v5
;
521 static const hmc5883Config_t spRacingF3Hmc5883Config
= {
522 .gpioAHBPeripherals
= RCC_AHBPeriph_GPIOC
,
525 .exti_port_source
= EXTI_PortSourceGPIOC
,
526 .exti_pin_source
= EXTI_PinSource14
,
527 .exti_line
= EXTI_Line14
,
528 .exti_irqn
= EXTI15_10_IRQn
531 hmc5883Config
= &spRacingF3Hmc5883Config
;
538 magAlign
= ALIGN_DEFAULT
;
540 switch(magHardwareToUse
) {
545 #ifdef USE_MAG_HMC5883
546 if (hmc5883lDetect(&mag
, hmc5883Config
)) {
547 #ifdef MAG_HMC5883_ALIGN
548 magAlign
= MAG_HMC5883_ALIGN
;
550 magHardware
= MAG_HMC5883
;
557 #ifdef USE_MAG_AK8975
558 if (ak8975detect(&mag
)) {
559 #ifdef MAG_AK8975_ALIGN
560 magAlign
= MAG_AK8975_ALIGN
;
562 magHardware
= MAG_AK8975
;
569 magHardware
= MAG_NONE
;
573 if (magHardware
== MAG_NONE
&& magHardwareToUse
!= MAG_DEFAULT
&& magHardwareToUse
!= MAG_NONE
) {
574 // Nothing was found and we have a forced sensor that isn't present.
575 magHardwareToUse
= MAG_DEFAULT
;
579 if (magHardware
== MAG_NONE
) {
583 detectedSensors
[SENSOR_INDEX_MAG
] = magHardware
;
584 sensorsSet(SENSOR_MAG
);
587 void reconfigureAlignment(sensorAlignmentConfig_t
*sensorAlignmentConfig
)
589 if (sensorAlignmentConfig
->gyro_align
!= ALIGN_DEFAULT
) {
590 gyroAlign
= sensorAlignmentConfig
->gyro_align
;
592 if (sensorAlignmentConfig
->acc_align
!= ALIGN_DEFAULT
) {
593 accAlign
= sensorAlignmentConfig
->acc_align
;
595 if (sensorAlignmentConfig
->mag_align
!= ALIGN_DEFAULT
) {
596 magAlign
= sensorAlignmentConfig
->mag_align
;
600 bool sensorsAutodetect(sensorAlignmentConfig_t
*sensorAlignmentConfig
, uint16_t gyroLpf
, uint8_t accHardwareToUse
, uint8_t magHardwareToUse
, uint8_t baroHardwareToUse
, int16_t magDeclinationFromConfig
, uint32_t looptime
, uint8_t syncGyroToLoop
)
604 memset(&acc
, 0, sizeof(acc
));
605 memset(&gyro
, 0, sizeof(gyro
));
607 if (!detectGyro(gyroLpf
)) {
610 detectAcc(accHardwareToUse
);
611 detectBaro(baroHardwareToUse
);
614 // Now time to init things, acc first
615 if (sensors(SENSOR_ACC
))
617 // this is safe because either mpu6050 or mpu3050 or lg3d20 sets it, and in case of fail, we never get here.
618 gyroUpdateSampleRate(looptime
, gyroLpf
, syncGyroToLoop
); // Set gyro refresh rate before initialisation
621 detectMag(magHardwareToUse
);
623 reconfigureAlignment(sensorAlignmentConfig
);
625 // FIXME extract to a method to reduce dependencies, maybe move to sensors_compass.c
626 if (sensors(SENSOR_MAG
)) {
627 // calculate magnetic declination
628 deg
= magDeclinationFromConfig
/ 100;
629 min
= magDeclinationFromConfig
% 100;
631 magneticDeclination
= (deg
+ ((float)min
* (1.0f
/ 60.0f
))) * 10; // heading is in 0.1deg units
633 magneticDeclination
= 0.0f
; // TODO investigate if this is actually needed if there is no mag sensor or if the value stored in the config should be used.