8 static const char *
const TAG =
"tsl2591.sensor";
11 #define TSL2591_COMMAND_BIT (0xA0) // 1010 0000: bits 7 and 5 for 'command, normal' 12 #define TSL2591_ENABLE_POWERON (0x01) // Flag for ENABLE register, to enable 13 #define TSL2591_ENABLE_POWEROFF (0x00) // Flag for ENABLE register, to disable 14 #define TSL2591_ENABLE_AEN (0x02) // Flag for ENABLE register, to turn on ADCs 17 #define TSL2591_REGISTER_ENABLE (0x00) 18 #define TSL2591_REGISTER_CONTROL (0x01) 19 #define TSL2591_REGISTER_DEVICE_ID (0x12) 20 #define TSL2591_REGISTER_STATUS (0x13) 21 #define TSL2591_REGISTER_CHAN0_LOW (0x14) 22 #define TSL2591_REGISTER_CHAN0_HIGH (0x15) 23 #define TSL2591_REGISTER_CHAN1_LOW (0x16) 24 #define TSL2591_REGISTER_CHAN1_HIGH (0x17) 28 if (!this->
write_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWERON | TSL2591_ENABLE_AEN)) {
29 ESP_LOGE(TAG,
"Failed I2C write during enable()");
34 if (!this->
write_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWEROFF)) {
35 ESP_LOGE(TAG,
"Failed I2C write during disable()");
65 ESP_LOGI(TAG,
"Setting up TSL2591 sensor at I2C address 0x%02X", address);
68 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_ID, &
id)) {
69 ESP_LOGE(TAG,
"Failed I2C read during setup()");
76 "Could not find the TSL2591 sensor. The ID register of the device at address 0x%02X reported 0x%02X " 88 ESP_LOGCONFIG(TAG,
"TSL2591:");
92 ESP_LOGE(TAG,
"Communication with TSL2591 failed earlier, during setup");
96 ESP_LOGCONFIG(TAG,
" Name: %s", this->
name_);
99 std::string gain_word =
"unknown";
107 gain_word =
"medium";
115 gain_word =
"maximum";
122 ESP_LOGCONFIG(TAG,
" Gain: %dx (%s)", gain, gain_word.c_str());
124 int timing_ms = (1 + raw_timing) * 100;
125 ESP_LOGCONFIG(TAG,
" Integration Time: %d ms", timing_ms);
135 LOG_UPDATE_INTERVAL(
this);
145 ESP_LOGD(TAG,
"Got illuminance: combined 0x%" PRIX32
", full %d, IR %d, vis %d. Calc lux: %f. Actual gain: %d.",
146 combined, full, infrared, visible, lux, actual_gain);
170 #define interval_name "tsl2591_interval_for_update" 175 ESP_LOGD(TAG,
"Elapsed %3llu ms; still waiting for valid ADC", (now - this->
interval_start_));
177 ESP_LOGW(TAG,
"Interval timeout for TSL2591 '%s' expired before ADCs became valid.", this->
name_);
236 if (!this->
write_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL,
238 ESP_LOGE(TAG,
"Failed I2C write during set_integration_time_and_gain()");
257 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_STATUS, &status)) {
258 ESP_LOGE(TAG,
"Failed I2C read during is_adc_valid()");
261 return status & 0x01;
271 const uint8_t mini_delay = 100;
272 for (uint16_t d = 0; d < 620; d += mini_delay) {
278 ESP_LOGD(TAG,
" after %3d ms: ADC valid? %s", d, avalid ?
"true" :
"false");
284 ESP_LOGE(TAG,
"tsl2591 device '%s' did not return valid readings.", this->
name_);
294 uint8_t ch0low, ch0high, ch1low, ch1high;
297 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_LOW, &ch0low)) {
298 ESP_LOGE(TAG,
"Failed I2C read during get_combined_illuminance()");
301 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_HIGH, &ch0high)) {
302 ESP_LOGE(TAG,
"Failed I2C read during get_combined_illuminance()");
305 ch0_16 = (ch0high << 8) | ch0low;
306 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_LOW, &ch1low)) {
307 ESP_LOGE(TAG,
"Failed I2C read during get_combined_illuminance()");
310 if (!this->
read_byte(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_HIGH, &ch1high)) {
311 ESP_LOGE(TAG,
"Failed I2C read during get_combined_illuminance()");
314 ch1_16 = (ch1high << 8) | ch1low;
315 x32 = (ch1_16 << 16) | ch0_16;
329 return (combined_illuminance & 0xFFFF);
332 return (combined_illuminance >> 16);
335 return ((combined_illuminance & 0xFFFF) - (combined_illuminance >> 16));
338 ESP_LOGE(TAG,
"TSL2591Component::get_illuminance() caller requested an unknown channel: %d", channel);
359 if ((full_spectrum == max_count) || (infrared == max_count)) {
361 ESP_LOGW(TAG,
"Apparent saturation on TSL2591 (%s). You could reduce the gain or integration time.", this->
name_);
365 if ((full_spectrum == 0) && (infrared == 0)) {
367 ESP_LOGW(TAG,
"Zero reading on both TSL2591 (%s) sensors. Is the device having a problem?", this->
name_);
374 switch (this->
gain_) {
403 float lux = (((float) full_spectrum - (
float) infrared)) * (1.0F - ((float) infrared / (
float) full_spectrum)) / cpl;
404 return std::max(lux, 0.0F);
424 switch (this->
gain_) {
426 if (full_spectrum < 54) {
428 }
else if (full_spectrum < 875) {
433 if (full_spectrum < 57) {
435 }
else if (full_spectrum < 1365) {
437 }
else if (full_spectrum > 62000 / fs_divider) {
442 if (full_spectrum < 920) {
444 }
else if (full_spectrum > 62000 / fs_divider) {
449 if (full_spectrum > 62000 / fs_divider)
454 if (this->
gain_ != new_gain) {
455 this->
gain_ = new_gain;
458 ESP_LOGD(TAG,
"Gain setting: %d", this->
gain_);
466 switch (this->
gain_) {
void dump_config() override
Used by ESPHome framework.
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
sensor::Sensor * visible_sensor_
const float DATA
For components that import data from directly connected sensors like DHT.
void set_interval(const std::string &name, uint32_t interval, std::function< void()> &&f)
Set an interval function with a unique name.
bool power_save_mode_enabled_
void set_full_spectrum_sensor(sensor::Sensor *full_spectrum_sensor)
Used by ESPHome framework.
sensor::Sensor * calculated_lux_sensor_
uint64_t interval_timeout_
uint16_t get_illuminance(TSL2591SensorChannel channel)
Get an individual sensor channel reading.
void disable_if_power_saving_()
bool cancel_interval(const std::string &name)
Cancel an interval function.
void set_name(const char *name)
Sets the name for this instance of the device.
float get_actual_gain()
Reads the actual gain used.
void set_actual_gain_sensor(sensor::Sensor *actual_gain_sensor)
Used by ESPHome framework.
T id(T value)
Helper function to make id(var) known from lambdas work in custom components.
void set_calculated_lux_sensor(sensor::Sensor *calculated_lux_sensor)
Used by ESPHome framework.
TSL2591IntegrationTime
Enum listing all conversion/integration time settings for the TSL2591.
uint32_t IRAM_ATTR HOT millis()
sensor::Sensor * infrared_sensor_
void update() override
Used by ESPHome framework.
TSL2591ComponentGain component_gain_
void set_power_save_mode(bool enable)
Should the device be powered down between readings?
sensor::Sensor * actual_gain_sensor_
void set_integration_time_and_gain(TSL2591IntegrationTime integration_time, TSL2591Gain gain)
Set device integration time and gain.
void set_integration_time(TSL2591IntegrationTime integration_time)
Used by ESPHome framework.
void status_clear_warning()
void publish_state(float state)
Publish a new state to the front-end.
void setup() override
Used by ESPHome framework.
void set_infrared_sensor(sensor::Sensor *infrared_sensor)
Used by ESPHome framework.
sensor::Sensor * full_spectrum_sensor_
IntegrationTime501 integration_time
uint8_t address_
store the address of the device on the bus
TSL2591ComponentGain
Enum listing all gain settings for the TSL2591 component.
void enable()
Powers on the TSL2591 device and enables its sensors.
TSL2591Gain
Enum listing all gain settings for the TSL2591.
TSL2591IntegrationTime integration_time_
TSL2591SensorChannel
Enum listing sensor channels.
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
virtual void mark_failed()
Mark this component as failed.
void set_gain(TSL2591ComponentGain gain)
Used by ESPHome framework.
float glass_attenuation_factor_
void disable()
Powers off the TSL2591 device.
Implementation of SPI Controller mode.
bool is_adc_valid()
Are the device ADC values valid?
float get_setup_priority() const override
Used by ESPHome framework.
Base-class for all sensors.
void automatic_gain_update(uint16_t full_spectrum)
Updates the gain setting based on the most recent full spectrum reading.
void set_visible_sensor(sensor::Sensor *visible_sensor)
Used by ESPHome framework.
void interval_function_for_update_()
void set_device_and_glass_attenuation_factors(float device_factor, float glass_attenuation_factor)
Sets the device and glass attenuation factors.
void IRAM_ATTR HOT delay(uint32_t ms)
float get_calculated_lux(uint16_t full_spectrum, uint16_t infrared)
Calculates and returns a lux value based on the ADC readings.
uint32_t get_combined_illuminance()
Get the combined illuminance value.