diff --git a/lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp b/lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp new file mode 100644 index 000000000..a8b63d7ef --- /dev/null +++ b/lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.cpp @@ -0,0 +1,479 @@ +/**************************************************************************/ +/*! + @file Adafruit_TSL2591.cpp + @author KT0WN (adafruit.com) + + This is a library for the Adafruit TSL2591 breakout board + This library works with the Adafruit TSL2591 breakout + ----> https://www.adafruit.com/products/1980 + + Check out the links above for our tutorials and wiring diagrams + These chips use I2C to communicate + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2014 Adafruit Industries + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ +#if defined(ESP8266) || defined(ESP32) + #include +#else + #include +#endif +#if defined(__AVR__) + #include +#endif +#include + +#include "Adafruit_TSL2591.h" + +/**************************************************************************/ +/*! + @brief Instantiates a new Adafruit TSL2591 class + @param sensorID An optional ID # so you can track this sensor, it will tag sensorEvents you create. +*/ +/**************************************************************************/ +Adafruit_TSL2591::Adafruit_TSL2591(int32_t sensorID) +{ + _initialized = false; + _integration = TSL2591_INTEGRATIONTIME_100MS; + _gain = TSL2591_GAIN_MED; + _sensorID = sensorID; + + // we cant do wire initialization till later, because we havent loaded Wire yet +} + +/**************************************************************************/ +/*! + @brief Setups the I2C interface and hardware, identifies if chip is found + @returns True if a TSL2591 is found, false on any failure +*/ +/**************************************************************************/ +boolean Adafruit_TSL2591::begin(void) +{ + Wire.begin(); + + /* + for (uint8_t i=0; i<0x20; i++) + { + uint8_t id = read8(0x12); + Serial.print("$"); Serial.print(i, HEX); + Serial.print(" = 0x"); Serial.println(read8(i), HEX); + } + */ + + uint8_t id = read8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_ID); + if (id != 0x50 ) { + return false; + } + // Serial.println("Found Adafruit_TSL2591"); + + _initialized = true; + + // Set default integration time and gain + setTiming(_integration); + setGain(_gain); + + // Note: by default, the device is in power down mode on bootup + disable(); + + return true; +} + +/**************************************************************************/ +/*! + @brief Enables the chip, so it's ready to take readings +*/ +/**************************************************************************/ +void Adafruit_TSL2591::enable(void) +{ + if (!_initialized) + { + if (!begin()) + { + return; + } + } + + // Enable the device by setting the control bit to 0x01 + write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, + TSL2591_ENABLE_POWERON | TSL2591_ENABLE_AEN | TSL2591_ENABLE_AIEN | TSL2591_ENABLE_NPIEN); +} + + +/**************************************************************************/ +/*! + @brief Disables the chip, so it's in power down mode +*/ +/**************************************************************************/ +void Adafruit_TSL2591::disable(void) +{ + if (!_initialized) { + if (!begin()) { + return; + } + } + + // Disable the device by setting the control bit to 0x00 + write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWEROFF); +} + +/************************************************************************/ +/*! + @brief Setter for sensor light gain + @param gain {@link tsl2591Gain_t} gain value +*/ +/**************************************************************************/ +void Adafruit_TSL2591::setGain(tsl2591Gain_t gain) +{ + if (!_initialized) { + if (!begin()) { + return; + } + } + + enable(); + _gain = gain; + write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL, _integration | _gain); + disable(); +} + +/************************************************************************/ +/*! + @brief Getter for sensor light gain + @returns {@link tsl2591Gain_t} gain value +*/ +/**************************************************************************/ +tsl2591Gain_t Adafruit_TSL2591::getGain() +{ + return _gain; +} + +/************************************************************************/ +/*! + @brief Setter for sensor integration time setting + @param integration {@link tsl2591IntegrationTime_t} integration time setting +*/ +/**************************************************************************/ +void Adafruit_TSL2591::setTiming(tsl2591IntegrationTime_t integration) +{ + if (!_initialized) { + if (!begin()) { + return; + } + } + + enable(); + _integration = integration; + write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL, _integration | _gain); + disable(); +} + +/************************************************************************/ +/*! + @brief Getter for sensor integration time setting + @returns {@link tsl2591IntegrationTime_t} integration time +*/ +/**************************************************************************/ +tsl2591IntegrationTime_t Adafruit_TSL2591::getTiming() +{ + return _integration; +} + +/************************************************************************/ +/*! + @brief Calculates the visible Lux based on the two light sensors + @param ch0 Data from channel 0 (IR+Visible) + @param ch1 Data from channel 1 (IR) + @returns Lux, based on AMS coefficients (or < 0 if overflow) +*/ +/**************************************************************************/ +float Adafruit_TSL2591::calculateLux(uint16_t ch0, uint16_t ch1) +{ + float atime, again; + float cpl, lux1, lux2, lux; + uint32_t chan0, chan1; + + // Check for overflow conditions first + if ((ch0 == 0xFFFF) | (ch1 == 0xFFFF)) + { + // Signal an overflow + return -1; + } + + // Note: This algorithm is based on preliminary coefficients + // provided by AMS and may need to be updated in the future + + switch (_integration) + { + case TSL2591_INTEGRATIONTIME_100MS : + atime = 100.0F; + break; + case TSL2591_INTEGRATIONTIME_200MS : + atime = 200.0F; + break; + case TSL2591_INTEGRATIONTIME_300MS : + atime = 300.0F; + break; + case TSL2591_INTEGRATIONTIME_400MS : + atime = 400.0F; + break; + case TSL2591_INTEGRATIONTIME_500MS : + atime = 500.0F; + break; + case TSL2591_INTEGRATIONTIME_600MS : + atime = 600.0F; + break; + default: // 100ms + atime = 100.0F; + break; + } + + switch (_gain) + { + case TSL2591_GAIN_LOW : + again = 1.0F; + break; + case TSL2591_GAIN_MED : + again = 25.0F; + break; + case TSL2591_GAIN_HIGH : + again = 428.0F; + break; + case TSL2591_GAIN_MAX : + again = 9876.0F; + break; + default: + again = 1.0F; + break; + } + + // cpl = (ATIME * AGAIN) / DF + cpl = (atime * again) / TSL2591_LUX_DF; + + // Original lux calculation (for reference sake) + //lux1 = ( (float)ch0 - (TSL2591_LUX_COEFB * (float)ch1) ) / cpl; + //lux2 = ( ( TSL2591_LUX_COEFC * (float)ch0 ) - ( TSL2591_LUX_COEFD * (float)ch1 ) ) / cpl; + //lux = lux1 > lux2 ? lux1 : lux2; + + // Alternate lux calculation 1 + // See: https://github.com/adafruit/Adafruit_TSL2591_Library/issues/14 + lux = ( ((float)ch0 - (float)ch1 )) * (1.0F - ((float)ch1/(float)ch0) ) / cpl; + + // Alternate lux calculation 2 + //lux = ( (float)ch0 - ( 1.7F * (float)ch1 ) ) / cpl; + + // Signal I2C had no errors + return lux; +} + +/************************************************************************/ +/*! + @brief Reads the raw data from both light channels + @returns 32-bit raw count where high word is IR, low word is IR+Visible +*/ +/**************************************************************************/ +uint32_t Adafruit_TSL2591::getFullLuminosity (void) +{ + if (!_initialized) { + if (!begin()) { + return 0; + } + } + + // Enable the device + enable(); + + // Wait x ms for ADC to complete + for (uint8_t d=0; d<=_integration; d++) + { + delay(120); + } + + // CHAN0 must be read before CHAN1 + // See: https://forums.adafruit.com/viewtopic.php?f=19&t=124176 + uint32_t x; + uint16_t y; + y = read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_LOW); + x = read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_LOW); + x <<= 16; + x |= y; + + disable(); + + return x; +} + +/************************************************************************/ +/*! + @brief Reads the raw data from the channel + @param channel Can be 0 (IR+Visible, 1 (IR) or 2 (Visible only) + @returns 16-bit raw count, or 0 if channel is invalid +*/ +/**************************************************************************/ +uint16_t Adafruit_TSL2591::getLuminosity (uint8_t channel) +{ + uint32_t x = getFullLuminosity(); + + if (channel == TSL2591_FULLSPECTRUM) + { + // Reads two byte value from channel 0 (visible + infrared) + return (x & 0xFFFF); + } + else if (channel == TSL2591_INFRARED) + { + // Reads two byte value from channel 1 (infrared) + return (x >> 16); + } + else if (channel == TSL2591_VISIBLE) + { + // Reads all and subtracts out just the visible! + return ( (x & 0xFFFF) - (x >> 16)); + } + + // unknown channel! + return 0; +} + +/************************************************************************/ +/*! + @brief Set up the interrupt to go off when light level is outside the lower/upper range. + @param lowerThreshold Raw light data reading level that is the lower value threshold for interrupt + @param upperThreshold Raw light data reading level that is the higher value threshold for interrupt + @param persist How many counts we must be outside range for interrupt to fire, default is any single value +*/ +/**************************************************************************/ +void Adafruit_TSL2591::registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold, tsl2591Persist_t persist = TSL2591_PERSIST_ANY) +{ + if (!_initialized) { + if (!begin()) { + return; + } + } + + enable(); + write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_PERSIST_FILTER, persist); + write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AILTL, lowerThreshold); + write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AILTH, lowerThreshold >> 8); + write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AIHTL, upperThreshold); + write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AIHTH, upperThreshold >> 8); + disable(); +} + +/************************************************************************/ +/*! + @brief Clear interrupt status +*/ +/**************************************************************************/ +void Adafruit_TSL2591::clearInterrupt() +{ + if (!_initialized) { + if (!begin()) { + return; + } + } + + enable(); + write8(TSL2591_CLEAR_INT); + disable(); +} + + +/************************************************************************/ +/*! + @brief Gets the most recent sensor event from the hardware status register. + @return Sensor status as a byte. Bit 0 is ALS Valid. Bit 4 is ALS Interrupt. Bit 5 is No-persist Interrupt. +*/ +/**************************************************************************/ +uint8_t Adafruit_TSL2591::getStatus(void) +{ + if (!_initialized) { + if (!begin()) { + return 0; + } + } + + // Enable the device + enable(); + uint8_t x; + x = read8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_STATUS); + disable(); + return x; +} + +uint8_t Adafruit_TSL2591::read8(uint8_t reg) +{ + uint8_t x; + + Wire.beginTransmission(TSL2591_ADDR); + Wire.write(reg); + Wire.endTransmission(); + + Wire.requestFrom(TSL2591_ADDR, 1); + x = Wire.read(); + + return x; +} + +uint16_t Adafruit_TSL2591::read16(uint8_t reg) +{ + uint16_t x; + uint16_t t; + + Wire.beginTransmission(TSL2591_ADDR); + Wire.write(reg); + Wire.endTransmission(); + + Wire.requestFrom(TSL2591_ADDR, 2); + t = Wire.read(); + x = Wire.read(); + + x <<= 8; + x |= t; + return x; +} + +void Adafruit_TSL2591::write8 (uint8_t reg, uint8_t value) +{ + Wire.beginTransmission(TSL2591_ADDR); + Wire.write(reg); + Wire.write(value); + Wire.endTransmission(); +} + + +void Adafruit_TSL2591::write8 (uint8_t reg) +{ + Wire.beginTransmission(TSL2591_ADDR); + Wire.write(reg); + Wire.endTransmission(); +} diff --git a/lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.h b/lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.h new file mode 100644 index 000000000..7fad72739 --- /dev/null +++ b/lib/Adafruit_TSL2591_Library/Adafruit_TSL2591.h @@ -0,0 +1,166 @@ +/**************************************************************************/ +/*! + @file Adafruit_TSL2591.h + @author KT0WN (adafruit.com) + + This is a library for the Adafruit TSL2591 breakout board + This library works with the Adafruit TSL2591 breakout + ----> https://www.adafruit.com/products/1980 + + Check out the links above for our tutorials and wiring diagrams + These chips use I2C to communicate + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! +*/ +/**************************************************************************/ + +#ifndef _TSL2591_H_ +#define _TSL2591_H_ + +#if ARDUINO >= 100 + #include +#else + #include +#endif +#include + +#define TSL2591_VISIBLE (2) ///< (channel 0) - (channel 1) +#define TSL2591_INFRARED (1) ///< channel 1 +#define TSL2591_FULLSPECTRUM (0) ///< channel 0 + +#define TSL2591_ADDR (0x29) ///< Default I2C address + +#define TSL2591_COMMAND_BIT (0xA0) ///< 1010 0000: bits 7 and 5 for 'command normal' + +///! Special Function Command for "Clear ALS and no persist ALS interrupt" +#define TSL2591_CLEAR_INT (0xE7) +///! Special Function Command for "Interrupt set - forces an interrupt" +#define TSL2591_TEST_INT (0xE4) + + +#define TSL2591_WORD_BIT (0x20) ///< 1 = read/write word (rather than byte) +#define TSL2591_BLOCK_BIT (0x10) ///< 1 = using block read/write + +#define TSL2591_ENABLE_POWEROFF (0x00) ///< Flag for ENABLE register to disable +#define TSL2591_ENABLE_POWERON (0x01) ///< Flag for ENABLE register to enable +#define TSL2591_ENABLE_AEN (0x02) ///< ALS Enable. This field activates ALS function. Writing a one activates the ALS. Writing a zero disables the ALS. +#define TSL2591_ENABLE_AIEN (0x10) ///< ALS Interrupt Enable. When asserted permits ALS interrupts to be generated, subject to the persist filter. +#define TSL2591_ENABLE_NPIEN (0x80) ///< No Persist Interrupt Enable. When asserted NP Threshold conditions will generate an interrupt, bypassing the persist filter + +#define TSL2591_LUX_DF (408.0F) ///< Lux cooefficient +#define TSL2591_LUX_COEFB (1.64F) ///< CH0 coefficient +#define TSL2591_LUX_COEFC (0.59F) ///< CH1 coefficient A +#define TSL2591_LUX_COEFD (0.86F) ///< CH2 coefficient B + +/// TSL2591 Register map +enum +{ + TSL2591_REGISTER_ENABLE = 0x00, // Enable register + TSL2591_REGISTER_CONTROL = 0x01, // Control register + TSL2591_REGISTER_THRESHOLD_AILTL = 0x04, // ALS low threshold lower byte + TSL2591_REGISTER_THRESHOLD_AILTH = 0x05, // ALS low threshold upper byte + TSL2591_REGISTER_THRESHOLD_AIHTL = 0x06, // ALS high threshold lower byte + TSL2591_REGISTER_THRESHOLD_AIHTH = 0x07, // ALS high threshold upper byte + TSL2591_REGISTER_THRESHOLD_NPAILTL = 0x08, // No Persist ALS low threshold lower byte + TSL2591_REGISTER_THRESHOLD_NPAILTH = 0x09, // No Persist ALS low threshold higher byte + TSL2591_REGISTER_THRESHOLD_NPAIHTL = 0x0A, // No Persist ALS high threshold lower byte + TSL2591_REGISTER_THRESHOLD_NPAIHTH = 0x0B, // No Persist ALS high threshold higher byte + TSL2591_REGISTER_PERSIST_FILTER = 0x0C, // Interrupt persistence filter + TSL2591_REGISTER_PACKAGE_PID = 0x11, // Package Identification + TSL2591_REGISTER_DEVICE_ID = 0x12, // Device Identification + TSL2591_REGISTER_DEVICE_STATUS = 0x13, // Internal Status + TSL2591_REGISTER_CHAN0_LOW = 0x14, // Channel 0 data, low byte + TSL2591_REGISTER_CHAN0_HIGH = 0x15, // Channel 0 data, high byte + TSL2591_REGISTER_CHAN1_LOW = 0x16, // Channel 1 data, low byte + TSL2591_REGISTER_CHAN1_HIGH = 0x17, // Channel 1 data, high byte +}; + +/// Enumeration for the sensor integration timing +typedef enum +{ + TSL2591_INTEGRATIONTIME_100MS = 0x00, // 100 millis + TSL2591_INTEGRATIONTIME_200MS = 0x01, // 200 millis + TSL2591_INTEGRATIONTIME_300MS = 0x02, // 300 millis + TSL2591_INTEGRATIONTIME_400MS = 0x03, // 400 millis + TSL2591_INTEGRATIONTIME_500MS = 0x04, // 500 millis + TSL2591_INTEGRATIONTIME_600MS = 0x05, // 600 millis +} +tsl2591IntegrationTime_t; + +/// Enumeration for the persistance filter (for interrupts) +typedef enum +{ + // bit 7:4: 0 + TSL2591_PERSIST_EVERY = 0x00, // Every ALS cycle generates an interrupt + TSL2591_PERSIST_ANY = 0x01, // Any value outside of threshold range + TSL2591_PERSIST_2 = 0x02, // 2 consecutive values out of range + TSL2591_PERSIST_3 = 0x03, // 3 consecutive values out of range + TSL2591_PERSIST_5 = 0x04, // 5 consecutive values out of range + TSL2591_PERSIST_10 = 0x05, // 10 consecutive values out of range + TSL2591_PERSIST_15 = 0x06, // 15 consecutive values out of range + TSL2591_PERSIST_20 = 0x07, // 20 consecutive values out of range + TSL2591_PERSIST_25 = 0x08, // 25 consecutive values out of range + TSL2591_PERSIST_30 = 0x09, // 30 consecutive values out of range + TSL2591_PERSIST_35 = 0x0A, // 35 consecutive values out of range + TSL2591_PERSIST_40 = 0x0B, // 40 consecutive values out of range + TSL2591_PERSIST_45 = 0x0C, // 45 consecutive values out of range + TSL2591_PERSIST_50 = 0x0D, // 50 consecutive values out of range + TSL2591_PERSIST_55 = 0x0E, // 55 consecutive values out of range + TSL2591_PERSIST_60 = 0x0F, // 60 consecutive values out of range +} +tsl2591Persist_t; + +/// Enumeration for the sensor gain +typedef enum +{ + TSL2591_GAIN_LOW = 0x00, /// low gain (1x) + TSL2591_GAIN_MED = 0x10, /// medium gain (25x) + TSL2591_GAIN_HIGH = 0x20, /// medium gain (428x) + TSL2591_GAIN_MAX = 0x30, /// max gain (9876x) +} +tsl2591Gain_t; + + +/**************************************************************************/ +/*! + @brief Class that stores state and functions for interacting with TSL2591 Light Sensor +*/ +/**************************************************************************/ +class Adafruit_TSL2591 +{ + public: + Adafruit_TSL2591(int32_t sensorID = -1); + + boolean begin ( void ); + void enable ( void ); + void disable ( void ); + + float calculateLux ( uint16_t ch0, uint16_t ch1 ); + void setGain ( tsl2591Gain_t gain ); + void setTiming ( tsl2591IntegrationTime_t integration ); + uint16_t getLuminosity (uint8_t channel ); + uint32_t getFullLuminosity ( ); + + tsl2591IntegrationTime_t getTiming(); + tsl2591Gain_t getGain(); + + // Interrupt + void clearInterrupt(void); + void registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold, tsl2591Persist_t persist); + uint8_t getStatus(); + + private: + void write8 ( uint8_t r); + void write8 ( uint8_t r, uint8_t v ); + uint16_t read16 ( uint8_t reg ); + uint8_t read8 ( uint8_t reg ); + + tsl2591IntegrationTime_t _integration; + tsl2591Gain_t _gain; + int32_t _sensorID; + + boolean _initialized; +}; +#endif diff --git a/tasmota/tasmota_post.h b/tasmota/tasmota_post.h index a11938fd6..904648cc3 100644 --- a/tasmota/tasmota_post.h +++ b/tasmota/tasmota_post.h @@ -130,6 +130,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c //#define USE_INA226 // Enable INA226 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+2k3 code) #define USE_SHT3X // Add I2C code for SHT3x sensor (+0k6 code) #define USE_TSL2561 // Add I2C code for TSL2561 sensor using library Adafruit TSL2561 Arduino (+1k2 code) +//#define USE_TSL2591 // Add I2C code for TSL2591 sensor #define USE_MGS // Add I2C code for Xadow and Grove Mutichannel Gas sensor using library Multichannel_Gas_Sensor (+10k code) #define USE_SGP30 // Add I2C code for SGP30 sensor (+1k1 code) //#define USE_SI1145 // Add I2C code for SI1145/46/47 sensor (+1k code) diff --git a/tasmota/xsns_57_tsl2591.ino b/tasmota/xsns_57_tsl2591.ino new file mode 100644 index 000000000..e7bd7f9bb --- /dev/null +++ b/tasmota/xsns_57_tsl2591.ino @@ -0,0 +1,116 @@ +/* + xsns_57_tsl2591.ino - TSL2591 light sensor support for Sonoff-Tasmota + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifdef USE_I2C +#ifdef USE_TSL2591 +/*********************************************************************************************\ + * TSL2591 - Light Intensity + * + * I2C Addresses: 0x29 (low), 0x39 (float) or 0x49 (high) +\*********************************************************************************************/ + +#define XSNS_57 57 + +#include + +Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); + +uint8_t tsl2591_type = 0; +uint8_t tsl2591_valid = 0; +float tsl2591_lux = 0; + +void Tsl2591Init(void) +{ + if (tsl2591_type) { + return; + } + if (tsl.begin()) { + tsl.setGain(TSL2591_GAIN_MED); + tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS); + tsl2591_type = 1; + } +} + +bool Tsl2591Read(void) +{ + uint32_t lum = tsl.getFullLuminosity(); + uint16_t ir, full; + ir = lum >> 16; + full = lum & 0xFFFF; + tsl2591_lux = tsl.calculateLux(full, ir); + tsl2591_valid = 1; +} + +void Tsl2591EverySecond(void) +{ + Tsl2591Read(); +} + +#ifdef USE_WEBSERVER +const char HTTP_SNS_TSL2591[] PROGMEM = + "{s}TSL2591 " D_ILLUMINANCE "{m}%s " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = +#endif // USE_WEBSERVER + +void Tsl2591Show(bool json) +{ + if (tsl2591_valid) { + char lux_str[10]; + dtostrf(tsl2591_lux, sizeof(lux_str)-1, 3, lux_str); + if (json) { + ResponseAppend_P(PSTR(",\"TSL2591\":{\"" D_JSON_ILLUMINANCE "\":%s}"), lux_str); +#ifdef USE_DOMOTICZ + if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, tsl2591_lux); } +#endif // USE_DOMOTICZ +#ifdef USE_WEBSERVER + } else { + WSContentSend_PD(HTTP_SNS_TSL2591, lux_str); +#endif // USE_WEBSERVER + } + } +} + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ + +bool Xsns57(uint8_t function) +{ + bool result = false; + + if (i2c_flg) { + switch (function) { + case FUNC_INIT: + Tsl2591Init(); + break; + case FUNC_EVERY_SECOND: + Tsl2591EverySecond(); + break; + case FUNC_JSON_APPEND: + Tsl2591Show(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + Tsl2591Show(0); + break; +#endif // USE_WEBSERVER + } + } + return result; +} + +#endif // USE_TSL2591 +#endif // USE_I2C