added TSL2561 Light sesnor
This commit is contained in:
parent
de87b64728
commit
d124d1144f
|
@ -125,23 +125,20 @@ HDC1000_init(HDC1000_drv *drv, HDC1000_config *config) {
|
|||
HDC1000_CONFIG_RES;
|
||||
drv->delay = (HDC1000_DELAY_ACQUIRE +
|
||||
HDC1000_DELAY_ACQUIRE_SAFETY) / 1000;
|
||||
drv->state = HDC1000_INIT;
|
||||
drv->state = SENSOR_INIT;
|
||||
}
|
||||
|
||||
msg_t
|
||||
HDC1000_check(HDC1000_drv *drv) {
|
||||
msg_t msg = -10;
|
||||
uint16_t val;
|
||||
uint16_t manuf, device;
|
||||
|
||||
if ((msg = i2c_reg_recv16_be(HDC1000_REG_MANUF_ID, &val)) < MSG_OK)
|
||||
msg_t msg;
|
||||
if (((msg = i2c_reg_recv16_be(HDC1000_REG_MANUF_ID, &manuf )) < MSG_OK) ||
|
||||
((msg = i2c_reg_recv16_be(HDC1000_REG_DEVICE_ID, &device)) < MSG_OK))
|
||||
return msg;
|
||||
if (val != HDC1000_MANUF_ID)
|
||||
return -2;
|
||||
|
||||
if ((msg = i2c_reg_recv16_be(HDC1000_REG_DEVICE_ID, &val)) < MSG_OK)
|
||||
return msg;
|
||||
if (val != HDC1000_DEVICE_ID)
|
||||
return -2;
|
||||
if ((manuf != HDC1000_MANUF_ID) || (device != HDC1000_DEVICE_ID))
|
||||
return SENSOR_NOTFOUND;
|
||||
|
||||
return MSG_OK;
|
||||
}
|
||||
|
@ -149,22 +146,22 @@ HDC1000_check(HDC1000_drv *drv) {
|
|||
|
||||
msg_t
|
||||
HDC1000_start(HDC1000_drv *drv) {
|
||||
osalDbgAssert((drv->state == HDC1000_INIT ) ||
|
||||
(drv->state == HDC1000_ERROR ) ||
|
||||
(drv->state == HDC1000_STOPPED),
|
||||
osalDbgAssert((drv->state == SENSOR_INIT ) ||
|
||||
(drv->state == SENSOR_ERROR ) ||
|
||||
(drv->state == SENSOR_STOPPED),
|
||||
"invalid state");
|
||||
msg_t msg;
|
||||
if ((msg = _apply_config(drv)) < MSG_OK) {
|
||||
drv->state = HDC1000_ERROR;
|
||||
drv->state = SENSOR_ERROR;
|
||||
return msg;
|
||||
}
|
||||
drv->state = HDC1000_STARTED;
|
||||
drv->state = SENSOR_STARTED;
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
msg_t
|
||||
HDC1000_stop(HDC1000_drv *drv) {
|
||||
drv->state = HDC1000_STOPPED;
|
||||
drv->state = SENSOR_STOPPED;
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
|
@ -175,7 +172,7 @@ HDC1000_setHeater(HDC1000_drv *drv, bool on) {
|
|||
|
||||
msg_t msg;
|
||||
if ((msg = _apply_config(drv)) < MSG_OK) {
|
||||
drv->state = HDC1000_ERROR;
|
||||
drv->state = SENSOR_ERROR;
|
||||
return msg;
|
||||
}
|
||||
return MSG_OK;
|
||||
|
@ -184,10 +181,10 @@ HDC1000_setHeater(HDC1000_drv *drv, bool on) {
|
|||
msg_t
|
||||
HDC1000_startMeasure(HDC1000_drv *drv) {
|
||||
msg_t msg;
|
||||
osalDbgAssert(drv->state == HDC1000_STARTED, "invalid state");
|
||||
osalDbgAssert(drv->state == SENSOR_STARTED, "invalid state");
|
||||
if ((msg = i2c_reg(HDC1000_REG_TEMP_HUMID)) < MSG_OK)
|
||||
return msg;
|
||||
drv->state = HDC1000_MEASURING;
|
||||
drv->state = SENSOR_MEASURING;
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
|
@ -195,7 +192,7 @@ HDC1000_startMeasure(HDC1000_drv *drv) {
|
|||
msg_t
|
||||
HDC1000_readSerial(HDC1000_drv *drv, uint8_t *serial) {
|
||||
msg_t msg;
|
||||
osalDbgAssert(drv->state == HDC1000_STARTED, "invalid state");
|
||||
osalDbgAssert(drv->state == SENSOR_STARTED, "invalid state");
|
||||
|
||||
if (((msg = i2c_reg_recv16(HDC1000_REG_SERIAL_1,
|
||||
(uint16_t*)&serial[0])) < MSG_OK) ||
|
||||
|
@ -214,16 +211,16 @@ HDC1000_readMeasure(HDC1000_drv *drv,
|
|||
msg_t msg;
|
||||
uint32_t val;
|
||||
|
||||
osalDbgAssert((drv->state == HDC1000_MEASURING) ||
|
||||
(drv->state == HDC1000_READY ),
|
||||
osalDbgAssert((drv->state == SENSOR_MEASURING) ||
|
||||
(drv->state == SENSOR_READY ),
|
||||
"invalid state");
|
||||
|
||||
if ((msg = i2c_recv32_be(&val)) < MSG_OK) {
|
||||
drv->state = HDC1000_ERROR;
|
||||
drv->state = SENSOR_ERROR;
|
||||
return msg;
|
||||
}
|
||||
|
||||
drv->state = HDC1000_STARTED;
|
||||
drv->state = SENSOR_STARTED;
|
||||
|
||||
return _decode_measure(drv, val, temperature, humidity);
|
||||
}
|
||||
|
@ -234,7 +231,7 @@ HDC1000_readTemperatureHumidity(HDC1000_drv *drv,
|
|||
msg_t msg;
|
||||
uint32_t val;
|
||||
|
||||
osalDbgAssert(drv->state == HDC1000_STARTED, "invalid state");
|
||||
osalDbgAssert(drv->state == SENSOR_STARTED, "invalid state");
|
||||
|
||||
/* Request value */
|
||||
if ((msg = i2c_reg(HDC1000_REG_TEMP_HUMID)) < MSG_OK)
|
||||
|
@ -245,7 +242,7 @@ HDC1000_readTemperatureHumidity(HDC1000_drv *drv,
|
|||
|
||||
/* Get value */
|
||||
if ((msg = i2c_recv32_be(&val)) < MSG_OK) {
|
||||
drv->state = HDC1000_ERROR;
|
||||
drv->state = SENSOR_ERROR;
|
||||
return msg;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,12 @@
|
|||
* @file hdc1000.h
|
||||
* @brief HDC1000 Temperature/Humidiry sensor interface module header.
|
||||
*
|
||||
* When changing sensor settings, you generally need to wait
|
||||
* for 2 * getAquisitionTime(), as usually the first acquisition
|
||||
* will be corrupted by the change of settings.
|
||||
*
|
||||
* No locking is done.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
@ -15,6 +21,14 @@
|
|||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include "i2c_helpers.h"
|
||||
#include "sensor.h"
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define HDC1000_CONTINUOUS_ACQUISITION_SUPPORTED FALSE
|
||||
|
||||
/* I2C address */
|
||||
#define HDC1000_I2CADDR_1 0x40
|
||||
|
@ -22,23 +36,33 @@
|
|||
#define HDC1000_I2CADDR_3 0x42
|
||||
#define HDC1000_I2CADDR_4 0x43
|
||||
|
||||
#define HDC1000_SERIAL_SIZE 5 /**< @brief Size of serial (40bits) */
|
||||
|
||||
/**
|
||||
* @brief Time necessary for the sensor to boot
|
||||
*/
|
||||
#define HDC1000_BOOTUP_TIME 15
|
||||
|
||||
/**
|
||||
* @brief Time necessary for the sensor to start
|
||||
*/
|
||||
#define HDC1000_STARTUP_TIME 0
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define HDC1000_I2CADDR_DEFAULT HDC1000_I2CADDR_1
|
||||
|
||||
|
||||
/* Size of serial (40 bits) */
|
||||
#define HDC1000_SERIAL_SIZE 5
|
||||
|
||||
#define HDC1000_CONTINUOUS_ACQUISITION_SUPPORTED FALSE
|
||||
|
||||
|
||||
/**
|
||||
* When changing sensor settings, you generally need to wait
|
||||
* for 2 * getAquisitionTime(), as usually the first acquisition
|
||||
* will be corrupted by the change of settings.
|
||||
*
|
||||
* No locking is done.
|
||||
*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief HDC1000 configuration structure.
|
||||
|
@ -47,31 +71,25 @@ typedef struct {
|
|||
I2CHelper i2c; /* keep it first */
|
||||
} HDC1000_config;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Driver state machine possible states.
|
||||
*/
|
||||
typedef enum __attribute__ ((__packed__)) {
|
||||
HDC1000_UNINIT = 0, /**< Not initialized. */
|
||||
HDC1000_INIT = 1, /**< Initialized. */
|
||||
HDC1000_STARTED = 2, /**< Started. */
|
||||
HDC1000_MEASURING = 4, /**< Measuring. */
|
||||
HDC1000_READY = 3, /**< Ready. */
|
||||
HDC1000_STOPPED = 5, /**< Stopped. */
|
||||
HDC1000_ERROR = 6, /**< Error. */
|
||||
} HDC1000_state_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief HDC1000 configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
HDC1000_config *config;
|
||||
HDC1000_state_t state;
|
||||
sensor_state_t state;
|
||||
unsigned int delay;
|
||||
uint16_t cfg;
|
||||
} HDC1000_drv;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the sensor driver
|
||||
*/
|
||||
|
@ -111,30 +129,6 @@ HDC1000_setHeater(HDC1000_drv *drv,
|
|||
bool on);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Time necessary for the sensor to boot
|
||||
*
|
||||
* @returns
|
||||
* unsigned int time in millis-seconds
|
||||
*/
|
||||
|
||||
static inline unsigned int
|
||||
HDC1000_getBootupTime(HDC1000_drv *drv) {
|
||||
(void)drv;
|
||||
return 15;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Time necessary the sensor to for starting
|
||||
*
|
||||
* @returns
|
||||
* unsigned int time in millis-seconds
|
||||
*/
|
||||
static inline unsigned int
|
||||
HDC1000_getStartupTime(HDC1000_drv *drv) {
|
||||
(void)drv;
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Time in milli-seconds necessary for acquiring a naw measure
|
||||
|
@ -178,7 +172,7 @@ HDC1000_readMeasure(HDC1000_drv *drv,
|
|||
*
|
||||
* @note In continuous measurement mode, if you just started
|
||||
* the sensor, you will need to wait getAcquisitionTime()
|
||||
* in addition to the usual getStartupTime()
|
||||
* in addition to the usual #HDC1000_STARTUP_TIME
|
||||
|
||||
* @note If using several sensors, it is better to start all the
|
||||
* measure together, wait for the sensor having the longuest
|
||||
|
@ -229,3 +223,6 @@ HDC1000_getTemperature(HDC1000_drv *drv) {
|
|||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
|
|
@ -62,6 +62,16 @@
|
|||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static inline msg_t
|
||||
_apply_config(MCP9808_drv *drv) {
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t reg;
|
||||
uint16_t conf;
|
||||
} tx = { MCP9808_REG_CONFIG, cpu_to_be16(drv->cfg) };
|
||||
|
||||
return i2c_send((uint8_t*)&tx, sizeof(tx));
|
||||
}
|
||||
|
||||
static inline msg_t
|
||||
_decode_measure(MCP9808_drv *drv,
|
||||
uint16_t val, float *temperature) {
|
||||
|
@ -95,24 +105,21 @@ void
|
|||
MCP9808_init(MCP9808_drv *drv, MCP9808_config *config) {
|
||||
drv->config = config;
|
||||
drv->cfg = 0;
|
||||
drv->resolution = RES_16;
|
||||
drv->state = MCP9808_INIT;
|
||||
drv->resolution = RES_16; /* power up default */
|
||||
drv->state = SENSOR_INIT;
|
||||
}
|
||||
|
||||
msg_t
|
||||
MCP9808_check(MCP9808_drv *drv) {
|
||||
msg_t msg = -10;
|
||||
uint16_t val;
|
||||
uint16_t manuf, device;
|
||||
|
||||
if ((msg = i2c_reg_recv16_be(MCP9808_REG_MANUF_ID, &val)) < MSG_OK)
|
||||
msg_t msg;
|
||||
if (((msg = i2c_reg_recv16_be(MCP9808_REG_MANUF_ID, &manuf )) < MSG_OK) ||
|
||||
((msg = i2c_reg_recv16_be(MCP9808_REG_DEVICE_ID, &device)) < MSG_OK))
|
||||
return msg;
|
||||
if (val != MCP9808_MANUF_ID)
|
||||
return -2;
|
||||
|
||||
if ((msg = i2c_reg_recv16_be(MCP9808_REG_DEVICE_ID, &val)) < MSG_OK)
|
||||
return msg;
|
||||
if (val != MCP9808_DEVICE_ID)
|
||||
return -2;
|
||||
if ((manuf != MCP9808_MANUF_ID) || (device != MCP9808_DEVICE_ID))
|
||||
return SENSOR_NOTFOUND;
|
||||
|
||||
return MSG_OK;
|
||||
}
|
||||
|
@ -132,33 +139,18 @@ MCP9808_setResolution(MCP9808_drv *drv, MCP9808_resolution_t res) {
|
|||
return MSG_OK;
|
||||
}
|
||||
|
||||
|
||||
msg_t
|
||||
MCP9808_start(MCP9808_drv *drv) {
|
||||
drv->cfg &= ~(MCP9808_REG_CONFIG_SHUTDOWN);
|
||||
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t reg;
|
||||
uint16_t conf;
|
||||
} tx = { MCP9808_REG_CONFIG, cpu_to_be16(drv->cfg) };
|
||||
|
||||
return i2c_send((uint8_t*)&tx, sizeof(tx)) >= 0;
|
||||
return _apply_config(drv);
|
||||
}
|
||||
|
||||
msg_t
|
||||
MCP9808_stop(MCP9808_drv *drv) {
|
||||
drv->cfg |= (MCP9808_REG_CONFIG_SHUTDOWN);
|
||||
|
||||
struct __attribute__((packed)) {
|
||||
uint8_t reg;
|
||||
uint16_t conf;
|
||||
} tx = { MCP9808_REG_CONFIG, cpu_to_be16(drv->cfg) };
|
||||
|
||||
return i2c_send((uint8_t*)&tx, sizeof(tx)) >= 0;
|
||||
return _apply_config(drv);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned int
|
||||
MCP9808_getAcquisitionTime(MCP9808_drv *drv) {
|
||||
switch(drv->resolution) {
|
||||
|
@ -167,8 +159,8 @@ MCP9808_getAcquisitionTime(MCP9808_drv *drv) {
|
|||
case RES_8 : return MCP9808_DELAY_ACQUIRE_RES_8;
|
||||
case RES_16: return MCP9808_DELAY_ACQUIRE_RES_16;
|
||||
}
|
||||
osalDbgAssert(false, "programming error");
|
||||
return -1;
|
||||
osalDbgAssert(false, "OOPS");
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg_t
|
||||
|
@ -188,7 +180,7 @@ MCP9808_readMeasure(MCP9808_drv *drv,
|
|||
msg_t
|
||||
MCP9808_readTemperature(MCP9808_drv *drv,
|
||||
float *temperature) {
|
||||
osalDbgAssert(drv->state == MCP9808_STARTED, "invalid state");
|
||||
osalDbgAssert(drv->state == SENSOR_STARTED, "invalid state");
|
||||
|
||||
msg_t msg;
|
||||
uint16_t val;
|
||||
|
|
|
@ -6,23 +6,43 @@
|
|||
#define _SENSOR_MCP9808_H_
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include "i2c_helpers.h"
|
||||
#include "sensor.h"
|
||||
|
||||
|
||||
#define MCP9808_I2CADDR_DEFAULT 0x18
|
||||
|
||||
typedef enum {
|
||||
RES_2 = 0x00, /* 1/2 = 0.5 */
|
||||
RES_4 = 0x01, /* 1/4 = 0.25 */
|
||||
RES_8 = 0x10, /* 1/8 = 0.125 */
|
||||
RES_16 = 0x11, /* 1/16 = 0.0625 */
|
||||
} MCP9808_resolution_t;
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define MCP9808_CONTINUOUS_ACQUISITION_SUPPORTED TRUE
|
||||
|
||||
|
||||
#define MCP9808_I2CADDR 0x18
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define MCP9808_I2CADDR_DEFAULT MCP9808_I2CADDR
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Different possible resolution
|
||||
*/
|
||||
typedef enum {
|
||||
RES_2 = 0x00, /**< @brief Resolution of 1/2 = 0.5 */
|
||||
RES_4 = 0x01, /**< @brief Resolution of 1/4 = 0.25 */
|
||||
RES_8 = 0x10, /**< @brief Resolution of 1/8 = 0.125 */
|
||||
RES_16 = 0x11, /**< @brief Resolution of 1/16 = 0.0625 */
|
||||
} MCP9808_resolution_t;
|
||||
|
||||
/**
|
||||
* @brief MCP9808 configuration structure.
|
||||
*/
|
||||
|
@ -30,26 +50,12 @@ typedef struct {
|
|||
I2CHelper i2c; /* keep it first */
|
||||
} MCP9808_config;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Driver state machine possible states.
|
||||
*/
|
||||
typedef enum __attribute__ ((__packed__)) {
|
||||
MCP9808_UNINIT = 0, /**< Not initialized. */
|
||||
MCP9808_INIT = 1, /**< Initialized. */
|
||||
MCP9808_STARTED = 2, /**< Started. */
|
||||
MCP9808_MEASURING = 4, /**< Measuring. */
|
||||
MCP9808_READY = 3, /**< Ready. */
|
||||
MCP9808_STOPPED = 5, /**< Stopped. */
|
||||
MCP9808_ERROR = 6, /**< Error. */
|
||||
} MCP9808_state_t;
|
||||
|
||||
/**
|
||||
* @brief MCP9808 configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
MCP9808_config *config;
|
||||
MCP9808_state_t state;
|
||||
sensor_state_t state;
|
||||
MCP9808_resolution_t resolution;
|
||||
uint16_t cfg;
|
||||
} MCP9808_drv;
|
||||
|
@ -61,6 +67,15 @@ typedef struct {
|
|||
float temperature;
|
||||
} MCP9808_measure;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the sensor driver
|
||||
*/
|
||||
|
@ -88,8 +103,6 @@ MCP9808_start(MCP9808_drv *drv);
|
|||
msg_t
|
||||
MCP9808_stop(MCP9808_drv *drv);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Control the MCP9809 resolution.
|
||||
*/
|
||||
|
@ -97,7 +110,6 @@ msg_t
|
|||
MCP9808_setResolution(MCP9808_drv *drv,
|
||||
MCP9808_resolution_t res);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Time necessary for the sensor to boot
|
||||
*
|
||||
|
@ -137,6 +149,7 @@ MCP9808_getAcquisitionTime(MCP9808_drv *drv);
|
|||
*/
|
||||
static inline msg_t
|
||||
MCP9808_startMeasure(MCP9808_drv *drv) {
|
||||
(void)drv;
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
|
@ -178,14 +191,11 @@ MCP9808_readTemperature(MCP9808_drv *drv,
|
|||
/**
|
||||
* @brief Return the temperature value in °C.
|
||||
*
|
||||
* @details Use readTemperatureHumidity() for returning the humidity value.
|
||||
* @note Prefere readTemperature(), if you need better error handling.
|
||||
*
|
||||
* @note Prefere readTemperatureHumidity(), if you need both temperature
|
||||
* and humidity, or if you need better error handling.
|
||||
*
|
||||
* @returns
|
||||
* float humidity percent
|
||||
* NAN on failure
|
||||
* @return The temperature in °C
|
||||
* @retval float humidity percent
|
||||
* @retval NAN on failure
|
||||
*/
|
||||
static inline float
|
||||
MCP9808_getTemperature(MCP9808_drv *drv) {
|
||||
|
@ -194,10 +204,5 @@ MCP9808_getTemperature(MCP9808_drv *drv) {
|
|||
return temperature;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
TSL2561 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
|
||||
*/
|
||||
|
||||
#define I2C_HELPERS_AUTOMATIC_DRV TRUE
|
||||
|
||||
#include "hal.h"
|
||||
#include "i2c_helpers.h"
|
||||
#include "tsl2561.h"
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local definitions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
// Integration time in µs
|
||||
#define TSL2561_DELAY_INTTIME_SHORT 13700 // 13.7 ms
|
||||
#define TSL2561_DELAY_INTTIME_MEDIUM 120000 // 120.0 ms
|
||||
#define TSL2561_DELAY_INTTIME_LONG 450000 // 450.0 ms
|
||||
|
||||
|
||||
#define TSL2561_COMMAND_BIT (0x80)
|
||||
#define TSL2561_CLEAR_BIT (0x40)
|
||||
#define TSL2561_WORD_BIT (0x20)
|
||||
#define TSL2561_BLOCK_BIT (0x10)
|
||||
|
||||
#define TSL2561_CONTROL_POWERON (0x03)
|
||||
#define TSL2561_CONTROL_POWEROFF (0x00)
|
||||
|
||||
#define TSL2561_LUX_LUXSCALE (14)
|
||||
#define TSL2561_LUX_RATIOSCALE (9)
|
||||
#define TSL2561_LUX_CHSCALE (10) // Scale channel values by 2^10
|
||||
#define TSL2561_LUX_CHSCALE_TINT0 (0x7517) // 322/11 * 2^TSL2561_LUX_CHSCALE
|
||||
#define TSL2561_LUX_CHSCALE_TINT1 (0x0FE7) // 322/81 * 2^TSL2561_LUX_CHSCALE
|
||||
|
||||
|
||||
// I2C Register
|
||||
#define TSL2561_REG_CONTROL 0x00
|
||||
#define TSL2561_REG_TIMING 0x01
|
||||
#define TSL2561_REG_THRESHHOLDL_LOW 0x02
|
||||
#define TSL2561_REG_THRESHHOLDL_HIGH 0x03
|
||||
#define TSL2561_REG_THRESHHOLDH_LOW 0x04
|
||||
#define TSL2561_REG_THRESHHOLDH_HIGH 0x05
|
||||
#define TSL2561_REG_INTERRUPT 0x06
|
||||
#define TSL2561_REG_CRC 0x08
|
||||
#define TSL2561_REG_ID 0x0A
|
||||
#define TSL2561_REG_CHAN0_LOW 0x0C
|
||||
#define TSL2561_REG_CHAN0_HIGH 0x0D
|
||||
#define TSL2561_REG_CHAN1_LOW 0x0E
|
||||
#define TSL2561_REG_CHAN1_HIGH 0x0F
|
||||
|
||||
|
||||
// Auto-gain thresholds
|
||||
#define TSL2561_AGC_THI_SHORT (4850) // Max value at Ti 13ms = 5047
|
||||
#define TSL2561_AGC_TLO_SHORT (100)
|
||||
#define TSL2561_AGC_THI_MEDIUM (36000) // Max value at Ti 101ms = 37177
|
||||
#define TSL2561_AGC_TLO_MEDIUM (200)
|
||||
#define TSL2561_AGC_THI_LONG (63000) // Max value at Ti 402ms = 65535
|
||||
#define TSL2561_AGC_TLO_LONG (500)
|
||||
|
||||
// Clipping thresholds
|
||||
#define TSL2561_CLIPPING_SHORT (4900)
|
||||
#define TSL2561_CLIPPING_MEDIUM (37000)
|
||||
#define TSL2561_CLIPPING_LONG (65000)
|
||||
|
||||
// T, FN and CL package values
|
||||
#define TSL2561_LUX_K1T (0x0040) // 0.125 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B1T (0x01f2) // 0.0304 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M1T (0x01be) // 0.0272 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K2T (0x0080) // 0.250 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B2T (0x0214) // 0.0325 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M2T (0x02d1) // 0.0440 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K3T (0x00c0) // 0.375 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B3T (0x023f) // 0.0351 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M3T (0x037b) // 0.0544 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K4T (0x0100) // 0.50 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B4T (0x0270) // 0.0381 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M4T (0x03fe) // 0.0624 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K5T (0x0138) // 0.61 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B5T (0x016f) // 0.0224 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M5T (0x01fc) // 0.0310 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K6T (0x019a) // 0.80 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B6T (0x00d2) // 0.0128 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M6T (0x00fb) // 0.0153 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K7T (0x029a) // 1.3 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B7T (0x0018) // 0.00146 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M7T (0x0012) // 0.00112 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K8T (0x029a) // 1.3 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B8T (0x0000) // 0.000 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M8T (0x0000) // 0.000 * 2^LUX_SCALE
|
||||
|
||||
// CS package values
|
||||
#define TSL2561_LUX_K1C (0x0043) // 0.130 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B1C (0x0204) // 0.0315 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M1C (0x01ad) // 0.0262 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K2C (0x0085) // 0.260 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B2C (0x0228) // 0.0337 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M2C (0x02c1) // 0.0430 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K3C (0x00c8) // 0.390 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B3C (0x0253) // 0.0363 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M3C (0x0363) // 0.0529 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K4C (0x010a) // 0.520 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B4C (0x0282) // 0.0392 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M4C (0x03df) // 0.0605 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K5C (0x014d) // 0.65 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B5C (0x0177) // 0.0229 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M5C (0x01dd) // 0.0291 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K6C (0x019a) // 0.80 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B6C (0x0101) // 0.0157 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M6C (0x0127) // 0.0180 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K7C (0x029a) // 1.3 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B7C (0x0037) // 0.00338 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M7C (0x002b) // 0.00260 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_K8C (0x029a) // 1.3 * 2^RATIO_SCALE
|
||||
#define TSL2561_LUX_B8C (0x0000) // 0.000 * 2^LUX_SCALE
|
||||
#define TSL2561_LUX_M8C (0x0000) // 0.000 * 2^LUX_SCALE
|
||||
|
||||
|
||||
|
||||
|
||||
#define CEILING(x,y) (((x) + (y) - 1) / (y))
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported variables. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local variables and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver local functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
static inline unsigned int
|
||||
calculateIlluminance(TSL2561_integration_time_t integration_time,
|
||||
TSL2561_gain_t gain,
|
||||
uint16_t broadband, uint16_t ir,
|
||||
unsigned int partno) {
|
||||
unsigned long channel_1;
|
||||
unsigned long channel_0;
|
||||
|
||||
/* Get value for channel scaling, and clipping */
|
||||
uint16_t clip_threshold = 0;
|
||||
unsigned long channel_scale = 0;
|
||||
switch (integration_time) {
|
||||
case TSL2561_INTEGRATIONTIME_SHORT:
|
||||
clip_threshold = TSL2561_CLIPPING_SHORT;
|
||||
channel_scale = TSL2561_LUX_CHSCALE_TINT0;
|
||||
break;
|
||||
case TSL2561_INTEGRATIONTIME_MEDIUM:
|
||||
clip_threshold = TSL2561_CLIPPING_MEDIUM;
|
||||
channel_scale = TSL2561_LUX_CHSCALE_TINT1;
|
||||
break;
|
||||
case TSL2561_INTEGRATIONTIME_LONG:
|
||||
clip_threshold = TSL2561_CLIPPING_LONG;
|
||||
channel_scale = (1 << TSL2561_LUX_CHSCALE);
|
||||
break;
|
||||
default:
|
||||
// assert failed
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check for saturated sensor (ie: clipping) */
|
||||
if ((broadband > clip_threshold) || (ir > clip_threshold)) {
|
||||
return TSL2561_OVERLOADED;
|
||||
}
|
||||
|
||||
/* Scale for gain (1x or 16x) */
|
||||
if (gain == TSL2561_GAIN_1X)
|
||||
channel_scale <<= 4;
|
||||
|
||||
/* Scale the channel values */
|
||||
channel_0 = (broadband * channel_scale) >> TSL2561_LUX_CHSCALE;
|
||||
channel_1 = (ir * channel_scale) >> TSL2561_LUX_CHSCALE;
|
||||
|
||||
/* Find the ratio of the channel values (Channel_1/Channel_0) */
|
||||
unsigned long _ratio = 0;
|
||||
if (channel_0 != 0)
|
||||
_ratio = (channel_1 << (TSL2561_LUX_RATIOSCALE+1)) / channel_0;
|
||||
unsigned long ratio = (_ratio + 1) >> 1; /* round the ratio value */
|
||||
|
||||
/* Find linear approximation */
|
||||
unsigned int b = 0;
|
||||
unsigned int m = 0;
|
||||
|
||||
switch (partno) {
|
||||
#if TSL2561_WITH_CS
|
||||
case 0x1: // 0001 = TSL2561 CS
|
||||
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1C))
|
||||
{ b=TSL2561_LUX_B1C; m=TSL2561_LUX_M1C; }
|
||||
else if (ratio <= TSL2561_LUX_K2C)
|
||||
{ b=TSL2561_LUX_B2C; m=TSL2561_LUX_M2C; }
|
||||
else if (ratio <= TSL2561_LUX_K3C)
|
||||
{ b=TSL2561_LUX_B3C; m=TSL2561_LUX_M3C; }
|
||||
else if (ratio <= TSL2561_LUX_K4C)
|
||||
{ b=TSL2561_LUX_B4C; m=TSL2561_LUX_M4C; }
|
||||
else if (ratio <= TSL2561_LUX_K5C)
|
||||
{ b=TSL2561_LUX_B5C; m=TSL2561_LUX_M5C; }
|
||||
else if (ratio <= TSL2561_LUX_K6C)
|
||||
{ b=TSL2561_LUX_B6C; m=TSL2561_LUX_M6C; }
|
||||
else if (ratio <= TSL2561_LUX_K7C)
|
||||
{ b=TSL2561_LUX_B7C; m=TSL2561_LUX_M7C; }
|
||||
else if (ratio > TSL2561_LUX_K8C)
|
||||
{ b=TSL2561_LUX_B8C; m=TSL2561_LUX_M8C; }
|
||||
break;
|
||||
#endif
|
||||
#if TSL2561_WITH_T_FN_CL
|
||||
case 0x5: // 0101 = TSL2561 T/FN/CL
|
||||
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T))
|
||||
{ b=TSL2561_LUX_B1T; m=TSL2561_LUX_M1T; }
|
||||
else if (ratio <= TSL2561_LUX_K2T)
|
||||
{ b=TSL2561_LUX_B2T; m=TSL2561_LUX_M2T; }
|
||||
else if (ratio <= TSL2561_LUX_K3T)
|
||||
{ b=TSL2561_LUX_B3T; m=TSL2561_LUX_M3T; }
|
||||
else if (ratio <= TSL2561_LUX_K4T)
|
||||
{ b=TSL2561_LUX_B4T; m=TSL2561_LUX_M4T; }
|
||||
else if (ratio <= TSL2561_LUX_K5T)
|
||||
{ b=TSL2561_LUX_B5T; m=TSL2561_LUX_M5T; }
|
||||
else if (ratio <= TSL2561_LUX_K6T)
|
||||
{ b=TSL2561_LUX_B6T; m=TSL2561_LUX_M6T; }
|
||||
else if (ratio <= TSL2561_LUX_K7T)
|
||||
{ b=TSL2561_LUX_B7T; m=TSL2561_LUX_M7T; }
|
||||
else if (ratio > TSL2561_LUX_K8T)
|
||||
{ b=TSL2561_LUX_B8T; m=TSL2561_LUX_M8T; }
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
// assert failed
|
||||
break;
|
||||
}
|
||||
|
||||
/* Compute illuminance */
|
||||
long ill = ((channel_0 * b) - (channel_1 * m));
|
||||
if (ill < 0) ill = 0; /* Do not allow negative lux value */
|
||||
ill += (1 << (TSL2561_LUX_LUXSCALE-1)); /* Round lsb (2^(LUX_SCALE-1)) */
|
||||
ill >>= TSL2561_LUX_LUXSCALE; /* Strip fractional part */
|
||||
|
||||
/* Signal I2C had no errors */
|
||||
return ill;
|
||||
}
|
||||
|
||||
static inline msg_t
|
||||
_readChannel(TSL2561_drv *drv, uint16_t *broadband, uint16_t *ir) {
|
||||
msg_t msg;
|
||||
if (((msg = i2c_reg_recv16_le(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT |
|
||||
TSL2561_REG_CHAN0_LOW,
|
||||
broadband)) < MSG_OK) ||
|
||||
((msg = i2c_reg_recv16_le(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT |
|
||||
TSL2561_REG_CHAN1_LOW,
|
||||
ir )) < MSG_OK))
|
||||
return msg;
|
||||
|
||||
|
||||
chprintf(&SD1, "CHANNELS : %x, %x\r\n", *broadband, *ir);
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver exported functions. */
|
||||
/*===========================================================================*/
|
||||
|
||||
void
|
||||
TSL2561_init(TSL2561_drv *drv, TSL2561_config *config) {
|
||||
drv->config = config;
|
||||
drv->gain = TSL2561_GAIN_1X;
|
||||
drv->integration_time = TSL2561_INTEGRATIONTIME_SHORT;
|
||||
drv->state = SENSOR_INIT;
|
||||
|
||||
i2c_reg_recv8(TSL2561_COMMAND_BIT | TSL2561_REG_ID,
|
||||
(uint8_t*)&drv->id);
|
||||
}
|
||||
|
||||
msg_t
|
||||
TSL2561_check(TSL2561_drv *drv) {
|
||||
uint8_t rx;
|
||||
|
||||
msg_t msg;
|
||||
if ((msg = i2c_reg_recv8(TSL2561_REG_ID, &rx)) < MSG_OK)
|
||||
return msg;
|
||||
if (!(rx & 0x0A))
|
||||
return SENSOR_NOTFOUND;
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
msg_t
|
||||
TSL2561_stop(TSL2561_drv *drv) {
|
||||
struct PACKED {
|
||||
uint8_t reg;
|
||||
uint8_t conf;
|
||||
} tx = { TSL2561_COMMAND_BIT | TSL2561_REG_CONTROL,
|
||||
TSL2561_CONTROL_POWEROFF };
|
||||
|
||||
return i2c_send((uint8_t*)&tx, sizeof(tx));
|
||||
}
|
||||
|
||||
msg_t
|
||||
TSL2561_start(TSL2561_drv *drv) {
|
||||
struct PACKED {
|
||||
uint8_t reg;
|
||||
uint8_t conf;
|
||||
} tx = { TSL2561_COMMAND_BIT | TSL2561_REG_CONTROL,
|
||||
TSL2561_CONTROL_POWERON };
|
||||
|
||||
return i2c_send((uint8_t*)&tx, sizeof(tx));
|
||||
}
|
||||
|
||||
msg_t
|
||||
TSL2561_setIntegrationTime(TSL2561_drv *drv,
|
||||
TSL2561_integration_time_t time) {
|
||||
struct PACKED {
|
||||
uint8_t reg;
|
||||
uint8_t conf;
|
||||
} tx = { TSL2561_COMMAND_BIT | TSL2561_REG_TIMING,
|
||||
(uint8_t)(time | drv->gain) };
|
||||
|
||||
msg_t msg;
|
||||
if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
|
||||
return msg;
|
||||
|
||||
drv->integration_time = time;
|
||||
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
msg_t
|
||||
TSL2561_setGain(TSL2561_drv *drv,
|
||||
TSL2561_gain_t gain) {
|
||||
struct PACKED {
|
||||
uint8_t reg;
|
||||
uint8_t conf;
|
||||
} tx = { TSL2561_COMMAND_BIT | TSL2561_REG_TIMING,
|
||||
(uint8_t)(drv->integration_time | gain) };
|
||||
|
||||
msg_t msg;
|
||||
if ((msg = i2c_send((uint8_t*)&tx, sizeof(tx))) < MSG_OK)
|
||||
return msg;
|
||||
|
||||
drv->gain = gain;
|
||||
|
||||
return MSG_OK;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
TSL2561_getAcquisitionTime(TSL2561_drv *drv) {
|
||||
switch (drv->integration_time) {
|
||||
case TSL2561_INTEGRATIONTIME_SHORT:
|
||||
return CEILING(TSL2561_DELAY_INTTIME_SHORT , 1000);
|
||||
case TSL2561_INTEGRATIONTIME_MEDIUM:
|
||||
return CEILING(TSL2561_DELAY_INTTIME_MEDIUM, 1000);
|
||||
case TSL2561_INTEGRATIONTIME_LONG:
|
||||
return CEILING(TSL2561_DELAY_INTTIME_LONG , 1000);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
msg_t
|
||||
TSL2561_readIlluminance(TSL2561_drv *drv,
|
||||
unsigned int *illuminance) {
|
||||
uint16_t broadband;
|
||||
uint16_t ir;
|
||||
|
||||
/* Read channels */
|
||||
msg_t msg;
|
||||
if ((msg = _readChannel(drv, &broadband, &ir)) < MSG_OK)
|
||||
return msg;
|
||||
|
||||
/* Calculate illuminance */
|
||||
*illuminance =
|
||||
calculateIlluminance(drv->integration_time, drv->gain,
|
||||
broadband, ir, drv->id.partno);
|
||||
/* Ok */
|
||||
return SENSOR_OK;
|
||||
}
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
TSL2561 for ChibiOS/RT - Copyright (C) 2016 Stephane D'Alu
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file tsl2561.h
|
||||
* @brief TSL2561 Light sensor interface module header.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _SENSOR_TSL2561_H_
|
||||
#define _SENSOR_TSL2561_H_
|
||||
|
||||
#include <math.h>
|
||||
#include "i2c_helpers.h"
|
||||
#include "sensor.h"
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver constants. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#define TSL2561_CONTINUOUS_ACQUISITION_SUPPORTED TRUE
|
||||
|
||||
#define TSL2561_OVERLOADED (-1)
|
||||
|
||||
|
||||
// I2C address
|
||||
#define TSL2561_I2CADDR_LOW (0x29)
|
||||
#define TSL2561_I2CADDR_FLOAT (0x39)
|
||||
#define TSL2561_I2CADDR_HIGH (0x49)
|
||||
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver pre-compile time settings. */
|
||||
/*===========================================================================*/
|
||||
|
||||
#ifndef TSL2561_WITH_CS
|
||||
#define TSL2561_WITH_CS 0
|
||||
#endif
|
||||
|
||||
#ifndef TSL2561_WITH_T_FN_CL
|
||||
#define TSL2561_WITH_T_FN_CL 1
|
||||
#endif
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Derived constants and error checks. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
#define TSL2561_I2CADDR_DEFAULT TSL2561_I2CADDR_FLOAT
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver data structures and types. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief TSL2561 configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
I2CHelper i2c; /* keep it first */
|
||||
} TSL2561_config;
|
||||
|
||||
|
||||
typedef enum {
|
||||
TSL2561_INTEGRATIONTIME_SHORT = 0x00, // 13.7ms
|
||||
TSL2561_INTEGRATIONTIME_MEDIUM = 0x01, // 101ms
|
||||
TSL2561_INTEGRATIONTIME_LONG = 0x02, // 402ms
|
||||
} TSL2561_integration_time_t;
|
||||
|
||||
typedef enum {
|
||||
TSL2561_GAIN_1X = 0x00, // No gain
|
||||
TSL2561_GAIN_16X = 0x10, // 16x gain
|
||||
} TSL2561_gain_t;
|
||||
|
||||
/**
|
||||
* @brief TSL2561 configuration structure.
|
||||
*/
|
||||
typedef struct {
|
||||
TSL2561_config *config;
|
||||
sensor_state_t state;
|
||||
unsigned int delay;
|
||||
uint16_t cfg;
|
||||
TSL2561_gain_t gain;
|
||||
TSL2561_integration_time_t integration_time;
|
||||
struct PACKED {
|
||||
uint8_t revno : 4;
|
||||
uint8_t partno : 4; } id;
|
||||
} TSL2561_drv;
|
||||
|
||||
/*===========================================================================*/
|
||||
/* Driver macros. */
|
||||
/*===========================================================================*/
|
||||
|
||||
|
||||
/*===========================================================================*/
|
||||
/* External declarations. */
|
||||
/*===========================================================================*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the sensor driver
|
||||
*/
|
||||
void
|
||||
TSL2561_init(TSL2561_drv *drv,
|
||||
TSL2561_config *config);
|
||||
|
||||
/**
|
||||
* @brief Start the sensor
|
||||
*/
|
||||
msg_t
|
||||
TSL2561_start(TSL2561_drv *drv);
|
||||
|
||||
/**
|
||||
* @brief Stop the sensor
|
||||
*
|
||||
* @details If the sensor support it, it will be put in low energy mode.
|
||||
*/
|
||||
msg_t
|
||||
TSL2561_stop(TSL2561_drv *drv);
|
||||
|
||||
/**
|
||||
* @brief Check that the sensor is really present
|
||||
*/
|
||||
msg_t
|
||||
TSL2561_check(TSL2561_drv *drv);
|
||||
|
||||
/**
|
||||
* @brief Time in milli-seconds necessary for acquiring a naw measure
|
||||
*
|
||||
* @returns
|
||||
* unsigned int time in millis-seconds
|
||||
*/
|
||||
unsigned int
|
||||
TSL2561_getAcquisitionTime(TSL2561_drv *drv);
|
||||
|
||||
/**
|
||||
* @brief Trigger a mesure acquisition
|
||||
*/
|
||||
static inline msg_t
|
||||
TSL2561_startMeasure(TSL2561_drv *drv) {
|
||||
(void)drv;
|
||||
return MSG_OK;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read the newly acquiered measure
|
||||
*
|
||||
* @note According the the sensor design the measure read
|
||||
* can be any value acquired after the acquisition time
|
||||
* and the call to readMeasure.
|
||||
*/
|
||||
msg_t
|
||||
TSL2561_readMeasure(TSL2561_drv *drv,
|
||||
unsigned int illuminance);
|
||||
|
||||
msg_t
|
||||
TSL2561_setGain(TSL2561_drv *drv,
|
||||
TSL2561_gain_t gain);
|
||||
|
||||
msg_t
|
||||
TSL2561_setIntegrationTime(TSL2561_drv *drv,
|
||||
TSL2561_integration_time_t time);
|
||||
|
||||
/**
|
||||
* @brief Read temperature and humidity
|
||||
*
|
||||
* @details According to the sensor specification/configuration
|
||||
* (see #TSL2561_CONTINUOUS_ACQUISITION_SUPPORTED),
|
||||
* if the sensor is doing continuous measurement
|
||||
* it's value will be requested and returned immediately.
|
||||
* Otherwise a measure is started, the necessary amount of
|
||||
* time for acquiring the value is spend sleeping (not spinning),
|
||||
* and finally the measure is read.
|
||||
*
|
||||
* @note In continuous measurement mode, if you just started
|
||||
* the sensor, you will need to wait getAcquisitionTime()
|
||||
* in addition to the usual getStartupTime()
|
||||
|
||||
* @note If using several sensors, it is better to start all the
|
||||
* measure together, wait for the sensor having the longuest
|
||||
* aquisition time, and finally read all the values
|
||||
*/
|
||||
msg_t
|
||||
TSL2561_readIlluminance(TSL2561_drv *drv,
|
||||
unsigned int *illuminance);
|
||||
|
||||
/**
|
||||
* @brief Return the illuminance value in Lux
|
||||
*
|
||||
* @details Use readIlluminance() for returning the humidity value.
|
||||
*
|
||||
* @note Prefere readIlluminance()if you need better error handling.
|
||||
*
|
||||
* @return Illuminance in Lux
|
||||
* @retval unsigned int illuminace value
|
||||
* @retval -1 on failure
|
||||
*/
|
||||
static inline unsigned int
|
||||
TSL2561_getIlluminance(TSL2561_drv *drv) {
|
||||
unsigned int illuminance = -1;
|
||||
TSL2561_readIlluminance(drv, &illuminance);
|
||||
return illuminance;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef _SENSOR_H_
|
||||
#define _SENSOR_H_
|
||||
|
||||
#define SENSOR_OK MSG_OK /**< @brief Operation successful. */
|
||||
#define SENSOR_TIMEOUT MSG_TIMEOUT /**< @brief Communication timeout */
|
||||
#define SENSOR_RESET MSG_REST /**< @brief Communication error. */
|
||||
#define SENSOR_NOTFOUND (msg_t)-20 /**< @brief Sensor not found. */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Driver state machine possible states.
|
||||
*/
|
||||
typedef enum __attribute__ ((__packed__)) {
|
||||
SENSOR_UNINIT = 0, /**< Not initialized. */
|
||||
SENSOR_INIT = 1, /**< Initialized. */
|
||||
SENSOR_STARTED = 2, /**< Started. */
|
||||
SENSOR_MEASURING = 4, /**< Measuring. */
|
||||
SENSOR_READY = 3, /**< Ready. */
|
||||
SENSOR_STOPPED = 5, /**< Stopped. */
|
||||
SENSOR_ERROR = 6, /**< Error. */
|
||||
} sensor_state_t;
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue