ESPHome  2024.4.1
as7341.cpp
Go to the documentation of this file.
1 #include "as7341.h"
2 #include "esphome/core/log.h"
3 #include "esphome/core/hal.h"
4 
5 namespace esphome {
6 namespace as7341 {
7 
8 static const char *const TAG = "as7341";
9 
11  ESP_LOGCONFIG(TAG, "Setting up AS7341...");
12  LOG_I2C_DEVICE(this);
13 
14  // Verify device ID
15  uint8_t id;
16  this->read_byte(AS7341_ID, &id);
17  ESP_LOGCONFIG(TAG, " Read ID: 0x%X", id);
18  if ((id & 0xFC) != (AS7341_CHIP_ID << 2)) {
19  this->mark_failed();
20  return;
21  }
22 
23  // Power on (enter IDLE state)
24  if (!this->enable_power(true)) {
25  ESP_LOGE(TAG, " Power on failed!");
26  this->mark_failed();
27  return;
28  }
29 
30  // Set configuration
31  this->write_byte(AS7341_CONFIG, 0x00);
32  this->setup_atime(this->atime_);
33  this->setup_astep(this->astep_);
34  this->setup_gain(this->gain_);
35 }
36 
38  ESP_LOGCONFIG(TAG, "AS7341:");
39  LOG_I2C_DEVICE(this);
40  if (this->is_failed()) {
41  ESP_LOGE(TAG, "Communication with AS7341 failed!");
42  }
43  LOG_UPDATE_INTERVAL(this);
44  ESP_LOGCONFIG(TAG, " Gain: %u", get_gain());
45  ESP_LOGCONFIG(TAG, " ATIME: %u", get_atime());
46  ESP_LOGCONFIG(TAG, " ASTEP: %u", get_astep());
47 
48  LOG_SENSOR(" ", "F1", this->f1_);
49  LOG_SENSOR(" ", "F2", this->f2_);
50  LOG_SENSOR(" ", "F3", this->f3_);
51  LOG_SENSOR(" ", "F4", this->f4_);
52  LOG_SENSOR(" ", "F5", this->f5_);
53  LOG_SENSOR(" ", "F6", this->f6_);
54  LOG_SENSOR(" ", "F7", this->f7_);
55  LOG_SENSOR(" ", "F8", this->f8_);
56  LOG_SENSOR(" ", "Clear", this->clear_);
57  LOG_SENSOR(" ", "NIR", this->nir_);
58 }
59 
61 
63  this->read_channels(this->channel_readings_);
64 
65  if (this->f1_ != nullptr) {
66  this->f1_->publish_state(this->channel_readings_[0]);
67  }
68  if (this->f2_ != nullptr) {
69  this->f2_->publish_state(this->channel_readings_[1]);
70  }
71  if (this->f3_ != nullptr) {
72  this->f3_->publish_state(this->channel_readings_[2]);
73  }
74  if (this->f4_ != nullptr) {
75  this->f4_->publish_state(this->channel_readings_[3]);
76  }
77  if (this->f5_ != nullptr) {
78  this->f5_->publish_state(this->channel_readings_[6]);
79  }
80  if (this->f6_ != nullptr) {
81  this->f6_->publish_state(this->channel_readings_[7]);
82  }
83  if (this->f7_ != nullptr) {
84  this->f7_->publish_state(this->channel_readings_[8]);
85  }
86  if (this->f8_ != nullptr) {
87  this->f8_->publish_state(this->channel_readings_[9]);
88  }
89  if (this->clear_ != nullptr) {
90  this->clear_->publish_state(this->channel_readings_[10]);
91  }
92  if (this->nir_ != nullptr) {
93  this->nir_->publish_state(this->channel_readings_[11]);
94  }
95 }
96 
98  uint8_t data;
99  this->read_byte(AS7341_CFG1, &data);
100  return (AS7341Gain) data;
101 }
102 
104  uint8_t data;
105  this->read_byte(AS7341_ATIME, &data);
106  return data;
107 }
108 
110  uint16_t data;
111  this->read_byte_16(AS7341_ASTEP, &data);
112  return this->swap_bytes(data);
113 }
114 
115 bool AS7341Component::setup_gain(AS7341Gain gain) { return this->write_byte(AS7341_CFG1, gain); }
116 
117 bool AS7341Component::setup_atime(uint8_t atime) { return this->write_byte(AS7341_ATIME, atime); }
118 
119 bool AS7341Component::setup_astep(uint16_t astep) { return this->write_byte_16(AS7341_ASTEP, swap_bytes(astep)); }
120 
121 bool AS7341Component::read_channels(uint16_t *data) {
122  this->set_smux_low_channels(true);
123  this->enable_spectral_measurement(true);
124  this->wait_for_data();
125  bool low_success = this->read_bytes_16(AS7341_CH0_DATA_L, data, 6);
126 
127  this->set_smux_low_channels(false);
128  this->enable_spectral_measurement(true);
129  this->wait_for_data();
130  bool high_sucess = this->read_bytes_16(AS7341_CH0_DATA_L, &data[6], 6);
131 
132  return low_success && high_sucess;
133 }
134 
136  this->enable_spectral_measurement(false);
138 
139  if (enable) {
141 
142  } else {
144  }
145  this->enable_smux();
146 }
147 
149  uint8_t data = command << 3; // Write to bits 4:3 of the register
150  return this->write_byte(AS7341_CFG6, data);
151 }
152 
154  // SMUX Config for F1,F2,F3,F4,NIR,Clear
155  this->write_byte(0x00, 0x30); // F3 left set to ADC2
156  this->write_byte(0x01, 0x01); // F1 left set to ADC0
157  this->write_byte(0x02, 0x00); // Reserved or disabled
158  this->write_byte(0x03, 0x00); // F8 left disabled
159  this->write_byte(0x04, 0x00); // F6 left disabled
160  this->write_byte(0x05, 0x42); // F4 left connected to ADC3/f2 left connected to ADC1
161  this->write_byte(0x06, 0x00); // F5 left disbled
162  this->write_byte(0x07, 0x00); // F7 left disbled
163  this->write_byte(0x08, 0x50); // CLEAR connected to ADC4
164  this->write_byte(0x09, 0x00); // F5 right disabled
165  this->write_byte(0x0A, 0x00); // F7 right disabled
166  this->write_byte(0x0B, 0x00); // Reserved or disabled
167  this->write_byte(0x0C, 0x20); // F2 right connected to ADC1
168  this->write_byte(0x0D, 0x04); // F4 right connected to ADC3
169  this->write_byte(0x0E, 0x00); // F6/F8 right disabled
170  this->write_byte(0x0F, 0x30); // F3 right connected to AD2
171  this->write_byte(0x10, 0x01); // F1 right connected to AD0
172  this->write_byte(0x11, 0x50); // CLEAR right connected to AD4
173  this->write_byte(0x12, 0x00); // Reserved or disabled
174  this->write_byte(0x13, 0x06); // NIR connected to ADC5
175 }
176 
178  // SMUX Config for F5,F6,F7,F8,NIR,Clear
179  this->write_byte(0x00, 0x00); // F3 left disable
180  this->write_byte(0x01, 0x00); // F1 left disable
181  this->write_byte(0x02, 0x00); // reserved/disable
182  this->write_byte(0x03, 0x40); // F8 left connected to ADC3
183  this->write_byte(0x04, 0x02); // F6 left connected to ADC1
184  this->write_byte(0x05, 0x00); // F4/ F2 disabled
185  this->write_byte(0x06, 0x10); // F5 left connected to ADC0
186  this->write_byte(0x07, 0x03); // F7 left connected to ADC2
187  this->write_byte(0x08, 0x50); // CLEAR Connected to ADC4
188  this->write_byte(0x09, 0x10); // F5 right connected to ADC0
189  this->write_byte(0x0A, 0x03); // F7 right connected to ADC2
190  this->write_byte(0x0B, 0x00); // Reserved or disabled
191  this->write_byte(0x0C, 0x00); // F2 right disabled
192  this->write_byte(0x0D, 0x00); // F4 right disabled
193  this->write_byte(0x0E, 0x24); // F8 right connected to ADC2/ F6 right connected to ADC1
194  this->write_byte(0x0F, 0x00); // F3 right disabled
195  this->write_byte(0x10, 0x00); // F1 right disabled
196  this->write_byte(0x11, 0x50); // CLEAR right connected to AD4
197  this->write_byte(0x12, 0x00); // Reserved or disabled
198  this->write_byte(0x13, 0x06); // NIR connected to ADC5
199 }
200 
202  this->set_register_bit(AS7341_ENABLE, 4);
203 
204  uint16_t timeout = 1000;
205  for (uint16_t time = 0; time < timeout; time++) {
206  // The SMUXEN bit is cleared once the SMUX operation is finished
207  bool smuxen = this->read_register_bit(AS7341_ENABLE, 4);
208  if (!smuxen) {
209  return true;
210  }
211 
212  delay(1);
213  }
214 
215  return false;
216 }
217 
219  uint16_t timeout = 1000;
220  for (uint16_t time = 0; time < timeout; time++) {
221  if (this->is_data_ready()) {
222  return true;
223  }
224 
225  delay(1);
226  }
227 
228  return false;
229 }
230 
231 bool AS7341Component::is_data_ready() { return this->read_register_bit(AS7341_STATUS2, 6); }
232 
233 bool AS7341Component::enable_power(bool enable) { return this->write_register_bit(AS7341_ENABLE, enable, 0); }
234 
236  return this->write_register_bit(AS7341_ENABLE, enable, 1);
237 }
238 
239 bool AS7341Component::read_register_bit(uint8_t address, uint8_t bit_position) {
240  uint8_t data;
241  this->read_byte(address, &data);
242  bool bit = (data & (1 << bit_position)) > 0;
243  return bit;
244 }
245 
246 bool AS7341Component::write_register_bit(uint8_t address, bool value, uint8_t bit_position) {
247  if (value) {
248  return this->set_register_bit(address, bit_position);
249  }
250 
251  return this->clear_register_bit(address, bit_position);
252 }
253 
254 bool AS7341Component::set_register_bit(uint8_t address, uint8_t bit_position) {
255  uint8_t data;
256  this->read_byte(address, &data);
257  data |= (1 << bit_position);
258  return this->write_byte(address, data);
259 }
260 
261 bool AS7341Component::clear_register_bit(uint8_t address, uint8_t bit_position) {
262  uint8_t data;
263  this->read_byte(address, &data);
264  data &= ~(1 << bit_position);
265  return this->write_byte(address, data);
266 }
267 
268 uint16_t AS7341Component::swap_bytes(uint16_t data) { return (data >> 8) | (data << 8); }
269 
270 } // namespace as7341
271 } // namespace esphome
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
Definition: i2c.h:235
bool read_byte_16(uint8_t a_register, uint16_t *data)
Definition: i2c.h:246
const float DATA
For components that import data from directly connected sensors like DHT.
Definition: component.cpp:19
bool setup_gain(AS7341Gain gain)
Definition: as7341.cpp:115
bool read_channels(uint16_t *data)
Definition: as7341.cpp:121
bool enable_power(bool enable)
Definition: as7341.cpp:233
Write SMUX configuration from RAM to SMUX chain.
Definition: as7341.h:60
bool read_register_bit(uint8_t address, uint8_t bit_position)
Definition: as7341.cpp:239
uint16_t channel_readings_[12]
Definition: as7341.h:140
T id(T value)
Helper function to make id(var) known from lambdas work in custom components.
Definition: helpers.h:689
bool enable_spectral_measurement(bool enable)
Definition: as7341.cpp:235
bool setup_atime(uint8_t atime)
Definition: as7341.cpp:117
bool write_register_bit(uint8_t address, bool value, uint8_t bit_position)
Definition: as7341.cpp:246
bool setup_astep(uint16_t astep)
Definition: as7341.cpp:119
void dump_config() override
Definition: as7341.cpp:37
void publish_state(float state)
Publish a new state to the front-end.
Definition: sensor.cpp:39
bool set_register_bit(uint8_t address, uint8_t bit_position)
Definition: as7341.cpp:254
sensor::Sensor * clear_
Definition: as7341.h:134
bool clear_register_bit(uint8_t address, uint8_t bit_position)
Definition: as7341.cpp:261
bool write_byte(uint8_t a_register, uint8_t data, bool stop=true)
Definition: i2c.h:262
virtual void mark_failed()
Mark this component as failed.
Definition: component.cpp:118
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7
float get_setup_priority() const override
Definition: as7341.cpp:60
void set_smux_low_channels(bool enable)
Definition: as7341.cpp:135
bool write_byte_16(uint8_t a_register, uint16_t data)
Definition: i2c.h:266
uint16_t swap_bytes(uint16_t data)
Definition: as7341.cpp:268
bool read_bytes_16(uint8_t a_register, uint16_t *data, uint8_t len)
Definition: i2c.cpp:44
void IRAM_ATTR HOT delay(uint32_t ms)
Definition: core.cpp:26
bool set_smux_command(AS7341SmuxCommand command)
Definition: as7341.cpp:148