ESPHome 2025.9.0-dev
Loading...
Searching...
No Matches
bh1750.cpp
Go to the documentation of this file.
1#include "bh1750.h"
2#include "esphome/core/log.h"
3
4namespace esphome {
5namespace bh1750 {
6
7static const char *const TAG = "bh1750.sensor";
8
9static const uint8_t BH1750_COMMAND_POWER_ON = 0b00000001;
10static const uint8_t BH1750_COMMAND_MT_REG_HI = 0b01000000; // last 3 bits
11static const uint8_t BH1750_COMMAND_MT_REG_LO = 0b01100000; // last 5 bits
12static const uint8_t BH1750_COMMAND_ONE_TIME_L = 0b00100011;
13static const uint8_t BH1750_COMMAND_ONE_TIME_H = 0b00100000;
14static const uint8_t BH1750_COMMAND_ONE_TIME_H2 = 0b00100001;
15
16/*
17bh1750 properties:
18
19L-resolution mode:
20- resolution 4lx (@ mtreg=69)
21- measurement time: typ=16ms, max=24ms, scaled by MTreg value divided by 69
22- formula: counts / 1.2 * (69 / MTreg) lx
23H-resolution mode:
24- resolution 1lx (@ mtreg=69)
25- measurement time: typ=120ms, max=180ms, scaled by MTreg value divided by 69
26- formula: counts / 1.2 * (69 / MTreg) lx
27H-resolution mode2:
28- resolution 0.5lx (@ mtreg=69)
29- measurement time: typ=120ms, max=180ms, scaled by MTreg value divided by 69
30- formula: counts / 1.2 * (69 / MTreg) / 2 lx
31
32MTreg:
33- min=31, default=69, max=254
34
35-> only reason to use l-resolution is faster, but offers no higher range
36-> below ~7000lx, makes sense to use H-resolution2 @ MTreg=254
37-> try to maximize MTreg to get lowest noise level
38*/
39
41 uint8_t turn_on = BH1750_COMMAND_POWER_ON;
42 if (this->write(&turn_on, 1) != i2c::ERROR_OK) {
43 this->mark_failed();
44 return;
45 }
46}
47
48void BH1750Sensor::read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function<void(float)> &f) {
49 // turn on (after one-shot sensor automatically powers down)
50 uint8_t turn_on = BH1750_COMMAND_POWER_ON;
51 if (this->write(&turn_on, 1) != i2c::ERROR_OK) {
52 ESP_LOGW(TAG, "Power on failed");
53 f(NAN);
54 return;
55 }
56
57 if (active_mtreg_ != mtreg) {
58 // set mtreg
59 uint8_t mtreg_hi = BH1750_COMMAND_MT_REG_HI | ((mtreg >> 5) & 0b111);
60 uint8_t mtreg_lo = BH1750_COMMAND_MT_REG_LO | ((mtreg >> 0) & 0b11111);
61 if (this->write(&mtreg_hi, 1) != i2c::ERROR_OK || this->write(&mtreg_lo, 1) != i2c::ERROR_OK) {
62 ESP_LOGW(TAG, "Set measurement time failed");
63 active_mtreg_ = 0;
64 f(NAN);
65 return;
66 }
67 active_mtreg_ = mtreg;
68 }
69
70 uint8_t cmd;
71 uint16_t meas_time;
72 switch (mode) {
73 case BH1750_MODE_L:
74 cmd = BH1750_COMMAND_ONE_TIME_L;
75 meas_time = 24 * mtreg / 69;
76 break;
77 case BH1750_MODE_H:
78 cmd = BH1750_COMMAND_ONE_TIME_H;
79 meas_time = 180 * mtreg / 69;
80 break;
81 case BH1750_MODE_H2:
82 cmd = BH1750_COMMAND_ONE_TIME_H2;
83 meas_time = 180 * mtreg / 69;
84 break;
85 default:
86 f(NAN);
87 return;
88 }
89 if (this->write(&cmd, 1) != i2c::ERROR_OK) {
90 ESP_LOGW(TAG, "Start measurement failed");
91 f(NAN);
92 return;
93 }
94
95 // probably not needed, but adjust for rounding
96 meas_time++;
97
98 this->set_timeout("read", meas_time, [this, mode, mtreg, f]() {
99 uint16_t raw_value;
100 if (this->read(reinterpret_cast<uint8_t *>(&raw_value), 2) != i2c::ERROR_OK) {
101 ESP_LOGW(TAG, "Read data failed");
102 f(NAN);
103 return;
104 }
105 raw_value = i2c::i2ctohs(raw_value);
106
107 float lx = float(raw_value) / 1.2f;
108 lx *= 69.0f / mtreg;
109 if (mode == BH1750_MODE_H2)
110 lx /= 2.0f;
111
112 f(lx);
113 });
114}
115
117 LOG_SENSOR("", "BH1750", this);
118 LOG_I2C_DEVICE(this);
119 if (this->is_failed()) {
120 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL_FOR, this->get_name().c_str());
121 }
122
123 LOG_UPDATE_INTERVAL(this);
124}
125
127 // first do a quick measurement in L-mode with full range
128 // to find right range
129 this->read_lx_(BH1750_MODE_L, 31, [this](float val) {
130 if (std::isnan(val)) {
131 this->status_set_warning();
132 this->publish_state(NAN);
133 return;
134 }
135
136 BH1750Mode use_mode;
137 uint8_t use_mtreg;
138 if (val <= 7000) {
139 use_mode = BH1750_MODE_H2;
140 use_mtreg = 254;
141 } else {
142 use_mode = BH1750_MODE_H;
143 // lx = counts / 1.2 * (69 / mtreg)
144 // -> mtreg = counts / 1.2 * (69 / lx)
145 // calculate for counts=50000 (allow some range to not saturate, but maximize mtreg)
146 // -> mtreg = 50000*(10/12)*(69/lx)
147 int ideal_mtreg = 50000 * 10 * 69 / (12 * (int) val);
148 use_mtreg = std::min(254, std::max(31, ideal_mtreg));
149 }
150 ESP_LOGV(TAG, "L result: %f -> Calculated mode=%d, mtreg=%d", val, (int) use_mode, use_mtreg);
151
152 this->read_lx_(use_mode, use_mtreg, [this](float val) {
153 if (std::isnan(val)) {
154 this->status_set_warning();
155 this->publish_state(NAN);
156 return;
157 }
158 ESP_LOGD(TAG, "'%s': Illuminance=%.1flx", this->get_name().c_str(), val);
159 this->status_clear_warning();
160 this->publish_state(val);
161 });
162 });
163}
164
166
167} // namespace bh1750
168} // namespace esphome
BedjetMode mode
BedJet operating mode.
virtual void mark_failed()
Mark this component as failed.
bool is_failed() const
void status_set_warning(const char *message=nullptr)
void status_clear_warning()
void set_timeout(const std::string &name, uint32_t timeout, std::function< void()> &&f)
Set a timeout function with a unique name.
const StringRef & get_name() const
void read_lx_(BH1750Mode mode, uint8_t mtreg, const std::function< void(float)> &f)
Definition bh1750.cpp:48
void dump_config() override
Definition bh1750.cpp:116
float get_setup_priority() const override
Definition bh1750.cpp:165
ErrorCode write(const uint8_t *data, size_t len, bool stop=true)
writes an array of bytes to a device using an I2CBus
Definition i2c.h:190
ErrorCode read(uint8_t *data, size_t len)
reads an array of bytes from the device using an I2CBus
Definition i2c.h:164
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:45
mopeka_std_values val[4]
uint16_t i2ctohs(uint16_t i2cshort)
Definition i2c.h:128
@ ERROR_OK
No error found during execution of method.
Definition i2c_bus.h:13
const float DATA
For components that import data from directly connected sensors like DHT.
Definition component.cpp:50
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7