Skip to content

Home Assistant: Light Intensity Sensor APDS-9960

By Sebastian Günther

Posted in Iot, Home_assistant, Esp8266

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.