Link Search Menu Expand Document

Detect light intensity

Table of contents

  1. Overview
  2. Install the APDS9960 Library
  3. Run the color_sensor.ino sketch from the Adafruit Library
  4. Run the ambientLight.ino sketch
    1. Viewing the Ambient Light Data
    2. Walk Through the Code
  5. Further Reading

Overview

This web page demonstrates how to retrieve the ambient light readings from the APDS9960 sensor mounted on the Feather nRF52840 Sense. A separate web page describes the use of the APDS9960 as a proximity sensor.

The location of the sensor on the Feather nRF52840 Sense board is shown in the image below.

APDS9960 on Adafruit Feather Sense

The APDS9960 has its internal processing and communication hardware. Proximity, gesture, ambient light and light color readings are sent to the host Arduino program via a I2C digital interface. Since the APDS9960 is mounted directly on the Feather nRF52840 Sense, no additional wiring is needed.

Adafruit provides a software library and instructions with examples for using the APDS9960. The source code is available on github. The color_sensor sketch in the Adafruit APDS9960 Library shows how to read light levels from the sensor. That sketch was used as a starting point for the simpler sketch presented below.

APDS9960 usage is also demonstrated in the sample code provided by Adafruit for the Feather nRF52840 Sense.

Install the APDS9960 Library

To write Arduino sketches that use the APDS9960, you first need to install the Adafruit APDS9960 Library. The following steps use the Arduino Library Manager and assume that you have properly configured the board support page.

From menu at the top of the Arduino IDE, select Sketch –> Include Library –> Manage Libraries…

  1. Enter “9960” in the search box to narrow the range of choices. Or, if you prefer, scroll through the entire list of libraries
  2. Choose the “Adafruit APDS9960 Library” panel
  3. Click Install

Select and install the Adafruit APDS9960 library

Run the color_sensor.ino sketch from the Adafruit Library

The Adafruit APDS9960 library includes three example sketches to demonstrate features of the APDS9960 sensor. The color_sensor.ino sketch shows how to extract red, blue and green readings from the sensor. The gesture_sensor.ino sketch reads the left-right, up-down and near-far motions of objects above the sensor. The proximity_sensor.ino sketch prints the raw proximity output. We will discuss the proximity_sensor sketch and then develop a modified version that smooths out the readings with a running average.

To run the color_sensor sketch, open it from the Example folder. From the File menu of the Arduino IDE, select Examples –> Adafruit APDX9960 Library –> color_sensor. The code for the color_sensor.ino sketch should appear in a new text window of the Arduino IDE.

Upload the color_sensor sketch and open the Serial Monitor to see the continuous stream of readings from the sensor. Expose the Feather nRF52840 Sense board to different light levels, for example by turning it toward a window or desk lamp or covering the board with your hand to see the output change. When the color_sensor sketch is running, the output of the Serial Monitor should be something like the following

red: 82 green: 63 blue: 41 clear: 191

red: 83 green: 63 blue: 42 clear: 192

red: 83 green: 63 blue: 41 clear: 192

red: 8 green: 5 blue: 4 clear: 14

red: 3 green: 2 blue: 2 clear: 4

red: 4 green: 3 blue: 2 clear: 7

red: 82 green: 63 blue: 41 clear: 191

red: 83 green: 63 blue: 41 clear: 192

red: 82 green: 63 blue: 41 clear: 191

Run the ambientLight.ino sketch

The ambientLight sketch is a variation on the color_sensor sketch from the Adafuit Library.

Download the ambientLight.ino sketch and upload it to your board. While uploading, the NeoPixel on the Feather nRF52840 glows green and then red. After the upload is complete you can open the Serial Monitor to see the ambient light data from the sensor. Make sure the baud rate of the Serial Monitor is the same as the baud rate in the Serial.begin() command. In the ambientLight code (shown below) the baud rate is 115200.

//  File:  ambientLight.ino
//
//  Read the clear channel of the on-board APDS 9960 light sensor
//  and print the reading to the Serial object for display in the
//  Serial Monitor or Serial Plotter
//
//  Derived from the color_sensor.ino sketch in the Examples library
//  by Adafruit.  See http://www.adafruit.com/products/3595

#include "Adafruit_APDS9960.h"   //  Use the Adafruit Library for APDS9960
Adafruit_APDS9960 apds;          //  Create a global object called apds

// ----------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);          //  Open Serial object for messages and data
  delay(3000);                   //  Wait for USB connection
  setupAPDSambientLight();       //  Configure APDS9960 to read ambient light
}

// ----------------------------------------------------------------------------
void loop() {
  int level;                     //  Value of clear channel from APDS 9960  

  level = readAmbientLight();    //  Get the ambient light level
  Serial.println(level);
  delay(50);
}

// ----------------------------------------------------------------------------
//  Configure the APDS9960 sensor to read ambient light levels, not gestures.
//
void setupAPDSambientLight() {

  // -- Check to see that the sensor is connected
  if ( !apds.begin() ) {
    Serial.println("Failed to initialize device! Please check your wiring.");
  }
  else {
    Serial.println("Device initialized!");
  }
  apds.enableColor(true);  //  Enable color sensing
}

