ESPHome 2025.5.0
Loading...
Searching...
No Matches
apds9306.cpp
Go to the documentation of this file.
1// Based on this datasheet:
2// https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf
3
4#include "apds9306.h"
6#include "esphome/core/log.h"
7
8namespace esphome {
9namespace apds9306 {
10
11static const char *const TAG = "apds9306";
12
13enum { // APDS9306 registers
19 APDS9306_CLEAR_DATA_0 = 0x0A, // LSB
21 APDS9306_CLEAR_DATA_2 = 0x0C, // MSB
22 APDS9306_ALS_DATA_0 = 0x0D, // LSB
24 APDS9306_ALS_DATA_2 = 0x0F, // MSB
34};
35
36#define APDS9306_ERROR_CHECK(func, error) \
37 if (!(func)) { \
38 ESP_LOGE(TAG, error); \
39 this->mark_failed(); \
40 return; \
41 }
42#define APDS9306_WARNING_CHECK(func, warning) \
43 if (!(func)) { \
44 ESP_LOGW(TAG, warning); \
45 this->status_set_warning(); \
46 return; \
47 }
48#define APDS9306_WRITE_BYTE(reg, value) \
49 ESP_LOGV(TAG, "Writing 0x%02x to 0x%02x", value, reg); \
50 if (!this->write_byte(reg, value)) { \
51 ESP_LOGE(TAG, "Failed writing 0x%02x to 0x%02x", value, reg); \
52 this->mark_failed(); \
53 return; \
54 }
55
57 ESP_LOGCONFIG(TAG, "Setting up APDS9306...");
58
59 uint8_t id;
60 if (!this->read_byte(APDS9306_PART_ID, &id)) { // Part ID register
61 this->error_code_ = COMMUNICATION_FAILED;
62 this->mark_failed();
63 return;
64 }
65
66 if (id != 0xB1 && id != 0xB3) { // 0xB1 for APDS9306 0xB3 for APDS9306-065
67 this->error_code_ = WRONG_ID;
68 this->mark_failed();
69 return;
70 }
71
72 // ALS resolution and measurement, see datasheet or init.py for options
73 uint8_t als_meas_rate = ((this->bit_width_ & 0x07) << 4) | (this->measurement_rate_ & 0x07);
74 APDS9306_WRITE_BYTE(APDS9306_ALS_MEAS_RATE, als_meas_rate);
75
76 // ALS gain, see datasheet or init.py for options
77 uint8_t als_gain = (this->gain_ & 0x07);
78 APDS9306_WRITE_BYTE(APDS9306_ALS_GAIN, als_gain);
79
80 // Set to standby mode
81 APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x00);
82
83 // Check for data, clear main status
84 uint8_t status;
85 APDS9306_WARNING_CHECK(this->read_byte(APDS9306_MAIN_STATUS, &status), "Reading MAIN STATUS failed.");
86
87 // Set to active mode
88 APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x02);
89
90 ESP_LOGCONFIG(TAG, "APDS9306 setup complete");
91}
92
94 LOG_SENSOR("", "APDS9306", this);
95 LOG_I2C_DEVICE(this);
96
97 if (this->is_failed()) {
98 switch (this->error_code_) {
100 ESP_LOGE(TAG, "Communication with APDS9306 failed!");
101 break;
102 case WRONG_ID:
103 ESP_LOGE(TAG, "APDS9306 has invalid id!");
104 break;
105 default:
106 ESP_LOGE(TAG, "Setting up APDS9306 registers failed!");
107 break;
108 }
109 }
110
111 ESP_LOGCONFIG(TAG, " Gain: %u", AMBIENT_LIGHT_GAIN_VALUES[this->gain_]);
112 ESP_LOGCONFIG(TAG, " Measurement rate: %u", MEASUREMENT_RATE_VALUES[this->measurement_rate_]);
113 ESP_LOGCONFIG(TAG, " Measurement Resolution/Bit width: %d", MEASUREMENT_BIT_WIDTH_VALUES[this->bit_width_]);
114
115 LOG_UPDATE_INTERVAL(this);
116}
117
119 // Check for new data
120 uint8_t status;
121 APDS9306_WARNING_CHECK(this->read_byte(APDS9306_MAIN_STATUS, &status), "Reading MAIN STATUS failed.");
122
123 this->status_clear_warning();
124
125 status &= 0b00001000;
126 if (!status) { // No new data
127 return;
128 }
129
130 // Set to standby mode
131 APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x00);
132
133 // Clear MAIN STATUS
134 APDS9306_WARNING_CHECK(this->read_byte(APDS9306_MAIN_STATUS, &status), "Reading MAIN STATUS failed.");
135
136 uint8_t als_data[3];
137 APDS9306_WARNING_CHECK(this->read_bytes(APDS9306_ALS_DATA_0, als_data, 3), "Reading ALS data has failed.");
138
139 // Set to active mode
140 APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x02);
141
142 uint32_t light_level = 0x00 | encode_uint24(als_data[2], als_data[1], als_data[0]);
143
144 float lux = ((float) light_level / AMBIENT_LIGHT_GAIN_VALUES[this->gain_]) *
145 (100.0f / MEASUREMENT_RATE_VALUES[this->measurement_rate_]);
146
147 ESP_LOGD(TAG, "Got illuminance=%.1flx from", lux);
148 this->publish_state(lux);
149}
150
151} // namespace apds9306
152} // namespace esphome
uint8_t status
Definition bl0942.h:8
virtual void mark_failed()
Mark this component as failed.
bool is_failed() const
void status_clear_warning()
MeasurementBitWidth bit_width_
Definition apds9306.h:60
AmbientLightGain gain_
Definition apds9306.h:62
void dump_config() override
Definition apds9306.cpp:93
MeasurementRate measurement_rate_
Definition apds9306.h:61
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
Definition i2c.h:239
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
Definition i2c.h:216
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:39
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
constexpr uint32_t encode_uint24(uint8_t byte1, uint8_t byte2, uint8_t byte3)
Encode a 24-bit value given three bytes in most to least significant byte order.
Definition helpers.h:200
T id(T value)
Helper function to make id(var) known from lambdas work in custom components.
Definition helpers.h:798