ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
tsl2561.cpp
Go to the documentation of this file.
1#include "tsl2561.h"
2#include "esphome/core/log.h"
3
4namespace esphome::tsl2561 {
5
6ESPHOME_LOG_TAG(TAG, "tsl2561");
7
8static constexpr uint32_t READ_TIMEOUT_ID = 0;
9
10static const uint8_t TSL2561_COMMAND_BIT = 0x80;
11static const uint8_t TSL2561_WORD_BIT = 0x20;
12static const uint8_t TSL2561_REGISTER_CONTROL = 0x00;
13static const uint8_t TSL2561_REGISTER_TIMING = 0x01;
14static const uint8_t TSL2561_REGISTER_ID = 0x0A;
15static const uint8_t TSL2561_REGISTER_DATA_0 = 0x0C;
16static const uint8_t TSL2561_REGISTER_DATA_1 = 0x0E;
17
19 uint8_t id;
20 if (!this->tsl2561_read_byte(TSL2561_REGISTER_ID, &id)) {
21 this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
22 return;
23 }
24
25 uint8_t timing;
26 if (!this->tsl2561_read_byte(TSL2561_REGISTER_TIMING, &timing)) {
27 this->mark_failed(LOG_STR(ESP_LOG_MSG_COMM_FAIL));
28 return;
29 }
30
31 timing &= ~0b00010000;
32 timing |= this->gain_ == TSL2561_GAIN_16X ? 0b00010000 : 0;
33
34 timing &= ~0b00000011;
35 timing |= this->integration_time_ & 0b11;
36
37 this->tsl2561_write_byte(TSL2561_REGISTER_TIMING, timing);
38}
40 LOG_SENSOR("", "TSL2561", this);
41 LOG_I2C_DEVICE(this);
42
43 int gain = this->gain_ == TSL2561_GAIN_1X ? 1 : 16;
44 ESP_LOGCONFIG(TAG,
45 " Gain: %dx\n"
46 " Integration Time: %.1f ms",
48
49 LOG_UPDATE_INTERVAL(this);
50}
52 // Power on
53 if (!this->tsl2561_write_byte(TSL2561_REGISTER_CONTROL, 0b00000011)) {
54 this->status_set_warning();
55 return;
56 }
57
58 // Make sure the data is there when we will read it.
59 auto timeout = static_cast<uint32_t>(this->get_integration_time_ms_() + 20);
60
61 this->set_timeout(READ_TIMEOUT_ID, timeout, [this]() { this->read_data_(); });
62}
63
64float TSL2561Sensor::calculate_lx_(uint16_t ch0, uint16_t ch1) {
65 if ((ch0 == 0xFFFF) || (ch1 == 0xFFFF)) {
66 ESP_LOGW(TAG, "Sensor is saturated");
67 return NAN;
68 }
69
70 if (ch0 == 0) {
71 ESP_LOGVV(TAG, "No light detected");
72 return 0.0f;
73 }
74 float d0 = ch0, d1 = ch1;
75 float ratio = d1 / d0;
76
77 float ms = this->get_integration_time_ms_();
78 d0 *= (402.0f / ms);
79 d1 *= (402.0f / ms);
80
81 if (this->gain_ == TSL2561_GAIN_1X) {
82 d0 *= 16;
83 d1 *= 16;
84 }
85
86 if (this->package_cs_) {
87 if (ratio < 0.52f) {
88 return 0.0315f * d0 - 0.0593f * d0 * powf(ratio, 1.4f);
89 } else if (ratio < 0.65f) {
90 return 0.0229f * d0 - 0.0291f * d1;
91 } else if (ratio < 0.80f) {
92 return 0.0157f * d0 - 0.0153f * d1;
93 } else if (ratio < 1.30f) {
94 return 0.00338f * d0 - 0.00260f * d1;
95 }
96
97 return 0.0f;
98 } else {
99 if (ratio < 0.5f) {
100 return 0.0304f * d0 - 0.062f * d0 * powf(ratio, 1.4f);
101 } else if (ratio < 0.61f) {
102 return 0.0224f * d0 - 0.031f * d1;
103 } else if (ratio < 0.80f) {
104 return 0.0128f * d0 - 0.0153f * d1;
105 } else if (ratio < 1.30f) {
106 return 0.00146f * d0 - 0.00112f * d1;
107 }
108 return 0.0f;
109 }
110}
112 uint16_t data1, data0;
113 if (!this->tsl2561_read_uint(TSL2561_WORD_BIT | TSL2561_REGISTER_DATA_1, &data1)) {
114 this->status_set_warning();
115 return;
116 }
117 if (!this->tsl2561_read_uint(TSL2561_WORD_BIT | TSL2561_REGISTER_DATA_0, &data0)) {
118 this->status_set_warning();
119 return;
120 }
121 // Power off
122 if (!this->status_comm_result(this->tsl2561_write_byte(TSL2561_REGISTER_CONTROL, 0b00000000)))
123 return;
124
125 float lx = this->calculate_lx_(data0, data1);
126 ESP_LOGD(TAG, "Got illuminance=%.1flx", lx);
127 this->publish_state(lx);
128}
130 switch (this->integration_time_) {
132 return 13.7f;
134 return 100.0f;
136 return 402.0f;
137 }
138 return 0.0f;
139}
143
144bool TSL2561Sensor::tsl2561_write_byte(uint8_t a_register, uint8_t value) {
145 return this->write_byte(a_register | TSL2561_COMMAND_BIT, value);
146}
147bool TSL2561Sensor::tsl2561_read_uint(uint8_t a_register, uint16_t *value) {
148 return this->read_byte_16_le(a_register | TSL2561_COMMAND_BIT, value);
149}
150bool TSL2561Sensor::tsl2561_read_byte(uint8_t a_register, uint8_t *value) {
151 return this->read_byte(a_register | TSL2561_COMMAND_BIT, value);
152}
153
154} // namespace esphome::tsl2561
void mark_failed()
Mark this component as failed.
bool status_comm_result(bool ok)
Clears the warning when ok, else sets it with message (default "Communication failed"); returns ok.
void set_timeout(const char *name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a const char* name.
Definition component.cpp:96
bool write_byte(uint8_t a_register, uint8_t data) const
Definition i2c.h:312
bool read_byte(uint8_t a_register, uint8_t *data)
Definition i2c.h:272
bool read_byte_16_le(uint8_t a_register, uint16_t *data)
Read a 16-bit value stored least significant byte first.
Definition i2c.h:296
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:65
TSL2561IntegrationTime integration_time_
Definition tsl2561.h:79
bool tsl2561_write_byte(uint8_t a_register, uint8_t value)
Definition tsl2561.cpp:144
bool tsl2561_read_uint(uint8_t a_register, uint16_t *value)
Definition tsl2561.cpp:147
float calculate_lx_(uint16_t ch0, uint16_t ch1)
Definition tsl2561.cpp:64
bool tsl2561_read_byte(uint8_t a_register, uint8_t *value)
Definition tsl2561.cpp:150
void set_integration_time(TSL2561IntegrationTime integration_time)
Set the time that sensor values should be accumulated for.
Definition tsl2561.cpp:140
uint16_t id
AlsGain501 gain
IntegrationTime501 integration_time
TSL2561IntegrationTime
Enum listing all conversion/integration time settings for the TSL2561.
Definition tsl2561.h:13
@ TSL2561_INTEGRATION_14MS
Definition tsl2561.h:14
@ TSL2561_INTEGRATION_402MS
Definition tsl2561.h:16
@ TSL2561_INTEGRATION_101MS
Definition tsl2561.h:15
ESPHOME_LOG_TAG(TAG, "tsl2561")
static void uint32_t