forked from adafruit/Adafruit_TSL2561
error handling and optimizations
This commit is contained in:
@@ -43,27 +43,13 @@
|
|||||||
|
|
||||||
#include <espchrono.h>
|
#include <espchrono.h>
|
||||||
|
|
||||||
/*========================================================================*/
|
//#define DEBUG_OUTPUT
|
||||||
/* CONSTRUCTORS */
|
#ifdef DEBUG_OUTPUT
|
||||||
/*========================================================================*/
|
#include <esp_log.h>
|
||||||
|
#define DBGPRNT(format, ...) ESP_LOGW("TSL2561", format, ##__VA_ARGS__)
|
||||||
/**************************************************************************/
|
#else
|
||||||
/*!
|
#define DBGPRNT(format, ...)
|
||||||
@brief Constructor
|
#endif
|
||||||
@param addr The I2C address this chip can be found on, 0x29, 0x39 or 0x49
|
|
||||||
@param sensorID An optional ID that will be placed in sensor events to help
|
|
||||||
keep track if you have many sensors in use
|
|
||||||
*/
|
|
||||||
/**************************************************************************/
|
|
||||||
Adafruit_TSL2561_Unified::Adafruit_TSL2561_Unified(uint8_t addr,
|
|
||||||
int32_t sensorID) {
|
|
||||||
_addr = addr;
|
|
||||||
_tsl2561Initialised = false;
|
|
||||||
_tsl2561AutoGain = false;
|
|
||||||
_tsl2561IntegrationTime = TSL2561_INTEGRATIONTIME_13MS;
|
|
||||||
_tsl2561Gain = TSL2561_GAIN_1X;
|
|
||||||
_tsl2561SensorID = sensorID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
/* PUBLIC FUNCTIONS */
|
/* PUBLIC FUNCTIONS */
|
||||||
@@ -76,11 +62,16 @@ Adafruit_TSL2561_Unified::Adafruit_TSL2561_Unified(uint8_t addr,
|
|||||||
@returns True if sensor is found and initialized, false otherwise.
|
@returns True if sensor is found and initialized, false otherwise.
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
boolean Adafruit_TSL2561_Unified::begin(bool skipWireBegin) {
|
bool Adafruit_TSL2561_Unified::begin(bool skipWireBegin) {
|
||||||
_i2c = &Wire;
|
_i2c = &Wire;
|
||||||
|
|
||||||
if (!skipWireBegin)
|
if (!skipWireBegin)
|
||||||
_i2c->begin();
|
if (!_i2c->begin())
|
||||||
return init();
|
{ DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
if (!init()) { DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -91,11 +82,16 @@ boolean Adafruit_TSL2561_Unified::begin(bool skipWireBegin) {
|
|||||||
@returns True if sensor is found and initialized, false otherwise.
|
@returns True if sensor is found and initialized, false otherwise.
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
boolean Adafruit_TSL2561_Unified::begin(TwoWire *theWire, bool skipWireBegin) {
|
bool Adafruit_TSL2561_Unified::begin(TwoWire *theWire, bool skipWireBegin) {
|
||||||
_i2c = theWire;
|
_i2c = theWire;
|
||||||
|
|
||||||
if (!skipWireBegin)
|
if (!skipWireBegin)
|
||||||
_i2c->begin();
|
if (!_i2c->begin())
|
||||||
return init();
|
{ DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
if (!init()) { DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -106,22 +102,30 @@ boolean Adafruit_TSL2561_Unified::begin(TwoWire *theWire, bool skipWireBegin) {
|
|||||||
@returns True if sensor is found and initialized, false otherwise.
|
@returns True if sensor is found and initialized, false otherwise.
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
boolean Adafruit_TSL2561_Unified::init() {
|
bool Adafruit_TSL2561_Unified::init() {
|
||||||
|
if (!_i2c) { DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
/* Make sure we're actually connected */
|
/* Make sure we're actually connected */
|
||||||
uint8_t x = read8(TSL2561_REGISTER_ID);
|
if (std::optional<uint8_t> x = read8(TSL2561_REGISTER_ID)) {
|
||||||
if (x & 0x05) { // ID code for TSL2561
|
if (*x & 0x05) { // ID code for TSL2561
|
||||||
return false;
|
DBGPRNT("fail"); return false;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
DBGPRNT("fail"); return false;
|
||||||
|
}
|
||||||
|
|
||||||
_tsl2561Initialised = true;
|
_tsl2561Initialised = true;
|
||||||
|
|
||||||
|
bool succ{true};
|
||||||
|
|
||||||
/* Set default integration time and gain */
|
/* Set default integration time and gain */
|
||||||
setIntegrationTime(_tsl2561IntegrationTime);
|
if (!setIntegrationTimePriv(_tsl2561IntegrationTime)) { DBGPRNT("fail"); succ = false; }
|
||||||
setGain(_tsl2561Gain);
|
if (!setGainPriv(_tsl2561Gain)) { DBGPRNT("fail"); succ = false; }
|
||||||
|
|
||||||
/* Note: by default, the device is in power down mode on bootup */
|
/* Note: by default, the device is in power down mode on bootup */
|
||||||
disable();
|
if (!disable()) { DBGPRNT("fail"); succ = false; }
|
||||||
|
|
||||||
return true;
|
return succ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -143,22 +147,41 @@ void Adafruit_TSL2561_Unified::enableAutoRange(bool enable) {
|
|||||||
@param time The amount of time we'd like to add up values
|
@param time The amount of time we'd like to add up values
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void Adafruit_TSL2561_Unified::setIntegrationTime(
|
bool Adafruit_TSL2561_Unified::setIntegrationTime(tsl2561IntegrationTime_t time) {
|
||||||
tsl2561IntegrationTime_t time) {
|
|
||||||
if (!_tsl2561Initialised)
|
if (!_tsl2561Initialised)
|
||||||
begin();
|
if (!init())
|
||||||
|
{ DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
return setIntegrationTimePriv(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@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
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
bool Adafruit_TSL2561_Unified::setIntegrationTimePriv(tsl2561IntegrationTime_t time) {
|
||||||
/* Enable the device by setting the control bit to 0x03 */
|
/* Enable the device by setting the control bit to 0x03 */
|
||||||
enable();
|
if (!enable())
|
||||||
|
{ DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
bool succ{true};
|
||||||
|
|
||||||
/* Update the timing register */
|
/* Update the timing register */
|
||||||
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | _tsl2561Gain);
|
if (!write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING, time | _tsl2561Gain))
|
||||||
|
{ DBGPRNT("fail"); succ = false; }
|
||||||
|
|
||||||
/* Update value placeholders */
|
/* Update value placeholders */
|
||||||
_tsl2561IntegrationTime = time;
|
_tsl2561IntegrationTime = time;
|
||||||
|
|
||||||
/* Turn the device off to save power */
|
/* Turn the device off to save power */
|
||||||
disable();
|
if (!disable()) { DBGPRNT("fail"); succ = false; }
|
||||||
|
|
||||||
|
return succ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -167,22 +190,40 @@ void Adafruit_TSL2561_Unified::setIntegrationTime(
|
|||||||
@param gain The value we'd like to set the gain to
|
@param gain The value we'd like to set the gain to
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void Adafruit_TSL2561_Unified::setGain(tsl2561Gain_t gain) {
|
bool Adafruit_TSL2561_Unified::setGain(tsl2561Gain_t gain) {
|
||||||
if (!_tsl2561Initialised)
|
if (!_tsl2561Initialised)
|
||||||
begin();
|
if (!init())
|
||||||
|
{ DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
return setGainPriv(gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************/
|
||||||
|
/*!
|
||||||
|
@brief Adjusts the gain on the TSL2561 (adjusts the sensitivity to light)
|
||||||
|
@param gain The value we'd like to set the gain to
|
||||||
|
*/
|
||||||
|
/**************************************************************************/
|
||||||
|
bool Adafruit_TSL2561_Unified::setGainPriv(tsl2561Gain_t gain) {
|
||||||
/* Enable the device by setting the control bit to 0x03 */
|
/* Enable the device by setting the control bit to 0x03 */
|
||||||
enable();
|
if (!enable())
|
||||||
|
{ DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
bool succ{true};
|
||||||
|
|
||||||
/* Update the timing register */
|
/* Update the timing register */
|
||||||
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,
|
if (!write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_TIMING,
|
||||||
_tsl2561IntegrationTime | gain);
|
_tsl2561IntegrationTime | gain))
|
||||||
|
{ DBGPRNT("fail"); succ = false; }
|
||||||
|
|
||||||
/* Update value placeholders */
|
/* Update value placeholders */
|
||||||
_tsl2561Gain = gain;
|
_tsl2561Gain = gain;
|
||||||
|
|
||||||
/* Turn the device off to save power */
|
/* Turn the device off to save power */
|
||||||
disable();
|
if (!disable()) { DBGPRNT("fail"); succ = false; }
|
||||||
|
|
||||||
|
return succ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -195,23 +236,23 @@ void Adafruit_TSL2561_Unified::setGain(tsl2561Gain_t gain) {
|
|||||||
IR-only light diode.
|
IR-only light diode.
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void Adafruit_TSL2561_Unified::getLuminosity(uint16_t *broadband,
|
std::optional<Adafruit_TSL2561_Unified::Luminosity> Adafruit_TSL2561_Unified::getLuminosity() {
|
||||||
uint16_t *ir) {
|
|
||||||
bool valid = false;
|
|
||||||
|
|
||||||
if (!_tsl2561Initialised)
|
if (!_tsl2561Initialised)
|
||||||
begin();
|
if (!init())
|
||||||
|
{ DBGPRNT("fail"); return std::nullopt; }
|
||||||
|
|
||||||
/* If Auto gain disabled get a single reading and continue */
|
/* If Auto gain disabled get a single reading and continue */
|
||||||
if (!_tsl2561AutoGain) {
|
if (!_tsl2561AutoGain) {
|
||||||
getData(broadband, ir);
|
if (const auto result = getData())
|
||||||
return;
|
return *result;
|
||||||
|
else
|
||||||
|
{ DBGPRNT("fail"); return std::nullopt; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read data until we find a valid range */
|
/* Read data until we find a valid range */
|
||||||
bool _agcCheck = false;
|
bool _agcCheck = false;
|
||||||
do {
|
while (true) {
|
||||||
uint16_t _b, _ir;
|
Luminosity luminosity;
|
||||||
uint16_t _hi, _lo;
|
uint16_t _hi, _lo;
|
||||||
tsl2561IntegrationTime_t _it = _tsl2561IntegrationTime;
|
tsl2561IntegrationTime_t _it = _tsl2561IntegrationTime;
|
||||||
|
|
||||||
@@ -231,40 +272,51 @@ void Adafruit_TSL2561_Unified::getLuminosity(uint16_t *broadband,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
getData(&_b, &_ir);
|
if (const auto result = getData())
|
||||||
|
luminosity = *result;
|
||||||
|
else
|
||||||
|
{ DBGPRNT("fail"); return std::nullopt; }
|
||||||
|
|
||||||
/* Run an auto-gain check if we haven't already done so ... */
|
/* Run an auto-gain check if we haven't already done so ... */
|
||||||
if (!_agcCheck) {
|
if (!_agcCheck) {
|
||||||
if ((_b < _lo) && (_tsl2561Gain == TSL2561_GAIN_1X)) {
|
if ((luminosity.broadband < _lo) && (_tsl2561Gain == TSL2561_GAIN_1X)) {
|
||||||
/* Increase the gain and try again */
|
/* Increase the gain and try again */
|
||||||
setGain(TSL2561_GAIN_16X);
|
if (!setGain(TSL2561_GAIN_16X))
|
||||||
|
{ DBGPRNT("fail"); return std::nullopt; }
|
||||||
|
|
||||||
/* Drop the previous conversion results */
|
/* Drop the previous conversion results */
|
||||||
getData(&_b, &_ir);
|
if (const auto result = getData())
|
||||||
|
luminosity = *result;
|
||||||
|
else
|
||||||
|
{ DBGPRNT("fail"); return std::nullopt; }
|
||||||
|
|
||||||
/* Set a flag to indicate we've adjusted the gain */
|
/* Set a flag to indicate we've adjusted the gain */
|
||||||
_agcCheck = true;
|
_agcCheck = true;
|
||||||
} else if ((_b > _hi) && (_tsl2561Gain == TSL2561_GAIN_16X)) {
|
} else if ((luminosity.broadband > _hi) && (_tsl2561Gain == TSL2561_GAIN_16X)) {
|
||||||
/* Drop gain to 1x and try again */
|
/* Drop gain to 1x and try again */
|
||||||
setGain(TSL2561_GAIN_1X);
|
if (!setGain(TSL2561_GAIN_1X))
|
||||||
|
{ DBGPRNT("fail"); return std::nullopt; }
|
||||||
|
|
||||||
/* Drop the previous conversion results */
|
/* Drop the previous conversion results */
|
||||||
getData(&_b, &_ir);
|
if (const auto result = getData())
|
||||||
|
luminosity = *result;
|
||||||
|
else
|
||||||
|
{ DBGPRNT("fail"); return std::nullopt; }
|
||||||
|
|
||||||
/* Set a flag to indicate we've adjusted the gain */
|
/* Set a flag to indicate we've adjusted the gain */
|
||||||
_agcCheck = true;
|
_agcCheck = true;
|
||||||
} else {
|
} else {
|
||||||
/* Nothing to look at here, keep moving ....
|
/* Nothing to look at here, keep moving ....
|
||||||
Reading is either valid, or we're already at the chips limits */
|
Reading is either valid, or we're already at the chips limits */
|
||||||
*broadband = _b;
|
return luminosity;
|
||||||
*ir = _ir;
|
|
||||||
valid = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* If we've already adjusted the gain once, just return the new results.
|
/* 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,
|
This avoids endless loops where a value is at one extreme pre-gain,
|
||||||
and the the other extreme post-gain */
|
and the the other extreme post-gain */
|
||||||
*broadband = _b;
|
return luminosity;
|
||||||
*ir = _ir;
|
}
|
||||||
valid = true;
|
|
||||||
}
|
}
|
||||||
} while (!valid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -272,10 +324,13 @@ void Adafruit_TSL2561_Unified::getLuminosity(uint16_t *broadband,
|
|||||||
Enables the device
|
Enables the device
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void Adafruit_TSL2561_Unified::enable(void) {
|
bool Adafruit_TSL2561_Unified::enable(void) {
|
||||||
/* Enable the device by setting the control bit to 0x03 */
|
/* Enable the device by setting the control bit to 0x03 */
|
||||||
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL,
|
if (!write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL,
|
||||||
TSL2561_CONTROL_POWERON);
|
TSL2561_CONTROL_POWERON))
|
||||||
|
{ DBGPRNT("fail"); return false; }
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -283,10 +338,13 @@ void Adafruit_TSL2561_Unified::enable(void) {
|
|||||||
Disables the device (putting it in lower power sleep mode)
|
Disables the device (putting it in lower power sleep mode)
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void Adafruit_TSL2561_Unified::disable(void) {
|
bool Adafruit_TSL2561_Unified::disable(void) {
|
||||||
/* Turn the device off to save power */
|
/* Turn the device off to save power */
|
||||||
write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL,
|
if (!write8(TSL2561_COMMAND_BIT | TSL2561_REGISTER_CONTROL,
|
||||||
TSL2561_CONTROL_POWEROFF);
|
TSL2561_CONTROL_POWEROFF))
|
||||||
|
{ DBGPRNT("fail"); return false; }
|
||||||
|
else
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -294,9 +352,10 @@ void Adafruit_TSL2561_Unified::disable(void) {
|
|||||||
Private function to read luminosity on both channels
|
Private function to read luminosity on both channels
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void Adafruit_TSL2561_Unified::getData(uint16_t *broadband, uint16_t *ir) {
|
std::optional<Adafruit_TSL2561_Unified::Luminosity> Adafruit_TSL2561_Unified::getData() {
|
||||||
/* Enable the device by setting the control bit to 0x03 */
|
/* Enable the device by setting the control bit to 0x03 */
|
||||||
enable();
|
if (!enable())
|
||||||
|
{ DBGPRNT("fail"); return std::nullopt; }
|
||||||
|
|
||||||
/* Wait x ms for ADC to complete */
|
/* Wait x ms for ADC to complete */
|
||||||
switch (_tsl2561IntegrationTime) {
|
switch (_tsl2561IntegrationTime) {
|
||||||
@@ -311,16 +370,28 @@ void Adafruit_TSL2561_Unified::getData(uint16_t *broadband, uint16_t *ir) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool succ{true};
|
||||||
|
Luminosity luminosity;
|
||||||
|
|
||||||
/* Reads a two byte value from channel 0 (visible + infrared) */
|
/* Reads a two byte value from channel 0 (visible + infrared) */
|
||||||
*broadband = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT |
|
if (const auto broadband = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN0_LOW))
|
||||||
TSL2561_REGISTER_CHAN0_LOW);
|
luminosity.broadband = *broadband;
|
||||||
|
else
|
||||||
|
{ DBGPRNT("fail"); succ = false; }
|
||||||
|
|
||||||
/* Reads a two byte value from channel 1 (infrared) */
|
/* Reads a two byte value from channel 1 (infrared) */
|
||||||
*ir = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT |
|
if (const auto ir = read16(TSL2561_COMMAND_BIT | TSL2561_WORD_BIT | TSL2561_REGISTER_CHAN1_LOW))
|
||||||
TSL2561_REGISTER_CHAN1_LOW);
|
luminosity.ir = *ir;
|
||||||
|
else
|
||||||
|
{ DBGPRNT("fail"); succ = false; }
|
||||||
|
|
||||||
/* Turn the device off to save power */
|
/* Turn the device off to save power */
|
||||||
disable();
|
if (!disable()) { DBGPRNT("fail"); succ = false; }
|
||||||
|
|
||||||
|
if (succ)
|
||||||
|
return luminosity;
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -339,11 +410,9 @@ void Adafruit_TSL2561_Unified::getData(uint16_t *broadband, uint16_t *ir) {
|
|||||||
Returns
|
Returns
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband,
|
std::optional<uint32_t> Adafruit_TSL2561_Unified::calculateLux(Luminosity luminosity) {
|
||||||
uint16_t ir) {
|
const uint16_t broadband = luminosity.broadband;
|
||||||
unsigned long chScale;
|
const uint16_t ir = luminosity.ir;
|
||||||
unsigned long channel1;
|
|
||||||
unsigned long channel0;
|
|
||||||
|
|
||||||
/* Make sure the sensor isn't saturated! */
|
/* Make sure the sensor isn't saturated! */
|
||||||
uint16_t clipThreshold;
|
uint16_t clipThreshold;
|
||||||
@@ -361,10 +430,12 @@ uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband,
|
|||||||
|
|
||||||
/* Return 65536 lux if the sensor is saturated */
|
/* Return 65536 lux if the sensor is saturated */
|
||||||
if ((broadband > clipThreshold) || (ir > clipThreshold)) {
|
if ((broadband > clipThreshold) || (ir > clipThreshold)) {
|
||||||
return 65536;
|
DBGPRNT("saturated");
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the correct scale depending on the intergration time */
|
/* Get the correct scale depending on the intergration time */
|
||||||
|
unsigned long chScale;
|
||||||
switch (_tsl2561IntegrationTime) {
|
switch (_tsl2561IntegrationTime) {
|
||||||
case TSL2561_INTEGRATIONTIME_13MS:
|
case TSL2561_INTEGRATIONTIME_13MS:
|
||||||
chScale = TSL2561_LUX_CHSCALE_TINT0;
|
chScale = TSL2561_LUX_CHSCALE_TINT0;
|
||||||
@@ -382,8 +453,8 @@ uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband,
|
|||||||
chScale = chScale << 4;
|
chScale = chScale << 4;
|
||||||
|
|
||||||
/* Scale the channel values */
|
/* Scale the channel values */
|
||||||
channel0 = (broadband * chScale) >> TSL2561_LUX_CHSCALE;
|
unsigned long channel0 = (broadband * chScale) >> TSL2561_LUX_CHSCALE;
|
||||||
channel1 = (ir * chScale) >> TSL2561_LUX_CHSCALE;
|
unsigned long channel1 = (ir * chScale) >> TSL2561_LUX_CHSCALE;
|
||||||
|
|
||||||
/* Find the ratio of the channel values (Channel1/Channel0) */
|
/* Find the ratio of the channel values (Channel1/Channel0) */
|
||||||
unsigned long ratio1 = 0;
|
unsigned long ratio1 = 0;
|
||||||
@@ -393,10 +464,10 @@ uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband,
|
|||||||
/* round the ratio value */
|
/* round the ratio value */
|
||||||
unsigned long ratio = (ratio1 + 1) >> 1;
|
unsigned long ratio = (ratio1 + 1) >> 1;
|
||||||
|
|
||||||
unsigned int b, m;
|
unsigned int b{}, m{};
|
||||||
|
|
||||||
#ifdef TSL2561_PACKAGE_CS
|
#ifdef TSL2561_PACKAGE_CS
|
||||||
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1C)) {
|
if ((ratio <= TSL2561_LUX_K1C)) {
|
||||||
b = TSL2561_LUX_B1C;
|
b = TSL2561_LUX_B1C;
|
||||||
m = TSL2561_LUX_M1C;
|
m = TSL2561_LUX_M1C;
|
||||||
} else if (ratio <= TSL2561_LUX_K2C) {
|
} else if (ratio <= TSL2561_LUX_K2C) {
|
||||||
@@ -422,7 +493,7 @@ uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband,
|
|||||||
m = TSL2561_LUX_M8C;
|
m = TSL2561_LUX_M8C;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if ((ratio >= 0) && (ratio <= TSL2561_LUX_K1T)) {
|
if ((ratio <= TSL2561_LUX_K1T)) {
|
||||||
b = TSL2561_LUX_B1T;
|
b = TSL2561_LUX_B1T;
|
||||||
m = TSL2561_LUX_M1T;
|
m = TSL2561_LUX_M1T;
|
||||||
} else if (ratio <= TSL2561_LUX_K2T) {
|
} else if (ratio <= TSL2561_LUX_K2T) {
|
||||||
@@ -446,20 +517,20 @@ uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband,
|
|||||||
} else if (ratio > TSL2561_LUX_K8T) {
|
} else if (ratio > TSL2561_LUX_K8T) {
|
||||||
b = TSL2561_LUX_B8T;
|
b = TSL2561_LUX_B8T;
|
||||||
m = TSL2561_LUX_M8T;
|
m = TSL2561_LUX_M8T;
|
||||||
} else {
|
|
||||||
b = 0;
|
|
||||||
m = 0;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned long temp;
|
|
||||||
channel0 = channel0 * b;
|
channel0 = channel0 * b;
|
||||||
channel1 = channel1 * m;
|
channel1 = channel1 * m;
|
||||||
|
|
||||||
temp = 0;
|
unsigned long temp{};
|
||||||
/* Do not allow negative lux value */
|
/* Do not allow negative lux value */
|
||||||
if (channel0 > channel1)
|
if (channel0 > channel1)
|
||||||
temp = channel0 - channel1;
|
temp = channel0 - channel1;
|
||||||
|
else {
|
||||||
|
DBGPRNT("negative lux");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
/* Round lsb (2^(LUX_SCALE-1)) */
|
/* Round lsb (2^(LUX_SCALE-1)) */
|
||||||
temp += (1 << (TSL2561_LUX_LUXSCALE - 1));
|
temp += (1 << (TSL2561_LUX_LUXSCALE - 1));
|
||||||
@@ -481,23 +552,20 @@ uint32_t Adafruit_TSL2561_Unified::calculateLux(uint16_t broadband,
|
|||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
std::optional<sensors_event_t> Adafruit_TSL2561_Unified::getEvent() {
|
std::optional<sensors_event_t> Adafruit_TSL2561_Unified::getEvent() {
|
||||||
|
auto luminosity = getLuminosity();
|
||||||
|
if (!luminosity) { DBGPRNT("fail"); return std::nullopt; }
|
||||||
|
|
||||||
|
/* Calculate the actual lux value */
|
||||||
|
auto lux = calculateLux(*luminosity);
|
||||||
|
if (!lux) { DBGPRNT("fail"); return std::nullopt; }
|
||||||
|
|
||||||
sensors_event_t event;
|
sensors_event_t event;
|
||||||
event.version = sizeof(sensors_event_t);
|
event.version = sizeof(sensors_event_t);
|
||||||
event.sensor_id = _tsl2561SensorID;
|
event.sensor_id = _tsl2561SensorID;
|
||||||
event.type = SENSOR_TYPE_LIGHT;
|
event.type = SENSOR_TYPE_LIGHT;
|
||||||
event.reserved0 = 0;
|
event.reserved0 = 0;
|
||||||
event.timestamp = espchrono::millis_clock::now();
|
event.timestamp = espchrono::millis_clock::now();
|
||||||
|
event.light = *lux;
|
||||||
{
|
|
||||||
/* Calculate the actual lux value */
|
|
||||||
uint16_t broadband, ir;
|
|
||||||
getLuminosity(&broadband, &ir);
|
|
||||||
event.light = calculateLux(broadband, ir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event.light == 65536) {
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
return event;
|
return event;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,11 +603,20 @@ sensor_t Adafruit_TSL2561_Unified::getSensor() {
|
|||||||
@param value The 8-bit value we're writing to the register
|
@param value The 8-bit value we're writing to the register
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
void Adafruit_TSL2561_Unified::write8(uint8_t reg, uint8_t value) {
|
bool Adafruit_TSL2561_Unified::write8(uint8_t reg, uint8_t value) {
|
||||||
|
if (!_i2c) { DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
bool succ{true};
|
||||||
|
|
||||||
_i2c->beginTransmission(_addr);
|
_i2c->beginTransmission(_addr);
|
||||||
_i2c->write(reg);
|
if (_i2c->write(reg) != 1) { DBGPRNT("fail"); succ = false; }
|
||||||
_i2c->write(value);
|
if (_i2c->write(value) != 1) { DBGPRNT("fail"); succ = false; }
|
||||||
_i2c->endTransmission();
|
if (const auto result = _i2c->endTransmission(); result != I2C_ERROR_OK) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||||
|
|
||||||
|
if (!succ)
|
||||||
|
_tsl2561Initialised = false;
|
||||||
|
|
||||||
|
return succ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -549,13 +626,27 @@ void Adafruit_TSL2561_Unified::write8(uint8_t reg, uint8_t value) {
|
|||||||
@returns 8-bit value containing single byte data read
|
@returns 8-bit value containing single byte data read
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
uint8_t Adafruit_TSL2561_Unified::read8(uint8_t reg) {
|
std::optional<uint8_t> Adafruit_TSL2561_Unified::read8(uint8_t reg) {
|
||||||
|
if (!_i2c) { DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
bool succ{true};
|
||||||
|
|
||||||
_i2c->beginTransmission(_addr);
|
_i2c->beginTransmission(_addr);
|
||||||
_i2c->write(reg);
|
if (_i2c->write(reg) != 1) { DBGPRNT("fail"); succ = false; }
|
||||||
|
if (const auto result = _i2c->endTransmission(); result != I2C_ERROR_OK) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||||
|
|
||||||
|
if (const auto result = _i2c->requestFrom(_addr, 1); result != 1) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||||
|
const auto result = _i2c->read();
|
||||||
|
if (result == -1) { DBGPRNT("fail %i", result); succ = false; }
|
||||||
_i2c->endTransmission();
|
_i2c->endTransmission();
|
||||||
|
|
||||||
_i2c->requestFrom(_addr, 1);
|
if (!succ)
|
||||||
return _i2c->read();
|
_tsl2561Initialised = false;
|
||||||
|
|
||||||
|
if (succ)
|
||||||
|
return result;
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
@@ -565,17 +656,32 @@ uint8_t Adafruit_TSL2561_Unified::read8(uint8_t reg) {
|
|||||||
@returns 16-bit value containing 2-byte data read
|
@returns 16-bit value containing 2-byte data read
|
||||||
*/
|
*/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
uint16_t Adafruit_TSL2561_Unified::read16(uint8_t reg) {
|
std::optional<uint16_t> Adafruit_TSL2561_Unified::read16(uint8_t reg) {
|
||||||
uint16_t x, t;
|
if (!_i2c) { DBGPRNT("fail"); return false; }
|
||||||
|
|
||||||
|
bool succ{true};
|
||||||
|
|
||||||
_i2c->beginTransmission(_addr);
|
_i2c->beginTransmission(_addr);
|
||||||
_i2c->write(reg);
|
if (_i2c->write(reg) != 1) { DBGPRNT("fail"); succ = false; }
|
||||||
_i2c->endTransmission();
|
if (const auto result = _i2c->endTransmission(); result != I2C_ERROR_OK) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||||
|
|
||||||
_i2c->requestFrom(_addr, 2);
|
if (const auto result = _i2c->requestFrom(_addr, 2); result != 2) { DBGPRNT("fail %hhu", result); succ = false; }
|
||||||
t = _i2c->read();
|
const auto result0 = _i2c->read();
|
||||||
x = _i2c->read();
|
const auto result1 = _i2c->read();
|
||||||
|
Wire.endTransmission();
|
||||||
|
|
||||||
|
if (result0 == -1) { DBGPRNT("fail %i", result0); succ = false; }
|
||||||
|
else if (result1 == -1) { DBGPRNT("fail %i", result1); succ = false; }
|
||||||
|
|
||||||
|
if (!succ)
|
||||||
|
_tsl2561Initialised = false;
|
||||||
|
|
||||||
|
if (succ) {
|
||||||
|
uint16_t t = result0, x = result1;
|
||||||
x <<= 8;
|
x <<= 8;
|
||||||
x |= t;
|
x |= t;
|
||||||
return x;
|
return x;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
@@ -146,17 +146,17 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Three options for how long to integrate readings for */
|
/** Three options for how long to integrate readings for */
|
||||||
typedef enum {
|
enum tsl2561IntegrationTime_t {
|
||||||
TSL2561_INTEGRATIONTIME_13MS = 0x00, // 13.7ms
|
TSL2561_INTEGRATIONTIME_13MS = 0x00, // 13.7ms
|
||||||
TSL2561_INTEGRATIONTIME_101MS = 0x01, // 101ms
|
TSL2561_INTEGRATIONTIME_101MS = 0x01, // 101ms
|
||||||
TSL2561_INTEGRATIONTIME_402MS = 0x02 // 402ms
|
TSL2561_INTEGRATIONTIME_402MS = 0x02 // 402ms
|
||||||
} tsl2561IntegrationTime_t;
|
};
|
||||||
|
|
||||||
/** TSL2561 offers 2 gain settings */
|
/** TSL2561 offers 2 gain settings */
|
||||||
typedef enum {
|
enum tsl2561Gain_t {
|
||||||
TSL2561_GAIN_1X = 0x00, // No gain
|
TSL2561_GAIN_1X = 0x00, // No gain
|
||||||
TSL2561_GAIN_16X = 0x10, // 16x gain
|
TSL2561_GAIN_16X = 0x10, // 16x gain
|
||||||
} tsl2561Gain_t;
|
};
|
||||||
|
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/*!
|
/*!
|
||||||
@@ -166,38 +166,50 @@ typedef enum {
|
|||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
class Adafruit_TSL2561_Unified : public Adafruit_Sensor {
|
class Adafruit_TSL2561_Unified : public Adafruit_Sensor {
|
||||||
public:
|
public:
|
||||||
Adafruit_TSL2561_Unified(uint8_t addr, int32_t sensorID = -1);
|
Adafruit_TSL2561_Unified(uint8_t addr, int32_t sensorID = -1) :
|
||||||
boolean begin(bool skipWireBegin = false);
|
_addr{addr},
|
||||||
boolean begin(TwoWire *theWire, bool skipWireBegin = false);
|
_tsl2561SensorID{sensorID}
|
||||||
boolean init();
|
{}
|
||||||
|
|
||||||
|
bool begin(bool skipWireBegin = false);
|
||||||
|
bool begin(TwoWire *theWire, bool skipWireBegin = false);
|
||||||
|
bool init();
|
||||||
|
|
||||||
/* TSL2561 Functions */
|
/* TSL2561 Functions */
|
||||||
void enableAutoRange(bool enable);
|
void enableAutoRange(bool enable);
|
||||||
void setIntegrationTime(tsl2561IntegrationTime_t time);
|
bool setIntegrationTime(tsl2561IntegrationTime_t time);
|
||||||
void setGain(tsl2561Gain_t gain);
|
private:
|
||||||
void getLuminosity(uint16_t *broadband, uint16_t *ir);
|
bool setIntegrationTimePriv(tsl2561IntegrationTime_t time);
|
||||||
uint32_t calculateLux(uint16_t broadband, uint16_t ir);
|
public:
|
||||||
|
bool setGain(tsl2561Gain_t gain);
|
||||||
|
private:
|
||||||
|
bool setGainPriv(tsl2561Gain_t gain);
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct Luminosity { uint16_t broadband; uint16_t ir; };
|
||||||
|
std::optional<Luminosity> getLuminosity();
|
||||||
|
std::optional<uint32_t> calculateLux(Luminosity luminosity);
|
||||||
|
|
||||||
/* Unified Sensor API Functions */
|
/* Unified Sensor API Functions */
|
||||||
std::optional<sensors_event_t> getEvent() override;
|
std::optional<sensors_event_t> getEvent() override;
|
||||||
sensor_t getSensor() override;
|
sensor_t getSensor() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TwoWire *_i2c;
|
TwoWire *_i2c{};
|
||||||
|
|
||||||
int8_t _addr;
|
uint8_t _addr;
|
||||||
boolean _tsl2561Initialised;
|
bool _tsl2561Initialised{};
|
||||||
boolean _tsl2561AutoGain;
|
bool _tsl2561AutoGain{};
|
||||||
tsl2561IntegrationTime_t _tsl2561IntegrationTime;
|
tsl2561IntegrationTime_t _tsl2561IntegrationTime{TSL2561_INTEGRATIONTIME_13MS};
|
||||||
tsl2561Gain_t _tsl2561Gain;
|
tsl2561Gain_t _tsl2561Gain{TSL2561_GAIN_1X};
|
||||||
int32_t _tsl2561SensorID;
|
int32_t _tsl2561SensorID;
|
||||||
|
|
||||||
void enable(void);
|
bool enable(void);
|
||||||
void disable(void);
|
bool disable(void);
|
||||||
void write8(uint8_t reg, uint8_t value);
|
bool write8(uint8_t reg, uint8_t value);
|
||||||
uint8_t read8(uint8_t reg);
|
std::optional<uint8_t> read8(uint8_t reg);
|
||||||
uint16_t read16(uint8_t reg);
|
std::optional<uint16_t> read16(uint8_t reg);
|
||||||
void getData(uint16_t *broadband, uint16_t *ir);
|
std::optional<Luminosity> getData();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ADAFRUIT_TSL2561_H
|
#endif // ADAFRUIT_TSL2561_H
|
||||||
|
Reference in New Issue
Block a user