diff --git a/drivers/include/lsm6dsl.h b/drivers/include/lsm6dsl.h index 5feebd88acdeffcf3f562807c7f15b4fe4c07150..6b98261d28dd92f5592b23c445462275b9c11444 100644 --- a/drivers/include/lsm6dsl.h +++ b/drivers/include/lsm6dsl.h @@ -13,10 +13,13 @@ * @brief Device driver for the LSM6DSL 3D accelerometer/gyroscope * * @{ + * * @file * @brief Device driver interface for the LSM6DSL 3D accelerometer/gyroscope. * * @author Vincent Dupont <vincent@otakeys.com> + * @author Sebastian Meiling <s@mlng.net> + * */ #ifndef LSM6DSL_H @@ -28,7 +31,9 @@ extern "C" { #include "periph/i2c.h" -/** Data rate */ +/** + * @brief Data rate settings + */ enum { LSM6DSL_DATA_RATE_POWER_DOWN = 0x0, LSM6DSL_DATA_RATE_1_6HZ = 0xB, @@ -44,35 +49,45 @@ enum { LSM6DSL_DATA_RATE_6_66KHZ = 0xa, }; -/** Decimation */ +/** + * @brief Decimation settings + */ enum { LSM6DSL_DECIMATION_NOT_IN_FIFO = 0, - LSM6DSL_DECIMATION_NO = 1, - LSM6DSL_DECIMATION_2 = 2, - LSM6DSL_DECIMATION_3 = 3, - LSM6DSL_DECIMATION_4 = 4, - LSM6DSL_DECIMATION_8 = 5, - LSM6DSL_DECIMATION_16 = 6, - LSM6DSL_DECIMATION_32 = 7, + LSM6DSL_DECIMATION_NO, + LSM6DSL_DECIMATION_2, + LSM6DSL_DECIMATION_3, + LSM6DSL_DECIMATION_4, + LSM6DSL_DECIMATION_8, + LSM6DSL_DECIMATION_16, + LSM6DSL_DECIMATION_32, }; -/** Accelerometer full scale */ +/** + * @brief Accelerometer full scale + */ enum { LSM6DSL_ACC_FS_2G = 0, - LSM6DSL_ACC_FS_4G = 2, - LSM6DSL_ACC_FS_8G = 3, - LSM6DSL_ACC_FS_16G = 1, + LSM6DSL_ACC_FS_16G, + LSM6DSL_ACC_FS_4G, + LSM6DSL_ACC_FS_8G, + LSM6DSL_ACC_FS_MAX, }; -/** Gyroscope full scale */ +/** + * @brief Gyroscope full scale + */ enum { LSM6DSL_GYRO_FS_245DPS = 0, - LSM6DSL_GYRO_FS_500DPS = 1, - LSM6DSL_GYRO_FS_1000DPS = 2, - LSM6DSL_GYRO_FS_2000DPS = 3, + LSM6DSL_GYRO_FS_500DPS, + LSM6DSL_GYRO_FS_1000DPS, + LSM6DSL_GYRO_FS_2000DPS, + LSM6DSL_GYRO_FS_MAX, }; -/** LSM6DSL driver parameters */ +/** + * @brief LSM6DSL driver parameters + */ typedef struct { i2c_t i2c; /**< i2c bus */ uint8_t addr; /**< i2c address */ @@ -84,25 +99,39 @@ typedef struct { uint8_t gyro_decimation; /**< gyroscope decimation */ } lsm6dsl_params_t; -/** LSM6DSL device descriptor */ +/** + * @brief LSM6DSL device descriptor + */ typedef struct { lsm6dsl_params_t params; /**< driver parameters */ } lsm6dsl_t; -/** 3D output data */ +/** + * @brief 3D output data + */ typedef struct { int16_t x; /**< X axis */ int16_t y; /**< Y axis */ int16_t z; /**< Z axis */ } lsm6dsl_3d_data_t; +/** + * @brief Named return values + */ +enum { + LSM6DSL_OK = 0, /**< all good */ + LSM6DSL_ERROR_BUS, /**< I2C bus error */ + LSM6DSL_ERROR_CNF, /**< Config error */ + LSM6DSL_ERROR_DEV, /**< device error */ +}; + /** * @brief Initialize a LSM6DSL device * - * @param[in] dev device to initialize + * @param[out] dev device to initialize * @param[in] params driver parameters * - * @return 0 on success + * @return LSM6DSL_OK on success * @return < 0 on error */ int lsm6dsl_init(lsm6dsl_t *dev, const lsm6dsl_params_t *params); @@ -113,7 +142,7 @@ int lsm6dsl_init(lsm6dsl_t *dev, const lsm6dsl_params_t *params); * @param[in] dev device to read * @param[out] data accelerometer values * - * @return 0 on success + * @return LSM6DSL_OK on success * @return < 0 on error */ int lsm6dsl_read_acc(const lsm6dsl_t *dev, lsm6dsl_3d_data_t *data); @@ -124,7 +153,7 @@ int lsm6dsl_read_acc(const lsm6dsl_t *dev, lsm6dsl_3d_data_t *data); * @param[in] dev device to read * @param[out] data gyroscope values * - * @return 0 on success + * @return LSM6DSL_OK on success * @return < 0 on error */ int lsm6dsl_read_gyro(const lsm6dsl_t *dev, lsm6dsl_3d_data_t *data); @@ -132,10 +161,14 @@ int lsm6dsl_read_gyro(const lsm6dsl_t *dev, lsm6dsl_3d_data_t *data); /** * @brief Read temperature data * + * @note To avoid floating point data types but still provide high resolution + * for temperature readings, resulting values are scale by factor 100. + * + * * @param[in] dev device to read - * @param[out] data temperature value + * @param[out] data temperature value, in °C x 100 * - * @return 0 on success + * @return LSM6DSL_OK on success * @return < 0 on error */ int lsm6dsl_read_temp(const lsm6dsl_t *dev, int16_t *data); diff --git a/drivers/lsm6dsl/include/lsm6dsl_internal.h b/drivers/lsm6dsl/include/lsm6dsl_internal.h index 7d112db207c307a7c94083b7d32dee5ac8d3fe32..0d2f4280d31733b1e8202b2487e49e29fc03152d 100644 --- a/drivers/lsm6dsl/include/lsm6dsl_internal.h +++ b/drivers/lsm6dsl/include/lsm6dsl_internal.h @@ -9,17 +9,21 @@ /** * @ingroup drivers_lsm6dsl - * * @{ + * * @file * @brief Internal configuration for LSM6DSL devices * * @author Vincent Dupont <vincent@otakeys.com> + * @author Sebastian Meiling <s@mlng.net> + * */ #ifndef LSM6DSL_INTERNAL_H #define LSM6DSL_INTERNAL_H +#include "xtimer.h" + #ifdef __cplusplus extern "C" { #endif @@ -28,127 +32,137 @@ extern "C" { * @name LSM6DSL registers * @{ */ -#define LSM6DSL_REG_FUNC_CFG_ACCESS (0x01) -#define LSM6DSL_REG_SENSOR_SYNC_TIME_FRAME (0x04) -#define LSM6DSL_REG_SENSOR_SYC_RES_RATIO (0x05) -#define LSM6DSL_REG_FIFO_CTRL1 (0x06) -#define LSM6DSL_REG_FIFO_CTRL2 (0x07) -#define LSM6DSL_REG_FIFO_CTRL3 (0x08) -#define LSM6DSL_REG_FIFO_CTRL4 (0x09) -#define LSM6DSL_REG_FIFO_CTRL5 (0x0A) -#define LSM6DSL_REG_DRDY_PULSE_CFG_G (0x0B) -#define LSM6DSL_REG_INT1_CTRL (0x0D) -#define LSM6DSL_REG_INT2_CTRL (0x0E) -#define LSM6DSL_REG_WHO_AM_I (0x0F) -#define LSM6DSL_REG_CTRL1_XL (0x10) -#define LSM6DSL_REG_CTRL2_G (0x11) -#define LSM6DSL_REG_CTRL3_C (0x12) -#define LSM6DSL_REG_CTRL4_C (0x13) -#define LSM6DSL_REG_CTRL5_C (0x14) -#define LSM6DSL_REG_CTRL6_C (0x15) -#define LSM6DSL_REG_CTRL7_G (0x16) -#define LSM6DSL_REG_CTRL8_XL (0x17) -#define LSM6DSL_REG_CTRL9_XL (0x18) -#define LSM6DSL_REG_CTRL10_C (0x19) -#define LSM6DSL_REG_MASTER_CONFIG (0x1A) -#define LSM6DSL_REG_WAKE_UP_SRC (0x1B) -#define LSM6DSL_REG_TAP_SRC (0x1C) -#define LSM6DSL_REG_D6D_SRC (0x1D) -#define LSM6DSL_REG_STATUS_REG (0x1E) -#define LSM6DSL_REG_OUT_TEMP_L (0x20) -#define LSM6DSL_REG_OUT_TEMP_H (0x21) -#define LSM6DSL_REG_OUTX_L_G (0x22) -#define LSM6DSL_REG_OUTX_H_G (0x23) -#define LSM6DSL_REG_OUTY_L_G (0x24) -#define LSM6DSL_REG_OUTY_H_G (0x25) -#define LSM6DSL_REG_OUTZ_L_G (0x26) -#define LSM6DSL_REG_OUTZ_H_G (0x27) -#define LSM6DSL_REG_OUTX_L_XL (0x28) -#define LSM6DSL_REG_OUTX_H_XL (0x29) -#define LSM6DSL_REG_OUTY_L_XL (0x2A) -#define LSM6DSL_REG_OUTY_H_XL (0x2B) -#define LSM6DSL_REG_OUTZ_L_XL (0x2C) -#define LSM6DSL_REG_OUTZ_H_XL (0x2D) -#define LSM6DSL_REG_SENSORHUB1_REG (0x2E) -#define LSM6DSL_REG_SENSORHUB2_REG (0x2F) -#define LSM6DSL_REG_SENSORHUB3_REG (0x30) -#define LSM6DSL_REG_SENSORHUB4_REG (0x31) -#define LSM6DSL_REG_SENSORHUB5_REG (0x32) -#define LSM6DSL_REG_SENSORHUB6_REG (0x33) -#define LSM6DSL_REG_SENSORHUB7_REG (0x34) -#define LSM6DSL_REG_SENSORHUB8_REG (0x35) -#define LSM6DSL_REG_SENSORHUB9_REG (0x36) -#define LSM6DSL_REG_SENSORHUB10_REG (0x37) -#define LSM6DSL_REG_SENSORHUB11_REG (0x38) -#define LSM6DSL_REG_SENSORHUB12_REG (0x39) -#define LSM6DSL_REG_FIFO_STATUS1 (0x3A) -#define LSM6DSL_REG_FIFO_STATUS2 (0x3B) -#define LSM6DSL_REG_FIFO_STATUS3 (0x3C) -#define LSM6DSL_REG_FIFO_STATUS4 (0x3D) -#define LSM6DSL_REG_FIFO_DATA_OUT_L (0x3E) -#define LSM6DSL_REG_FIFO_DATA_OUT_H (0x3F) -#define LSM6DSL_REG_TIMESTAMP0_REG (0x40) -#define LSM6DSL_REG_TIMESTAMP1_REG (0x41) -#define LSM6DSL_REG_TIMESTAMP2_REG (0x42) -#define LSM6DSL_REG_STEP_TIMESTAMP_L (0x49) -#define LSM6DSL_REG_STEP_TIMESTAMP_H (0x4A) -#define LSM6DSL_REG_STEP_COUNTER_L (0x4B) -#define LSM6DSL_REG_STEP_COUNTER_H (0x4C) -#define LSM6DSL_REG_SENSORHUB13_REG (0x4D) -#define LSM6DSL_REG_SENSORHUB14_REG (0x4E) -#define LSM6DSL_REG_SENSORHUB15_REG (0x4F) -#define LSM6DSL_REG_SENSORHUB16_REG (0x50) -#define LSM6DSL_REG_SENSORHUB17_REG (0x51) -#define LSM6DSL_REG_SENSORHUB18_REG (0x52) -#define LSM6DSL_REG_FUNC_SRC_1 (0x53) -#define LSM6DSL_REG_FUNC_SRC_2 (0x54) -#define LSM6DSL_REG_WRIST_TILT_IA (0x55) -#define LSM6DSL_REG_TAP_CFG (0x58) -#define LSM6DSL_REG_TAP_THS_6D (0x59) -#define LSM6DSL_REG_INT_DUR2 (0x5A) -#define LSM6DSL_REG_WAKE_UP_THS (0x5B) -#define LSM6DSL_REG_WAKE_UP_DUR (0x5C) -#define LSM6DSL_REG_FREE_FALL (0x5D) -#define LSM6DSL_REG_MD1_CFG (0x5E) -#define LSM6DSL_REG_MD2_CFG (0x5F) -#define LSM6DSL_REG_MASTER_CMD_CODE (0x60) -#define LSM6DSL_REG_SENS_SYNC_SPI_ERR_CODE (0x61) -#define LSM6DSL_REG_OUT_MAG_RAW_X_L (0x66) -#define LSM6DSL_REG_OUT_MAG_RAW_X_H (0x67) -#define LSM6DSL_REG_OUT_MAG_RAW_Y_L (0x68) -#define LSM6DSL_REG_OUT_MAG_RAW_Y_H (0x69) -#define LSM6DSL_REG_OUT_MAG_RAW_Z_L (0x6A) -#define LSM6DSL_REG_OUT_MAG_RAW_Z_H (0x6B) -#define LSM6DSL_REG_X_OFS_USR (0x73) -#define LSM6DSL_REG_Y_OFS_USR (0x74) -#define LSM6DSL_REG_Z_OFS_USR (0x75) +#define LSM6DSL_REG_FUNC_CFG_ACCESS (0x01) +#define LSM6DSL_REG_SENSOR_SYNC_TIME_FRAME (0x04) +#define LSM6DSL_REG_SENSOR_SYC_RES_RATIO (0x05) +#define LSM6DSL_REG_FIFO_CTRL1 (0x06) +#define LSM6DSL_REG_FIFO_CTRL2 (0x07) +#define LSM6DSL_REG_FIFO_CTRL3 (0x08) +#define LSM6DSL_REG_FIFO_CTRL4 (0x09) +#define LSM6DSL_REG_FIFO_CTRL5 (0x0A) +#define LSM6DSL_REG_DRDY_PULSE_CFG_G (0x0B) +#define LSM6DSL_REG_INT1_CTRL (0x0D) +#define LSM6DSL_REG_INT2_CTRL (0x0E) +#define LSM6DSL_REG_WHO_AM_I (0x0F) +#define LSM6DSL_REG_CTRL1_XL (0x10) +#define LSM6DSL_REG_CTRL2_G (0x11) +#define LSM6DSL_REG_CTRL3_C (0x12) +#define LSM6DSL_REG_CTRL4_C (0x13) +#define LSM6DSL_REG_CTRL5_C (0x14) +#define LSM6DSL_REG_CTRL6_C (0x15) +#define LSM6DSL_REG_CTRL7_G (0x16) +#define LSM6DSL_REG_CTRL8_XL (0x17) +#define LSM6DSL_REG_CTRL9_XL (0x18) +#define LSM6DSL_REG_CTRL10_C (0x19) +#define LSM6DSL_REG_MASTER_CONFIG (0x1A) +#define LSM6DSL_REG_WAKE_UP_SRC (0x1B) +#define LSM6DSL_REG_TAP_SRC (0x1C) +#define LSM6DSL_REG_D6D_SRC (0x1D) +#define LSM6DSL_REG_STATUS_REG (0x1E) +#define LSM6DSL_REG_OUT_TEMP_L (0x20) +#define LSM6DSL_REG_OUT_TEMP_H (0x21) +#define LSM6DSL_REG_OUTX_L_G (0x22) +#define LSM6DSL_REG_OUTX_H_G (0x23) +#define LSM6DSL_REG_OUTY_L_G (0x24) +#define LSM6DSL_REG_OUTY_H_G (0x25) +#define LSM6DSL_REG_OUTZ_L_G (0x26) +#define LSM6DSL_REG_OUTZ_H_G (0x27) +#define LSM6DSL_REG_OUTX_L_XL (0x28) +#define LSM6DSL_REG_OUTX_H_XL (0x29) +#define LSM6DSL_REG_OUTY_L_XL (0x2A) +#define LSM6DSL_REG_OUTY_H_XL (0x2B) +#define LSM6DSL_REG_OUTZ_L_XL (0x2C) +#define LSM6DSL_REG_OUTZ_H_XL (0x2D) +#define LSM6DSL_REG_SENSORHUB1_REG (0x2E) +#define LSM6DSL_REG_SENSORHUB2_REG (0x2F) +#define LSM6DSL_REG_SENSORHUB3_REG (0x30) +#define LSM6DSL_REG_SENSORHUB4_REG (0x31) +#define LSM6DSL_REG_SENSORHUB5_REG (0x32) +#define LSM6DSL_REG_SENSORHUB6_REG (0x33) +#define LSM6DSL_REG_SENSORHUB7_REG (0x34) +#define LSM6DSL_REG_SENSORHUB8_REG (0x35) +#define LSM6DSL_REG_SENSORHUB9_REG (0x36) +#define LSM6DSL_REG_SENSORHUB10_REG (0x37) +#define LSM6DSL_REG_SENSORHUB11_REG (0x38) +#define LSM6DSL_REG_SENSORHUB12_REG (0x39) +#define LSM6DSL_REG_FIFO_STATUS1 (0x3A) +#define LSM6DSL_REG_FIFO_STATUS2 (0x3B) +#define LSM6DSL_REG_FIFO_STATUS3 (0x3C) +#define LSM6DSL_REG_FIFO_STATUS4 (0x3D) +#define LSM6DSL_REG_FIFO_DATA_OUT_L (0x3E) +#define LSM6DSL_REG_FIFO_DATA_OUT_H (0x3F) +#define LSM6DSL_REG_TIMESTAMP0_REG (0x40) +#define LSM6DSL_REG_TIMESTAMP1_REG (0x41) +#define LSM6DSL_REG_TIMESTAMP2_REG (0x42) +#define LSM6DSL_REG_STEP_TIMESTAMP_L (0x49) +#define LSM6DSL_REG_STEP_TIMESTAMP_H (0x4A) +#define LSM6DSL_REG_STEP_COUNTER_L (0x4B) +#define LSM6DSL_REG_STEP_COUNTER_H (0x4C) +#define LSM6DSL_REG_SENSORHUB13_REG (0x4D) +#define LSM6DSL_REG_SENSORHUB14_REG (0x4E) +#define LSM6DSL_REG_SENSORHUB15_REG (0x4F) +#define LSM6DSL_REG_SENSORHUB16_REG (0x50) +#define LSM6DSL_REG_SENSORHUB17_REG (0x51) +#define LSM6DSL_REG_SENSORHUB18_REG (0x52) +#define LSM6DSL_REG_FUNC_SRC_1 (0x53) +#define LSM6DSL_REG_FUNC_SRC_2 (0x54) +#define LSM6DSL_REG_WRIST_TILT_IA (0x55) +#define LSM6DSL_REG_TAP_CFG (0x58) +#define LSM6DSL_REG_TAP_THS_6D (0x59) +#define LSM6DSL_REG_INT_DUR2 (0x5A) +#define LSM6DSL_REG_WAKE_UP_THS (0x5B) +#define LSM6DSL_REG_WAKE_UP_DUR (0x5C) +#define LSM6DSL_REG_FREE_FALL (0x5D) +#define LSM6DSL_REG_MD1_CFG (0x5E) +#define LSM6DSL_REG_MD2_CFG (0x5F) +#define LSM6DSL_REG_MASTER_CMD_CODE (0x60) +#define LSM6DSL_REG_SENS_SYNC_SPI_ERR_CODE (0x61) +#define LSM6DSL_REG_OUT_MAG_RAW_X_L (0x66) +#define LSM6DSL_REG_OUT_MAG_RAW_X_H (0x67) +#define LSM6DSL_REG_OUT_MAG_RAW_Y_L (0x68) +#define LSM6DSL_REG_OUT_MAG_RAW_Y_H (0x69) +#define LSM6DSL_REG_OUT_MAG_RAW_Z_L (0x6A) +#define LSM6DSL_REG_OUT_MAG_RAW_Z_H (0x6B) +#define LSM6DSL_REG_X_OFS_USR (0x73) +#define LSM6DSL_REG_Y_OFS_USR (0x74) +#define LSM6DSL_REG_Z_OFS_USR (0x75) /** @} */ /** WHO_AM_I value */ -#define LSM6DSL_WHO_AM_I (0b01101010) +#define LSM6DSL_WHO_AM_I (0b01101010) /** * @name CTRL_x registers * @{ */ -#define LSM6DSL_CTRL_ODR_SHIFT (4) -#define LSM6DSL_CTRL_ODR_MASK (0xF0) -#define LSM6DSL_CTRL_FS_SHIFT (2) -#define LSM6DSL_CTRL_FS_MASK (0x0C) +#define LSM6DSL_CTRL_ODR_SHIFT (4) +#define LSM6DSL_CTRL_ODR_MASK (0xF0) +#define LSM6DSL_CTRL_FS_SHIFT (2) +#define LSM6DSL_CTRL_FS_MASK (0x0C) -#define LSM6DSL_CTRL3_C_BOOT (0x80) +#define LSM6DSL_CTRL3_C_BOOT (0x80) /** @} */ /** * @name FIFO_CTRL_x registers * @{ */ -#define LSM6DSL_FIFO_CTRL5_CONTINUOUS_MODE (0x6) -#define LSM6DSL_FIFO_CTRL5_FIFO_ODR_SHIFT (3) +#define LSM6DSL_FIFO_CTRL5_CONTINUOUS_MODE (0x6) +#define LSM6DSL_FIFO_CTRL5_FIFO_ODR_SHIFT (3) -#define LSM6DSL_FIFO_CTRL3_GYRO_DEC_SHIFT (3) +#define LSM6DSL_FIFO_CTRL3_GYRO_DEC_SHIFT (3) /** @} */ +/** + * @brief Offset for temperature calculation + */ +#define LSM6DSL_TEMP_OFFSET (0x1900) + +/** + * @brief Reboot wait interval in us (15ms) + */ +#define LSM6DSL_BOOT_WAIT (15 * US_PER_MS) + #ifdef __cplusplus } #endif diff --git a/drivers/lsm6dsl/include/lsm6dsl_params.h b/drivers/lsm6dsl/include/lsm6dsl_params.h index 2910b4a1a3909b37d2ee6c1f753064b9226e98bf..c6501ba0dd8c5702d2fff9373a3e9222887400c2 100644 --- a/drivers/lsm6dsl/include/lsm6dsl_params.h +++ b/drivers/lsm6dsl/include/lsm6dsl_params.h @@ -9,12 +9,13 @@ /** * @ingroup drivers_lsm6dsl - * * @{ + * * @file * @brief Default configuration for LSM6DSL devices * * @author Vincent Dupont <vincent@otakeys.com> + * */ #ifndef LSM6DSL_PARAMS_H diff --git a/drivers/lsm6dsl/lsm6dsl.c b/drivers/lsm6dsl/lsm6dsl.c index a641ab7c94ead8801d357f4e22b6bfd7f6f915f7..cecf13c23cde3970a8065c90fa38af868af3eced 100644 --- a/drivers/lsm6dsl/lsm6dsl.c +++ b/drivers/lsm6dsl/lsm6dsl.c @@ -8,10 +8,16 @@ */ /** + * @ingroup drivers_lsm6dsl + * @{ + * * @file * @brief Device driver implementation for the LSM6DSL 3D accelerometer/gyroscope. * * @author Vincent Dupont <vincent@otakeys.com> + * @author Sebastian Meiling <s@mlng.net> + * + * @} */ #include "xtimer.h" @@ -24,6 +30,22 @@ #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define BUS (dev->params.i2c) +#define ADDR (dev->params.addr) + +/** + * order in arry [0, 1, 2, 3] is + * LSM6DSL_ACC_FS_2G, LSM6DSL_ACC_FS_16G, LSM6DSL_ACC_FS_4G, LSM6DSL_ACC_FS_8G + */ +static const int16_t range_acc[] = { 2000, 16000, 4000, 8000 }; + +/** + * order in arry [0, 1, 2, 3] is + * LSM6DSL_GYRO_FS_245DPS, LSM6DSL_GYRO_FS_500DPS, + * LSM6DSL_GYRO_FS_1000DPS, LSM6DSL_GYRO_FS_2000DPS + */ +static const int16_t range_gyro[] = { 2450, 5000, 10000, 20000 }; + int lsm6dsl_init(lsm6dsl_t *dev, const lsm6dsl_params_t *params) { uint8_t tmp; @@ -33,47 +55,49 @@ int lsm6dsl_init(lsm6dsl_t *dev, const lsm6dsl_params_t *params) dev->params = *params; - i2c_acquire(dev->params.i2c); - i2c_init_master(dev->params.i2c, I2C_SPEED_NORMAL); + i2c_acquire(BUS); + i2c_init_master(BUS, I2C_SPEED_NORMAL); /* Reboot */ - i2c_write_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_CTRL3_C, LSM6DSL_CTRL3_C_BOOT); + i2c_write_reg(BUS, ADDR, LSM6DSL_REG_CTRL3_C, LSM6DSL_CTRL3_C_BOOT); + + xtimer_usleep(LSM6DSL_BOOT_WAIT); - xtimer_usleep(5000); + if (i2c_read_reg(BUS, ADDR, LSM6DSL_REG_WHO_AM_I, &tmp) != 1) { + i2c_release(BUS); + DEBUG("[ERROR] lsm6dsl_init: i2c_read_reg LSM6DSL_REG_WHO_AM_I!\n"); + return -LSM6DSL_ERROR_BUS; + } - res = i2c_read_reg(dev->params.i2c, dev->params.addr, LSM6DSL_REG_WHO_AM_I, &tmp); - if ((res != 1) || (tmp != LSM6DSL_WHO_AM_I)) { - i2c_release(dev->params.i2c); - DEBUG("[!!failed!!] WHO_AM_I\n"); - return -1; + if (tmp != LSM6DSL_WHO_AM_I) { + DEBUG("[ERROR] lsm6dsl_init: WHO_AM_I\n"); + return -LSM6DSL_ERROR_DEV; } /* Set acc odr / full scale */ - res = i2c_write_reg(dev->params.i2c, dev->params.addr, LSM6DSL_REG_CTRL1_XL, - ((dev->params.acc_odr << LSM6DSL_CTRL_ODR_SHIFT) | - (dev->params.acc_fs << LSM6DSL_CTRL_FS_SHIFT))); + tmp = (dev->params.acc_odr << LSM6DSL_CTRL_ODR_SHIFT) | + (dev->params.acc_fs << LSM6DSL_CTRL_FS_SHIFT); + res = i2c_write_reg(BUS, ADDR, LSM6DSL_REG_CTRL1_XL, tmp); /* Set gyro odr / full scale */ - res += i2c_write_reg(dev->params.i2c, dev->params.addr, LSM6DSL_REG_CTRL2_G, - ((dev->params.gyro_odr << LSM6DSL_CTRL_ODR_SHIFT) | - (dev->params.gyro_fs << LSM6DSL_CTRL_FS_SHIFT))); - + tmp = (dev->params.gyro_odr << LSM6DSL_CTRL_ODR_SHIFT) | + (dev->params.gyro_fs << LSM6DSL_CTRL_FS_SHIFT); + res += i2c_write_reg(BUS, ADDR, LSM6DSL_REG_CTRL2_G, tmp); /* Set continuous mode */ uint8_t fifo_odr = MAX(dev->params.acc_odr, dev->params.gyro_odr); - res += i2c_write_reg(dev->params.i2c, dev->params.addr, LSM6DSL_REG_FIFO_CTRL5, - (fifo_odr << LSM6DSL_FIFO_CTRL5_FIFO_ODR_SHIFT) | - LSM6DSL_FIFO_CTRL5_CONTINUOUS_MODE); - res += i2c_write_reg(dev->params.i2c, dev->params.addr, LSM6DSL_REG_FIFO_CTRL3, - (dev->params.gyro_decimation << LSM6DSL_FIFO_CTRL3_GYRO_DEC_SHIFT) | - dev->params.acc_decimation); + tmp = (fifo_odr << LSM6DSL_FIFO_CTRL5_FIFO_ODR_SHIFT) | + LSM6DSL_FIFO_CTRL5_CONTINUOUS_MODE; + res += i2c_write_reg(BUS, ADDR, LSM6DSL_REG_FIFO_CTRL5, tmp); + tmp = (dev->params.gyro_decimation << LSM6DSL_FIFO_CTRL3_GYRO_DEC_SHIFT) | + dev->params.acc_decimation; + res += i2c_write_reg(BUS, ADDR, LSM6DSL_REG_FIFO_CTRL3, tmp); - i2c_release(dev->params.i2c); + i2c_release(BUS); if (res < 4) { - DEBUG("[!!failed!!] config\n"); - return -1; + DEBUG("[ERROR] lsm6dsl_init: config\n"); + return -LSM6DSL_ERROR_CNF; } - return 0; + return LSM6DSL_OK; } int lsm6dsl_read_acc(const lsm6dsl_t *dev, lsm6dsl_3d_data_t *data) @@ -81,59 +105,35 @@ int lsm6dsl_read_acc(const lsm6dsl_t *dev, lsm6dsl_3d_data_t *data) int res; uint8_t tmp; - i2c_acquire(dev->params.i2c); - i2c_read_reg(dev->params.i2c, dev->params.addr, LSM6DSL_REG_STATUS_REG, &tmp); + i2c_acquire(BUS); + i2c_read_reg(BUS, ADDR, LSM6DSL_REG_STATUS_REG, &tmp); DEBUG("lsm6dsl status: %x\n", tmp); - res = i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTX_L_XL, &tmp); + res = i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTX_L_XL, &tmp); data->x = tmp; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTX_H_XL, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTX_H_XL, &tmp); data->x |= tmp << 8; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTY_L_XL, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTY_L_XL, &tmp); data->y = tmp; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTY_H_XL, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTY_H_XL, &tmp); data->y |= tmp << 8; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTZ_L_XL, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTZ_L_XL, &tmp); data->z = tmp; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTZ_H_XL, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTZ_H_XL, &tmp); data->z |= tmp << 8; - i2c_release(dev->params.i2c); + i2c_release(BUS); if (res < 6) { - DEBUG("[!!failed!!]\n"); - return -1; - } - DEBUG("[done]\n"); - - float range; - switch (dev->params.acc_fs) { - case LSM6DSL_ACC_FS_2G: - range = 2000.0; - break; - case LSM6DSL_ACC_FS_4G: - range = 4000.0; - break; - case LSM6DSL_ACC_FS_8G: - range = 8000.0; - break; - case LSM6DSL_ACC_FS_16G: - range = 16000.0; - break; - default: - return -1; + DEBUG("[ERROR] lsm6dsl_read_acc\n"); + return -LSM6DSL_ERROR_BUS; } - data->x = (data->x * range) / INT16_MAX; - data->y = (data->y * range) / INT16_MAX; - data->z = (data->z * range) / INT16_MAX; + assert(dev->params.acc_fs < LSM6DSL_ACC_FS_MAX); + data->x = ((int32_t)data->x * range_acc[dev->params.acc_fs]) / INT16_MAX; + data->y = ((int32_t)data->y * range_acc[dev->params.acc_fs]) / INT16_MAX; + data->z = ((int32_t)data->z * range_acc[dev->params.acc_fs]) / INT16_MAX; - return 0; + return LSM6DSL_OK; } int lsm6dsl_read_gyro(const lsm6dsl_t *dev, lsm6dsl_3d_data_t *data) @@ -141,78 +141,57 @@ int lsm6dsl_read_gyro(const lsm6dsl_t *dev, lsm6dsl_3d_data_t *data) int res; uint8_t tmp; - i2c_acquire(dev->params.i2c); - i2c_read_reg(dev->params.i2c, dev->params.addr, LSM6DSL_REG_STATUS_REG, &tmp); + i2c_acquire(BUS); + i2c_read_reg(BUS, ADDR, LSM6DSL_REG_STATUS_REG, &tmp); DEBUG("lsm6dsl status: %x\n", tmp); - res = i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTX_L_G, &tmp); + res = i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTX_L_G, &tmp); data->x = tmp; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTX_H_G, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTX_H_G, &tmp); data->x |= tmp << 8; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTY_L_G, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTY_L_G, &tmp); data->y = tmp; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTY_H_G, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTY_H_G, &tmp); data->y |= tmp << 8; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTZ_L_G, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTZ_L_G, &tmp); data->z = tmp; - res += i2c_read_reg(dev->params.i2c, dev->params.addr, - LSM6DSL_REG_OUTZ_H_G, &tmp); + res += i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUTZ_H_G, &tmp); data->z |= tmp << 8; - i2c_release(dev->params.i2c); + i2c_release(BUS); if (res < 6) { - DEBUG("[!!failed!!]\n"); - return -1; - } - DEBUG("[done]\n"); - - float range; - switch (dev->params.acc_fs) { - case LSM6DSL_GYRO_FS_245DPS: - range = 2450.0; - break; - case LSM6DSL_GYRO_FS_500DPS: - range = 5000.0; - break; - case LSM6DSL_GYRO_FS_1000DPS: - range = 10000.0; - break; - case LSM6DSL_GYRO_FS_2000DPS: - range = 20000.0; - break; - default: - return -1; + DEBUG("[ERROR] lsm6dsl_read_gyro\n"); + return -LSM6DSL_ERROR_BUS; } - data->x = (data->x * range) / INT16_MAX; - data->y = (data->y * range) / INT16_MAX; - data->z = (data->z * range) / INT16_MAX; + assert(dev->params.gyro_fs < LSM6DSL_GYRO_FS_MAX); + data->x = ((int32_t)data->x * range_gyro[dev->params.gyro_fs]) / INT16_MAX; + data->y = ((int32_t)data->y * range_gyro[dev->params.gyro_fs]) / INT16_MAX; + data->z = ((int32_t)data->z * range_gyro[dev->params.gyro_fs]) / INT16_MAX; - return 0; + return LSM6DSL_OK; } int lsm6dsl_read_temp(const lsm6dsl_t *dev, int16_t *data) { - int res; uint8_t tmp; - - i2c_acquire(dev->params.i2c); - res = i2c_read_reg(dev->params.i2c, dev->params.addr, LSM6DSL_REG_OUT_TEMP_L, &tmp); - *data = tmp; - - res += i2c_read_reg(dev->params.i2c, dev->params.addr, LSM6DSL_REG_OUT_TEMP_H, &tmp); - *data |= tmp << 8; - - i2c_release(dev->params.i2c); - - if (res < 2) { - return -1; + uint16_t traw; + /* read raw temperature */ + i2c_acquire(BUS); + if (i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUT_TEMP_L, &tmp) != 1) { + i2c_release(BUS); + return -LSM6DSL_ERROR_BUS; + } + traw = tmp; + if (i2c_read_reg(BUS, ADDR, LSM6DSL_REG_OUT_TEMP_H, &tmp) != 1) { + i2c_release(BUS); + return -LSM6DSL_ERROR_BUS; } + traw |= (uint16_t)tmp << 8; + i2c_release(BUS); + /* convert temperature to degC x 100 */ + traw += LSM6DSL_TEMP_OFFSET; + *data = (int16_t)(((int32_t)traw * 100) / 256); - return 0; + return LSM6DSL_OK; } diff --git a/drivers/lsm6dsl/lsm6dsl_saul.c b/drivers/lsm6dsl/lsm6dsl_saul.c index 4b86e6a7476184c70a301bc51bf22e898931110b..0894cc19644c90180d1acfb9981d7e7075ca174c 100644 --- a/drivers/lsm6dsl/lsm6dsl_saul.c +++ b/drivers/lsm6dsl/lsm6dsl_saul.c @@ -8,10 +8,16 @@ */ /** + * @ingroup drivers_lsm6dsl + * @{ + * * @file * @brief SAUL implementation for the LSM6DSL 3D accelerometer/gyroscope. * * @author Vincent Dupont <vincent@otakeys.com> + * @author Sebastian Meiling <s@mlng.net> + * + * @} */ #include "lsm6dsl.h" @@ -43,6 +49,17 @@ static int read_gyro(const void *dev, phydat_t *res) return 3; } +static int read_temp(const void *dev, phydat_t *res) +{ + if (lsm6dsl_read_temp((const lsm6dsl_t *)dev, (int16_t *)&res[0]) < 0) { + return -ECANCELED; + } + res->scale = -2; + res->unit = UNIT_TEMP_C; + + return 1; +} + const saul_driver_t lsm6dsl_saul_acc_driver = { .read = read_acc, .write = saul_notsup, @@ -54,3 +71,9 @@ const saul_driver_t lsm6dsl_saul_gyro_driver = { .write = saul_notsup, .type = SAUL_SENSE_GYRO, }; + +const saul_driver_t lsm6dsl_saul_temp_driver = { + .read = read_temp, + .write = saul_notsup, + .type = SAUL_SENSE_TEMP, +}; diff --git a/sys/auto_init/saul/auto_init_lsm6dsl.c b/sys/auto_init/saul/auto_init_lsm6dsl.c index d35beb6c35c7c875c00e43a4bfbbc8ff8f4bf9be..91b64551329bd3a0062ce187562ff97bbbd88b61 100644 --- a/sys/auto_init/saul/auto_init_lsm6dsl.c +++ b/sys/auto_init/saul/auto_init_lsm6dsl.c @@ -39,7 +39,7 @@ static lsm6dsl_t lsm6dsl_devs[LSM6DSL_NUM]; /** * @brief Memory for the SAUL registry entries */ -static saul_reg_t saul_entries[LSM6DSL_NUM * 2]; +static saul_reg_t saul_entries[LSM6DSL_NUM * 3]; /** * @brief Reference the driver structs @@ -47,6 +47,7 @@ static saul_reg_t saul_entries[LSM6DSL_NUM * 2]; */ extern saul_driver_t lsm6dsl_saul_acc_driver; extern saul_driver_t lsm6dsl_saul_gyro_driver; +extern saul_driver_t lsm6dsl_saul_temp_driver; /** @} */ @@ -61,14 +62,18 @@ void auto_init_lsm6dsl(void) continue; } - saul_entries[(i * 2)].dev = &(lsm6dsl_devs[i]); - saul_entries[(i * 2)].name = lsm6dsl_saul_info[i].name; - saul_entries[(i * 2)].driver = &lsm6dsl_saul_acc_driver; - saul_reg_add(&(saul_entries[(i * 2)])); - saul_entries[(i * 2) + 1].dev = &(lsm6dsl_devs[i]); - saul_entries[(i * 2) + 1].name = lsm6dsl_saul_info[i].name; - saul_entries[(i * 2) + 1].driver = &lsm6dsl_saul_gyro_driver; - saul_reg_add(&(saul_entries[(i * 2) + 1])); + saul_entries[(i * 3)].dev = &(lsm6dsl_devs[i]); + saul_entries[(i * 3)].name = lsm6dsl_saul_info[i].name; + saul_entries[(i * 3)].driver = &lsm6dsl_saul_acc_driver; + saul_reg_add(&(saul_entries[(i * 3)])); + saul_entries[(i * 3) + 1].dev = &(lsm6dsl_devs[i]); + saul_entries[(i * 3) + 1].name = lsm6dsl_saul_info[i].name; + saul_entries[(i * 3) + 1].driver = &lsm6dsl_saul_gyro_driver; + saul_reg_add(&(saul_entries[(i * 3) + 1])); + saul_entries[(i * 3) + 2].dev = &(lsm6dsl_devs[i]); + saul_entries[(i * 3) + 2].name = lsm6dsl_saul_info[i].name; + saul_entries[(i * 3) + 2].driver = &lsm6dsl_saul_temp_driver; + saul_reg_add(&(saul_entries[(i * 3) + 2])); } } diff --git a/tests/driver_lsm6dsl/README.md b/tests/driver_lsm6dsl/README.md new file mode 100644 index 0000000000000000000000000000000000000000..3d01dfa10013bad4a3bd28d7d37fe6495d531f3b --- /dev/null +++ b/tests/driver_lsm6dsl/README.md @@ -0,0 +1,10 @@ +# About +This is a manual test application for the ST LSM6DSL sensor driver. + +# Usage + +After successful initialization, the sensor reads the accelerometer, gyroscope, +and temperature values every 500ms and prints them to the STDOUT. If device +initialization fails the tests exits with 1, otherwise it runs forever. + +Note: reading sensor values may fail even on successful initialization. diff --git a/tests/driver_lsm6dsl/main.c b/tests/driver_lsm6dsl/main.c index f37a0fe480b066af651fb3628ce0e1e89d28d3f3..7ea329f1780d649ae059befd7f65cb315d39c082 100644 --- a/tests/driver_lsm6dsl/main.c +++ b/tests/driver_lsm6dsl/main.c @@ -1,5 +1,6 @@ /* * Copyright (C) 2017 OTA keys S.A. + * 2017 HAW Hamburg * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -7,11 +8,16 @@ */ /** + * @ingroup tests + * @{ + * * @file * @brief Test application for the LSM6DSL accelerometer/gyroscope driver. * * @author Vincent Dupont <vincent@otakeys.com> + * @author Sebastian Meiling <s@mlng.net> * + * @} */ #include <stdio.h> @@ -20,7 +26,7 @@ #include "lsm6dsl.h" #include "lsm6dsl_params.h" -#define SLEEP (100 * 1000U) +#define SLEEP (500UL * US_PER_MS) int main(void) { @@ -29,42 +35,42 @@ int main(void) lsm6dsl_3d_data_t mag_value; lsm6dsl_3d_data_t acc_value; - puts("LSM6DSL test application\n"); + puts("LSM6DSL test application"); printf("Initializing LSM6DSL sensor at I2C_%i... ", lsm6dsl_params->i2c); - if (lsm6dsl_init(&dev, lsm6dsl_params) == 0) { - puts("[OK]\n"); - } - else { - puts("[Failed]"); + if (lsm6dsl_init(&dev, lsm6dsl_params) != LSM6DSL_OK) { + puts("[ERROR]"); return 1; } + puts("[SUCCESS]\n"); while (1) { - if (lsm6dsl_read_acc(&dev, &acc_value) == 0) { + if (lsm6dsl_read_acc(&dev, &acc_value) == LSM6DSL_OK) { printf("Accelerometer x: %i y: %i z: %i\n", acc_value.x, acc_value.y, acc_value.z); } else { - puts("\nFailed reading accelerometer values\n"); - } - if (lsm6dsl_read_temp(&dev, &temp_value) == 0) { - printf("Temperature value: %i degrees\n", temp_value); - } - else { - puts("\nFailed reading value\n"); + puts("[ERROR] reading accelerometer!\n"); } - if (lsm6dsl_read_gyro(&dev, &mag_value) == 0) { + if (lsm6dsl_read_gyro(&dev, &mag_value) == LSM6DSL_OK) { printf("Gyroscope x: %i y: %i z: %i\n", mag_value.x, mag_value.y, mag_value.z); } else { - puts("\nFailed reading Gyroscope values\n"); + puts("[ERROR] reading gyroscope!\n"); + } + + if (lsm6dsl_read_temp(&dev, &temp_value) == LSM6DSL_OK) { + printf("Temperature [in °C x 100]: %i \n", temp_value); + } + else { + puts("[ERROR] reading temperature!\n"); } + puts(""); xtimer_usleep(SLEEP); }