8 static const char *
const TAG =
"apds9960";
10 #define APDS9960_ERROR_CHECK(func) \ 12 this->mark_failed(); \ 15 #define APDS9960_WRITE_BYTE(reg, value) APDS9960_ERROR_CHECK(this->write_byte(reg, value)); 18 ESP_LOGCONFIG(TAG,
"Setting up APDS9960...");
26 if (
id != 0xAB &&
id != 0x9C &&
id != 0xA8) {
33 APDS9960_WRITE_BYTE(0x81, 0xDB);
35 APDS9960_WRITE_BYTE(0x83, 0xF6);
37 APDS9960_WRITE_BYTE(0x8E, 0x87);
39 APDS9960_WRITE_BYTE(0x9D, 0x00);
41 APDS9960_WRITE_BYTE(0x9E, 0x00);
43 APDS9960_WRITE_BYTE(0x8D, 0x60);
47 APDS9960_ERROR_CHECK(this->
read_byte(0x8F, &val));
59 APDS9960_WRITE_BYTE(0x8F, val);
62 APDS9960_WRITE_BYTE(0x8C, 0x11);
64 APDS9960_WRITE_BYTE(0x90, 0x01);
66 APDS9960_WRITE_BYTE(0x9F, 0x00);
68 APDS9960_WRITE_BYTE(0xA0, 0x28);
70 APDS9960_WRITE_BYTE(0xA1, 0x1E);
73 APDS9960_WRITE_BYTE(0xA2, 0x40);
76 APDS9960_ERROR_CHECK(this->
read_byte(0xA3, &val));
90 APDS9960_WRITE_BYTE(0xA3, val);
93 APDS9960_WRITE_BYTE(0xA4, 0x00);
95 APDS9960_WRITE_BYTE(0xA5, 0x00);
97 APDS9960_WRITE_BYTE(0xA7, 0x00);
99 APDS9960_WRITE_BYTE(0xA9, 0x00);
101 APDS9960_WRITE_BYTE(0xA6, 0xC9);
105 APDS9960_WRITE_BYTE(0xAA, 0x00);
116 APDS9960_WRITE_BYTE(0x80, val);
120 return this->red_sensor_ !=
nullptr || this->green_sensor_ !=
nullptr || this->blue_sensor_ !=
nullptr ||
121 this->clear_sensor_ !=
nullptr;
127 void APDS9960::dump_config() {
128 ESP_LOGCONFIG(TAG,
"APDS9960:");
129 LOG_I2C_DEVICE(
this);
131 LOG_UPDATE_INTERVAL(
this);
134 LOG_SENSOR(
" ",
"Red channel", this->red_sensor_);
135 LOG_SENSOR(
" ",
"Green channel", this->green_sensor_);
136 LOG_SENSOR(
" ",
"Blue channel", this->blue_sensor_);
137 LOG_SENSOR(
" ",
"Clear channel", this->clear_sensor_);
138 LOG_SENSOR(
" ",
"Proximity", this->proximity_sensor_);
142 switch (this->error_code_) {
144 ESP_LOGE(TAG,
"Communication with APDS9960 failed!");
147 ESP_LOGE(TAG,
"APDS9960 has invalid id!");
150 ESP_LOGE(TAG,
"Setting up APDS9960 registers failed!");
156 #define APDS9960_WARNING_CHECK(func, warning) \ 158 ESP_LOGW(TAG, warning); \ 159 this->status_set_warning(); \ 163 void APDS9960::update() {
165 APDS9960_WARNING_CHECK(this->
read_byte(0x93, &status),
"Reading status bit failed.");
178 if ((status & 0x01) == 0x00) {
184 APDS9960_WARNING_CHECK(this->
read_bytes(0x94, raw, 8),
"Reading color values failed.");
186 uint16_t uint_clear = (uint16_t(raw[1]) << 8) | raw[0];
187 uint16_t uint_red = (uint16_t(raw[3]) << 8) | raw[2];
188 uint16_t uint_green = (uint16_t(raw[5]) << 8) | raw[4];
189 uint16_t uint_blue = (uint16_t(raw[7]) << 8) | raw[6];
191 float clear_perc = (uint_clear / float(UINT16_MAX)) * 100.0f;
192 float red_perc = (uint_red / float(UINT16_MAX)) * 100.0f;
193 float green_perc = (uint_green / float(UINT16_MAX)) * 100.0f;
194 float blue_perc = (uint_blue / float(UINT16_MAX)) * 100.0f;
196 ESP_LOGD(TAG,
"Got clear=%.1f%% red=%.1f%% green=%.1f%% blue=%.1f%%", clear_perc, red_perc, green_perc, blue_perc);
198 if (this->clear_sensor_ !=
nullptr)
199 this->clear_sensor_->publish_state(clear_perc);
200 if (this->red_sensor_ !=
nullptr)
201 this->red_sensor_->publish_state(red_perc);
202 if (this->green_sensor_ !=
nullptr)
203 this->green_sensor_->publish_state(green_perc);
204 if (this->blue_sensor_ !=
nullptr)
205 this->blue_sensor_->publish_state(blue_perc);
212 if (this->proximity_sensor_ ==
nullptr)
215 if ((status & 0b10) == 0x00) {
221 APDS9960_WARNING_CHECK(this->
read_byte(0x9C, &prox),
"Reading proximity values failed.");
223 float prox_perc = (prox / float(UINT8_MAX)) * 100.0f;
224 ESP_LOGD(TAG,
"Got proximity=%.1f%%", prox_perc);
225 this->proximity_sensor_->publish_state(prox_perc);
233 APDS9960_WARNING_CHECK(this->
read_byte(0xAF, &status),
"Reading gesture status failed.");
235 if ((status & 0b01) == 0) {
240 if ((status & 0b10) == 0b10) {
241 ESP_LOGV(TAG,
"FIFO buffer has filled to capacity!");
245 APDS9960_WARNING_CHECK(this->
read_byte(0xAE, &fifo_level),
"Reading FIFO level failed.");
246 if (fifo_level == 0) {
251 APDS9960_WARNING_CHECK(fifo_level <= 32,
"FIFO level has invalid value.")
254 for (uint8_t pos = 0; pos < fifo_level * 4; pos += 32) {
258 uint8_t
read = std::min(32, fifo_level * 4 - pos);
259 APDS9960_WARNING_CHECK(this->
read_bytes(0xFC + pos, buf + pos, read),
"Reading FIFO buffer failed.");
269 for (uint32_t i = 0; i < fifo_level * 4; i += 4) {
270 const int up = buf[i + 0];
271 const int down = buf[i + 1];
272 const int left = buf[i + 2];
273 const int right = buf[i + 3];
278 #ifdef USE_BINARY_SENSOR 282 bin = this->up_direction_binary_sensor_;
285 ESP_LOGD(TAG,
"Got gesture UP");
288 bin = this->down_direction_binary_sensor_;
291 ESP_LOGD(TAG,
"Got gesture DOWN");
294 bin = this->left_direction_binary_sensor_;
297 ESP_LOGD(TAG,
"Got gesture LEFT");
300 bin = this->right_direction_binary_sensor_;
303 ESP_LOGD(TAG,
"Got gesture RIGHT");
309 if (bin !=
nullptr) {
339 const int up_down_delta = up - down;
340 const int left_right_delta = left - right;
341 const bool up_down_significant = abs(up_down_delta) > 13;
342 const bool left_right_significant = abs(left_right_delta) > 13;
344 if (up_down_significant) {
345 if (up_down_delta < 0) {
366 if (left_right_significant) {
367 if (left_right_delta < 0) {
392 this->proximity_sensor_ !=
nullptr 399 #ifdef USE_BINARY_SENSOR 400 return this->up_direction_binary_sensor_ !=
nullptr || this->left_direction_binary_sensor_ !=
nullptr ||
401 this->down_direction_binary_sensor_ !=
nullptr || this->right_direction_binary_sensor_ !=
nullptr;
bool read_byte(uint8_t a_register, uint8_t *data, bool stop=true)
const float DATA
For components that import data from directly connected sensors like DHT.
bool gesture_right_started_
bool is_color_enabled_() const
bool gesture_left_started_
uint8_t gesture_led_drive_
uint8_t gesture_wait_time_
ErrorCode read(uint8_t *data, size_t len)
reads an array of bytes from the device using an I2CBus
void read_gesture_data_()
bool read_bytes(uint8_t a_register, uint8_t *data, uint8_t len)
Compat APIs All methods below have been added for compatibility reasons.
T id(T value)
Helper function to make id(var) known from lambdas work in custom components.
void read_color_data_(uint8_t status)
void process_dataset_(int up, int down, int left, int right)
uint32_t IRAM_ATTR HOT millis()
void read_proximity_data_(uint8_t status)
bool gesture_down_started_
virtual void setup()
Where the component's initialization should happen.
void status_clear_warning()
void publish_state(bool state)
Publish a new state to the front-end.
void report_gesture_(int gesture)
virtual void mark_failed()
Mark this component as failed.
Implementation of SPI Controller mode.
Base class for all binary_sensor-type classes.
bool is_gesture_enabled_() const
bool is_proximity_enabled_() const