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/build_config.h"
25 #include "common/axis.h"
27 #include "drivers/logging.h"
29 #include "drivers/io.h"
30 #include "drivers/system.h"
31 #include "drivers/exti.h"
33 #include "drivers/sensor.h"
35 #include "drivers/accgyro.h"
36 #include "drivers/accgyro_adxl345.h"
37 #include "drivers/accgyro_bma280.h"
38 #include "drivers/accgyro_l3g4200d.h"
39 #include "drivers/accgyro_mma845x.h"
40 #include "drivers/accgyro_mpu.h"
41 #include "drivers/accgyro_mpu3050.h"
42 #include "drivers/accgyro_mpu6050.h"
43 #include "drivers/accgyro_mpu6500.h"
44 #include "drivers/accgyro_l3gd20.h"
45 #include "drivers/accgyro_lsm303dlhc.h"
47 #include "drivers/bus_spi.h"
48 #include "drivers/accgyro_spi_mpu6000.h"
49 #include "drivers/accgyro_spi_mpu6500.h"
50 #include "drivers/accgyro_spi_mpu9250.h"
51 #include "drivers/gyro_sync.h"
53 #include "drivers/barometer.h"
54 #include "drivers/barometer_bmp085.h"
55 #include "drivers/barometer_bmp280.h"
56 #include "drivers/barometer_ms5611.h"
58 #include "drivers/compass.h"
59 #include "drivers/compass_hmc5883l.h"
60 #include "drivers/compass_ak8975.h"
61 #include "drivers/compass_ak8963.h"
62 #include "drivers/compass_mag3110.h"
64 #include "drivers/sonar_hcsr04.h"
65 #include "drivers/sonar_srf10.h"
67 #include "fc/runtime_config.h"
69 #include "config/config.h"
73 #include "sensors/sensors.h"
74 #include "sensors/acceleration.h"
75 #include "sensors/barometer.h"
76 #include "sensors/gyro.h"
77 #include "sensors/compass.h"
78 #include "sensors/rangefinder.h"
79 #include "sensors/initialisation.h"
81 #ifdef USE_HARDWARE_REVISION_DETECTION
82 #include "hardware_revision.h"
87 extern sensor_align_e gyroAlign
;
89 uint8_t detectedSensors
[SENSOR_INDEX_COUNT
] = { GYRO_NONE
, ACC_NONE
, BARO_NONE
, MAG_NONE
, RANGEFINDER_NONE
};
92 const extiConfig_t
*selectMPUIntExtiConfig(void)
94 #if defined(MPU_INT_EXTI)
95 static const extiConfig_t mpuIntExtiConfig
= { .tag
= IO_TAG(MPU_INT_EXTI
) };
96 return &mpuIntExtiConfig
;
97 #elif defined(USE_HARDWARE_REVISION_DETECTION)
98 return selectMPUIntExtiConfigByHardwareRevision();
105 static void fakeGyroInit(uint8_t lpf
)
110 static bool fakeGyroRead(int16_t *gyroADC
)
112 memset(gyroADC
, 0, sizeof(int16_t[XYZ_AXIS_COUNT
]));
116 static bool fakeGyroReadTemp(int16_t *tempData
)
123 static bool fakeGyroInitStatus(void) {
127 bool fakeGyroDetect(gyro_t
*gyro
)
129 gyro
->init
= fakeGyroInit
;
130 gyro
->intStatus
= fakeGyroInitStatus
;
131 gyro
->read
= fakeGyroRead
;
132 gyro
->temperature
= fakeGyroReadTemp
;
133 gyro
->scale
= 1.0f
/ 16.4f
;
139 static void fakeAccInit(acc_t
*acc
) {UNUSED(acc
);}
140 static bool fakeAccRead(int16_t *accData
) {
141 memset(accData
, 0, sizeof(int16_t[XYZ_AXIS_COUNT
]));
145 bool fakeAccDetect(acc_t
*acc
)
147 acc
->init
= fakeAccInit
;
148 acc
->read
= fakeAccRead
;
149 acc
->revisionCode
= 0;
155 static void fakeBaroStartGet(void)
159 static void fakeBaroCalculate(int32_t *pressure
, int32_t *temperature
)
162 *pressure
= 101325; // pressure in Pa (0m MSL)
164 *temperature
= 2500; // temperature in 0.01 C = 25 deg
167 bool fakeBaroDetect(baro_t
*baro
)
169 // these are dummy as temperature is measured as part of pressure
170 baro
->ut_delay
= 10000;
171 baro
->get_ut
= fakeBaroStartGet
;
172 baro
->start_ut
= fakeBaroStartGet
;
174 // only _up part is executed, and gets both temperature and pressure
175 baro
->up_delay
= 10000;
176 baro
->start_up
= fakeBaroStartGet
;
177 baro
->get_up
= fakeBaroStartGet
;
178 baro
->calculate
= fakeBaroCalculate
;
185 static bool fakeMagInit(void)
190 static bool fakeMagRead(int16_t *magData
)
192 // Always pointint North
199 static bool fakeMagDetect(mag_t
*mag
)
201 mag
->init
= fakeMagInit
;
202 mag
->read
= fakeMagRead
;
208 bool detectGyro(void)
210 gyroSensor_e gyroHardware
= GYRO_DEFAULT
;
212 gyroAlign
= ALIGN_DEFAULT
;
214 switch(gyroHardware
) {
218 #ifdef USE_GYRO_MPU6050
219 if (mpu6050GyroDetect(&gyro
)) {
220 gyroHardware
= GYRO_MPU6050
;
221 #ifdef GYRO_MPU6050_ALIGN
222 gyroAlign
= GYRO_MPU6050_ALIGN
;
229 #ifdef USE_GYRO_L3G4200D
230 if (l3g4200dDetect(&gyro
)) {
231 gyroHardware
= GYRO_L3G4200D
;
232 #ifdef GYRO_L3G4200D_ALIGN
233 gyroAlign
= GYRO_L3G4200D_ALIGN
;
241 #ifdef USE_GYRO_MPU3050
242 if (mpu3050Detect(&gyro
)) {
243 gyroHardware
= GYRO_MPU3050
;
244 #ifdef GYRO_MPU3050_ALIGN
245 gyroAlign
= GYRO_MPU3050_ALIGN
;
253 #ifdef USE_GYRO_L3GD20
254 if (l3gd20Detect(&gyro
)) {
255 gyroHardware
= GYRO_L3GD20
;
256 #ifdef GYRO_L3GD20_ALIGN
257 gyroAlign
= GYRO_L3GD20_ALIGN
;
265 #ifdef USE_GYRO_SPI_MPU6000
266 if (mpu6000SpiGyroDetect(&gyro
)) {
267 gyroHardware
= GYRO_MPU6000
;
268 #ifdef GYRO_MPU6000_ALIGN
269 gyroAlign
= GYRO_MPU6000_ALIGN
;
277 #if defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500)
278 #ifdef USE_GYRO_SPI_MPU6500
279 if (mpu6500GyroDetect(&gyro
) || mpu6500SpiGyroDetect(&gyro
)) {
281 if (mpu6500GyroDetect(&gyro
)) {
283 gyroHardware
= GYRO_MPU6500
;
284 #ifdef GYRO_MPU6500_ALIGN
285 gyroAlign
= GYRO_MPU6500_ALIGN
;
294 #ifdef USE_GYRO_SPI_MPU9250
295 if (mpu9250SpiGyroDetect(&gyro
))
297 gyroHardware
= GYRO_MPU9250
;
298 #ifdef GYRO_MPU9250_ALIGN
299 gyroAlign
= GYRO_MPU9250_ALIGN
;
308 if (fakeGyroDetect(&gyro
)) {
309 gyroHardware
= GYRO_FAKE
;
315 gyroHardware
= GYRO_NONE
;
318 addBootlogEvent6(BOOT_EVENT_GYRO_DETECTION
, BOOT_EVENT_FLAGS_NONE
, gyroHardware
, 0, 0, 0);
320 if (gyroHardware
== GYRO_NONE
) {
324 detectedSensors
[SENSOR_INDEX_GYRO
] = gyroHardware
;
325 sensorsSet(SENSOR_GYRO
);
330 static bool detectAcc(accelerationSensor_e accHardwareToUse
)
332 accelerationSensor_e accHardware
;
334 #ifdef USE_ACC_ADXL345
335 drv_adxl345_config_t acc_params
;
339 accAlign
= ALIGN_DEFAULT
;
341 switch (accHardwareToUse
) {
344 case ACC_ADXL345
: // ADXL345
345 #ifdef USE_ACC_ADXL345
346 acc_params
.useFifo
= false;
347 acc_params
.dataRate
= 800; // unused currently
349 if (hardwareRevision
< NAZE32_REV5
&& adxl345Detect(&acc_params
, &acc
)) {
351 if (adxl345Detect(&acc_params
, &acc
)) {
353 #ifdef ACC_ADXL345_ALIGN
354 accAlign
= ACC_ADXL345_ALIGN
;
356 accHardware
= ACC_ADXL345
;
362 #ifdef USE_ACC_LSM303DLHC
363 if (lsm303dlhcAccDetect(&acc
)) {
364 #ifdef ACC_LSM303DLHC_ALIGN
365 accAlign
= ACC_LSM303DLHC_ALIGN
;
367 accHardware
= ACC_LSM303DLHC
;
372 case ACC_MPU6050
: // MPU6050
373 #ifdef USE_ACC_MPU6050
374 if (mpu6050AccDetect(&acc
)) {
375 #ifdef ACC_MPU6050_ALIGN
376 accAlign
= ACC_MPU6050_ALIGN
;
378 accHardware
= ACC_MPU6050
;
383 case ACC_MMA8452
: // MMA8452
384 #ifdef USE_ACC_MMA8452
386 // Not supported with this frequency
387 if (hardwareRevision
< NAZE32_REV5
&& mma8452Detect(&acc
)) {
389 if (mma8452Detect(&acc
)) {
391 #ifdef ACC_MMA8452_ALIGN
392 accAlign
= ACC_MMA8452_ALIGN
;
394 accHardware
= ACC_MMA8452
;
399 case ACC_BMA280
: // BMA280
400 #ifdef USE_ACC_BMA280
401 if (bma280Detect(&acc
)) {
402 #ifdef ACC_BMA280_ALIGN
403 accAlign
= ACC_BMA280_ALIGN
;
405 accHardware
= ACC_BMA280
;
411 #ifdef USE_ACC_SPI_MPU6000
412 if (mpu6000SpiAccDetect(&acc
)) {
413 #ifdef ACC_MPU6000_ALIGN
414 accAlign
= ACC_MPU6000_ALIGN
;
416 accHardware
= ACC_MPU6000
;
422 #if defined(USE_ACC_MPU6500) || defined(USE_ACC_SPI_MPU6500)
423 #ifdef USE_ACC_SPI_MPU6500
424 if (mpu6500AccDetect(&acc
) || mpu6500SpiAccDetect(&acc
)) {
426 if (mpu6500AccDetect(&acc
)) {
428 #ifdef ACC_MPU6500_ALIGN
429 accAlign
= ACC_MPU6500_ALIGN
;
431 accHardware
= ACC_MPU6500
;
439 if (fakeAccDetect(&acc
)) {
440 accHardware
= ACC_FAKE
;
445 case ACC_NONE
: // disable ACC
446 accHardware
= ACC_NONE
;
451 // Found anything? Check if error or ACC is really missing.
452 if (accHardware
== ACC_NONE
&& accHardwareToUse
!= ACC_DEFAULT
&& accHardwareToUse
!= ACC_NONE
) {
453 // Nothing was found and we have a forced sensor that isn't present.
454 accHardwareToUse
= ACC_DEFAULT
;
458 addBootlogEvent6(BOOT_EVENT_ACC_DETECTION
, BOOT_EVENT_FLAGS_NONE
, accHardware
, 0, 0, 0);
460 if (accHardware
== ACC_NONE
) {
464 detectedSensors
[SENSOR_INDEX_ACC
] = accHardware
;
465 sensorsSet(SENSOR_ACC
);
470 static bool detectBaro(baroSensor_e baroHardwareToUse
)
472 // Detect what pressure sensors are available. baro->update() is set to sensor-specific update function
474 baroSensor_e baroHardware
= baroHardwareToUse
;
476 #ifdef USE_BARO_BMP085
478 const bmp085Config_t
*bmp085Config
= NULL
;
480 #if defined(BARO_XCLR_GPIO) && defined(BARO_EOC_GPIO)
481 static const bmp085Config_t defaultBMP085Config
= {
482 .xclrIO
= IO_TAG(BARO_XCLR_PIN
),
483 .eocIO
= IO_TAG(BARO_EOC_PIN
),
485 bmp085Config
= &defaultBMP085Config
;
489 if (hardwareRevision
== NAZE32
) {
490 bmp085Disable(bmp085Config
);
496 switch (baroHardware
) {
501 #ifdef USE_BARO_MS5611
502 if (ms5611Detect(&baro
)) {
503 baroHardware
= BARO_MS5611
;
509 #ifdef USE_BARO_BMP085
510 if (bmp085Detect(bmp085Config
, &baro
)) {
511 baroHardware
= BARO_BMP085
;
517 #ifdef USE_BARO_BMP280
518 if (bmp280Detect(&baro
)) {
519 baroHardware
= BARO_BMP280
;
526 if (fakeBaroDetect(&baro
)) {
527 baroHardware
= BARO_FAKE
;
533 baroHardware
= BARO_NONE
;
537 addBootlogEvent6(BOOT_EVENT_BARO_DETECTION
, BOOT_EVENT_FLAGS_NONE
, baroHardware
, 0, 0, 0);
539 if (baroHardware
== BARO_NONE
) {
543 detectedSensors
[SENSOR_INDEX_BARO
] = baroHardware
;
544 sensorsSet(SENSOR_BARO
);
550 static bool detectMag(magSensor_e magHardwareToUse
)
552 magSensor_e magHardware
= MAG_NONE
;
554 #ifdef USE_MAG_HMC5883
555 const hmc5883Config_t
*hmc5883Config
= 0;
557 #ifdef NAZE // TODO remove this target specific define
558 static const hmc5883Config_t nazeHmc5883Config_v1_v4
= {
559 .intTag
= IO_TAG(PB12
) /* perhaps disabled? */
561 static const hmc5883Config_t nazeHmc5883Config_v5
= {
562 .intTag
= IO_TAG(MAG_INT_EXTI
)
564 if (hardwareRevision
< NAZE32_REV5
) {
565 hmc5883Config
= &nazeHmc5883Config_v1_v4
;
567 hmc5883Config
= &nazeHmc5883Config_v5
;
572 static const hmc5883Config_t extiHmc5883Config
= {
573 .intTag
= IO_TAG(MAG_INT_EXTI
)
576 hmc5883Config
= &extiHmc5883Config
;
581 magAlign
= ALIGN_DEFAULT
;
583 switch(magHardwareToUse
) {
588 #ifdef USE_MAG_HMC5883
589 if (hmc5883lDetect(&mag
, hmc5883Config
)) {
590 #ifdef MAG_HMC5883_ALIGN
591 magAlign
= MAG_HMC5883_ALIGN
;
593 magHardware
= MAG_HMC5883
;
600 #ifdef USE_MAG_AK8975
601 if (ak8975Detect(&mag
)) {
602 #ifdef MAG_AK8975_ALIGN
603 magAlign
= MAG_AK8975_ALIGN
;
605 magHardware
= MAG_AK8975
;
612 #ifdef USE_MAG_AK8963
613 if (ak8963Detect(&mag
)) {
614 #ifdef MAG_AK8963_ALIGN
615 magAlign
= MAG_AK8963_ALIGN
;
617 magHardware
= MAG_AK8963
;
625 if (gpsMagDetect(&mag
)) {
627 magAlign
= MAG_GPS_ALIGN
;
629 magHardware
= MAG_GPS
;
636 #ifdef USE_MAG_MAG3110
637 if (mag3110detect(&mag
)) {
638 #ifdef MAG_MAG3110_ALIGN
639 magAlign
= MAG_MAG3110_ALIGN
;
641 magHardware
= MAG_MAG3110
;
649 if (fakeMagDetect(&mag
)) {
650 magHardware
= MAG_FAKE
;
657 magHardware
= MAG_NONE
;
661 addBootlogEvent6(BOOT_EVENT_MAG_DETECTION
, BOOT_EVENT_FLAGS_NONE
, magHardware
, 0, 0, 0);
663 // If not in autodetect mode and detected the wrong chip - disregard the compass even if detected
664 if ((magHardwareToUse
!= MAG_DEFAULT
&& magHardware
!= magHardwareToUse
) || (magHardware
== MAG_NONE
)) {
668 detectedSensors
[SENSOR_INDEX_MAG
] = magHardware
;
669 sensorsSet(SENSOR_MAG
);
676 * Detect which rangefinder is present
678 static rangefinderType_e
detectRangefinder(void)
680 rangefinderType_e rangefinderType
= RANGEFINDER_NONE
;
681 if (feature(FEATURE_SONAR
)) {
682 // the user has set the sonar feature, so assume they have an HC-SR04 plugged in,
683 // since there is no way to detect it
684 rangefinderType
= RANGEFINDER_HCSR04
;
686 #ifdef USE_SONAR_SRF10
687 if (srf10_detect()) {
688 // if an SFR10 sonar rangefinder is detected then use it in preference to the assumed HC-SR04
689 rangefinderType
= RANGEFINDER_SRF10
;
693 addBootlogEvent6(BOOT_EVENT_RANGEFINDER_DETECTION
, BOOT_EVENT_FLAGS_NONE
, rangefinderType
, 0, 0, 0);
695 detectedSensors
[SENSOR_INDEX_RANGEFINDER
] = rangefinderType
;
697 if (rangefinderType
!= RANGEFINDER_NONE
) {
698 sensorsSet(SENSOR_SONAR
);
701 return rangefinderType
;
705 static void reconfigureAlignment(const sensorAlignmentConfig_t
*sensorAlignmentConfig
)
707 if (sensorAlignmentConfig
->gyro_align
!= ALIGN_DEFAULT
) {
708 gyroAlign
= sensorAlignmentConfig
->gyro_align
;
710 if (sensorAlignmentConfig
->acc_align
!= ALIGN_DEFAULT
) {
711 accAlign
= sensorAlignmentConfig
->acc_align
;
713 if (sensorAlignmentConfig
->mag_align
!= ALIGN_DEFAULT
) {
714 magAlign
= sensorAlignmentConfig
->mag_align
;
718 bool sensorsAutodetect(sensorAlignmentConfig_t
*sensorAlignmentConfig
,
719 uint8_t accHardwareToUse
,
720 uint8_t magHardwareToUse
,
721 uint8_t baroHardwareToUse
,
722 int16_t magDeclinationFromConfig
,
726 uint8_t gyroSyncDenominator
)
728 memset(&acc
, 0, sizeof(acc
));
729 memset(&gyro
, 0, sizeof(gyro
));
731 #if defined(USE_GYRO_MPU6050) || defined(USE_GYRO_MPU3050) || defined(USE_GYRO_MPU6500) || defined(USE_GYRO_SPI_MPU6500) || defined(USE_GYRO_SPI_MPU6000) || defined(USE_ACC_MPU6050) || defined(USE_GYRO_SPI_MPU9250)
732 const extiConfig_t
*extiConfig
= selectMPUIntExtiConfig();
733 detectMpu(extiConfig
);
740 // this is safe because either mpu6050 or mpu3050 or lg3d20 sets it, and in case of fail, we never get here.
741 gyro
.targetLooptime
= gyroSetSampleRate(looptime
, gyroLpf
, gyroSync
, gyroSyncDenominator
); // Set gyro sample rate before initialisation
742 gyro
.init(gyroLpf
); // driver initialisation
743 gyroInit(); // sensor initialisation
745 if (detectAcc(accHardwareToUse
)) {
746 acc
.acc_1G
= 256; // set default
748 accInit(gyro
.targetLooptime
); // acc and gyro updated at same frequency in taskMainPidLoop in mw.c
752 detectBaro(baroHardwareToUse
);
754 UNUSED(baroHardwareToUse
);
757 // FIXME extract to a method to reduce dependencies, maybe move to sensors_compass.c
758 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.
760 if (detectMag(magHardwareToUse
)) {
761 // calculate magnetic declination
762 if (!compassInit(magDeclinationFromConfig
)) {
763 addBootlogEvent2(BOOT_EVENT_MAG_INIT_FAILED
, BOOT_EVENT_FLAGS_ERROR
);
764 sensorsClear(SENSOR_MAG
);
768 UNUSED(magHardwareToUse
);
769 UNUSED(magDeclinationFromConfig
);
773 const rangefinderType_e rangefinderType
= detectRangefinder();
774 rangefinderInit(rangefinderType
);
776 reconfigureAlignment(sensorAlignmentConfig
);