Luminosity sensor by Texas Advanced Optoelectronic Solutions Inc.. Device combines one broadband photodiode (visible plus infrared) and one infrared-responding photodiode. Sets Gain x1 and 402mS as default.
Dependents: MusicBoxForFathersDay FTHR_SensorHub Affich_Lum_Moist Projetv0 ... more
TSL2561.cpp
- Committer:
- kenjiArai
- Date:
- 2018-09-21
- Revision:
- 5:5b1b625fda6f
- Parent:
- 4:05d322353720
File content as of revision 5:5b1b625fda6f:
/*!
* @file Adafruit_TSL2561_U.cpp
*
* @mainpage Adafruit TSL2561 Light/Lux sensor driver
*
* @section intro_sec Introduction
*
* This is the documentation for Adafruit's TSL2561 driver for the
* Arduino platform. It is designed specifically to work with the
* Adafruit TSL2561 breakout: http://www.adafruit.com/products/439
*
* These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
* to interface with the breakout.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* @section dependencies Dependencies
*
* This library depends on
* <a href="https://github.com/adafruit/Adafruit_Sensor">
* Adafruit_Sensor</a> being present on your system. Please make sure you have
* installed the latest version before using this library.
*
* @section author Author
*
* Written by Kevin "KTOWN" Townsend for Adafruit Industries.
*
* @section license License
*
* BSD license, all text here must be included in any redistribution.
*
* @section HISTORY
*
* v2.0 - Rewrote driver for Adafruit_Sensor and Auto-Gain support, and
* added lux clipping check (returns 0 lux on sensor saturation)
* v1.0 - First release (previously TSL2561)
*/
/**************************************************************************/
//------- Modified by ----------------------------------------------------------
// Kenji Arai / JH1PJL
// http://www.page.sannet.ne.jp/kenjia/index.html
// http://mbed.org/users/kenjiArai/
// Created: Feburary 21st, 2015
// Revised: August 23rd, 2017
// Revised: Feburary 20th, 2018 bug fix -> read_ID() & who_am_i()
// Thanks PARK JAICHANG
// Revised: March 31st, 2018 Added "Auto Range mode"
// Use Adafruit library
//
// Original information https://www.adafruit.com/product/439
// Original source files https://github.com/adafruit/TSL2561-Arduino-Library
// https://github.com/adafruit/Adafruit_TSL2561
// Change for Mbed platform
// modified -> all related files
//------------------------------------------------------------------------------
#include "TSL2561.h"
// 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
// Auto-gain thresholds
#define TSL2561_AGC_THI_13MS (4850) ///< Max value at Ti 13ms = 5047
#define TSL2561_AGC_TLO_13MS (100) ///< Min value at Ti 13ms = 100
#define TSL2561_AGC_THI_101MS (36000) ///< Max value at Ti 101ms = 37177
#define TSL2561_AGC_TLO_101MS (200) ///< Min value at Ti 101ms = 200
#define TSL2561_AGC_THI_402MS (63000) ///< Max value at Ti 402ms = 65535
#define TSL2561_AGC_TLO_402MS (500) ///< Min value at Ti 402ms = 500
// Clipping thresholds ///< # Counts that trigger a change in gain/integration
#define TSL2561_CLIPPING_13MS (4900)
#define TSL2561_CLIPPING_101MS (37000)
#define TSL2561_CLIPPING_402MS (65000)
// Delay for integration times
#define TSL2561_DELAY_INTTIME_13MS (15) ///< Wait 15ms for 13ms integration
#define TSL2561_DELAY_INTTIME_101MS (120) ///< Wait 120ms for 101ms integration
#define TSL2561_DELAY_INTTIME_402MS (450) ///< Wait 450ms for 402ms integration
/*========================================================================*/
/* CONSTRUCTORS */
/*========================================================================*/
TSL2561::TSL2561 (PinName p_sda, PinName p_scl)
: _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p)
{
_addr = TSL2561_ADDR_LOW;
init();
}
TSL2561::TSL2561 (PinName p_sda, PinName p_scl, uint8_t addr)
: _i2c_p(new I2C(p_sda, p_scl)), _i2c(*_i2c_p)
{
_addr = addr;
init();
}
TSL2561::TSL2561 (I2C& p_i2c)
: _i2c(p_i2c)
{
_addr = TSL2561_ADDR_LOW;
init();
}
TSL2561::TSL2561 (I2C& p_i2c, uint8_t addr)
: _i2c(p_i2c)
{
_addr = addr;
init();
}
/*========================================================================*/
/* PUBLIC FUNCTIONS */
/*========================================================================*/
/////////////// Read Lux from sensor //////////////////////
/*
For 0 < CH1/CH0 < 0.50 Lux = 0.0304 x CH0-0.062 x CH0 x ((CH1/CH0)1.4)
For 0.50 < CH1/CH0 < 0.61 Lux = 0.0224 x CH0-0.031 x CH1
For 0.61 < CH1/CH0 < 0.80 Lux = 0.0128 x CH0-0.0153 x CH1
For 0.80 < CH1/CH0 < 1.30 Lux = 0.00146 x CH0-0.00112x CH1
For CH1/CH0 > 1.30 Lux = 0
*/
float TSL2561::lux()
{
double lux0, lux1;
double ratio;
double dlux;
_TSL2561AutoGain = false;
_TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS;
_TSL2561Gain = TSL2561_GAIN_1X;
/* Set default integration time and gain */
setIntegrationTime(_TSL2561IntegrationTime);
setGain(_TSL2561Gain);
uint16_t x0, x1;
getLuminosity(&x0, &x1);
ch0 = x0;
ch1 = x1;
//printf("ch0 = %d, ch1 = %d\r\n", ch0, ch1);
//printf("Integ. Time = %d, Gain %d\r\n",
// _TSL2561IntegrationTime, _TSL2561Gain);
lux0 = (double)ch0;
lux1 = (double)ch1;
ratio = lux1 / lux0;
read_timing_reg();
lux0 *= (402.0/(double)integ_time);
lux1 *= (402.0/(double)integ_time);
lux0 /= gain;
lux1 /= gain;
//printf("Integ. Time = %f, Gain %d\r\n", integ_time, gain);
if (ratio <= 0.5) {
dlux = 0.03040 * lux0 - 0.06200 * lux0 * pow(ratio,1.4);
} else if (ratio <= 0.61) {
dlux = 0.02240 * lux0 - 0.03100 * lux1;
} else if (ratio <= 0.80) {
dlux = 0.01280 * lux0 - 0.01530 * lux1;
} else if (ratio <= 1.30) {
dlux = 0.00146 * lux0 - 0.00112 * lux1;
} else {
dlux = 0;
}
disable();
return (float)dlux;
}
float TSL2561::lux_auto(void)
{
uint32_t data;
enableAutoRange(true);
getEvent(&data);
//printf("line:%d\r\n", __LINE__);
return (float)data;
}
/**************************************************************************/
/*!
@brief Initializes I2C connection and settings.
Attempts to determine if the sensor is contactable, then sets up a default
integration time and gain. Then powers down the chip.
@returns True if sensor is found and initialized, false otherwise.
*/
/**************************************************************************/
bool TSL2561::init()
{
_TSL2561Initialised = false;
_TSL2561AutoGain = false;
_TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS;
_TSL2561Gain = TSL2561_GAIN_1X;
/* Make sure we're actually connected */
uint8_t x = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_ID);
if (x & 0xF0 != 0x50) { // ID code for TSL2561
//printf("initialize error!\r\n");
return false;
}
//printf("ID=0x%02x\r\n", x);
_TSL2561Initialised = true;
/* Set default integration time and gain */
setIntegrationTime(_TSL2561IntegrationTime);
setGain(_TSL2561Gain);
read_timing_reg();
/* Note: by default, the device is in power down mode on bootup */
disable();
t.reset();
t.start();
//printf("Integ. Time = %d, Gain %d\r\n",
// _TSL2561IntegrationTime, _TSL2561Gain);
//printf("initialize finished!\r\n");
x = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING);
//printf("TIMING REG=0x%02x\r\n", x);
return true;
}
/**************************************************************************/
/*!
@brief Enables or disables the auto-gain settings when reading
data from the sensor
@param enable Set to true to enable, False to disable
*/
/**************************************************************************/
void TSL2561::enableAutoRange(bool enable)
{
_TSL2561AutoGain = enable ? true : false;
}
/**************************************************************************/
/*!
@brief Sets the integration time for the TSL2561. Higher time means
more light captured (better for low light conditions) but will
take longer to run readings.
@param time The amount of time we'd like to add up values
*/
/**************************************************************************/
void TSL2561::setIntegrationTime(TSL2561IntegrationTime_t time)
{
/* Enable the device by setting the control bit to 0x03 */
enable();
/* Update the timing register */
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | _TSL2561Gain);
/* Update value placeholders */
_TSL2561IntegrationTime = time;
/* Turn the device off to save power */
disable();
}
/**************************************************************************/
/*!
@brief Adjusts the gain on the TSL2561 (adjusts the sensitivity to light)
@param gain The value we'd like to set the gain to
*/
/**************************************************************************/
void TSL2561::setGain(TSL2561Gain_t gain)
{
/* Enable the device by setting the control bit to 0x03 */
enable();
/* Update the timing register */
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, _TSL2561IntegrationTime | gain);
/* Update value placeholders */
_TSL2561Gain = gain;
/* Turn the device off to save power */
disable();
}
/**************************************************************************/
/*!
@brief Gets the broadband (mixed lighting) and IR only values from
the TSL2561, adjusting gain if auto-gain is enabled
@param broadband Pointer to a uint16_t we will fill with a sensor
reading from the IR+visible light diode.
@param ir Pointer to a uint16_t we will fill with a sensor the
IR-only light diode.
*/
/**************************************************************************/
void TSL2561::getLuminosity (uint16_t *broadband, uint16_t *ir)
{
bool valid = false;
/* If Auto gain disabled get a single reading and continue */
if(!_TSL2561AutoGain) {
//printf("Get data without Auto gain\r\n");
getData (broadband, ir);
return;
}
//printf("Get data with Auto gain\r\n");
/* Read data until we find a valid range */
bool _agcCheck = false;
do {
uint16_t _b, _ir;
uint16_t _hi, _lo;
TSL2561IntegrationTime_t _it = _TSL2561IntegrationTime;
/* Get the hi/low threshold for the current integration time */
switch(_it) {
case TSL2561_INTEGRATIONTIME_13MS:
_hi = TSL2561_AGC_THI_13MS;
_lo = TSL2561_AGC_TLO_13MS;
break;
case TSL2561_INTEGRATIONTIME_101MS:
_hi = TSL2561_AGC_THI_101MS;
_lo = TSL2561_AGC_TLO_101MS;
break;
default:
_hi = TSL2561_AGC_THI_402MS;
_lo = TSL2561_AGC_TLO_402MS;
break;
}
getData(&_b, &_ir);
/* Run an auto-gain check if we haven't already done so ... */
if (!_agcCheck) {
if ((_b < _lo) && (_TSL2561Gain == TSL2561_GAIN_1X)) {
/* Increase the gain and try again */
setGain(TSL2561_GAIN_16X);
/* Drop the previous conversion results */
getData(&_b, &_ir);
/* Set a flag to indicate we've adjusted the gain */
_agcCheck = true;
} else if ((_b > _hi) && (_TSL2561Gain == TSL2561_GAIN_16X)) {
/* Drop gain to 1x and try again */
setGain(TSL2561_GAIN_1X);
/* Drop the previous conversion results */
getData(&_b, &_ir);
/* Set a flag to indicate we've adjusted the gain */
_agcCheck = true;
} else {
/* Nothing to look at here, keep moving ....
Reading is either valid, or we're already at the chips limits */
*broadband = _b;
*ir = _ir;
valid = true;
}
} else {
/* If we've already adjusted the gain once, just return the new results.
This avoids endless loops where a value is at one extreme pre-gain,
and the the other extreme post-gain */
*broadband = _b;
*ir = _ir;
valid = true;
}
} while (!valid);
}
/**************************************************************************/
/*!
Enables the device
*/
/**************************************************************************/
void TSL2561::enable(void)
{
/* Enable the device by setting the control bit to 0x03 */
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWERON);
}
/**************************************************************************/
/*!
Disables the device (putting it in lower power sleep mode)
*/
/**************************************************************************/
void TSL2561::disable(void)
{
/* Turn the device off to save power */
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL, TSL2561_CONTROL_POWEROFF);
}
/**************************************************************************/
/*!
Private function to read luminosity on both channels
*/
/**************************************************************************/
void TSL2561::getData (uint16_t *broadband, uint16_t *ir)
{
/* Enable the device by setting the control bit to 0x03 */
enable();
/* Wait x ms for ADC to complete */
switch (_TSL2561IntegrationTime) {
case TSL2561_INTEGRATIONTIME_13MS:
wait_ms(TSL2561_DELAY_INTTIME_13MS);
break;
case TSL2561_INTEGRATIONTIME_101MS:
wait_ms(TSL2561_DELAY_INTTIME_101MS);
break;
default:
wait_ms(TSL2561_DELAY_INTTIME_402MS);
break;
}
/* Reads a two byte value from channel 0 (visible + infrared) */
*broadband = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW);
/* Reads a two byte value from channel 1 (infrared) */
*ir = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW);
/* Turn the device off to save power */
disable();
}
/**************************************************************************/
/*!
@brief Converts the raw sensor values to the standard SI lux equivalent.
@param broadband The 16-bit sensor reading from the IR+visible light diode.
@param ir The 16-bit sensor reading from the IR-only light diode.
@returns The integer Lux value we calcuated.
Returns 0 if the sensor is saturated and the values are
unreliable, or 65536 if the sensor is saturated.
*/
/**************************************************************************/
/**************************************************************************/
/*!
Returns
*/
/**************************************************************************/
uint32_t TSL2561::calculateLux(uint16_t broadband, uint16_t ir)
{
unsigned long chScale;
unsigned long channel1;
unsigned long channel0;
//printf("line:%d\r\n", __LINE__);
/* Make sure the sensor isn't saturated! */
uint16_t clipThreshold;
//printf("_TSL2561IntegrationTime=%d\r\n", _TSL2561IntegrationTime);
switch (_TSL2561IntegrationTime) {
case TSL2561_INTEGRATIONTIME_13MS:
clipThreshold = TSL2561_CLIPPING_13MS;
chScale = TSL2561_LUX_CHSCALE_TINT0;
//printf("line:%d\r\n", __LINE__);
break;
case TSL2561_INTEGRATIONTIME_101MS:
clipThreshold = TSL2561_CLIPPING_101MS;
chScale = TSL2561_LUX_CHSCALE_TINT1;
break;
default:
clipThreshold = TSL2561_CLIPPING_402MS;
chScale = (1 << TSL2561_LUX_CHSCALE);
break;
}
//printf("clipThreshold=%d\r\n", clipThreshold);
/* Return 65536 lux if the sensor is saturated */
if ((broadband > clipThreshold) || (ir > clipThreshold)) {
//printf("line:%d\r\n", __LINE__);
return 65536;
}
//printf("line:%d\r\n", __LINE__);
//printf("chScale=%d\r\n", chScale);
/* Scale for gain (1x or 16x) */
if (!_TSL2561Gain) {
chScale = chScale << 4;
}
//printf("chScale=%d\r\n", chScale);
/* Scale the channel values */
channel0 = (broadband * chScale) >> TSL2561_LUX_CHSCALE;
channel1 = (ir * chScale) >> TSL2561_LUX_CHSCALE;
//printf("channel0=%d, channel1=%d\r\n", channel0, channel1);
/* Find the ratio of the channel values (Channel1/Channel0) */
unsigned long ratio1 = 0;
if (channel0 != 0) {
ratio1 = (channel1 << (TSL2561_LUX_RATIOSCALE+1)) / channel0;
}
/* round the ratio value */
long ratio = (ratio1 + 1) >> 1;
//printf("ratio1=%d, ratio=%d\r\n", ratio1, ratio);
unsigned int b, m;
#ifdef TSL2561_PACKAGE_CS
//printf("line:%d\r\n", __LINE__);
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;
}
#else
//printf("line:%d\r\n", __LINE__);
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;
}
#endif
long temp;
temp = ((channel0 * b) - (channel1 * m));
/* Do not allow negative lux value */
if (temp < 0L) {
temp = 0;
}
//printf("line:%d\r\n", __LINE__);
/* Round lsb (2^(LUX_SCALE-1)) */
temp += (1 << (TSL2561_LUX_LUXSCALE-1));
/* Strip off fractional portion */
uint32_t lux = temp >> TSL2561_LUX_LUXSCALE;
/* Signal I2C had no errors */
//printf("Lux=%d\r\n", lux);
return lux;
}
/**************************************************************************/
/*!
@brief Gets the most recent sensor event
@param event Pointer to a sensor_event_t type that will be filled
with the lux value, timestamp, data type and sensor ID.
@returns True if sensor reading is between 0 and 65535 lux,
false if sensor is saturated
*/
/**************************************************************************/
bool TSL2561::getEvent(uint32_t *event)
{
uint16_t broadband, ir;
/* Calculate the actual lux value */
getLuminosity(&broadband, &ir);
//printf("broadband=%d, ir=%d\r\n", broadband, ir);
*event = calculateLux(broadband, ir);
//printf("LUX=%f\r\n", event->light);
//printf("LUX=%d\r\n", *event);
//printf("line:%d\r\n", __LINE__);
if (*event == 65536) {
//printf("line:%d\r\n", __LINE__);
return false;
}
//printf("line:%d\r\n", __LINE__);
return true;
}
/**************************************************************************/
/*!
@brief Gets the sensor_t data
@param sensor A pointer to a sensor_t structure that we will fill with
details about the TSL2561 and its capabilities
*/
/**************************************************************************/
void TSL2561::getSensor(sensor_t *sensor)
{
/* Insert the sensor name in the fixed length char array */
//sensor->version = 1;
sensor->min_delay = 0;
sensor->max_value = 17000.0; /* Based on trial and error ... confirm! */
sensor->min_value = 1.0;
sensor->resolution = 1.0;
}
/*========================================================================*/
/* PRIVATE FUNCTIONS */
/*========================================================================*/
/**************************************************************************/
/*!
@brief Writes a register and an 8 bit value over I2C
@param reg I2C register to write the value to
@param value The 8-bit value we're writing to the register
*/
/**************************************************************************/
void TSL2561::write8 (uint8_t reg, uint8_t value)
{
dt[0] = reg;
dt[1] = value;
_i2c.write((int)_addr, (char *)dt, 2, false);
}
/**************************************************************************/
/*!
@brief Reads an 8 bit value over I2C
@param reg I2C register to read from
@returns 8-bit value containing single byte data read
*/
/**************************************************************************/
uint8_t TSL2561::read8(uint8_t reg)
{
dt[0] = reg;
_i2c.write((int)_addr, (char *)dt, 1, true);
_i2c.read(_addr, (char *)dt, 1, false);
return dt[0];
}
/**************************************************************************/
/*!
@brief Reads a 16 bit values over I2C
@param reg I2C register to read from
@returns 16-bit value containing 2-byte data read
*/
/**************************************************************************/
uint16_t TSL2561::read16(uint8_t reg)
{
dt[0] = reg;
_i2c.write((int)_addr, (char *)dt, 1, true);
_i2c.read(_addr, (char *)dt, 2, false);
uint16_t data = ((uint16_t)dt[1] << 8) + dt[0];
return data;
}
/*========================================================================*/
/* JH1PJL Original Functions -> Keep compacibility for older revision */
/*========================================================================*/
/////////////// Timing Register ///////////////////////////
uint8_t TSL2561::set_timing_reg(uint8_t parameter)
{
enable();
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, parameter);
return read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING);
}
uint8_t TSL2561::read_timing_reg(void)
{
uint8_t i, data;
data = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING);
if (data & TSL2561_GAIN_16X) {
gain = 16;
_TSL2561Gain = TSL2561_GAIN_16X;
} else {
gain = 1;
_TSL2561Gain = TSL2561_GAIN_1X;
}
i = data & 0x3;
switch (i) {
case 0:
integ_time = 13.7;
_TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS;
break;
case 1:
integ_time = 101.0;
_TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_101MS;
break;
case 2:
integ_time = 402.0;
_TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_402MS;
break;
default:
integ_time = 0;
_TSL2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS;
break;
}
return dt[0];
}
/////////////// ID ////////////////////////////////////////
uint8_t TSL2561::read_ID()
{
id_number = read8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_ID);
return id_number;
}
uint8_t TSL2561::who_am_i()
{
read_ID();
if ((id_number >> 4) == I_AM_TSL2561CS) {
return 1;
} else if ((id_number >> 4) == I_AM_TSL2561T_FN_CL) {
return 1;
} else {
return 0;
}
}
/////////////// Power ON/OFF //////////////////////////////
void TSL2561::power_up()
{
enable();
}
void TSL2561::power_down()
{
disable();
}
/////////////// I2C Freq. /////////////////////////////////
void TSL2561::frequency(int hz)
{
_i2c.frequency(hz);
}