ESPHome 2025.6.3
Loading...
Searching...
No Matches
nau7802.cpp
Go to the documentation of this file.
1#include "nau7802.h"
2#include "esphome/core/log.h"
3#include "esphome/core/hal.h"
4
5namespace esphome {
6namespace nau7802 {
7
8static const char *const TAG = "nau7802";
9
10// Only define what we need
11
12static const uint8_t READ_BIT = 0x01;
13
14static const uint8_t PU_CTRL_REG = 0x00;
15static const uint8_t PU_CTRL_REGISTER_RESET = 0x01;
16static const uint8_t PU_CTRL_POWERUP_DIGITAL = 0x02;
17static const uint8_t PU_CTRL_POWERUP_ANALOG = 0x04;
18static const uint8_t PU_CTRL_POWERUP_READY = 0x08;
19static const uint8_t PU_CTRL_CYCLE_START = 0x10;
20static const uint8_t PU_CTRL_CYCLE_READY = 0x20;
21static const uint8_t PU_CTRL_AVDD_EXTERNAL = 0x80;
22
23static const uint8_t CTRL1_REG = 0x01;
24static const uint8_t CTRL1_LDO_SHIFT = 3;
25static const uint8_t CTRL1_LDO_MASK = (0x7 << CTRL1_LDO_SHIFT);
26static const uint8_t CTRL1_GAIN_MASK = 0x7;
27
28static const uint8_t CTRL2_REG = 0x02;
29static const uint8_t CTRL2_CRS_SHIFT = 4;
30static const uint8_t CTRL2_CRS_MASK = (0x7 << CTRL2_CRS_SHIFT);
31static const uint8_t CTRL2_CALS = 0x04;
32static const uint8_t CTRL2_CAL_ERR = 0x08;
33static const uint8_t CTRL2_GAIN_CALIBRATION = 0x03;
34static const uint8_t CTRL2_CONFIG_MASK = 0xF0;
35
36static const uint8_t OCAL1_B2_REG = 0x03;
37static const uint8_t GCAL1_B3_REG = 0x06;
38static const uint8_t GCAL1_FRACTIONAL = 23;
39
40// only need the first data register for sequential read method
41static const uint8_t ADCO_B2_REG = 0x12;
42
43static const uint8_t ADC_REG = 0x15;
44static const uint8_t ADC_CHPS_DISABLE = 0x30;
45
46static const uint8_t PGA_REG = 0x1B;
47static const uint8_t PGA_LDOMODE_ESR = 0x40;
48
49static const uint8_t POWER_REG = 0x1C;
50static const uint8_t POWER_PGA_CAP_EN = 0x80;
51
52static const uint8_t DEVICE_REV = 0x1F;
53
55 ESP_LOGCONFIG(TAG, "Running setup for '%s'", this->name_.c_str());
56 i2c::I2CRegister pu_ctrl = this->reg(PU_CTRL_REG);
57 uint8_t rev;
58
59 if (this->read_register(DEVICE_REV | READ_BIT, &rev, 1)) {
60 ESP_LOGE(TAG, "Failed I2C read during setup()");
61 this->mark_failed();
62 return;
63 }
64 ESP_LOGI(TAG, "Setting up NAU7802 Rev %d", rev);
65
66 // reset
67 pu_ctrl |= PU_CTRL_REGISTER_RESET;
68 delay(10);
69 pu_ctrl &= ~PU_CTRL_REGISTER_RESET;
70
71 // power up digital hw
72 pu_ctrl |= PU_CTRL_POWERUP_DIGITAL;
73
74 delay(1);
75 if (!(pu_ctrl.get() & PU_CTRL_POWERUP_READY)) {
76 ESP_LOGE(TAG, "Failed to reset sensor during setup()");
77 this->mark_failed();
78 return;
79 }
80
81 uint32_t gcal = (uint32_t) (round(this->gain_calibration_ * (1 << GCAL1_FRACTIONAL)));
82 this->write_value_(OCAL1_B2_REG, 3, this->offset_calibration_);
83 this->write_value_(GCAL1_B3_REG, 4, gcal);
84
85 // turn on AFE
86 pu_ctrl |= PU_CTRL_POWERUP_ANALOG;
87 auto f = std::bind(&NAU7802Sensor::complete_setup_, this);
88 this->set_timeout(600, f);
89}
90
92 i2c::I2CRegister pu_ctrl = this->reg(PU_CTRL_REG);
93 i2c::I2CRegister ctrl1 = this->reg(CTRL1_REG);
94 i2c::I2CRegister ctrl2 = this->reg(CTRL2_REG);
95 pu_ctrl |= PU_CTRL_CYCLE_START;
96
97 // set gain
98 ctrl1 &= ~CTRL1_GAIN_MASK;
99 ctrl1 |= this->gain_;
100
101 // enable internal LDO
102 if (this->ldo_ != NAU7802_LDO_EXTERNAL) {
103 pu_ctrl |= PU_CTRL_AVDD_EXTERNAL;
104 ctrl1 &= ~CTRL1_LDO_MASK;
105 ctrl1 |= this->ldo_ << CTRL1_LDO_SHIFT;
106 }
107
108 // set sps
109 ctrl2 &= ~CTRL2_CRS_MASK;
110 ctrl2 |= this->sps_ << CTRL2_CRS_SHIFT;
111
112 // disable ADC chopper clock
113 i2c::I2CRegister adc_reg = this->reg(ADC_REG);
114 adc_reg |= ADC_CHPS_DISABLE;
115
116 // use low ESR caps
117 i2c::I2CRegister pga_reg = this->reg(PGA_REG);
118 pga_reg &= ~PGA_LDOMODE_ESR;
119
120 // PGA stabilizer cap on output
121 i2c::I2CRegister pwr_reg = this->reg(POWER_REG);
122 pwr_reg |= POWER_PGA_CAP_EN;
123}
124
126 LOG_SENSOR("", "NAU7802", this);
127 LOG_I2C_DEVICE(this);
128
129 if (this->is_failed()) {
130 ESP_LOGE(TAG, ESP_LOG_MSG_COMM_FAIL_FOR, this->get_name().c_str());
131 return;
132 }
133 // Note these may differ from the values on the device if calbration has been run
134 ESP_LOGCONFIG(TAG,
135 " Offset Calibration: %s\n"
136 " Gain Calibration: %f",
137 to_string(this->offset_calibration_).c_str(), this->gain_calibration_);
138
139 std::string voltage = "unknown";
140 switch (this->ldo_) {
141 case NAU7802_LDO_2V4:
142 voltage = "2.4V";
143 break;
144 case NAU7802_LDO_2V7:
145 voltage = "2.7V";
146 break;
147 case NAU7802_LDO_3V0:
148 voltage = "3.0V";
149 break;
150 case NAU7802_LDO_3V3:
151 voltage = "3.3V";
152 break;
153 case NAU7802_LDO_3V6:
154 voltage = "3.6V";
155 break;
156 case NAU7802_LDO_3V9:
157 voltage = "3.9V";
158 break;
159 case NAU7802_LDO_4V2:
160 voltage = "4.2V";
161 break;
162 case NAU7802_LDO_4V5:
163 voltage = "4.5V";
164 break;
166 voltage = "External";
167 break;
168 }
169 ESP_LOGCONFIG(TAG, " LDO Voltage: %s", voltage.c_str());
170 int gain = 0;
171 switch (this->gain_) {
172 case NAU7802_GAIN_128:
173 gain = 128;
174 break;
175 case NAU7802_GAIN_64:
176 gain = 64;
177 break;
178 case NAU7802_GAIN_32:
179 gain = 32;
180 break;
181 case NAU7802_GAIN_16:
182 gain = 16;
183 break;
184 case NAU7802_GAIN_8:
185 gain = 8;
186 break;
187 case NAU7802_GAIN_4:
188 gain = 4;
189 break;
190 case NAU7802_GAIN_2:
191 gain = 2;
192 break;
193 case NAU7802_GAIN_1:
194 gain = 1;
195 break;
196 }
197 ESP_LOGCONFIG(TAG, " Gain: %dx", gain);
198 int sps = 0;
199 switch (this->sps_) {
200 case NAU7802_SPS_320:
201 sps = 320;
202 break;
203 case NAU7802_SPS_80:
204 sps = 80;
205 break;
206 case NAU7802_SPS_40:
207 sps = 40;
208 break;
209 case NAU7802_SPS_20:
210 sps = 20;
211 break;
212 case NAU7802_SPS_10:
213 sps = 10;
214 break;
215 }
216 ESP_LOGCONFIG(TAG, " Samples Per Second: %d", sps);
217 LOG_UPDATE_INTERVAL(this);
218}
219
220void NAU7802Sensor::write_value_(uint8_t start_reg, size_t size, int32_t value) {
221 uint8_t data[4];
222 for (int i = 0; i < size; i++) {
223 data[i] = 0xFF & (value >> (size - 1 - i) * 8);
224 }
225 this->write_register(start_reg, data, size);
226}
227
228int32_t NAU7802Sensor::read_value_(uint8_t start_reg, size_t size) {
229 uint8_t data[4];
230 this->read_register(start_reg, data, size);
231 int32_t result = 0;
232 for (int i = 0; i < size; i++) {
233 result |= data[i] << (size - 1 - i) * 8;
234 }
235 // extend sign bit
236 if (result & 0x800000 && size == 3) {
237 result |= 0xFF000000;
238 }
239 return result;
240}
241
243 // check if already calbrating
244 if (this->state_ != CalibrationState::INACTIVE) {
245 ESP_LOGW(TAG, "Calibration already in progress");
246 return false;
247 }
248
250
251 i2c::I2CRegister ctrl2 = this->reg(CTRL2_REG);
252 // clear calibraye registers
253 ctrl2 &= CTRL2_CONFIG_MASK;
254 // Calibrate
255 ctrl2 |= mode;
256 ctrl2 |= CTRL2_CALS;
257 return true;
258}
259
261 switch (this->state_) {
263 this->gain_calibration_failed_ = failed;
264 break;
266 this->offset_calibration_failed_ = failed;
267 break;
269 // shouldn't happen
270 break;
271 }
272}
273
275 i2c::I2CRegister ctrl2 = this->reg(CTRL2_REG);
276
277 if (this->state_ != CalibrationState::INACTIVE && !(ctrl2.get() & CTRL2_CALS)) {
278 if (ctrl2.get() & CTRL2_CAL_ERR) {
279 this->set_calibration_failure_(true);
280 this->state_ = CalibrationState::INACTIVE;
281 ESP_LOGE(TAG, "Failed to calibrate sensor");
282 this->status_set_error("Calibration Failed");
283 return;
284 }
285
286 this->set_calibration_failure_(false);
287 this->state_ = CalibrationState::INACTIVE;
288
290 this->status_clear_error();
291
292 int32_t ocal = this->read_value_(OCAL1_B2_REG, 3);
293 ESP_LOGI(TAG, "New Offset: %s", to_string(ocal).c_str());
294 uint32_t gcal = this->read_value_(GCAL1_B3_REG, 4);
295 float gcal_f = ((float) gcal / (float) (1 << GCAL1_FRACTIONAL));
296 ESP_LOGI(TAG, "New Gain: %f", gcal_f);
297 }
298}
299
301
303 if (!this->is_data_ready_()) {
304 ESP_LOGW(TAG, "No measurements ready!");
305 this->status_set_warning();
306 return;
307 }
308
309 this->status_clear_warning();
310
311 // Get the most recent sample to publish
312 int32_t result = this->read_value_(ADCO_B2_REG, 3);
313
314 ESP_LOGD(TAG, "'%s': Got value %" PRId32, this->name_.c_str(), result);
315 this->publish_state(result);
316}
317
318bool NAU7802Sensor::is_data_ready_() { return this->reg(PU_CTRL_REG).get() & PU_CTRL_CYCLE_READY; }
319
320} // namespace nau7802
321} // 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="unspecified")
void status_set_error(const char *message="unspecified")
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.
Definition component.cpp:75
const StringRef & get_name() const
constexpr const char * c_str() const
Definition string_ref.h:69
ErrorCode write_register(uint8_t a_register, const uint8_t *data, size_t len, bool stop=true)
writes an array of bytes to a specific register in the I²C device
Definition i2c.cpp:25
I2CRegister reg(uint8_t a_register)
calls the I2CRegister constructor
Definition i2c.h:153
ErrorCode read_register(uint8_t a_register, uint8_t *data, size_t len, bool stop=true)
reads an array of bytes from a specific register in the I²C device
Definition i2c.cpp:10
This class is used to create I2CRegister objects that act as proxies to read/write internal registers...
Definition i2c.h:33
uint8_t get() const
returns the register value
Definition i2c.cpp:75
bool calibrate_(enum NAU7802CalibrationModes mode)
Definition nau7802.cpp:242
float get_setup_priority() const override
Definition nau7802.cpp:300
void write_value_(uint8_t start_reg, size_t size, int32_t value)
Definition nau7802.cpp:220
int32_t read_value_(uint8_t start_reg, size_t size)
Definition nau7802.cpp:228
void set_calibration_failure_(bool failed)
Definition nau7802.cpp:260
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:39
AlsGain501 gain
@ NAU7802_CALIBRATE_GAIN
Definition nau7802.h:48
const float DATA
For components that import data from directly connected sensors like DHT.
Definition component.cpp:20
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string to_string(int value)
Definition helpers.cpp:82
void IRAM_ATTR HOT delay(uint32_t ms)
Definition core.cpp:29