Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

APDS9306 Ambient Light Sensor #6709

Draft
wants to merge 133 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
e96cce7
Added apds9306 component, not yet tested
aodrenah May 8, 2024
737b9cc
[remote_receiver, remote_transmitter] Improve error messages on the E…
Mat931 May 8, 2024
401f051
Added tests for APDS9306
aodrenah May 8, 2024
68cb6f1
Merge branch 'esphome:dev' into apds9306
aodrenah May 8, 2024
92e8ac6
Added test for esp32 which is the only board I can test with
aodrenah May 8, 2024
5634f4d
Fixed cv.enum lines in init.py
aodrenah May 8, 2024
d858ea4
Fixed typo (set_bid_width instead of set_bit_width)
aodrenah May 8, 2024
cf62e35
removed get_setup_priority which was not being used (i think)
aodrenah May 8, 2024
75f1817
Reoredered setup function to start apds9306 before setting up registe…
aodrenah May 9, 2024
d555070
Try not checking for new data
aodrenah May 9, 2024
9ed0735
enable and software reset simultaneously
aodrenah May 9, 2024
357333e
added a logvv showing content of als_data in update
aodrenah May 9, 2024
a3e9687
inverted the way it combines the sensor reading bytes in update and r…
aodrenah May 9, 2024
194d0aa
restructured combination of bytes in update
aodrenah May 9, 2024
117968e
restructured combination of bytes in update
aodrenah May 9, 2024
b9a1bef
testing
aodrenah May 9, 2024
a8da3d8
testing
aodrenah May 9, 2024
8c500c2
testing
aodrenah May 9, 2024
570ca59
added tests for apds9306
aodrenah May 9, 2024
bf1750f
added parentheses in als bytes combination
aodrenah May 9, 2024
959b04b
testing
aodrenah May 9, 2024
ab42c25
Restructured to only use a sensor block instead of both component and…
aodrenah May 9, 2024
790edcc
removed get_setup_priority
aodrenah May 9, 2024
f02b30e
added float conversion to light level in lux calculation
aodrenah May 9, 2024
9a3b467
reordered update
aodrenah May 9, 2024
3185770
added logvv state to write_byte macro
aodrenah May 9, 2024
b7d96f8
Merge branch 'dev' into apds9306
aodrenah May 9, 2024
7ebb6b6
added myself to codeowners
aodrenah May 9, 2024
74e3cbc
added newline to end of yaml test files
aodrenah May 9, 2024
464e865
added newlines to all files I added
aodrenah May 9, 2024
4be1c8c
fixed formatting for sensor.py
aodrenah May 9, 2024
173202f
fixed formating on cpp and h files
aodrenah May 9, 2024
7b40e00
again, fixed formatting
aodrenah May 9, 2024
b733df6
fixed CONF_GAIN
aodrenah May 9, 2024
cc6963c
fixed CONF_GAIN
aodrenah May 9, 2024
4fbb3ea
reverted CONF_GAIN to CONF_AMBIANT_LIGHT_GAIN and fixed its value
aodrenah May 9, 2024
e43d703
constants
aodrenah May 9, 2024
3035add
built codeowners. fixed constants again. fixed clang-format errors
aodrenah May 9, 2024
1025425
fixed logvv error
aodrenah May 9, 2024
b5c17f3
fixed log_sensor
aodrenah May 9, 2024
6fdd477
Merge branch 'dev' into apds9306
aodrenah May 9, 2024
7b4bd97
Moved register addresses to named constants
aodrenah May 14, 2024
a11b130
Update esphome/components/apds9306/apds9306.cpp
aodrenah May 14, 2024
a31930b
Update esphome/components/apds9306/apds9306.cpp
aodrenah May 14, 2024
e068161
Update esphome/components/apds9306/apds9306.cpp
aodrenah May 14, 2024
fce24fa
Update esphome/components/apds9306/sensor.py
aodrenah May 14, 2024
0fc7081
Update esphome/components/apds9306/sensor.py
aodrenah May 14, 2024
58c16b6
Update esphome/components/apds9306/sensor.py
aodrenah May 14, 2024
bc7ed70
Update esphome/components/apds9306/sensor.py
aodrenah May 14, 2024
9d1266e
Update esphome/components/apds9306/apds9306.cpp
aodrenah May 14, 2024
1eb95ac
Update esphome/components/apds9306/sensor.py
aodrenah May 14, 2024
2bd7f1a
Merge branch 'dev' into apds9306
aodrenah May 14, 2024
eb72f56
added header for core/helpers.h
aodrenah May 14, 2024
7920a3e
Replaced #defines with static const uint8_t
aodrenah May 14, 2024
10520b8
modified tests for new syntax
aodrenah May 15, 2024
5677464
reverted changes to tests and fixed sensor.py
aodrenah May 15, 2024
3a95ab9
testing
aodrenah May 15, 2024
04ccf4e
testing
aodrenah May 15, 2024
322f4ba
testing
aodrenah May 15, 2024
e9dee83
Merge branch 'esphome:dev' into apds9306
aodrenah May 19, 2024
c6f36da
reverted rate options to strings
aodrenah May 19, 2024
eaaff93
Merge branch 'esphome:dev' into apds9306
aodrenah May 23, 2024
f63f4ea
added this-> to all internal variables
aodrenah May 23, 2024
4488b31
switched to using positive_time_;eriod_milliseconds for measurement rate
aodrenah May 23, 2024
99b2a46
made all register names capitalized
aodrenah May 23, 2024
7462327
updated tests
aodrenah May 23, 2024
68dbb3f
trying different order for positive_time_period_milliseconds
aodrenah May 23, 2024
531218d
changed default ms value from 100ms to 100
aodrenah May 23, 2024
93a4f34
switched back to 100ms and tried lower instead of int
aodrenah May 23, 2024
4849bbc
switched back to 100 and tried lower instead of int
aodrenah May 23, 2024
f63f59a
switched back to 100 and tried int
aodrenah May 23, 2024
7f038e1
testing
aodrenah May 23, 2024
7e63483
testing
aodrenah May 23, 2024
965341a
testing
aodrenah May 23, 2024
451bd6e
switched to int to avoid issues with 'ms'
aodrenah May 23, 2024
e45f9dd
updated tests
aodrenah May 23, 2024
b9b4ca1
added logv to all apds9306_error_check calls
aodrenah May 23, 2024
1995303
added BUS setup priority
aodrenah May 23, 2024
eb9f1b9
Update esphome/components/apds9306/sensor.py
aodrenah May 23, 2024
f6e9599
testing
aodrenah May 26, 2024
99adfb5
added test message for d, v, and vv logs
aodrenah May 26, 2024
3f049ad
added check to see if setup run
aodrenah May 26, 2024
dd7d163
fixed format error
aodrenah May 26, 2024
02c325b
Merge branch 'esphome:dev' into apds9306
aodrenah May 27, 2024
2d52ff4
moved registers to an enum and added more error messages
aodrenah May 27, 2024
e1b4da9
simplified update()
aodrenah May 27, 2024
e9cebe3
test
aodrenah May 27, 2024
ae73973
test
aodrenah May 27, 2024
610bf8f
resetting to 'moved registers to an enum and added more error messages
aodrenah May 27, 2024
9847ec4
simplified update and options from the yaml are now actually set
aodrenah May 27, 2024
515dbbd
trying to read from CLEAR instead of ALS
aodrenah May 27, 2024
68aa46f
switched to turning on the sensor only for the reading then turning i…
aodrenah May 27, 2024
84cdb3a
delay() -> esp_delay()
aodrenah May 27, 2024
5b80eb9
went back to constant measurements to avoid delays
aodrenah May 27, 2024
020a37c
added check to see if setup is running
aodrenah May 27, 2024
302aa6f
marking failed at start of setup to see if it runs
aodrenah May 27, 2024
fcda6de
set error code
aodrenah May 27, 2024
1fc2e0b
testing
aodrenah May 27, 2024
e7d5692
clang-format
aodrenah May 27, 2024
210e861
run setup from update if it doesnt on its own
aodrenah May 27, 2024
03c4493
testing
aodrenah May 27, 2024
63276b2
added debug message to end of setup because warn and logconfig messag…
aodrenah May 27, 2024
5f73888
clang-format
aodrenah May 27, 2024
b8547c4
clang-format
aodrenah May 27, 2024
b86468f
Merge branch 'esphome:dev' into apds9306
aodrenah May 28, 2024
b606a04
changed tests to use common.yaml
aodrenah May 29, 2024
d06dff1
Merge branch 'dev' into apds9306
aodrenah May 29, 2024
c2bcef1
fixed lux calculation, restructured some sections, trying cv time per…
aodrenah May 29, 2024
7477874
added newlines to end of files
aodrenah May 29, 2024
8de7f42
moved time period in milliseconds in sensor.py
aodrenah May 29, 2024
a59f592
testint
aodrenah May 29, 2024
3891dbb
removed time period in milliseconds
aodrenah May 29, 2024
cde5373
added restart of the sensor at the end of update
aodrenah May 29, 2024
ecc8851
clang-format
aodrenah May 29, 2024
761c069
run setup at start of each update
aodrenah May 29, 2024
b81daec
reverted last change
aodrenah May 29, 2024
17eaf58
test new reading at each updtate
aodrenah May 29, 2024
121b4e6
added check in dump config to see if setup runs
aodrenah May 29, 2024
5a3ee0c
testing
aodrenah May 29, 2024
37848e0
testing
aodrenah May 29, 2024
6b23c9b
testing
aodrenah May 29, 2024
f5a81d7
testing
aodrenah May 29, 2024
858f553
Merge branch 'dev' into apds9306
aodrenah Jun 6, 2024
5afab8b
Merge branch 'esphome:dev' into apds9306
aodrenah Jun 8, 2024
d83e3f8
fixed formatting issues
aodrenah Jun 8, 2024
9d8f4e0
edited test values
aodrenah Jun 8, 2024
4c110d5
try setting APDS9306 to standby before reading data
aodrenah Jun 8, 2024
33b8440
clang-format
aodrenah Jun 8, 2024
f18115e
fliped MSB and LSB in light level calculation
aodrenah Jun 8, 2024
60bd5c4
read byte should have been read bytes ?
aodrenah Jun 8, 2024
18e1a24
reordered MSB and LSB again
aodrenah Jun 8, 2024
7fbb328
Merge branch 'esphome:dev' into apds9306
aodrenah Jun 15, 2024
c8bd197
using array instead of switch statement to convert register value for…
aodrenah Jun 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ esphome/components/am43/sensor/* @buxtronix
esphome/components/analog_threshold/* @ianchi
esphome/components/animation/* @syndlex
esphome/components/anova/* @buxtronix
esphome/components/apds9306/* @aodrenah
esphome/components/api/* @OttoWinter
esphome/components/as5600/* @ammmze
esphome/components/as5600/sensor/* @ammmze
Expand Down
4 changes: 4 additions & 0 deletions esphome/components/apds9306/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Based on this datasheet:
# https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf

CODEOWNERS = ["@aodrenah"]
150 changes: 150 additions & 0 deletions esphome/components/apds9306/apds9306.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
// Based on this datasheet:
// https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf

#include "apds9306.h"
#include "esphome/core/log.h"
#include "esphome/core/helpers.h"

namespace esphome {
namespace apds9306 {

static const char *const TAG = "apds9306";

enum { // APDS9306 registers
APDS9306_MAIN_CTRL = 0x00,
APDS9306_ALS_MEAS_RATE = 0x04,
APDS9306_ALS_GAIN = 0x05,
APDS9306_PART_ID = 0x06,
APDS9306_MAIN_STATUS = 0x07,
APDS9306_CLEAR_DATA_0 = 0x0A, // LSB
APDS9306_CLEAR_DATA_1 = 0x0B,
APDS9306_CLEAR_DATA_2 = 0x0C, // MSB
APDS9306_ALS_DATA_0 = 0x0D, // LSB
APDS9306_ALS_DATA_1 = 0x0E,
APDS9306_ALS_DATA_2 = 0x0F, // MSB
APDS9306_INT_CFG = 0x19,
APDS9306_INT_PERSISTENCE = 0x1A,
APDS9306_ALS_THRES_UP_0 = 0x21, // LSB
APDS9306_ALS_THRES_UP_1 = 0x22,
APDS9306_ALS_THRES_UP_2 = 0x23, // MSB
APDS9306_ALS_THRES_LOW_0 = 0x24, // LSB
APDS9306_ALS_THRES_LOW_1 = 0x25,
APDS9306_ALS_THRES_LOW_2 = 0x26, // MSB
APDS9306_ALS_THRES_VAR = 0x27
};

#define APDS9306_ERROR_CHECK(func, error) \
if (!(func)) { \
ESP_LOGE(TAG, error); \
this->mark_failed(); \
return; \
}
#define APDS9306_WARNING_CHECK(func, warning) \
if (!(func)) { \
ESP_LOGW(TAG, warning); \
this->status_set_warning(); \
return; \
}
#define APDS9306_WRITE_BYTE(reg, value) \
ESP_LOGV(TAG, "Writing 0x%02x to 0x%02x", value, reg); \
if (!this->write_byte(reg, value)) { \
ESP_LOGE(TAG, "Failed writing 0x%02x to 0x%02x", value, reg); \
this->mark_failed(); \
return; \
}

void APDS9306::setup() {
ESP_LOGCONFIG(TAG, "Setting up APDS9306...");

uint8_t id;
if (!this->read_byte(APDS9306_PART_ID, &id)) { // Part ID register
this->error_code_ = COMMUNICATION_FAILED;
this->mark_failed();
return;
}

if (id != 0xB1 && id != 0xB3) { // 0xB1 for APDS9306 0xB3 for APDS9306-065
this->error_code_ = WRONG_ID;
this->mark_failed();
return;
}

// ALS resolution and measurement, see datasheet or init.py for options
uint8_t als_meas_rate = ((this->bit_width_ & 0x07) << 4) | (this->measurement_rate_ & 0x07);
APDS9306_WRITE_BYTE(APDS9306_ALS_MEAS_RATE, als_meas_rate);

// ALS gain, see datasheet or init.py for options
uint8_t als_gain = (this->gain_ & 0x07);
APDS9306_WRITE_BYTE(APDS9306_ALS_GAIN, als_gain);

// Set to standby mode
APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x00);

// Check for data, clear main status
uint8_t status;
APDS9306_WARNING_CHECK(this->read_byte(APDS9306_MAIN_STATUS, &status), "Reading MAIN STATUS failed.");

// Set to active mode
APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x02);

ESP_LOGCONFIG(TAG, "setup complete");
}

void APDS9306::dump_config() {
LOG_SENSOR("", "apds9306", this);
LOG_I2C_DEVICE(this);

if (this->is_failed()) {
switch (this->error_code_) {
case COMMUNICATION_FAILED:
ESP_LOGE(TAG, "Communication with APDS9306 failed!");
break;
case WRONG_ID:
ESP_LOGE(TAG, "APDS9306 has invalid id!");
break;
default:
ESP_LOGE(TAG, "Setting up APDS9306 registers failed!");
break;
}
}

ESP_LOGCONFIG(TAG, " Gain: %f", gain_val_[gain_]);
ESP_LOGCONFIG(TAG, " Measurement rate: %f", measurement_time_[measurement_rate_]);
ESP_LOGCONFIG(TAG, " Measurement Resolution/Bit width: %d", bit_width_val_[bit_width_]);

LOG_UPDATE_INTERVAL(this);
}

void APDS9306::update() {
// Check for new data
uint8_t status;
APDS9306_WARNING_CHECK(this->read_byte(APDS9306_MAIN_STATUS, &status), "Reading MAIN STATUS failed.");

this->status_clear_warning();

if (!(status &= 0b00001000)) { // No new data
return;
}

// Set to standby mode
APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x00);

// Clear MAIN STATUS
APDS9306_WARNING_CHECK(this->read_byte(APDS9306_MAIN_STATUS, &status), "Reading MAIN STATUS failed.");

uint8_t als_data[3];
APDS9306_WARNING_CHECK(this->read_bytes(APDS9306_ALS_DATA_0, als_data, 3), "Reading ALS data has failed.");

// Set to active mode
APDS9306_WRITE_BYTE(APDS9306_MAIN_CTRL, 0x02);

uint32_t light_level = 0x00 | encode_uint24(als_data[2], als_data[1], als_data[0]);

float lux = (light_level / this->gain_val_[gain_]) * (100.0f / this->measurement_time_[measurement_rate_]);

ESP_LOGD(TAG, "Got illuminance=%.1flx from", lux);
this->publish_state(lux);
}

} // namespace apds9306
} // namespace esphome
39 changes: 39 additions & 0 deletions esphome/components/apds9306/apds9306.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Based on this datasheet:
// https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf

#pragma once

#include "esphome/components/i2c/i2c.h"
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"

namespace esphome {
namespace apds9306 {

class APDS9306 : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice {
public:
void setup() override;
float get_setup_priority() const override { return setup_priority::BUS; }
void dump_config() override;
void update() override;
void set_bit_width(uint8_t bit_width) { this->bit_width_ = bit_width; }
void set_measurement_rate(uint8_t measurement_rate) { this->measurement_rate_ = measurement_rate; }
void set_ambient_light_gain(uint8_t gain) { this->gain_ = gain; }

protected:
enum ErrorCode {
NONE = 0,
COMMUNICATION_FAILED,
WRONG_ID,
} error_code_{NONE};

uint8_t bit_width_;
uint8_t bit_width_val_[6] = {20, 19, 18, 17, 16, 13};
uint8_t measurement_rate_;
float measurement_time_[7] = {25, 50, 100, 200, 500, 1000, 2000};
uint8_t gain_;
float gain_val_[5] = {1, 3, 6, 9, 18};
};

} // namespace apds9306
} // namespace esphome
85 changes: 85 additions & 0 deletions esphome/components/apds9306/sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Based on this datasheet:
# https://www.mouser.ca/datasheet/2/678/AVGO_S_A0002854364_1-2574547.pdf

import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.components import i2c, sensor
from esphome.const import (
CONF_GAIN,
DEVICE_CLASS_ILLUMINANCE,
ICON_LIGHTBULB,
STATE_CLASS_MEASUREMENT,
UNIT_LUX,
)

DEPENDENCIES = ["i2c"]

CONF_APDS9306_ID = "apds9306_id"
CONF_BIT_WIDTH = "bit_width"
CONF_MEASUREMENT_RATE = "measurement_rate"

MEASUREMENT_BIT_WIDTHS = {
20: 0,
19: 1,
18: 2,
17: 3,
16: 4,
13: 5,
}

MEASUREMENT_RATES = {
25: 0,
50: 1,
100: 2,
200: 3,
500: 4,
1000: 5,
2000: 6,
}

AMBIENT_LIGHT_GAINS = {
1: 0,
3: 1,
6: 2,
9: 3,
18: 4,
}

apds9306_nds = cg.esphome_ns.namespace("apds9306")
APDS9306 = apds9306_nds.class_(
"APDS9306", sensor.Sensor, cg.PollingComponent, i2c.I2CDevice
)

CONFIG_SCHEMA = (
sensor.sensor_schema(
APDS9306,
unit_of_measurement=UNIT_LUX,
accuracy_decimals=1,
device_class=DEVICE_CLASS_ILLUMINANCE,
state_class=STATE_CLASS_MEASUREMENT,
icon=ICON_LIGHTBULB,
)
.extend(
{
cv.Optional(CONF_GAIN, default="1"): cv.enum(AMBIENT_LIGHT_GAINS, int=True),
cv.Optional(CONF_BIT_WIDTH, default="18"): cv.enum(
MEASUREMENT_BIT_WIDTHS, int=True
),
cv.Optional(CONF_MEASUREMENT_RATE, default="100"): cv.enum(
MEASUREMENT_RATES, int=True
),
}
)
.extend(cv.polling_component_schema("60s"))
.extend(i2c.i2c_device_schema(0x52))
)


async def to_code(config):
var = await sensor.new_sensor(config)
await cg.register_component(var, config)
await i2c.register_i2c_device(var, config)

cg.add(var.set_bit_width(config[CONF_BIT_WIDTH]))
cg.add(var.set_measurement_rate(config[CONF_MEASUREMENT_RATE]))
cg.add(var.set_ambient_light_gain(config[CONF_GAIN]))
12 changes: 12 additions & 0 deletions tests/components/apds9306/common.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
i2c:
- id: i2c_apds9306
scl: ${scl_pin}
sda: ${sda_pin}

sensor:
- platform: apds9306
name: "APDS9306 Light Level"
gain: 3
bit_width: 16
measurement_rate: 2000
update_interval: 60s
5 changes: 5 additions & 0 deletions tests/components/apds9306/test.esp32-c3-idf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO5
sda_pin: GPIO4

<<: !include common.yaml
5 changes: 5 additions & 0 deletions tests/components/apds9306/test.esp32-c3.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO5
sda_pin: GPIO4

<<: !include common.yaml
5 changes: 5 additions & 0 deletions tests/components/apds9306/test.esp32-idf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO22
sda_pin: GPIO21

<<: !include common.yaml
5 changes: 5 additions & 0 deletions tests/components/apds9306/test.esp32.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO22
sda_pin: GPIO21

<<: !include common.yaml
5 changes: 5 additions & 0 deletions tests/components/apds9306/test.esp8266.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO5
sda_pin: GPIO4

<<: !include common.yaml
5 changes: 5 additions & 0 deletions tests/components/apds9306/test.rp2040.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
substitutions:
scl_pin: GPIO5
sda_pin: GPIO4

<<: !include common.yaml