diff --git a/drivers/Makefile.dep b/drivers/Makefile.dep index 8085fbd9a4..c7b1579ee6 100644 --- a/drivers/Makefile.dep +++ b/drivers/Makefile.dep @@ -11,6 +11,11 @@ ifneq (,$(filter at86rf2%,$(USEMODULE))) USEMODULE += netif endif +ifneq (,$(filter bh1750fvi,$(USEMODULE))) + USEMODULE += xtimer + FEATURES_REQUIRED = periph_i2c +endif + ifneq (,$(filter cc110x,$(USEMODULE))) USEMODULE += ieee802154 endif diff --git a/drivers/Makefile.include b/drivers/Makefile.include index 7400131488..7d552a5432 100644 --- a/drivers/Makefile.include +++ b/drivers/Makefile.include @@ -55,3 +55,6 @@ endif ifneq (,$(filter enc28j60,$(USEMODULE))) USEMODULE_INCLUDES += $(RIOTBASE)/drivers/enc28j60/include endif +ifneq (,$(filter bh1750fvi,$(USEMODULE))) + USEMODULE_INCLUDES += $(RIOTBASE)/drivers/bh1750fvi/include +endif diff --git a/drivers/bh1750fvi/Makefile b/drivers/bh1750fvi/Makefile new file mode 100644 index 0000000000..48422e909a --- /dev/null +++ b/drivers/bh1750fvi/Makefile @@ -0,0 +1 @@ +include $(RIOTBASE)/Makefile.base diff --git a/drivers/bh1750fvi/bh1750fvi.c b/drivers/bh1750fvi/bh1750fvi.c new file mode 100644 index 0000000000..7b249afa77 --- /dev/null +++ b/drivers/bh1750fvi/bh1750fvi.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2016 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 drivers_bh1750fvi + * @{ + * + * @file + * @brief BH1750FVI ambient light sensor driver implementation + * + * @author Hauke Petersen + * + * @} + */ + +#include + +#include "xtimer.h" + +#include "bh1750fvi.h" +#include "bh1750fvi_internal.h" + +int bh1750fvi_init(bh1750fvi_t *dev, bh1750fvi_params_t *params) +{ + int res; + + /* initialize the device descriptor */ + dev->i2c = params->i2c; + dev->addr = params->addr; + + /* initialize the I2C bus */ + i2c_acquire(dev->i2c); + i2c_init_master(dev->i2c, params->clk); + + /* send a power down command to make sure we can speak to the device */ + res = i2c_write_byte(dev->i2c, dev->addr, OP_POWER_DOWN); + i2c_release(dev->i2c); + if (res < 0) { + return -1; + } + return 0; +} + +uint16_t bh1750fvi_sample(bh1750fvi_t *dev) +{ + uint32_t tmp; + char raw[2]; + + /* power on the device and send single H-mode measurement command */ + i2c_acquire(dev->i2c); + i2c_write_byte(dev->i2c, dev->addr, OP_POWER_ON); + i2c_write_byte(dev->i2c, dev->addr, OP_SINGLE_HRES1); + i2c_release(dev->i2c); + + /* wait for measurement to complete */ + xtimer_usleep(DELAY_HMODE); + + /* read the results */ + i2c_acquire(dev->i2c); + i2c_read_bytes(dev->i2c, dev->addr, raw, 2); + i2c_release(dev->i2c); + + /* and finally we calculate the actual LUX value */ + tmp = (raw[0] << 24) | (raw[1] << 16); + tmp /= RES_DIV; + return (uint16_t)(tmp); +} diff --git a/drivers/bh1750fvi/include/bh1750fvi_internal.h b/drivers/bh1750fvi/include/bh1750fvi_internal.h new file mode 100644 index 0000000000..b9d65347bd --- /dev/null +++ b/drivers/bh1750fvi/include/bh1750fvi_internal.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 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 drivers_bh1750fvi + * @{ + * + * @file + * @brief Command definition for the BH1750FVI light sensor + * + * @author Hauke Petersen + */ + +#ifndef BH1750FVI_REGS_H +#define BH1750FVI_REGS_H + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Result divisor (1.2 times 65535) + * + * The 16-bit RAW results have to be divided by 1.2. We do this by using fixed + * floating point arithmetics by multiplying divisor and RAW value by 65535 ( + * uint16_t max). + */ +#define RES_DIV (78642) + +/** + * @brief Opcodes + * @{ + */ +#define OP_POWER_DOWN (0x00) +#define OP_POWER_ON (0x01) +#define OP_RESET (0x03) +#define OP_CONT_HRES1 (0x10) +#define OP_CONT_HRES2 (0x11) +#define OP_CONT_LRES (0x13) +#define OP_SINGLE_HRES1 (0x20) +#define OP_SINGLE_HRES2 (0x21) +#define OP_SINGLE_LRES (0x23) +#define OP_CHANGE_TIME_H_MASK (0x40) +#define OP_CHANGE_TIME_L_MASK (0x60) +/** @} */ + +/** + * @brief Measurement delays (in us) + * @{ + */ +#define DELAY_HMODE (120000) /**< typ. 120ms in H-mode */ +#define DELAY_LMODE (16000) /**< typ. 16ms in L-mode */ +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* BH1750FVI_REGS_H */ +/** @} */ diff --git a/drivers/bh1750fvi/include/bh1750fvi_params.h b/drivers/bh1750fvi/include/bh1750fvi_params.h new file mode 100644 index 0000000000..2551990f61 --- /dev/null +++ b/drivers/bh1750fvi/include/bh1750fvi_params.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2016 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 drivers_bh1750fvi + * + * @{ + * @file + * @brief Default configuration for BH1750FVI devices + * + * @author Hauke Petersen + */ + +#ifndef BH1750FVI_PARAMS_H +#define BH1750FVI_PARAMS_H + +#include "board.h" +#include "bh1750fvi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Set default configuration parameters for BH1750FVI devices + * @{ + */ +#ifndef BH1750FVI_PARAM_I2C +#define BH1750FVI_PARAM_I2C I2C_DEV(0) +#endif +#ifndef BH1750FVI_PARAM_ADDR +#define BH1750FVI_PARAM_ADDR (BH1750FVI_DEFAULT_ADDR) +#endif +#ifndef BH1750FVI_PARAM_I2C_CLK +#define BH1750FVI_PARAM_I2C_CLK (BH1750FVI_I2C_MAX_CLK) +#endif + +#define BH1750FVI_PARAMS_DEFAULT {.i2c = BH1750FVI_PARAM_I2C, \ + .addr = BH1750FVI_PARAM_ADDR, \ + .clk = BH1750FVI_PARAM_I2C_CLK} +/**@}*/ + +/** + * @brief BH1750FVI configuration + */ +static const bh1750fvi_params_t bh1750fvi_params[] = +{ +#ifdef BH1750FVI_PARAMS_BOARD + BH1750FVI_PARAMS_BOARD, +#else + BH1750FVI_PARAMS_DEFAULT, +#endif +}; + +#ifdef __cplusplus +} +#endif + +#endif /* BH1750FVI_PARAMS_H */ +/** @} */ diff --git a/drivers/include/bh1750fvi.h b/drivers/include/bh1750fvi.h new file mode 100644 index 0000000000..4fe63a853f --- /dev/null +++ b/drivers/include/bh1750fvi.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 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 drivers_bh1750fvi BH1750FVI Light Sensor + * @ingroup drivers_periph + * @brief Driver for the Rohm BH1750FVI ambient light sensor + * + * @{ + * @file + * @brief Interface definition for the Rohm BH1750FVI ambient light sensor + * + * @author Hauke Petersen + */ + +#ifndef BH1750FVI_H +#define BH1750FVI_H + +#include "periph/i2c.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Possible I2C bus addresses of the device + * + * The actual address of the device depends on the state of the ADDR pin. + * @{ + */ +#define BH1750FVI_ADDR_PIN_LOW (0x5c) /**< ADDR pin := 0 */ +#define BH1750FVI_ADDR_PIN_HIGH (0x23) /**< ADDR pin := 1 */ +/** @} */ + + +/** + * @brief Default address of BH1750FVI sensors + */ +#define BH1750FVI_DEFAULT_ADDR BH1750FVI_ADDR_PIN_HIGH + +/** + * @brief Maximum I2C bus speed to use with the device + */ +#define BH1750FVI_I2C_MAX_CLK I2C_SPEED_FAST + +/** + * @brief Device descriptor for BH1570FVI devices + */ +typedef struct { + i2c_t i2c; /**< I2C bus the device is connected to */ + uint8_t addr; /**< slave address of the device */ +} bh1750fvi_t; + +/** + * @brief Set of configuration parameters for BH1750FV devices + */ +typedef struct { + i2c_t i2c; /**< I2C bus the device is connected to */ + uint8_t addr; /**< slave address of the device */ + i2c_speed_t clk; /**< clock speed to use on the I2C bus */ +} bh1750fvi_params_t; + +/** + * @brief Initialize the given BH1750FVI device + * + * @param[out] dev device descriptor of the targeted device + * @param[in] params device configuration (i2c bus, address and bus clock) + * + * @return 0 on success + * @return -1 if unable to speak to the device + */ +int bh1750fvi_init(bh1750fvi_t *dev, bh1750fvi_params_t *params); + +/** + * @brief Read a ambient light value from the given device [in LUX] + * + * The result value is the measured ambient light intensity in LUX and ranges + * from 0 to 54612. Taking one measurement takes ~120ms, so it takes this amount + * of time until the function returns. + * + * @param[in] dev device descriptor of the targeted device + * + * @return ambient light intensity in LUX + */ +uint16_t bh1750fvi_sample(bh1750fvi_t *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* BH1750FVI_H */ +/** @} */