diff --git a/boards/iot-lab_M3/include/periph_conf.h b/boards/iot-lab_M3/include/periph_conf.h index 6dca7900cb..65a14ec82b 100644 --- a/boards/iot-lab_M3/include/periph_conf.h +++ b/boards/iot-lab_M3/include/periph_conf.h @@ -168,10 +168,10 @@ extern "C" { #define GPIO_1_EXTI_CFG() (AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI8_PA) #define GPIO_1_IRQ EXTI9_5_IRQn /* GPIO channel 2 config */ -#define GPIO_2_PORT GPIOA +#define GPIO_2_PORT GPIOB #define GPIO_2_PIN 12 -#define GPIO_2_CLKEN() (RCC->APB2ENR |= RCC_APB2ENR_IOPAEN) -#define GPIO_2_EXTI_CFG() (AFIO->EXTICR[3] |= AFIO_EXTICR4_EXTI12_PA) +#define GPIO_2_CLKEN() (RCC->APB2ENR |= RCC_APB2ENR_IOPBEN) +#define GPIO_2_EXTI_CFG() (AFIO->EXTICR[3] |= AFIO_EXTICR4_EXTI12_PB) #define GPIO_2_IRQ EXTI15_10_IRQn /* GPIO channel 3 config */ #define GPIO_3_PORT GPIOB @@ -204,11 +204,11 @@ extern "C" { #define GPIO_7_EXTI_CFG() (AFIO->EXTICR[2] |= AFIO_EXTICR3_EXTI11_PC) #define GPIO_7_IRQ EXTI15_10_IRQn /* GPIO channel 8 config */ -#define GPIO_8_PORT GPIOA -#define GPIO_8_PIN 5 -#define GPIO_8_CLKEN() (RCC->APB2ENR |= RCC_APB2ENR_IOPAEN) -#define GPIO_8_EXTI_CFG() (AFIO->EXTICR[1] |= AFIO_EXTICR2_EXTI5_PA) -#define GPIO_8_IRQ EXTI9_5_IRQn +#define GPIO_8_PORT GPIOB +#define GPIO_8_PIN 2 +#define GPIO_8_CLKEN() (RCC->APB2ENR |= RCC_APB2ENR_IOPBEN) +#define GPIO_8_EXTI_CFG() (AFIO->EXTICR[1] |= AFIO_EXTICR1_EXTI2_PB) +#define GPIO_8_IRQ EXTI2_IRQn /* GPIO channel 9 config */ #define GPIO_9_PORT GPIOA #define GPIO_9_PIN 6 diff --git a/drivers/Makefile b/drivers/Makefile index f5c70edc18..24e345dc35 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -55,5 +55,8 @@ endif ifneq (,$(filter netdev_802154,$(USEMODULE))) DIRS += netdev/802154 endif +ifneq (,$(filter lsm303dlhc,$(USEMODULE))) + DIRS += lsm303dlhc +endif include $(RIOTBASE)/Makefile.base diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 6dce21a4cb..6f25c778a2 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -16,3 +16,6 @@ endif ifneq (,$(filter lps331ap,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/lps331ap/include endif +ifneq (,$(filter lsm303dlhc,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/lsm303dlhc/include +endif diff --git a/drivers/include/lsm303dlhc.h b/drivers/include/lsm303dlhc.h new file mode 100644 index 0000000000..1425135f03 --- /dev/null +++ b/drivers/include/lsm303dlhc.h @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * 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 driver_lsm303dlhc LSM303DLHC 3D accelerometer/magnetometer + * @ingroup drivers + * @brief Device driver for the LSM303DLHC 3D accelerometer/magnetometer + * @{ + * + * @file + * @brief Device driver interface for the LSM303DLHC 3D accelerometer/magnetometer + * + * @author Thomas Eichinger + */ + +#ifndef __LSM303DLHC_H +#define __LSM303DLHC_H + +#include +#include "periph/i2c.h" +#include "periph/gpio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The sensors default I2C address + */ +#define LSM303DLHC_ACC_DEFAULT_ADDRESS (0x19) +#define LSM303DLHC_MAG_DEFAULT_ADDRESS (0x1e) + +/** + * @brief 3d data container + */ +typedef struct { + int16_t x_axis; + int16_t y_axis; + int16_t z_axis; +} lsm303dlhc_3d_data_t; + +/** + * @brief Device descriptor for LSM303DLHC sensors + */ +typedef struct { + i2c_t i2c; /**< I2C device */ + uint8_t acc_address; /**< accelerometer's I2C address */ + uint8_t mag_address; /**< magnetometer's I2C address */ +} lsm303dlhc_t; + +/** + * @brief Possible accelerometer sample rates + */ +typedef enum { + LSM303DLHC_ACC_SAMPLE_RATE_1HZ = 0x10, /**< 1Hz sample rate */ + LSM303DLHC_ACC_SAMPLE_RATE_10HZ = 0x20, /**< 10Hz sample rate */ + LSM303DLHC_ACC_SAMPLE_RATE_25HZ = 0x30, /**< 25Hz sample rate */ + LSM303DLHC_ACC_SAMPLE_RATE_50HZ = 0x40, /**< 50Hz sample rate */ + LSM303DLHC_ACC_SAMPLE_RATE_100HZ = 0x50, /**< 100Hz sample rate */ + LSM303DLHC_ACC_SAMPLE_RATE_200HZ = 0x60, /**< 200Hz sample rate */ + LSM303DLHC_ACC_SAMPLE_RATE_400HZ = 0x70, /**< 400Hz sample rate */ + LSM303DLHC_ACC_SAMPLE_RATE_1620HZ = 0x80, /**< 1620Hz sample rate */ + LSM303DLHC_ACC_SAMPLE_RATE_N1344HZ_L5376HZ = 0x90 /**< 1344Hz normal mode, + * 5376Hz low power mode */ +} lsm303dlhc_acc_sample_rate_t; + +/** + * @brief Possible accelerometer scales + */ +typedef enum { + LSM303DLHC_ACC_SCALE_2G = 0x00, /**< +- 2g range */ + LSM303DLHC_ACC_SCALE_4G = 0x10, /**< +- 4g range */ + LSM303DLHC_ACC_SCALE_8G = 0x20, /**< +- 8g range */ + LSM303DLHC_ACC_SCALE_16G = 0x30, /**< +-16g range */ +} lsm303dlhc_acc_scale_t; + +/** + * @brief Possible magnetometer sample rates + */ +typedef enum { + LSM303DLHC_MAG_SAMPLE_RATE_0_75HZ = 0x00, /**< 0.75Hz sample rate */ + LSM303DLHC_MAG_SAMPLE_RATE_1_5HZ = 0x04, /**< 1.5 Hz sample rate */ + LSM303DLHC_MAG_SAMPLE_RATE_3HZ = 0x08, /**< 3 Hz sample rate */ + LSM303DLHC_MAG_SAMPLE_RATE_7_5HZ = 0x0c, /**< 7.5 Hz sample rate */ + LSM303DLHC_MAG_SAMPLE_RATE_15HZ = 0x10, /**< 15 Hz sample rate */ + LSM303DLHC_MAG_SAMPLE_RATE_30HZ = 0x14, /**< 30 Hz sample rate */ + LSM303DLHC_MAG_SAMPLE_RATE_75HZ = 0x18, /**< 75 Hz sample rate */ + LSM303DLHC_MAG_SAMPLE_RATE_220HZ = 0x1c, /**< 220 Hz sample rate */ +} lsm303dlhc_mag_sample_rate_t; + +/** + * @brief Possible magnetometer gain values + */ + typedef enum { + LSM303DLHC_MAG_GAIN_1100_980_GAUSS = 0x20, /**< 1100Gauss XYZ 980Gauss Z */ + LSM303DLHC_MAG_GAIN_855_760_GAUSS = 0x40, /**< 855Gauss XYZ 760Gauss Z */ + LSM303DLHC_MAG_GAIN_670_600_GAUSS = 0x60, /**< 670Gauss XYZ 600Gauss Z */ + LSM303DLHC_MAG_GAIN_450_400_GAUSS = 0x80, /**< 450Gauss XYZ 400Gauss Z */ + LSM303DLHC_MAG_GAIN_400_355_GAUSS = 0xa0, /**< 400Gauss XYZ 355Gauss Z */ + LSM303DLHC_MAG_GAIN_330_295_GAUSS = 0xc0, /**< 330Gauss XYZ 295Gauss Z */ + LSM303DLHC_MAG_GAIN_230_205_GAUSS = 0xe0, /**< 230Gauss XYZ 205Gauss Z */ + } lsm303dlhc_mag_gain_t; + +/** + * @brief Initialize a new LSM303DLHC device + * + * @param[in] dev device descriptor of an LSM303DLHC device + * @param[in] i2c I2C device the sensor is connected to + * @param[in] acc_pin GPIO pin connected to accelerometer + * @param[in] mag_pin GPIO pin connected to magnetometer + * @param[in] acc_address I2C address of the accelerometer + * @param[in] acc_sample_rate accelerometer sample rate + * @param[in] acc_scale accelerometer scale (from +- 2g to +-16g) + * @param[in] mag_address I2C address of the magnetometer + * @param[in] mag_sample_rate magnetometer sample rate + * @param[in] mag_gain magnetometer gain + * + * @return 0 on success + * @return -1 on error + */ +int lsm303dlhc_init(lsm303dlhc_t *dev, i2c_t i2c, gpio_t acc_pin, gpio_t mag_pin, + uint8_t acc_address, + lsm303dlhc_acc_sample_rate_t acc_sample_rate, + lsm303dlhc_acc_scale_t acc_scale, + uint8_t mag_address, + lsm303dlhc_mag_sample_rate_t mag_sample_rate, + lsm303dlhc_mag_gain_t mag_gain); + +/** + * @brief Read a accelerometer value from the sensor. + * + * @details This function provides raw acceleration data. To get the + * corresponding values in g please refer to the following + * table: + * measurement range | factor + * --------------------+--------- + * +- 2g | 1*10^-3 + * +- 4g | 2*10^-3 + * +- 8g | 4*10^-3 + * +-16g | 12*10^-3 + * + * @param[in] dev device descriptor of an LSM303DLHC device + * @param[out] data the measured accelerometer data + * + * @return 0 on success + * @return -1 on error + */ +int lsm303dlhc_read_acc(lsm303dlhc_t *dev, lsm303dlhc_3d_data_t *data); + +/** + * @brief Read a magnetometer value from the sensor. + * + * @details This function returns raw magnetic data. To get the + * corresponding values in gauss please refer to the following + * table: + * measurement range | factor + * --------------------+--------- + * +- 1.3 gauss | 1/1100 + * +- 1.9 gauss | 1/855 + * +- 2.5 gauss | 1/670 + * +- 4.0 gauss | 1/450 + * +- 4.7 gauss | 1/400 + * +- 5.6 gauss | 1/330 + * +- 8.1 gauss | 1/230 + * + * @param[in] dev device descriptor of an LSM303DLHC device + * @param[out] data the measured magnetometer data + * + * @return 0 on success + * @return -1 on error + */ +int lsm303dlhc_read_mag(lsm303dlhc_t *dev, lsm303dlhc_3d_data_t *data); + +/** + * @brief Read a temperature value from the sensor. + * + * @param[in] dev device descriptor of an LSM303DLHC device + * @param[out] value the measured temperature + * + * @return 0 on success + * @return -1 on error + */ +int lsm303dlhc_read_temp(lsm303dlhc_t *dev, int16_t *value); + +/** + * @brief Enable the given sensor + * + * @param[in] dev device descriptor of an LSM303DLHC device + * + * @return 0 on success + * @return -1 on error + */ +int lsm303dlhc_enable(lsm303dlhc_t *dev); + +/** + * @brief Disable the given sensor + * + * @param[in] dev device descriptor of an LSM303DLHC device + * + * @return 0 on success + * @return -1 on error + */ +int lsm303dlhc_disable(lsm303dlhc_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* __LSM303DLHC_H */ + /** @} */ diff --git a/drivers/lsm303dlhc/Makefile b/drivers/lsm303dlhc/Makefile new file mode 100644 index 0000000000..c3c0c2a641 --- /dev/null +++ b/drivers/lsm303dlhc/Makefile @@ -0,0 +1,3 @@ +MODULE = lsm303dlhc + +include $(RIOTBASE)/Makefile.base diff --git a/drivers/lsm303dlhc/include/lsm303dlhc-internal.h b/drivers/lsm303dlhc/include/lsm303dlhc-internal.h new file mode 100644 index 0000000000..ff4526e6a6 --- /dev/null +++ b/drivers/lsm303dlhc/include/lsm303dlhc-internal.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * 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 driver_lsm303dlhc + * + * @{ + * + * @file + * @brief Definitions for the LSM303DLHC 3D accelerometer/magnetometer + * + * @author Thomas Eichinger + */ + +#ifndef __LSM303DLHC_INTERNAL_H +#define __LSM303DLHC_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @name LSM303DLHC accelerometer registers + * @{ + */ +#define LSM303DLHC_REG_CTRL1_A (0x20) +#define LSM303DLHC_REG_CTRL2_A (0x21) +#define LSM303DLHC_REG_CTRL3_A (0x22) +#define LSM303DLHC_REG_CTRL4_A (0x23) +#define LSM303DLHC_REG_CTRL5_A (0x24) +#define LSM303DLHC_REG_CTRL6_A (0x25) +#define LSM303DLHC_REG_REFERENCE_A (0x26) +#define LSM303DLHC_REG_STATUS_A (0x27) +#define LSM303DLHC_REG_OUT_X_L_A (0x28) +#define LSM303DLHC_REG_OUT_X_H_A (0x29) +#define LSM303DLHC_REG_OUT_Y_L_A (0x2a) +#define LSM303DLHC_REG_OUT_Y_H_A (0x2b) +#define LSM303DLHC_REG_OUT_Z_L_A (0x2c) +#define LSM303DLHC_REG_OUT_Z_H_A (0x2d) +/** @} */ + +/** + * @name Masks for the LSM303DLHC CTRL1_A register + * @{ + */ +#define LSM303DLHC_CTRL1_A_XEN (0x01) +#define LSM303DLHC_CTRL1_A_YEN (0x02) +#define LSM303DLHC_CTRL1_A_ZEN (0x04) +#define LSM303DLHC_CTRL1_A_LOW_POWER (0x08) +#define LSM303DLHC_CTRL1_A_POWEROFF (0x00) +#define LSM303DLHC_CTRL1_A_1HZ (0x10) +#define LSM303DLHC_CTRL1_A_10HZ (0x20) +#define LSM303DLHC_CTRL1_A_25HZ (0x30) +#define LSM303DLHC_CTRL1_A_50HZ (0x40) +#define LSM303DLHC_CTRL1_A_100HZ (0x50) +#define LSM303DLHC_CTRL1_A_200HZ (0x60) +#define LSM303DLHC_CTRL1_A_400HZ (0x70) +#define LSM303DLHC_CTRL1_A_1620HZ (0x80) +#define LSM303DLHC_CTRL1_A_N1344HZ_L5376HZ (0x90) +/** @} */ + +/** + * @name Masks for the LSM303DLHC CTRL3_A register + * @{ + */ +#define LSM303DLHC_CTRL3_A_I1_CLICK (0x80) +#define LSM303DLHC_CTRL3_A_I1_AOI1 (0x40) +#define LSM303DLHC_CTRL3_A_I1_AOI2 (0x20) +#define LSM303DLHC_CTRL3_A_I1_DRDY1 (0x10) +#define LSM303DLHC_CTRL3_A_I1_DRDY2 (0x80) +#define LSM303DLHC_CTRL3_A_I1_WTM (0x40) +#define LSM303DLHC_CTRL3_A_I1_OVERRUN (0x20) +#define LSM303DLHC_CTRL3_A_I1_NONE (0x00) +/** @} */ + +/** + * @name Masks for the LSM303DLHC CTRL4_A register + * @{ + */ +#define LSM303DLHC_CTRL4_A_BDU (0x80) +#define LSM303DLHC_CTRL4_A_BLE (0x40) +#define LSM303DLHC_CTRL4_A_SCALE_2G (0x00) +#define LSM303DLHC_CTRL4_A_SCALE_4G (0x10) +#define LSM303DLHC_CTRL4_A_SCALE_8G (0x20) +#define LSM303DLHC_CTRL4_A_SCALE_16G (0x30) +#define LSM303DLHC_CTRL4_A_HR (0x04) +/** @} */ + +/** + * @name Masks for the LSM303DLHC STATUS_A register + * @{ + */ +#define LSM303DLHC_STATUS_ZYXOR (0x80) +#define LSM303DLHC_STATUS_ZOR (0x40) +#define LSM303DLHC_STATUS_YOR (0x20) +#define LSM303DLHC_STATUS_XOR (0x10) +#define LSM303DLHC_STATUS_ZYXDA (0x08) +#define LSM303DLHC_STATUS_ZDA (0x04) +#define LSM303DLHC_STATUS_YDA (0x02) +#define LSM303DLHC_STATUS_XDA (0x01) +/** *} */ + +/** + * @name Masks for the LSM303DLHC CTRL4_A register + * @{ + */ +#define LSM303DLHC_REG_CTRL5_A_BOOT (0x80) +#define LSM303DLHC_REG_CTRL5_A_FIFO_EN (0x40) +/** @} */ + +/** + * @name LSM303DLHC magnetometer registers + * @{ + */ +#define LSM303DLHC_REG_CRA_M (0x00) +#define LSM303DLHC_REG_CRB_M (0x01) +#define LSM303DLHC_REG_MR_M (0x02) +#define LSM303DLHC_REG_OUT_X_H_M (0x03) +#define LSM303DLHC_REG_OUT_X_L_M (0x04) +#define LSM303DLHC_REG_OUT_Y_H_M (0x05) +#define LSM303DLHC_REG_OUT_Y_L_M (0x06) +#define LSM303DLHC_REG_OUT_Z_H_M (0x07) +#define LSM303DLHC_REG_OUT_Z_L_M (0x08) +#define LSM303DLHC_REG_SR_M (0x09) +#define LSM303DLHC_REG_TEMP_OUT_L (0x32) +#define LSM303DLHC_REG_TEMP_OUT_H (0x31) +/** @} */ + +/** + * @name Masks for the LSM303DLHC CRA_REG_M register + * @{ + */ +#define LSM303DLHC_TEMP_EN (0x80) +#define LSM303DLHC_TEMP_DIS (0x00) + +#define LSM303DLHC_TEMP_SAMPLE_0_75HZ (0x00) +#define LSM303DLHC_TEMP_SAMPLE_1_5HZ (0x04) +#define LSM303DLHC_TEMP_SAMPLE_3HZ (0x08) +#define LSM303DLHC_TEMP_SAMPLE_7_5HZ (0x0c) +#define LSM303DLHC_TEMP_SAMPLE_15HZ (0x10) +#define LSM303DLHC_TEMP_SAMPLE_30HZ (0x14) +#define LSM303DLHC_TEMP_SAMPLE_75HZ (0x18) +#define LSM303DLHC_TEMP_SAMPLE_220HZ (0x1c) +/** @} */ + +/** + * @name Masks for the LSM303DLHC CRB_REG_M register + * @{ + */ +#define LSM303DLHC_GAIN_1 (0x20) +#define LSM303DLHC_GAIN_2 (0x40) +#define LSM303DLHC_GAIN_3 (0x60) +#define LSM303DLHC_GAIN_4 (0x80) +#define LSM303DLHC_GAIN_5 (0xa0) +#define LSM303DLHC_GAIN_6 (0xc0) +#define LSM303DLHC_GAIN_7 (0xe0) +/** @} */ + +/** + * @name Masks for the LSM303DLHC MR_REG_M register + * @{ + */ +#define LSM303DLHC_MAG_MODE_CONTINUOUS (0x00) +#define LSM303DLHC_MAG_MODE_SINGLE (0x01) +#define LSM303DLHC_MAG_MODE_SLEEP (0x02) +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* __LSM303DLHC_INTERNAL_H */ +/** @} */ diff --git a/drivers/lsm303dlhc/lsm303dlhc.c b/drivers/lsm303dlhc/lsm303dlhc.c new file mode 100644 index 0000000000..b985457412 --- /dev/null +++ b/drivers/lsm303dlhc/lsm303dlhc.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * 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 driver_lsm303dlhc + * @{ + * + * @file + * @brief Device driver implementation for the LSM303DLHC light sensor + * + * @author Thomas Eichinger + * + * @} + */ + +#include "lsm303dlhc.h" +#include "lsm303dlhc-internal.h" + +#define ENABLE_DEBUG (0) +#include "debug.h" + +int lsm303dlhc_init(lsm303dlhc_t *dev, i2c_t i2c, gpio_t acc_pin, gpio_t mag_pin, + uint8_t acc_address, + lsm303dlhc_acc_sample_rate_t acc_sample_rate, + lsm303dlhc_acc_scale_t acc_scale, + uint8_t mag_address, + lsm303dlhc_mag_sample_rate_t mag_sample_rate, + lsm303dlhc_mag_gain_t mag_gain) +{ + int res; + char tmp; + + dev->i2c = i2c; + dev->acc_address = acc_address; + dev->mag_address = mag_address; + + i2c_init_master(i2c, I2C_SPEED_NORMAL); + + DEBUG("lsm303dlhc reboot "); + res = i2c_write_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_CTRL5_A, LSM303DLHC_REG_CTRL5_A_BOOT); + DEBUG("[OK]"); + + /* configure accelerometer */ + /* enable all three axis and set sample rate */ + tmp = (LSM303DLHC_CTRL1_A_XEN + | LSM303DLHC_CTRL1_A_YEN + | LSM303DLHC_CTRL1_A_ZEN + | acc_sample_rate); + res += i2c_write_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_CTRL1_A, tmp); + /* update on read, MSB @ low address, scale and high-resolution */ + tmp = (acc_scale | LSM303DLHC_CTRL4_A_HR); + res += i2c_write_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_CTRL4_A, tmp); + /* no interrupt generation */ + res += i2c_write_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_CTRL3_A, LSM303DLHC_CTRL3_A_I1_NONE); + /* configure acc data ready pin */ + gpio_init_in(acc_pin, GPIO_NOPULL); + + /* configure magnetometer and temperature */ + /* enable temperature output and set sample rate */ + tmp = LSM303DLHC_TEMP_EN | mag_sample_rate; + res += i2c_write_reg(dev->i2c, dev->mag_address, + LSM303DLHC_REG_CRA_M, tmp); + /* configure z-axis gain */ + res += i2c_write_reg(dev->i2c, dev->mag_address, + LSM303DLHC_REG_CRB_M, mag_gain); + /* set continuous mode */ + res += i2c_write_reg(dev->i2c, dev->mag_address, + LSM303DLHC_REG_MR_M, LSM303DLHC_MAG_MODE_CONTINUOUS); + /* configure mag data ready pin */ + gpio_init_in(mag_pin, GPIO_NOPULL); + + return (res < 7) ? -1 : 0; +} + +int lsm303dlhc_read_acc(lsm303dlhc_t *dev, lsm303dlhc_3d_data_t *data) +{ + int res; + char tmp; + + i2c_read_reg(dev->i2c, dev->acc_address, LSM303DLHC_REG_STATUS_A, &tmp); + DEBUG("lsm303dlhc status: %x\n", tmp); + DEBUG("lsm303dlhc: wait for acc values ... "); + + res = i2c_read_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_OUT_X_L_A, &tmp); + data->x_axis = tmp; + res += i2c_read_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_OUT_X_H_A, &tmp); + data->x_axis |= tmp<<8; + res += i2c_read_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_OUT_Y_L_A, &tmp); + data->y_axis = tmp; + res += i2c_read_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_OUT_Y_H_A, &tmp); + data->y_axis |= tmp<<8; + res += i2c_read_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_OUT_Z_L_A, &tmp); + data->z_axis = tmp; + res += i2c_read_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_OUT_Z_H_A, &tmp); + data->z_axis |= tmp<<8; + DEBUG("read ... "); + + if (res < 6) { + DEBUG("[!!failed!!]\n"); + return -1; + } + DEBUG("[done]\n"); + + return 0; +} + +int lsm303dlhc_read_mag(lsm303dlhc_t *dev, lsm303dlhc_3d_data_t *data) +{ + int res; + + DEBUG("lsm303dlhc: wait for mag values... "); + while (gpio_read(GPIO_8) == 0){} + + DEBUG("read ... "); + + res = i2c_read_regs(dev->i2c, dev->mag_address, + LSM303DLHC_REG_OUT_X_H_M, (char*)data, 6); + + if (res < 6) { + DEBUG("[!!failed!!]\n"); + return -1; + } + DEBUG("[done]\n"); + + /* interchange y and z axis and fix endiness */ + int16_t tmp = data->y_axis; + data->x_axis = ((data->x_axis<<8)|((data->x_axis>>8)&0xff)); + data->y_axis = ((data->z_axis<<8)|((data->z_axis>>8)&0xff)); + data->z_axis = ((tmp<<8)|((tmp>>8)&0xff)); + + /* compensate z-axis sensitivity */ + /* gain is currently hardcoded to LSM303DLHC_GAIN_5 */ + data->z_axis = ((data->z_axis * 400) / 355); + + return 0; +} + +int lsm303dlhc_read_temp(lsm303dlhc_t *dev, int16_t *value) +{ + int res; + + res = i2c_read_regs(dev->i2c, dev->mag_address, LSM303DLHC_REG_TEMP_OUT_H, (char*)value, 2); + + if (res < 2) { + return -1; + } + + *value = (((*value) >> 8) & 0xff) | (*value << 8); + + DEBUG("LSM303DLHC: raw temp: %i\n", *value); + + return 0; +} + +int lsm303dlhc_disable(lsm303dlhc_t *dev) +{ + int res; + res = i2c_write_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_CTRL1_A, LSM303DLHC_CTRL1_A_POWEROFF); + res += i2c_write_reg(dev->i2c, dev->mag_address, + LSM303DLHC_REG_MR_M, LSM303DLHC_MAG_MODE_SLEEP); + res += i2c_write_reg(dev->i2c, dev->acc_address, + LSM303DLHC_REG_CRA_M, LSM303DLHC_TEMP_DIS); + + return (res < 3) ? -1 : 0; +} + +int lsm303dlhc_enable(lsm303dlhc_t *dev) +{ + int res; + char tmp = (LSM303DLHC_CTRL1_A_XEN + | LSM303DLHC_CTRL1_A_YEN + | LSM303DLHC_CTRL1_A_ZEN + | LSM303DLHC_CTRL1_A_N1344HZ_L5376HZ); + res = i2c_write_reg(dev->i2c, dev->acc_address, LSM303DLHC_REG_CTRL1_A, tmp); + + tmp = (LSM303DLHC_CTRL4_A_BDU| LSM303DLHC_CTRL4_A_SCALE_2G | LSM303DLHC_CTRL4_A_HR); + res += i2c_write_reg(dev->i2c, dev->acc_address, LSM303DLHC_REG_CTRL4_A, tmp); + res += i2c_write_reg(dev->i2c, dev->acc_address, LSM303DLHC_REG_CTRL3_A, LSM303DLHC_CTRL3_A_I1_DRDY1); + gpio_init_in(GPIO_2, GPIO_NOPULL); + + tmp = LSM303DLHC_TEMP_EN | LSM303DLHC_TEMP_SAMPLE_75HZ; + res += i2c_write_reg(dev->i2c, dev->mag_address, LSM303DLHC_REG_CRA_M, tmp); + + res += i2c_write_reg(dev->i2c, dev->mag_address, + LSM303DLHC_REG_CRB_M, LSM303DLHC_GAIN_5); + + res += i2c_write_reg(dev->i2c, dev->mag_address, + LSM303DLHC_REG_MR_M, LSM303DLHC_MAG_MODE_CONTINUOUS); + + gpio_init_in(GPIO_8, GPIO_NOPULL); + + return (res < 6) ? -1 : 0; +} diff --git a/tests/driver_lsm303dlhc/Makefile b/tests/driver_lsm303dlhc/Makefile new file mode 100644 index 0000000000..56416cd901 --- /dev/null +++ b/tests/driver_lsm303dlhc/Makefile @@ -0,0 +1,35 @@ +APPLICATION = driver_lsm303dlhc +include ../Makefile.tests_common + +FEATURES_REQUIRED = periph_i2c + +# Define default pin mappings for some boards: +ifneq (,$(filter iot-lab_M3,$(BOARD))) + export TEST_LSM303DLHC_MAG_ADDR=30 + export TEST_LSM303DLHC_ACC_ADDR=25 + export TEST_LSM303DLHC_I2C ?=I2C_0 +endif + +USEMODULE += lsm303dlhc +USEMODULE += vtimer + +ifneq (,$(TEST_LSM303DLHC_I2C)) + CFLAGS += -DTEST_LSM303DLHC_I2C=$(TEST_LSM303DLHC_I2C) +else + # set random default + CFLAGS += -DTEST_LSM303DLHC_I2C=I2C_0 +endif +ifneq (,$(TEST_LSM303DLHC_MAG_ADDR)) + CFLAGS += -DTEST_LSM303DLHC_MAG_ADDR=$(TEST_LSM303DLHC_MAG_ADDR) +else + # set random default + CFLAGS += -DTEST_LSM303DLHC_MAG_ADDR=30 +endif +ifneq (,$(TEST_LSM303DLHC_ACC_ADDR)) + CFLAGS += -DTEST_LSM303DLHC_ACC_ADDR=$(TEST_LSM303DLHC_ACC_ADDR) +else + # set random default + CFLAGS += -DTEST_LSM303DLHC_ACC_ADDR=25 +endif + +include $(RIOTBASE)/Makefile.include diff --git a/tests/driver_lsm303dlhc/main.c b/tests/driver_lsm303dlhc/main.c new file mode 100644 index 0000000000..566f528e61 --- /dev/null +++ b/tests/driver_lsm303dlhc/main.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2014 Freie Universität Berlin + * + * 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 tests + * @{ + * + * @file + * @brief Test application for the LSM303DLHC accelerometer/magnetometer + * + * @author Thomas Eichinger + * + * @} + */ + +#ifndef TEST_LSM303DLHC_I2C +#error "TEST_LSM303DLHC_I2C not defined" +#endif +#ifndef TEST_LSM303DLHC_MAG_ADDR +#error "TEST_LSM303DLHC_MAG_ADDR not defined" +#endif +#ifndef TEST_LSM303DLHC_ACC_ADDR +#error "TEST_LSM303DLHC_ACC_ADDR not defined" +#endif + +#include + +#include "vtimer.h" +#include "lsm303dlhc.h" + +#define SLEEP (100 * 1000U) +#define ACC_S_RATE LSM303DLHC_ACC_SAMPLE_RATE_10HZ +#define ACC_SCALE LSM303DLHC_ACC_SCALE_2G +#define MAG_S_RATE LSM303DLHC_MAG_SAMPLE_RATE_75HZ +#define MAG_GAIN LSM303DLHC_MAG_GAIN_400_355_GAUSS +#define ACC_PIN GPIO_2 +#define MAG_PIN GPIO_8 + +int main(void) +{ + lsm303dlhc_t dev; + int16_t temp_value; + lsm303dlhc_3d_data_t mag_value; + lsm303dlhc_3d_data_t acc_value; + + puts("LSM303DLHC temperature test application\n"); + printf("Initializing LSM303DLHC sensor at I2C_%i... ", TEST_LSM303DLHC_I2C); + + if (lsm303dlhc_init(&dev, TEST_LSM303DLHC_I2C, ACC_PIN, MAG_PIN, + TEST_LSM303DLHC_ACC_ADDR, ACC_S_RATE, ACC_SCALE, + TEST_LSM303DLHC_MAG_ADDR, MAG_S_RATE, MAG_GAIN) == 0) { + puts("[OK]\n"); + } + else { + puts("[Failed]"); + return 1; + } + + while (1) { + if (lsm303dlhc_read_acc(&dev, &acc_value) == 0) { + printf("Accelerometer x: %i y: %i z: %i\n", acc_value.x_axis, + acc_value.y_axis, + acc_value.z_axis); + } + else { + puts("\nFailed reading accelerometer values\n"); + } + if (lsm303dlhc_read_temp(&dev, &temp_value) == 0) { + printf("Temperature value: %i degrees\n", temp_value); + } + else { + puts("\nFailed reading value\n"); + } + + if (lsm303dlhc_read_mag(&dev, &mag_value) == 0) { + printf("Magnetometer x: %i y: %i z: %i\n", mag_value.x_axis, + mag_value.y_axis, + mag_value.z_axis); + } + else { + puts("\nFailed reading magnetometer values\n"); + } + + vtimer_usleep(SLEEP); + } + + return 0; +}