Through the combination of ESPHome and Home Assistant, a myriad of sensors can be added, managed, and their data visualized and stored. To extend the arsenal of sensor data, I wanted to detect light intensity as well. After some research on the internet, I decided to get the sensor APDS-9960. It detects the intensity of red, green and blue light, and it can detect simple directional gestures like up or down.
This article summarizes all required steps to get these sensors working with ESPHome and Home Assistant.
The technical context of this article is Home Assistant v2024.10.4
and ESPHome v2024.10.3
, but it should work with newer versions as well.
Hardware Overview
For this project, you need the following hardware:
- ESP8266 board
- APDS-9960 sensor
- Dupont cables
As in previous articles, I use a Wemos D1 Mini board, because it has a great form factor and works reliable for large amounts of time. As for the concrete APDS-9960 sensor, I checked my favorite online store and choose an affordable product with positive customer reviews.
Wiring
The APDS-9960 can be connected via I2C, which means a convenient connection with only two wires, plus VCC and ground. Its wired as follows:
- ESP8266 5V => APDS-9960 VCC
- ESP8266 Ground => APDS-9960 Ground
- ESP8266 GPIO 05 SCL / D1 => APDS-9960 SCL
- ESP8266 GPIO 04 SDA / D2 => APDS-9960 SDA
The D1 mini pin configuration is as shown:
Source: https://randomnerdtutorials.com
After completing these connections, the sensor is ready to be used,
Be sure that the small lens you see in the middle of the sensor board points to the direction from which you want to measure incoming light.
ESPHome Configuration & Flashing
In ESPHome, the APDS-9960 sensor can be configured for the following types of measurements:
- RED, GREEN, BLUE: Detects the color level in the light
- CLEAR: Detects the absolute level of light
- UP, RIGHT, LEFT, DOWN: Detects the direction of a gesture
- PROXIMITY: Detect an object that is close to the sensor
In order to see how these values are captured and which numerical range they have, I added a configuration for each - except the gesture detection, since this is not a relevant sensor reading for me.
Following the configuration stanza in the ESPHome article APDS9960 sensor, the initial configuration looks as follows:
# Source: EspHome, APDS9960 Sensor, https://esphome.io/components/sensor/apds9960
apds9960:
address: 0x39
update_interval: 60s
proximity_gain: 8x
ambient_light_gain: 16x
sensor:
- platform: apds9960
type: CLEAR
name: "APDS9960 Clear"
- platform: apds9960
type: RED
name: "APDS9960 RED"
- platform: apds9960
type: GREEN
name: "APDS9960 Green"
- platform: apds9960
type: BLUE
name: "APDS9960 Blue"
- platform: apds9960
type: PROXIMITY
name: "APDS9960 Proximity"
After flashing this configuration, log messages with measurement information appear immediately. Since these log messages were taken during the late evening, the detected light levels are rather small.
[18:50:30][D][apds9960:183]: Got clear=2.3% red=1.1% green=1.6% blue=1.2%
[18:50:30][V][sensor:076]: 'APDS9960 Clear': Received new state 2.311742
[18:50:30][D][sensor:127]: 'APDS9960 Clear': Sending state 2.31174 % with 1 decimals of accuracy
[18:50:30][V][sensor:076]: 'APDS9960 RED': Received new state 1.081865
[18:50:30][D][sensor:127]: 'APDS9960 RED': Sending state 1.08186 % with 1 decimals of accuracy
[18:50:30][V][sensor:076]: 'APDS9960 Green': Received new state 1.622034
[18:50:30][D][sensor:127]: 'APDS9960 Green': Sending state 1.62203 % with 1 decimals of accuracy
[18:50:30][V][sensor:076]: 'APDS9960 Blue': Received new state 1.246662
[18:50:30][D][sensor:127]: 'APDS9960 Blue': Sending state 1.24666 % with 1 decimals of accuracy
The proximity measurements are reported as shown:
[18:50:30][D][apds9960:206]: Got proximity=1.2%
[18:50:30][V][sensor:076]: 'APDS9960 Proximity': Received new state 1.176471
[18:50:30][D][sensor:127]: 'APDS9960 Proximity': Sending state 1.17647 % with 1 decimals of accuracy‚
Home Assistant Integration
The ESPHome configuration stanza from above is already suitable for Home Assistant to pick up all required values. In the dashboard, clicking on “Configuration” and then “Devices”, the new board and its sensors will be shown:
TODO Home Assistant Integration Picture
APDS-9960 Sensor Calibration
Adding all of these cards to the home assistant dashboard, and waiting for 1 day to collect enough data, I could see the following charts for the RGB values:
There is also the combined "clear" channel:
All channels show the same distribution, so they measure rgb of the sunlight in equal terms. The sensors reported light-levels seem reasonable to me - its detecting pure daylight in the living room.
However, other sensors, like the TCS3725, can measure the light intensity in Lux, with a range of 0 to 1000, and the Correlated Color Temperature (CCT) with a range of 2220 to 6500 kelvin measuring warm und cold light.
I want this too! Searching further, digesting this Tasmota thread and this Adafruit color utility library, it became clear that illuminance and cct can be measured from the raw RGB data. Lets dig into this and write a custom lambda function that calculates thes values.
My first try:
- platform: template
name: "APDS9960 Light Intensity"
icon: "mdi:volume-high"
unit_of_measurement: "Lux"
update_interval: 120s
lambda: |-
float red = id(apds9960_red).state;
float blue = id(apds9960_blue).state;
float green = id(apds9960_green).state;
return (-0.32466 * red) + (1.57837 * green) + (-0.73191 * blue);
The returned values:
[11:33:26][V][sensor:076]: 'APDS9960 Light Intensity': Received new state 1.379804
[11:33:26][D][sensor:127]: 'APDS9960 Light Intensity': Sending state 1.37980 Lux with 1 decimals of accuracy
Because the state
only returns a percentage value, theis value needs to be scaled by the factor 10
. The next measurements were better:
[11:37:01][V][sensor:076]: 'APDS9960 Light Intensity': Received new state 60.3971644
[11:37:01][D][sensor:127]: 'APDS9960 Light Intensity': Sending state 60.39716 Lux with 1 decimals of accuracy
And finally I added this sensor card to my Home Assistant dashboard:
Conclusion
The APDS-9960 light sensor is a compact board and easily connected via I2C. It measures the RGB levels of the sunlight, proximity, and can even recognize gestures. In this article, you learned all to get an APDS-9960 sensor integrated into Home Assistant and record its data. Only three steps are necessary: wiring, ESP Home integration with a few lines of YAML, and then adding Home Assistant cards for the individual readings. After one day, you have the measurements taken and stored in Home Assistant. Other sensor can detect light intensity in Lux or in CCT, but I learned that you can calculate these values from the RGB measurements themselves, and showed a template function for that. Now you can start to record light data as well.