// ----------------------------------------------------------------------------
//  Read the light sensors on the APDS 9960.  Return the level of the clear
//  channel as an indicator of the ambient light level.  Note that the Adafruit
//  APDS9960 Library does not have a method for reading only the clear channel.
//  In the interest of simplicity, we use the available methods in the library
//  and incurr the small extra overhead of reading the R, G, B and clear channels
//  when we only need the value from the clear channel
//
int readAmbientLight() {
  
  uint16_t r, g, b, c;   //  Variables to store color data returned by APDS
  
  while( !apds.colorDataReady() ) {  // Wait for color data to be ready
    delay(5);
  }
  apds.getColorData(&r, &g, &b, &c);  //  Retrieve the color data

  return(c);  //  Only the clear channel matters for this application
}

Viewing the Ambient Light Data

When connected to your computer the ambientLight sketch should produce a column of values related to the clear channel light reading from the APDS9960 sensor. The output from ambientLight can be viewed with the Serial Monitor or the Serial Plotter in the Arduino IDE.

Walk Through the Code

The ambientLight.ino sketch performs these main steps:

  1. Include the Adafruit_APDS9960.h library
  2. Create an Adafruit_APDS9960 object. In this code the object is called apds
  3. Configure and start the apds object
    • Enable the color sensing mode
  4. Repeat the loop function:
    • Call the readAmbientLight function to obtain the clear channel reading
    • Print the value returned by readAmbientLight

We’ll examine each step in more detail.

Include the APDS9960 Library

The first step is to include the Adafruit_APDS9960.h library, which provides support for the APDS9960 chip. You can read the code from the github repository.

#include <Adafruit_APDS9960.h>

The ambientLight.ino sketch uses only the light level readings of the APDS9960 chip.

Create an APDS9960 Object

The next step is create or instantiate a APDS9960 object, which is the mechanism to communicate with the APDS9960 chip in the Arduino software environment.

Adafruit_APDS9960 apds;

In this example the APDS9960 object is called apds. An object is like a variable with properties for storing and retrieving data. You can use any valid variable name for the object name. The Adafruit_APDS9960 apds statement invokes the constructor for Adafruit_APDS9960 objects. In this case the constructor does not require any input parameters. Therefore, apds appears without any parenthesis.

Configure and Start the APDS9960 Object

The APDS9960 chip has internal hardware to support several types of measurements. When configured for ambient light sensing, the chip makes four sensor readings, one each for the red, green, blue and clear channels of the light spectrum. In mounting the APDS9960 on the Feather board, Adafruit has connected this signal line from the APDS9960 to pin 3 on the nRF5280 microcontroller. The Adafruit library handles the low level details.

The code to start and configure the APDS9960 for ambient light readings is contained in the setupAPDSambientLight function.

void setupAPDSambientLight() {
  if ( !apds.begin() ) {
    Serial.println("failed to initialize device! Please check your wiring.");
  }
  else {
    Serial.println("Device initialized!");
  }
  apds.enableColor(true);  //  Enable color sensing
}

The block of code beginning with if ( !apds.begin() ) { tries to start the apds object with the .begin() method. The ! in front of apds.begin() negates the value returned by apds.begin(). Therefore, if apds.begin() returns 0, then !apds.begin() will evaluate as TRUE.

The last line of code in setupAPDSambientLight prepares the apds object for reading color light data. The apds.enableColor(true) statement is straightforward – it tells the apds object to set the APDS9960 into light sensing mode.

Read and print the clear channel values from the light sensor

The APDS9960 has three sensors to read the ambient light levels. These sensors have filters that allow red, green or blue light to pass through the sensing element. This gives the APDS9960 the ability to detect relative amounts of red, green and blue light. More precisely, the filters allow light within wavelength bands corresponding to visible red, green and blue light to be detected.

The following plot from the APDS9960 datasheet shows the spectral response of the R, G and B sensor sites on the APDS9960. The clear channel signal appears to be the sum of the R, G and B channels. (The datasheet does not say how the clear signal (C) is measured and there is no mention of a fourth sensor site.)

APDS9960 on Adafruit Feather Sense

The readAmbientLight function simplifies the clear channel reading by providing a wrapper around the getColorData method in the Adafruit APDS9960 library. The code in the loop function to read and print the clear channel reading to the Serial Monitor is simple:

  int level;                  //  Value of clear channel from APDS 9960  

  level = readAmbientLight();     //  Get the ambient light level
  Serial.println(level);

Retrieve the light sensor values

The readAmbientLight() function repackages the code for reading the color data from the color_sensor.ino example. Only the clear channel reading is returned. The red, green and blue channels are obtained from the sensor, but ignored.

int readAmbientLight() {
  
  uint16_t r, g, b, c;   //  Variables to store color data returned by APDS
  
  while( !apds.colorDataReady() ) {  // Wait for color data to be ready
    delay(5);
  }
  apds.getColorData(&r, &g, &b, &c);  //  Retrieve the color data

  return(c);  //  Only the clear channel matters for this application
}

Further Reading