11static constexpr uint8_t REG_SYSTEM_CONTROL = 0x40;
12static constexpr uint8_t REG_MODE_CONTROL1 = 0x41;
13static constexpr uint8_t REG_MODE_CONTROL2 = 0x42;
14static constexpr uint8_t REG_MODE_CONTROL3 = 0x44;
15static constexpr uint8_t REG_RED_DATA_LSB = 0x50;
16static constexpr uint8_t REG_INTERRUPT = 0x60;
17static constexpr uint8_t REG_TH_LSB = 0x62;
18static constexpr uint8_t REG_MANUFACTURER_ID = 0x92;
20static constexpr uint8_t MANUFACTURER_ID = 0xE0;
21static constexpr uint8_t PART_ID = 0b001011;
22static constexpr uint8_t SYSTEM_CONTROL_PART_ID_MASK = 0x3F;
23static constexpr uint8_t SYSTEM_CONTROL_SW_RESET = 0x80;
24static constexpr uint8_t MODE_CONTROL2_RGBC_EN = 0x10;
25static constexpr uint8_t MODE_CONTROL2_VALID = 0x80;
26static constexpr uint8_t MODE_CONTROL3_VALUE = 0x02;
27static constexpr uint8_t INTERRUPT_ENABLE = 0x01;
29static constexpr uint8_t BH1745_CHANNELS = 4;
30static constexpr uint32_t RESET_DELAY_MS = 100;
31static constexpr uint32_t BASE_MEAS_TIME_MS = 160;
34 return BASE_MEAS_TIME_MS << static_cast<uint8_t>(time);
41static float calculate_lux(uint16_t red, uint16_t green,
bool low_clear_ratio,
float scale) {
44 float lx = low_clear_ratio ? 0.202f * red + 0.766f * green : 0.159f * red + 0.646f * green;
48static float calculate_cct(uint16_t red, uint16_t green, uint16_t blue,
bool low_clear_ratio) {
51 float all =
static_cast<float>(
static_cast<uint32_t>(red) + green + blue);
52 float r_ratio = red / all;
53 float b_ratio = blue / all;
55 if (low_clear_ratio) {
56 float b_eff = std::fmin(b_ratio * 3.13f, 1.0f);
57 ct = ((1.0f - b_eff) * 12746.0f * std::exp(-2.911f * r_ratio)) + (b_eff * 1637.0f * std::exp(4.865f * b_ratio));
59 float b_eff = std::fmin(b_ratio * 10.67f, 1.0f);
60 ct = ((1.0f - b_eff) * 16234.0f * std::exp(-2.781f * r_ratio)) + (b_eff * 1882.0f * std::exp(4.448f * b_ratio));
66 uint8_t manufacturer_id;
67 if (!this->
read_byte(REG_MANUFACTURER_ID, &manufacturer_id)) {
71 if (manufacturer_id != MANUFACTURER_ID) {
72 this->
mark_failed(LOG_STR(
"Wrong manufacturer ID"));
75 uint8_t system_control;
76 if (!this->
read_byte(REG_SYSTEM_CONTROL, &system_control) ||
77 (system_control & SYSTEM_CONTROL_PART_ID_MASK) != PART_ID) {
81 if (!this->
write_byte(REG_SYSTEM_CONTROL, SYSTEM_CONTROL_SW_RESET)) {
94 static constexpr uint8_t THRESHOLDS[4] = {0x00, 0x00, 0xFF, 0xFF};
95 if (!this->
write_bytes(REG_TH_LSB, THRESHOLDS,
sizeof(THRESHOLDS))) {
102 !this->
write_byte(REG_MODE_CONTROL2,
static_cast<uint8_t
>(this->
adc_gain_) | MODE_CONTROL2_RGBC_EN) ||
103 !this->
write_byte(REG_MODE_CONTROL3, MODE_CONTROL3_VALUE)) {
111void BH1745Component::dump_config() {
115 " Integration time: %" PRIu32
" ms\n"
116 " Glass attenuation factor: %.2f",
119 LOG_I2C_DEVICE(
this);
120 LOG_UPDATE_INTERVAL(
this);
122 LOG_SENSOR(
" ",
"Red Counts", this->red_counts_sensor_);
123 LOG_SENSOR(
" ",
"Green Counts", this->green_counts_sensor_);
124 LOG_SENSOR(
" ",
"Blue Counts", this->blue_counts_sensor_);
125 LOG_SENSOR(
" ",
"Clear Counts", this->clear_counts_sensor_);
126 LOG_SENSOR(
" ",
"Illuminance", this->illuminance_sensor_);
127 LOG_SENSOR(
" ",
"Color Temperature", this->color_temperature_sensor_);
130void BH1745Component::update() {
135 uint8_t mode_control2;
136 if (!this->
read_byte(REG_MODE_CONTROL2, &mode_control2)) {
140 if ((mode_control2 & MODE_CONTROL2_VALID) == 0)
143 uint8_t
buffer[BH1745_CHANNELS * 2];
155 ESP_LOGV(TAG,
"Red: %u, Green: %u, Blue: %u, Clear: %u", red, green, blue, clear);
157 if (this->red_counts_sensor_ !=
nullptr)
158 this->red_counts_sensor_->publish_state(red);
159 if (this->green_counts_sensor_ !=
nullptr)
160 this->green_counts_sensor_->publish_state(green);
161 if (this->blue_counts_sensor_ !=
nullptr)
162 this->blue_counts_sensor_->publish_state(blue);
163 if (this->clear_counts_sensor_ !=
nullptr)
164 this->clear_counts_sensor_->publish_state(clear);
167 const bool low_clear_ratio =
static_cast<uint32_t>(clear) * 25 <
static_cast<uint32_t>(green) * 4;
168 if (this->illuminance_sensor_ !=
nullptr)
169 this->illuminance_sensor_->publish_state(calculate_lux(red, green, low_clear_ratio, this->
lux_scale_));
170 if (this->color_temperature_sensor_ !=
nullptr)
171 this->color_temperature_sensor_->publish_state(calculate_cct(red, green, blue, low_clear_ratio));
174void BH1745Component::set_interrupt_state(
bool on) {
177 if (!this->
write_byte(REG_INTERRUPT, on ? INTERRUPT_ENABLE : 0x00)) {