mirror of https://github.com/arendst/Tasmota.git
add xsns_57_tsl2591
This commit is contained in:
parent
538d40ab72
commit
3918f79117
|
@ -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 <pgmspace.h>
|
||||
#else
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
#if defined(__AVR__)
|
||||
#include <util/delay.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#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();
|
||||
}
|
|
@ -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 <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
#include <Wire.h>
|
||||
|
||||
#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
|
|
@ -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)
|
||||
|
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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.h>
|
||||
|
||||
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} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#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
|
Loading…
Reference in New Issue