1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 05:12:57 +01:00

Merge pull request #7288 from smlng/enh/driver/lsm6dsl

drivers: enhance lsm6dsl
This commit is contained in:
Alexandre Abadie 2017-07-03 17:34:59 +02:00 committed by GitHub
commit f6f9ba157d
8 changed files with 350 additions and 279 deletions

View File

@ -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
*
* @param[in] dev device to read
* @param[out] data temperature value
* @note To avoid floating point data types but still provide high resolution
* for temperature readings, resulting values are scale by factor 100.
*
* @return 0 on success
*
* @param[in] dev device to read
* @param[out] data temperature value, in °C x 100
*
* @return LSM6DSL_OK on success
* @return < 0 on error
*/
int lsm6dsl_read_temp(const lsm6dsl_t *dev, int16_t *data);

View File

@ -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

View File

@ -9,12 +9,13 @@
/**
* @ingroup drivers_lsm6dsl
*
* @{
*
* @file
* @brief Default configuration for LSM6DSL devices
*
* @author Vincent Dupont <vincent@otakeys.com>
*
*/
#ifndef LSM6DSL_PARAMS_H

View File

@ -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(5000);
xtimer_usleep(LSM6DSL_BOOT_WAIT);
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 (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;
}
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;
}

View File

@ -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,
};

View File

@ -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]));
}
}

View File

@ -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.

View File

@ -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);
}