

12 changed files with 846 additions and 0 deletions
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2017 OTA keys S.A. |
||||
* |
||||
* 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 |
||||
* directory for more details. |
||||
* |
||||
*/ |
||||
|
||||
/**
|
||||
* @defgroup drivers_lsm6dsl LSM6DSL 3D accelerometer/gyroscope |
||||
* @ingroup drivers_sensors |
||||
* @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> |
||||
*/ |
||||
|
||||
#ifndef LSM6DSL_H |
||||
#define LSM6DSL_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#include "periph/i2c.h" |
||||
|
||||
/** Data rate */ |
||||
enum { |
||||
LSM6DSL_DATA_RATE_POWER_DOWN = 0x0, |
||||
LSM6DSL_DATA_RATE_1_6HZ = 0xB, |
||||
LSM6DSL_DATA_RATE_12_5HZ = 0x1, |
||||
LSM6DSL_DATA_RATE_26HZ = 0x2, |
||||
LSM6DSL_DATA_RATE_52HZ = 0x3, |
||||
LSM6DSL_DATA_RATE_104HZ = 0x4, |
||||
LSM6DSL_DATA_RATE_208HZ = 0x5, |
||||
LSM6DSL_DATA_RATE_416HZ = 0x6, |
||||
LSM6DSL_DATA_RATE_833HZ = 0x7, |
||||
LSM6DSL_DATA_RATE_1_66KHZ = 0x8, |
||||
LSM6DSL_DATA_RATE_3_33KHZ = 0x9, |
||||
LSM6DSL_DATA_RATE_6_66KHZ = 0xa, |
||||
}; |
||||
|
||||
/** Decimation */ |
||||
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, |
||||
}; |
||||
|
||||
/** Accelerometer full scale */ |
||||
enum { |
||||
LSM6DSL_ACC_FS_2G = 0, |
||||
LSM6DSL_ACC_FS_4G = 2, |
||||
LSM6DSL_ACC_FS_8G = 3, |
||||
LSM6DSL_ACC_FS_16G = 1, |
||||
}; |
||||
|
||||
/** 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 driver parameters */ |
||||
typedef struct { |
||||
i2c_t i2c; /**< i2c bus */ |
||||
uint8_t addr; /**< i2c address */ |
||||
uint8_t acc_odr; /**< accelerometer output data rate */ |
||||
uint8_t gyro_odr; /**< gyroscope output data rate */ |
||||
uint8_t acc_fs; /**< accelerometer full scale */ |
||||
uint8_t gyro_fs; /**< gyroscope full scale */ |
||||
uint8_t acc_decimation; /**< accelerometer decimation */ |
||||
uint8_t gyro_decimation; /**< gyroscope decimation */ |
||||
} lsm6dsl_params_t; |
||||
|
||||
/** LSM6DSL device descriptor */ |
||||
typedef struct { |
||||
lsm6dsl_params_t params; /**< driver parameters */ |
||||
} lsm6dsl_t; |
||||
|
||||
/** 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 Initialize a LSM6DSL device |
||||
* |
||||
* @param[in] dev device to initialize |
||||
* @param[in] params driver parameters |
||||
* |
||||
* @return 0 on success |
||||
* @return < 0 on error |
||||
*/ |
||||
int lsm6dsl_init(lsm6dsl_t *dev, const lsm6dsl_params_t *params); |
||||
|
||||
/**
|
||||
* @brief Read accelerometer data |
||||
* |
||||
* @param[in] dev device to read |
||||
* @param[out] data accelerometer values |
||||
* |
||||
* @return 0 on success |
||||
* @return < 0 on error |
||||
*/ |
||||
int lsm6dsl_read_acc(lsm6dsl_t *dev, lsm6dsl_3d_data_t *data); |
||||
|
||||
/**
|
||||
* @brief Read gyroscope data |
||||
* |
||||
* @param[in] dev device to read |
||||
* @param[out] data gyroscope values |
||||
* |
||||
* @return 0 on success |
||||
* @return < 0 on error |
||||
*/ |
||||
int lsm6dsl_read_gyro(lsm6dsl_t *dev, lsm6dsl_3d_data_t *data); |
||||
|
||||
/**
|
||||
* @brief Read temperature data |
||||
* |
||||
* @param[in] dev device to read |
||||
* @param[out] data temperature value |
||||
* |
||||
* @return 0 on success |
||||
* @return < 0 on error |
||||
*/ |
||||
int lsm6dsl_read_temp(lsm6dsl_t *dev, int16_t *data); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* LSM6DSL_H */ |
||||
/** @} */ |
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2017 OTA keys S.A. |
||||
* |
||||
* 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 |
||||
* directory for more details. |
||||
* |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup drivers_lsm6dsl |
||||
* |
||||
* @{ |
||||
* @file |
||||
* @brief Internal configuration for LSM6DSL devices |
||||
* |
||||
* @author Vincent Dupont <vincent@otakeys.com> |
||||
*/ |
||||
|
||||
#ifndef LSM6DSL_INTERNAL_H |
||||
#define LSM6DSL_INTERNAL_H |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @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) |
||||
/** @} */ |
||||
|
||||
/** WHO_AM_I value */ |
||||
#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_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_CTRL3_GYRO_DEC_SHIFT (3) |
||||
/** @} */ |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* LSM6DS_LINTERNAL_H */ |
||||
/** @} */ |
@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2017 OTA keys S.A. |
||||
* |
||||
* 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 |
||||
* directory for more details. |
||||
* |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup drivers_lsm6dsl |
||||
* |
||||
* @{ |
||||
* @file |
||||
* @brief Default configuration for LSM6DSL devices |
||||
* |
||||
* @author Vincent Dupont <vincent@otakeys.com> |
||||
*/ |
||||
|
||||
#ifndef LSM6DSL_PARAMS_H |
||||
#define LSM6DSL_PARAMS_H |
||||
|
||||
#include "board.h" |
||||
#include "lsm6dsl.h" |
||||
#include "saul_reg.h" |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/**
|
||||
* @brief Set default configuration parameters |
||||
* @{ |
||||
*/ |
||||
#ifndef LSM6DSL_PARAM_I2C |
||||
#define LSM6DSL_PARAM_I2C I2C_DEV(0) |
||||
#endif |
||||
#ifndef LSM6DSL_PARAM_ADDR |
||||
#define LSM6DSL_PARAM_ADDR (0x6B) /* (0x6A) */ |
||||
#endif |
||||
#ifndef LSM6DSL_PARAM_ACC_ODR |
||||
#define LSM6DSL_PARAM_ACC_ODR (LSM6DSL_DATA_RATE_52HZ) |
||||
#endif |
||||
#ifndef LSM6DSL_PARAM_GYRO_ODR |
||||
#define LSM6DSL_PARAM_GYRO_ODR (LSM6DSL_DATA_RATE_52HZ) |
||||
#endif |
||||
#ifndef LSM6DSL_PARAM_ACC_FS |
||||
#define LSM6DSL_PARAM_ACC_FS (LSM6DSL_ACC_FS_2G) |
||||
#endif |
||||
#ifndef LSM6DSL_PARAM_GYRO_FS |
||||
#define LSM6DSL_PARAM_GYRO_FS (LSM6DSL_GYRO_FS_245DPS) |
||||
#endif |
||||
#ifndef LSM6DSL_PARAM_ACC_FIFO_DEC |
||||
#define LSM6DSL_PARAM_ACC_FIFO_DEC (LSM6DSL_DECIMATION_NO) |
||||
#endif |
||||
#ifndef LSM6DSL_PARAM_GYRO_FIFO_DEC |
||||
#define LSM6DSL_PARAM_GYRO_FIFO_DEC (LSM6DSL_DECIMATION_NO) |
||||
#endif |
||||
|
||||
#define LSM6DSL_PARAMS_DEFAULT { .i2c = LSM6DSL_PARAM_I2C, \ |
||||
.addr = LSM6DSL_PARAM_ADDR, \
|
||||
.acc_odr = LSM6DSL_PARAM_ACC_ODR, \
|
||||
.gyro_odr = LSM6DSL_PARAM_GYRO_ODR, \
|
||||
.acc_fs = LSM6DSL_PARAM_ACC_FS, \
|
||||
.gyro_fs = LSM6DSL_PARAM_GYRO_FS, \
|
||||
.acc_decimation = LSM6DSL_PARAM_ACC_FIFO_DEC, \
|
||||
.gyro_decimation = LSM6DSL_PARAM_GYRO_FIFO_DEC } |
||||
/** @} */ |
||||
|
||||
/**
|
||||
* @brief Allocate some memory to store the actual configuration |
||||
*/ |
||||
static const lsm6dsl_params_t lsm6dsl_params[] = |
||||
{ |
||||
#ifdef LSM6DSL_PARAMS_CUSTOM |
||||
LSM6DSL_PARAMS_CUSTOM, |
||||
#else |
||||
LSM6DSL_PARAMS_DEFAULT, |
||||
#endif |
||||
}; |
||||
|
||||
/**
|
||||
* @brief Additional meta information to keep in the SAUL registry |
||||
*/ |
||||
static const saul_reg_info_t lsm6dsl_saul_info[] = |
||||
{ |
||||
{ .name = "lsm6dsl" } |
||||
}; |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* LSM6DSL_PARAMS_H */ |
||||
/** @} */ |
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (C) 2017 OTA keys S.A. |
||||
* |
||||
* 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 |
||||
* directory for more details. |
||||
* |
||||
*/ |
||||
|
||||
/**
|
||||
* @file |
||||
* @brief Device driver implementation for the LSM6DSL 3D accelerometer/gyroscope. |
||||
* |
||||
* @author Vincent Dupont <vincent@otakeys.com> |
||||
*/ |
||||
|
||||
#include "xtimer.h" |
||||
|
||||
#include "lsm6dsl.h" |
||||
#include "lsm6dsl_internal.h" |
||||
|
||||
#define ENABLE_DEBUG (1) |
||||
#include "debug.h" |
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b)) |
||||
|
||||
int lsm6dsl_init(lsm6dsl_t *dev, const lsm6dsl_params_t *params) |
||||
{ |
||||
uint8_t tmp; |
||||
int res; |
||||
|
||||
assert(dev && params); |
||||
|
||||
dev->params = *params; |
||||
|
||||
i2c_acquire(dev->params.i2c); |
||||
i2c_init_master(dev->params.i2c, I2C_SPEED_NORMAL); |
||||
|
||||
/* Reboot */ |
||||
i2c_write_reg(dev->params.i2c, dev->params.addr, |
||||
LSM6DSL_REG_CTRL3_C, LSM6DSL_CTRL3_C_BOOT); |
||||
|
||||
xtimer_usleep(5000); |
||||
|
||||
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; |
||||
} |
||||
|
||||
/* 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))); |
||||
/* 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))); |
||||
|
||||
/* 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); |
||||
|
||||
i2c_release(dev->params.i2c); |
||||
|
||||
if (res < 4) { |
||||
DEBUG("[!!failed!!] config\n"); |
||||
return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int lsm6dsl_read_acc(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); |
||||
DEBUG("lsm6dsl status: %x\n", tmp); |
||||
|
||||
res = i2c_read_reg(dev->params.i2c, dev->params.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); |
||||
data->x |= tmp << 8; |
||||
res += i2c_read_reg(dev->params.i2c, dev->params.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); |
||||
data->y |= tmp << 8; |
||||
res += i2c_read_reg(dev->params.i2c, dev->params.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); |
||||
data->z |= tmp << 8; |
||||
i2c_release(dev->params.i2c); |
||||
|
||||
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; |
||||
} |
||||
|
||||
data->x = (data->x * range) / INT16_MAX; |
||||
data->y = (data->y * range) / INT16_MAX; |
||||
data->z = (data->z * range) / INT16_MAX; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int lsm6dsl_read_gyro(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); |
||||
DEBUG("lsm6dsl status: %x\n", tmp); |
||||
|
||||
res = i2c_read_reg(dev->params.i2c, dev->params.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); |
||||
data->x |= tmp << 8; |
||||
res += i2c_read_reg(dev->params.i2c, dev->params.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); |
||||
data->y |= tmp << 8; |
||||
res += i2c_read_reg(dev->params.i2c, dev->params.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); |
||||
data->z |= tmp << 8; |
||||
i2c_release(dev->params.i2c); |
||||
|
||||
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; |
||||
} |
||||
|
||||
data->x = (data->x * range) / INT16_MAX; |
||||
data->y = (data->y * range) / INT16_MAX; |
||||
data->z = (data->z * range) / INT16_MAX; |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
int lsm6dsl_read_temp(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; |
||||
} |
||||
|
||||
return 0; |
||||
} |
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2017 OTA keys S.A. |
||||
* |
||||
* 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 |
||||
* directory for more details. |
||||
* |
||||
*/ |
||||
|
||||
/**
|
||||
* @file |
||||
* @brief SAUL implementation for the LSM6DSL 3D accelerometer/gyroscope. |
||||
* |
||||
* @author Vincent Dupont <vincent@otakeys.com> |
||||
*/ |
||||
|
||||
#include "lsm6dsl.h" |
||||
#include "saul.h" |
||||
|
||||
static int read_acc(void *dev, phydat_t *res) |
||||
{ |
||||
int ret = lsm6dsl_read_acc(dev, (lsm6dsl_3d_data_t *)res); |
||||
if (ret < 0) { |
||||
return -ECANCELED; |
||||
} |
||||
|
||||
res->scale = -3; |
||||
res->unit = UNIT_G; |
||||
|
||||
return 3; |
||||
} |
||||
|
||||
static int read_gyro(void *dev, phydat_t *res) |
||||
{ |
||||
int ret = lsm6dsl_read_gyro(dev, (lsm6dsl_3d_data_t *)res); |
||||
if (ret < 0) { |
||||
return -ECANCELED; |
||||
} |
||||
|
||||
res->scale = -1; |
||||
res->unit = UNIT_DPS; |
||||
|
||||
return 3; |
||||
} |
||||
|
||||
const saul_driver_t lsm6dsl_saul_acc_driver = { |
||||
.read = read_acc, |
||||
.write = saul_notsup, |
||||
.type = SAUL_SENSE_ACCEL, |
||||
}; |
||||
|
||||
|
||||
const saul_driver_t lsm6dsl_saul_gyro_driver = { |
||||
.read = read_gyro, |
||||
.write = saul_notsup, |
||||
.type = SAUL_SENSE_GYRO, |
||||
}; |
@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (C) 2017 OTA keys S.A. |
||||
* |
||||
* 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 |
||||
* directory for more details. |
||||
* |
||||
*/ |
||||
|
||||
/*
|
||||
* @ingroup auto_init_saul |
||||
* @{ |
||||
* |
||||
* @file |
||||
* @brief Auto initialization of LSM6DSL accelerometer/gyroscope sensors |
||||
* |
||||
* @author Vincent Dupont <vincent@otakeys.com |
||||
* |
||||
* @} |
||||
*/ |
||||
|
||||
#ifdef MODULE_LSM6DSL |
||||
|
||||
#include "log.h" |
||||
#include "saul_reg.h" |
||||
#include "lsm6dsl.h" |
||||
#include "lsm6dsl_params.h" |
||||
|
||||
/**
|
||||
* @brief Define the number of configured sensors |
||||
*/ |
||||
#define LSM6DSL_NUM (sizeof(lsm6dsl_params)/sizeof(lsm6dsl_params[0])) |
||||
|
||||
/**
|
||||
* @brief Allocate memory for the device descriptors |
||||
*/ |
||||
static lsm6dsl_t lsm6dsl_devs[LSM6DSL_NUM]; |
||||
|
||||
/**
|
||||
* @brief Memory for the SAUL registry entries |
||||
*/ |
||||
static saul_reg_t saul_entries[LSM6DSL_NUM * 2]; |
||||
|
||||
/**
|
||||
* @brief Reference the driver structs |
||||
* @{ |
||||
*/ |
||||
extern saul_driver_t lsm6dsl_saul_acc_driver; |
||||
extern saul_driver_t lsm6dsl_saul_gyro_driver; |
||||
/** @} */ |
||||
|
||||
|
||||
void auto_init_lsm6dsl(void) |
||||
{ |
||||
for (unsigned int i = 0; i < LSM6DSL_NUM; i++) { |
||||
LOG_DEBUG("[auto_init_saul] initializing lsm6dsl #%u\n", i); |
||||
|
||||
int res = lsm6dsl_init(&lsm6dsl_devs[i], &lsm6dsl_params[i]); |
||||
if (res < 0) { |
||||
LOG_ERROR("[auto_init_saul] error initializing lsm6dsl #%u\n", i); |
||||
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])); |
||||
} |
||||
} |
||||
|
||||
#else |
||||
typedef int dont_be_pedantic; |
||||
#endif /* MODULE_LSM6DSL */ |
@ -0,0 +1,9 @@
|
||||
APPLICATION = driver_lsm6dsl
|
||||
include ../Makefile.tests_common |
||||
|
||||
FEATURES_REQUIRED = periph_i2c
|
||||
|
||||
USEMODULE += lsm6dsl
|
||||
USEMODULE += xtimer
|
||||
|
||||
include $(RIOTBASE)/Makefile.include |
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2017 OTA keys S.A. |
||||
* |
||||
* 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 |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @file |
||||
* @brief Test application for the LSM6DSL accelerometer/gyroscope driver. |
||||
* |
||||
* @author Vincent Dupont <vincent@otakeys.com> |
||||
* |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
|
||||
#include "xtimer.h" |
||||
#include "lsm6dsl.h" |
||||
#include "lsm6dsl_params.h" |
||||
|
||||
#define SLEEP (100 * 1000U) |
||||
|
||||
int main(void) |
||||
{ |
||||
lsm6dsl_t dev; |
||||
int16_t temp_value; |
||||
lsm6dsl_3d_data_t mag_value; |
||||
lsm6dsl_3d_data_t acc_value; |
||||
|
||||
puts("LSM6DSL test application\n"); |
||||
printf("Initializing LSM6DSL sensor at I2C_%i... ", lsm6dsl_params->i2c); |
||||
|
||||
if (lsm6dsl_init(&dev, lsm6dsl_params) == 0) { |
||||
puts("[OK]\n"); |
||||
} |
||||
else { |
||||
puts("[Failed]"); |
||||
return 1; |
||||
} |
||||
|
||||
while (1) { |
||||
if (lsm6dsl_read_acc(&dev, &acc_value) == 0) { |
||||
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"); |
||||
} |
||||
|
||||
if (lsm6dsl_read_gyro(&dev, &mag_value) == 0) { |
||||
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"); |
||||
} |
||||
|
||||
xtimer_usleep(SLEEP); |
||||
} |
||||
|
||||
return 0; |
||||
} |
Loading…
Reference in new issue