diff --git a/conf/firmwares/subsystems/shared/imu_mpu60x0_i2c.makefile b/conf/firmwares/subsystems/shared/imu_mpu60x0_i2c.makefile new file mode 100644 index 0000000000..8fc59d3662 --- /dev/null +++ b/conf/firmwares/subsystems/shared/imu_mpu60x0_i2c.makefile @@ -0,0 +1,49 @@ +# Hey Emacs, this is a -*- makefile -*- +# +# MPU60X0 IMU via I2C +# + +# for fixedwing firmware and ap only +ifeq ($(TARGET), ap) + IMU_MPU60X0_CFLAGS = -DUSE_IMU +endif + +IMU_MPU60X0_CFLAGS += -DIMU_TYPE_H=\"imu/imu_mpu60x0_i2c.h\" +IMU_MPU60X0_SRCS = $(SRC_SUBSYSTEMS)/imu.c +IMU_MPU60X0_SRCS += $(SRC_SUBSYSTEMS)/imu/imu_mpu60x0_i2c.c +IMU_MPU60X0_SRCS += peripherals/mpu60x0.c +IMU_MPU60X0_SRCS += peripherals/mpu60x0_i2c.c + + +# set default i2c bus +ifeq ($(ARCH), lpc21) +IMU_MPU60X0_I2C_DEV ?= i2c0 +else ifeq ($(ARCH), stm32) +IMU_MPU60X0_I2C_DEV ?= i2c2 +endif + +ifeq ($(TARGET), ap) +ifndef MPU60X0_I2C_DEV +$(error Error: MPU60X0_I2C_DEV not configured!) +endif +endif + +# convert i2cx to upper/lower case +IMU_MPU60X0_I2C_DEV_UPPER=$(shell echo $(IMU_MPU60X0_I2C_DEV) | tr a-z A-Z) +IMU_MPU60X0_I2C_DEV_LOWER=$(shell echo $(IMU_MPU60X0_I2C_DEV) | tr A-Z a-z) + +IMU_MPU60X0_CFLAGS += -DIMU_MPU60X0_I2C_DEV=$(IMU_MPU60X0_I2C_DEV_LOWER) +IMU_MPU60X0_CFLAGS += -DUSE_$(IMU_MPU60X0_I2C_DEV_UPPER) + + +# add it for all targets except sim, fbw and nps +ifeq (,$(findstring $(TARGET),sim fbw nps)) +$(TARGET).CFLAGS += $(IMU_MPU60X0_CFLAGS) +$(TARGET).srcs += $(IMU_MPU60X0_SRCS) +endif + + +# +# NPS simulator +# +include $(CFG_SHARED)/imu_nps.makefile diff --git a/sw/airborne/subsystems/abi_sender_ids.h b/sw/airborne/subsystems/abi_sender_ids.h index 1414659c07..84957fe12d 100644 --- a/sw/airborne/subsystems/abi_sender_ids.h +++ b/sw/airborne/subsystems/abi_sender_ids.h @@ -222,4 +222,8 @@ #define IMU_XSENS_ID 15 #endif +#ifndef IMU_MPU60X0_ID +#define IMU_MPU60X0_ID 16 +#endif + #endif /* ABI_SENDER_IDS_H */ diff --git a/sw/airborne/subsystems/imu/imu_mpu60x0_i2c.c b/sw/airborne/subsystems/imu/imu_mpu60x0_i2c.c new file mode 100644 index 0000000000..905459c757 --- /dev/null +++ b/sw/airborne/subsystems/imu/imu_mpu60x0_i2c.c @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2013-2015 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * paparazzi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file subsystems/imu/imu_mpu60x0_i2c.c + * Driver for IMU with only MPU60X0 via I2C. + */ + +#include +#include "subsystems/imu.h" +#include "subsystems/abi.h" +#include "mcu_periph/i2c.h" +#include "led.h" + +/* MPU60x0 gyro/accel internal lowpass frequency */ +#if !defined IMU_MPU60X0_LOWPASS_FILTER && !defined IMU_MPU60X0_SMPLRT_DIV +#if (PERIODIC_FREQUENCY == 60) || (PERIODIC_FREQUENCY == 120) +/* Accelerometer: Bandwidth 44Hz, Delay 4.9ms + * Gyroscope: Bandwidth 42Hz, Delay 4.8ms sampling 1kHz + */ +#define IMU_MPU60X0_LOWPASS_FILTER MPU60X0_DLPF_42HZ +#define IMU_MPU60X0_SMPLRT_DIV 9 +PRINT_CONFIG_MSG("Gyro/Accel output rate is 100Hz at 1kHz internal sampling") +#elif PERIODIC_FREQUENCY == 512 +/* Accelerometer: Bandwidth 260Hz, Delay 0ms + * Gyroscope: Bandwidth 256Hz, Delay 0.98ms sampling 8kHz + */ +#define IMU_MPU60X0_LOWPASS_FILTER MPU60X0_DLPF_256HZ +#define IMU_MPU60X0_SMPLRT_DIV 3 +PRINT_CONFIG_MSG("Gyro/Accel output rate is 2kHz at 8kHz internal sampling") +#else +#error Non-default PERIODIC_FREQUENCY: please define MPU60X0_HMC_LOWPASS_FILTER and MPU60X0_HMC_SMPLRT_DIV. +#endif +#endif +PRINT_CONFIG_VAR(IMU_MPU60X0_LOWPASS_FILTER) +PRINT_CONFIG_VAR(IMU_MPU60X0_SMPLRT_DIV) + +#ifndef IMU_MPU60X0_GYRO_RANGE +#define IMU_MPU60X0_GYRO_RANGE MPU60X0_GYRO_RANGE_2000 +#endif +PRINT_CONFIG_VAR(IMU_MPU60X0_GYRO_RANGE) + +#ifndef IMU_MPU60X0_ACCEL_RANGE +#define IMU_MPU60X0_ACCEL_RANGE MPU60X0_ACCEL_RANGE_16G +#endif +PRINT_CONFIG_VAR(IMU_MPU60X0_ACCEL_RANGE) + +#ifndef IMU_MPU60X0_I2C_ADDR +#define IMU_MPU60X0_I2C_ADDR MPU60X0_ADDR +#endif + +struct ImuMpu60x0 imu_mpu_i2c; + +void imu_impl_init(void) +{ + mpu60x0_i2c_init(&imu_mpu_i2c.mpu, &(IMU_MPU60X0_I2C_DEV), IMU_MPU60X0_I2C_ADDR >> 1); + // change the default configuration + imu_mpu_i2c.mpu.config.smplrt_div = IMU_MPU60X0_SMPLRT_DIV; + imu_mpu_i2c.mpu.config.dlpf_cfg = IMU_MPU60X0_LOWPASS_FILTER; + imu_mpu_i2c.mpu.config.gyro_range = IMU_MPU60X0_GYRO_RANGE; + imu_mpu_i2c.mpu.config.accel_range = IMU_MPU60X0_ACCEL_RANGE; +} + +void imu_periodic(void) +{ + mpu60x0_i2c_periodic(&imu_mpu_i2c.mpu); +} + +void imu_mpu_i2c_event(void) +{ + uint32_t now_ts = get_sys_time_usec(); + + // If the MPU60X0 I2C transaction has succeeded: convert the data + mpu60x0_i2c_event(&imu_mpu_i2c.mpu); + if (imu_mpu_i2c.mpu.data_available) { + RATES_COPY(imu.gyro_unscaled, imu_mpu_i2c.mpu.data_rates.rates); + VECT3_COPY(imu.accel_unscaled, imu_mpu_i2c.mpu.data_accel.vect); + imu_mpu_i2c.mpu.data_available = FALSE; + imu_scale_gyro(&imu); + imu_scale_accel(&imu); + AbiSendMsgIMU_GYRO_INT32(IMU_MPU60X0_ID, now_ts, &imu.gyro); + AbiSendMsgIMU_ACCEL_INT32(IMU_MPU60X0_ID, now_ts, &imu.accel); + } +} diff --git a/sw/airborne/subsystems/imu/imu_mpu60x0_i2c.h b/sw/airborne/subsystems/imu/imu_mpu60x0_i2c.h new file mode 100644 index 0000000000..cd519c6e0e --- /dev/null +++ b/sw/airborne/subsystems/imu/imu_mpu60x0_i2c.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2013 Felix Ruess + * + * This file is part of paparazzi. + * + * paparazzi is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * paparazzi is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * @file subsystems/imu/imu_mpu60x0_i2c.h + * Driver for IMU with only MPU60x0 via I2C. + */ + +#ifndef IMU_MPU60X0_I2C_H +#define IMU_MPU60X0_I2C_H + +#include "std.h" +#include "generated/airframe.h" +#include "subsystems/imu.h" + +#include "subsystems/imu/imu_mpu60x0_defaults.h" +#include "peripherals/mpu60x0_i2c.h" + + +struct ImuMpu60x0 { + struct Mpu60x0_I2c mpu; +}; + +extern struct ImuMpu60x0 imu_mpu_i2c; + +extern void imu_mpu_i2c_event(void); + + +#define ImuEvent imu_mpu_i2c_event + +#endif /* IMU_MPU60X0_I2C_H */