The APDS -9960 is a device which features advanced Gesture detection, Proximity detection, Digital Ambient Light Sense (ALS) and Color Sense (RGBC). Now let's look at each of the functions separately.
Gesture DetectionThe gesture detection utilizes four directional photodiodes to sense reflected IR energy (sourced by the integrated LED) to convert physical motion information (i.e. velocity, directional and distance) to digital information. The architecture of the gestures engine features automatic activation (based on Proximity engine results), ambient light subtraction, cross-talk cancellation, dual 8-bit data converters, power-saving inter-conversion delay, 32-dataset FIFO, and interrupt-driven I2C communication.
Proximity DetectionThe proximity detection features provide distance measurement by photodiode detection of reflected IR energy. One example is a mobile device screen to the user's ears. Detect/release events are interrupted driven and occur whenever proximity result crosses upper and/or lower threshold settings. The proximity engine features offset adjustment registers to compensate for system offset caused by unwanted IR energy reflections appearing at the sensor. The IR LED intensity is factory trimmed to eliminate the need for end-equipment calibration due to component variations. Proximity results are further improved by automatic ambient light subtraction.
Colour and ALS DetectionThe last feature that we want to see is the colour and ALS detection feature which provides red, green, blue, and clear light-intensity data. Each of the R, G, B, and C channels has a UV and IR blocking filter and a dedicated data converter producing 16-bit data simultaneously. This architecture allows applications to accurately measure ambient light and sense colour which enables devices to calculate colour temperature and control display backlight.
Below are the features of the sensor
- Ambient Light and RGB Color Sensin, Proximity Sensing, and Gesture Detection in an Optical Module
- Ambient Light and RGB Color Sensing
- UV and IR blocking filters
- Programmable gain and integration time
- Very high sensitivity – Ideally suited for operation behind dark glass
- Proximity Sensing
- Trimmed to provide a consistent reading
- Ambient light rejection
- Offset compensation
- Programmable driver for IR LED current
- Saturation indicator bit
- Complex Gesture Sensing
- Four separate diodes sensitive to different directions
- Ambient light rejection
- Offset compensation
- Programmable driver for IR LED current
- 32 dataset storage FIFO
- Interrupt driven I2C communication
- I2C-bus Fast Mode Compatible Interface
- Data Rates up to 400 kHz
- Dedicated Interrupt Pin
- Small Package L 3.94 × W 2.36 × H 1.35 mm
Now enough of the theory of the sensor. Let's look at the detail of the Grove APDS-9960
Grove APDS9960This is the actual image of Grove APDS-9960 sensor
Below is the gerber view of the grove sensor APDS9960
For the design of this board, I have used the eagle cad.
Powering Up The Grove APDS-9960To test the Grove APDS-9960 I have used the Seeeduino XIAO expansion board and connect them together via the grove cable As shown in the figure below.
The sensor is connected to the I2C grove port. As shown in the figure above, I just make a simple OLED display program to show the title of this project. Next, we start to program the XIAO to test the functionality of the sensor. Before we can proceed we need to install the related library. Go to Arduino IDE --> Sketch --> Include Library --> Manage Libraries.
In the search window type"APDS 9960" in the search window as shown in the figure below. You will see a list of libraries available for this sensor. For this project, I decided to go with the Sparkfun library.
With the library installed, now we can start to test the sensor. By referring to the example code given we will test the three different functions of the sensor as following, colour test, gesture test and proxomity test. Now let's look at the colour test.
APDS-9960 Color TestFor this colour test, we will use the sample code from Sparkfun as shown in the figure below.
And below is the actual code
Development environment specifics:
Written in Arduino 1.0.5
Tested with SparkFun Arduino Pro Mini 3.3V
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
uint16_t ambient_light = 0;
uint16_t red_light = 0;
uint16_t green_light = 0;
uint16_t blue_light = 0;
void setup() {
// Initialize Serial port
Serial.begin(9600);
Serial.println();
Serial.println(F("--------------------------------"));
Serial.println(F("SparkFun APDS-9960 - ColorSensor"));
Serial.println(F("--------------------------------"));
// Initialize APDS-9960 (configure I2C and initial values)
if ( apds.init() ) {
Serial.println(F("APDS-9960 initialization complete"));
} else {
Serial.println(F("Something went wrong during APDS-9960 init!"));
}
// Start running the APDS-9960 light sensor (no interrupts)
if ( apds.enableLightSensor(false) ) {
Serial.println(F("Light sensor is now running"));
} else {
Serial.println(F("Something went wrong during light sensor init!"));
}
// Wait for initialization and calibration to finish
delay(500);
}
void loop() {
// Read the light levels (ambient, red, green, blue)
if ( !apds.readAmbientLight(ambient_light) ||
!apds.readRedLight(red_light) ||
!apds.readGreenLight(green_light) ||
!apds.readBlueLight(blue_light) ) {
Serial.println("Error reading light values");
} else {
Serial.print("Ambient: ");
Serial.print(ambient_light);
Serial.print(" Red: ");
Serial.print(red_light);
Serial.print(" Green: ");
Serial.print(green_light);
Serial.print(" Blue: ");
Serial.println(blue_light);
Copy this code to Arduino IDE. compile and upload it to the board to test it. If everything goes smoothly then open the serial monitor and you should get a window as shown in the figure below.
Now we will try to program the board to display the colour of the object that is pointed to the sensor. The test will be done. To display the value of the sensor on the OLED display I have used this code.
#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h>
#include <SparkFun_APDS9960.h>
// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
uint16_t ambient_light = 0;
uint16_t red_light = 0;
uint16_t green_light = 0;
uint16_t blue_light = 0;
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ PIN_WIRE_SCL, /* data=*/ PIN_WIRE_SDA, /* reset=*/ U8X8_PIN_NONE); // OLEDs without Reset of the Display
void setup(void) {
apds.init();
u8x8.begin();
u8x8.setFlipMode(1); // set number from 1 to 3, the screen word will rotary 180
apds.enableLightSensor(false);
}
void loop(void) {
// Read the light levels (ambient, red, green, blue)
if ( !apds.readAmbientLight(ambient_light) ||
!apds.readRedLight(red_light) ||
!apds.readGreenLight(green_light) ||
!apds.readBlueLight(blue_light) ) {
Serial.println("Error reading light values");
} else {
Serial.print("Ambient: ");
Serial.print(ambient_light);
Serial.print(" Red: ");
Serial.print(red_light);
Serial.print(" Green: ");
Serial.print(green_light);
Serial.print(" Blue: ");
Serial.println(blue_light);
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.setCursor(0, 0);
u8x8.print("Ambient: ");
u8x8.print(ambient_light);
u8x8.setCursor(0, 5);
u8x8.print("Red: ");
u8x8.print(red_light);
u8x8.setCursor(0, 10);
u8x8.print("Green: ");
u8x8.print(green_light);
u8x8.setCursor(0, 15);
u8x8.print("Blue: ");
u8x8.print(blue_light);
}
}
And the below video shows the result of the test
APDS-9960 Gesture TestThe next step that we want to do is the gesture test. For this, we will use the example code from Adafruit. The reason to choose this library instead the one from Sparkfun is that, the Sparkfun library used an additional pin for the interrupt. Hence I decided to use the Adafruit library,
And this is the example code used
/***************************************************************************
This is a library for the APDS9960 digital proximity, ambient light, RGB, and gesture sensor
This sketch puts the sensor in gesture mode and decodes gestures.
To use this, first put your hand close to the sensor to enable gesture mode.
Then move your hand about 6" from the sensor in the up -> down, down -> up,
left -> right, or right -> left direction.
Designed specifically to work with the Adafruit APDS9960 breakout
----> http://www.adafruit.com/products/3595
These sensors use I2C to communicate. The device's I2C address is 0x39
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Dean Miller for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#include "Adafruit_APDS9960.h"
Adafruit_APDS9960 apds;
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(115200);
if(!apds.begin()){
Serial.println("failed to initialize device! Please check your wiring.");
}
else Serial.println("Device initialized!");
//gesture mode will be entered once proximity mode senses something close
apds.enableProximity(true);
apds.enableGesture(true);
}
// the loop function runs over and over again forever
void loop() {
//read a gesture from the device
uint8_t gesture = apds.readGesture();
if(gesture == APDS9960_DOWN) Serial.println("v");
if(gesture == APDS9960_UP) Serial.println("^");
if(gesture == APDS9960_LEFT) Serial.println("<");
if(gesture == APDS9960_RIGHT) Serial.println(">");
}
And this is the result obtained on the serial monitor.
And below is the modified code to display the result on the OLED display.
/***************************************************************************
This is a library for the APDS9960 digital proximity, ambient light, RGB, and gesture sensor
This sketch puts the sensor in gesture mode and decodes gestures.
To use this, first put your hand close to the sensor to enable gesture mode.
Then move your hand about 6" from the sensor in the up -> down, down -> up,
left -> right, or right -> left direction.
Designed specifically to work with the Adafruit APDS9960 breakout
----> http://www.adafruit.com/products/3595
These sensors use I2C to communicate. The device's I2C address is 0x39
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Dean Miller for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#include "Adafruit_APDS9960.h"
#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h>
Adafruit_APDS9960 apds;
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ PIN_WIRE_SCL, /* data=*/ PIN_WIRE_SDA, /* reset=*/ U8X8_PIN_NONE); // OLEDs without Reset of the Display
// the setup function runs once when you press reset or power the board
void setup() {
Serial.begin(115200);
u8x8.begin();
u8x8.setFlipMode(1); // set number from 1 to 3, the screen word will rotary 180
if(!apds.begin()){
Serial.println("failed to initialize device! Please check your wiring.");
}
else Serial.println("Device initialized!");
//gesture mode will be entered once proximity mode senses something close
apds.enableProximity(true);
apds.enableGesture(true);
}
// the loop function runs over and over again forever
void loop() {
//read a gesture from the device
uint8_t gesture = apds.readGesture();
if(gesture == APDS9960_DOWN) Serial.println("v");
if(gesture == APDS9960_UP) Serial.println("^");
if(gesture == APDS9960_LEFT) Serial.println("<");
if(gesture == APDS9960_RIGHT) Serial.println(">");
u8x8.clearDisplay();
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.setCursor(0, 0);
if(gesture == APDS9960_DOWN) u8x8.print("DOWN");
if(gesture == APDS9960_UP) u8x8.print("UP");
if(gesture == APDS9960_LEFT) u8x8.print("LEFT");
if(gesture == APDS9960_RIGHT) u8x8.print("RIGHT");
}
And below is the video of this test
The next test we want to do is the proximity test
APDS-9960 Proximity TestFor this, we will use the example code from Sparkfun.
And the code is as follow
/****************************************************************
ProximityTest.ino
APDS-9960 RGB and Gesture Sensor
Shawn Hymel @ SparkFun Electronics
October 28, 2014
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
Tests the proximity sensing abilities of the APDS-9960.
Configures the APDS-9960 over I2C and polls for the distance to
the object nearest the sensor.
Hardware Connections:
IMPORTANT: The APDS-9960 can only accept 3.3V!
Arduino Pin APDS-9960 Board Function
3.3V VCC Power
GND GND Ground
A4 SDA I2C Data
A5 SCL I2C Clock
Resources:
Include Wire.h and SparkFun_APDS-9960.h
Development environment specifics:
Written in Arduino 1.0.5
Tested with SparkFun Arduino Pro Mini 3.3V
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
buy us a round!
Distributed as-is; no warranty is given.
****************************************************************/
#include <Wire.h>
#include <SparkFun_APDS9960.h>
// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
uint8_t proximity_data = 0;
void setup() {
// Initialize Serial port
Serial.begin(9600);
Serial.println();
Serial.println(F("------------------------------------"));
Serial.println(F("SparkFun APDS-9960 - ProximitySensor"));
Serial.println(F("------------------------------------"));
// Initialize APDS-9960 (configure I2C and initial values)
if ( apds.init() ) {
Serial.println(F("APDS-9960 initialization complete"));
} else {
Serial.println(F("Something went wrong during APDS-9960 init!"));
}
// Adjust the Proximity sensor gain
if ( !apds.setProximityGain(PGAIN_2X) ) {
Serial.println(F("Something went wrong trying to set PGAIN"));
}
// Start running the APDS-9960 proximity sensor (no interrupts)
if ( apds.enableProximitySensor(false) ) {
Serial.println(F("Proximity sensor is now running"));
} else {
Serial.println(F("Something went wrong during sensor init!"));
}
}
void loop() {
// Read the proximity value
if ( !apds.readProximity(proximity_data) ) {
Serial.println("Error reading proximity value");
} else {
Serial.print("Proximity: ");
Serial.println(proximity_data);
}
// Wait 250 ms before next reading
delay(250);
}
And this is the result we get by viewing the serial monitor
And now lets modify the code to display on the OLED.
/****************************************************************
ProximityTest.ino
APDS-9960 RGB and Gesture Sensor
Shawn Hymel @ SparkFun Electronics
October 28, 2014
https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor
Tests the proximity sensing abilities of the APDS-9960.
Configures the APDS-9960 over I2C and polls for the distance to
the object nearest the sensor.
Hardware Connections:
IMPORTANT: The APDS-9960 can only accept 3.3V!
Arduino Pin APDS-9960 Board Function
3.3V VCC Power
GND GND Ground
A4 SDA I2C Data
A5 SCL I2C Clock
Resources:
Include Wire.h and SparkFun_APDS-9960.h
Development environment specifics:
Written in Arduino 1.0.5
Tested with SparkFun Arduino Pro Mini 3.3V
This code is beerware; if you see me (or any other SparkFun
employee) at the local, and you've found our code helpful, please
buy us a round!
Distributed as-is; no warranty is given.
****************************************************************/
#include <Wire.h>
#include <SparkFun_APDS9960.h>
#include <Arduino.h>
#include <U8x8lib.h>
#include <Wire.h>
// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
uint8_t proximity_data = 0;
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* clock=*/ PIN_WIRE_SCL, /* data=*/ PIN_WIRE_SDA, /* reset=*/ U8X8_PIN_NONE); // OLEDs without Reset of the Display
void setup() {
u8x8.begin();
u8x8.setFlipMode(1); // set number from 1 to 3, the screen word will rotary 180
// Initialize Serial port
Serial.begin(9600);
Serial.println();
Serial.println(F("------------------------------------"));
Serial.println(F("SparkFun APDS-9960 - ProximitySensor"));
Serial.println(F("------------------------------------"));
// Initialize APDS-9960 (configure I2C and initial values)
if ( apds.init() ) {
Serial.println(F("APDS-9960 initialization complete"));
} else {
Serial.println(F("Something went wrong during APDS-9960 init!"));
}
// Adjust the Proximity sensor gain
if ( !apds.setProximityGain(PGAIN_2X) ) {
Serial.println(F("Something went wrong trying to set PGAIN"));
}
// Start running the APDS-9960 proximity sensor (no interrupts)
if ( apds.enableProximitySensor(false) ) {
Serial.println(F("Proximity sensor is now running"));
} else {
Serial.println(F("Something went wrong during sensor init!"));
}
}
void loop() {
// Read the proximity value
if ( !apds.readProximity(proximity_data) ) {
Serial.println("Error reading proximity value");
} else {
Serial.print("Proximity: ");
Serial.println(proximity_data);
u8x8.clearDisplay();
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.setCursor(0, 0);
u8x8.print("Proximity: ");
u8x8.println(proximity_data);
}
// Wait 250 ms before next reading
delay(250);
}
And below is the resulting video
From all three different tests, the Grove APDS-9960 seems to be working fine. In the upcoming project would like to integrate this inside the project.
If you are interested to create your own grove sensor like me join the Grove sensor co-invent campaign via the link below
The blog:
And if you need PCBA service from Seeed Studio, you can always click the link below
https://www.seeedstudio.com/pcb-assembly.html
The PCB finishing was really good. Looking forward for more PCB fabrication with them, in the future.
Thank you.
Comments