En este tutorial aprenderás a usar el sensor de gestos y color RGB APDS-9960 con un Arduino u otros microcontroladores comunes como el ESP32 o ESP8266.
El APDS-9960 es un sensor muy pequeño que utiliza luz infrarroja y fotodiodos para reconocer cuatro gestos diferentes (de izquierda a derecha, de derecha a izquierda, de arriba a abajo y de abajo a arriba). También cuenta con detectores integrados para luz ambiental, medición de colores (rojo, verde, azul) y proximidad.
Componentes necesarios
Para este proyecto necesitarás un sensor APDS-9960 y un microcontrolador. Yo utilicé un Arduino Uno, pero cualquier otro Arduino o cualquier ESP32/ESP8266 funcionará igual de bien, siempre que proporcione una salida de 3.3V. Uno de los ejemplos también utiliza un servo, pero esto no es esencial para este proyecto.

Sensor APDS-9960

Arduino Uno

Cable USB para Arduino UNO

Juego de cables Dupont

Protoboard

Servo
Makerguides is a participant in affiliate advertising programs designed to provide a means for sites to earn advertising fees by linking to Amazon, AliExpress, Elecrow, and other sites. As an Affiliate we may earn from qualifying purchases.
Características del sensor de gestos y color RGB APDS-9960
El APDS-9960 es un chip diminuto (3.94×2.36×1.35 mm) que ofrece detección avanzada de gestos, detección de proximidad, sensor digital de luz ambiental (ALS) y sensor de color (RGBC). La imagen de abajo muestra el chip APDS-9960:

La detección de gestos se logra mediante cuatro fotodiodos direccionales que detectan la luz infrarroja reflejada (emitida por el LED integrado), la cual se convierte en información digital de movimiento (es decir, velocidad, dirección y distancia). Se pueden detectar gestos simples ARRIBA-ABAJO-DERECHA-IZQUIERDA o gestos más complejos.
La función de detección de color y ALS del APDS-9960 proporciona datos de intensidad de luz roja, verde, azul y clara. Cada uno de los canales R, G, B, C tiene un filtro bloqueador de UV e IR y un convertidor de datos dedicado que produce datos de 16 bits simultáneamente.
Diagrama de bloques funcional del APDS-9960
La imagen de abajo muestra el diagrama de bloques funcional del APDS-9960. Puedes identificar fácilmente el diodo emisor de IR LED, los cuatro fotodiodos para la detección de color (Clear, Red, Green, Blue) y los cuatro fotodiodos para la detección de gestos (Up, Down, Left, Right).

El APDS-9960 se comunica mediante una interfaz I2C (SCL, SDA) y tiene una salida de interrupción adicional (INT) que se activa cuando se supera un umbral programable (por ejemplo, proximidad).
El voltaje de funcionamiento del APDS-9960 es de 2.4V-3.6V, el rango de medición para gestos es de 10-20cm y la dirección I2C es 0x39. Para información más detallada consulta la hoja de datos enlazada abajo:
Placa adaptadora para APDS-9960
El chip APDS-9960 es demasiado pequeño para conectarlo directamente a un Arduino. Normalmente, necesitarás una placa adaptadora como la que se muestra a continuación:

La mayoría de las placas adaptadoras para el APDS-9960 tienen los siguientes seis pines:
- VCC : Alimentación (2.4 – 3.6V)
- GND : Tierra
- VL : Alimentación del LED IR
- SDA : Señal de datos I2C
- SCL : Señal de reloj I2C
- INT : Pin de interrupción
Normalmente solo necesitarás los pines de alimentación (VCC, GND), los pines para la comunicación I2C (SCL, SDA) y el pin de interrupción (INT). VL te permite alimentar el LED IR externamente, lo cual normalmente no es necesario.
Ten en cuenta que el APDS-9960 funciona a 3.3V y que la mayoría de las placas adaptadoras no suelen tener un regulador de voltaje.
Conectando el APDS-9960 al Arduino
Gracias a la interfaz I2C del APDS-9960, conectarlo a un Arduino es sencillo. Primero, conecta el pin SCL de la placa adaptadora del APDS-9960 al A5 del Arduino. De igual manera, conecta SDA al A4 del Arduino. Luego, conecta GND a GND y 3.3V a VCC del APDS-9960.

Asegúrate de usar 3.3V como fuente de alimentación. El sensor APDS-9960 no está diseñado para 5V y las placas adaptadoras para el APDS-9960 normalmente no tienen regulador de voltaje.
Instalar la librería para APDS-9960
Existen dos librerías principales de Arduino para el APDS-9960. La Adafruit_APDS9960 librería y la SparkFun_APDS-9960_Sensor_Arduino_Library. Yo usaré la Adafruit_APDS9960 librería en este proyecto.
Para instalar la librería Adafruit_APDS9960, abre el LIBRARY MANAGER, busca «APDS9960», encuentra la librería de Adafruit e instálala, como se muestra a continuación:

El instalador puede pedirte instalar dependencias de la librería. No hay problema. Simplemente pulsa «INSTALL ALL»

Con la librería instalada, vamos a escribir un código de prueba para probar el sensor. Sube el siguiente código y mueve tu mano frente al sensor a una distancia de unos 5cm.
#include "Adafruit_APDS9960.h"
Adafruit_APDS9960 sensor;
void setup() {
Serial.begin(9600);
if (!sensor.begin()) {
Serial.println("failed to initialize device!");
}
sensor.enableProximity(true);
sensor.enableGesture(true);
}
void loop() {
if(sensor.readGesture()) {
Serial.println("Movement detected");
}
}
Si ves el mensaje «Movement detected» impreso en tu Monitor Serie, todo está bien. Sin embargo, si ves «failed to initialize device!» la cosa se complica un poco y necesitas leer la siguiente sección. Si todo va bien puedes saltarla.
Adafruit_APDS9960: failed to initialize device!
Primero, revisa que el cableado sea correcto (SCL->A5, SDA->A4, VCC->3V3, GND->GND). Si el cableado está bien y el sensor no está defectuoso, entonces hay dos razones principales por las que sensor.begin() puede fallar. Una dirección I2C diferente o un chip ID diferente. Vamos a comprobar primero la dirección I2C.
Dirección I2C diferente del APDS9960
La dirección I2C habitual del APDS9960 es 0x39 y la librería Adafruit_APDS9960 espera esta dirección I2C. Para verificarlo, instala y ejecuta el siguiente código I2C scanner:
#include "I2CScanner.h"
I2CScanner scanner;
void setup() {
Serial.begin(9600);
scanner.Init();
}
void loop() {
scanner.Scan();
delay(5000);
}
El escáner I2C debería encontrar un dispositivo I2C con la dirección 0x39 y mostrarlo en el Monitor Serie.
I2C device found at address 0x39 ! --- Scan finished ---
Si ves una dirección I2C diferente, entonces tienes que cambiar el código en la función setup como sigue y reemplazar «addr» por la dirección I2C que ves.
void setup() {
...
if (!sensor.begin(10, APDS9960_AGAIN_4X, addr, &Wire)) {
Serial.println("failed to initialize device!");
}
...
}
Si tu dirección I2C es 0x39 o has cambiado la dirección I2C como se describe arriba pero sensor.begin() sigue fallando, entonces el siguiente candidato es un chip ID diferente. Si el escáner I2C no encuentra ningún dispositivo, lo más probable es que tu sensor esté roto (o el cableado sigue mal).
Chip ID diferente del APDS9960
Si miras el código de la función begin() en la librería Adafruit_APDS9960 verás que el código primero usa la dirección I2C addr. Luego comprueba el chip ID y espera que sea 0xAB.
boolean Adafruit_APDS9960::begin(uint16_t iTimeMS, apds9960AGain_t aGain,
uint8_t addr, TwoWire *theWire) {
if (i2c_dev)
delete i2c_dev;
i2c_dev = new Adafruit_I2CDevice(addr, theWire);
if (!i2c_dev->begin()) {
return false;
}
/* Make sure we're actually connected */
uint8_t x = read8(APDS9960_ID);
if (x != 0xAB) {
return false;
}
Sin embargo, yo tengo un APDS9960 con el chip ID 0xA8 (no 0xAB) y la SparkFun_APDS-9960_Sensor_Arduino_Library lista otro chip ID, que es 0x9C.
Como el chip ID está codificado en el código, tenemos que modificarlo. La forma más sencilla de hacerlo es descargar dos archivos Adafruit_APDS9960.h y Adafruit_APDS9960.cpp en tu carpeta del proyecto, junto a tu sketch, por ejemplo MySketch.ino:

Verás que estos dos archivos nuevos aparecen como pestañas en tu Arduino IDE:

Ahora abre la pestaña con el archivo Adafruit_APDS9960.cpp, busca la función begin y simplemente elimina o comenta el bloque anotado con /* Make sure we're actually connected * / como se muestra a continuación:
boolean Adafruit_APDS9960::begin(uint16_t iTimeMS, apds9960AGain_t aGain,
uint8_t addr, TwoWire *theWire) {
if (i2c_dev)
delete i2c_dev;
i2c_dev = new Adafruit_I2CDevice(addr, theWire);
if (!i2c_dev->begin()) {
return false;
}
/* Make sure we're actually connected */
// uint8_t x = read8(APDS9960_ID);
// if (x != 0xAB) {
// return false;
// }
Alternativamente, también podrías imprimir «x» para averiguar el ID de tu chip y cambiar la comprobación if (x != 0xAB), según corresponda.
Si no quieres modificar el código tú mismo, he creado una versión modificada de los dos archivos, que puedes descargar aquí (link). Aun así tendrás que descomprimir los archivos y copiarlos en tu proyecto. Con este arreglo, el código de prueba anterior debería funcionar.
Reconociendo gestos con el APDS-9960
El siguiente código es una pequeña extensión del código de prueba anterior. Como antes, en la función setup inicializamos el sensor con sensor.begin() y luego activamos la detección de proximidad y gestos:
#include "Adafruit_APDS9960.h"
Adafruit_APDS9960 sensor;
void setup() {
Serial.begin(9600);
if (!sensor.begin()) {
Serial.println("failed to initialize device!");
}
sensor.enableProximity(true);
sensor.enableGesture(true);
}
void loop() {
uint8_t gesture = sensor.readGesture();
if (gesture == APDS9960_DOWN) Serial.println("DOWN");
if (gesture == APDS9960_UP) Serial.println("UP");
if (gesture == APDS9960_LEFT) Serial.println("LEFT");
if (gesture == APDS9960_RIGHT) Serial.println("RIGHT");
}
En la función loop llamamos a sensor.readGesture() y, dependiendo del valor devuelto, mostramos el gesto detectado en el Monitor Serie.
Ahora, mueve tu mano sobre el sensor a una distancia de unos 5-10 cm y, dependiendo de la dirección, deberías ver el gesto detectado impreso en el Monitor Serie como se muestra a continuación:

En vez de imprimir en el Monitor Serie, ahora podrías modificar el código para encender LEDs, controlar servos o realizar cualquier otra acción que desees, dependiendo del gesto. Las siguientes secciones contienen un ejemplo sencillo de cómo controlar un servo con gestos.
Controlar un servo con el sensor de gestos APDS-9960
Primero necesitamos conectar el servo al Arduino. Si tienes uno de esos pequeños SG90 Micro Servos, puedes conectarlos directamente al Arduino (no necesitas una fuente de alimentación separada). Simplemente conecta el cable rojo (pin central) del servo a 5V, el cable marrón a tierra (GND) y el cable naranja/amarillo al pin 13, como se muestra a continuación.

Si necesitas más información sobre cómo conectar y usar estos servos, consulta el tutorial How to control servo motors with Arduino.
El código para controlar el servo con un gesto es una simple variación del código anterior de detección de gestos.
#include "Adafruit_APDS9960.h"
#include "Servo.h"
Adafruit_APDS9960 sensor;
Servo servo;
const int servoPin = 13;
void setup() {
if (!sensor.begin()) {
Serial.println("failed to initialize device!");
}
sensor.enableProximity(true);
sensor.enableGesture(true);
servo.attach(servoPin);
servo.write(90);
}
void loop() {
uint8_t gesture = sensor.readGesture();
if (gesture == APDS9960_DOWN) servo.write(90);
if (gesture == APDS9960_UP) servo.write(90);
if (gesture == APDS9960_LEFT) servo.write(10);
if (gesture == APDS9960_RIGHT) servo.write(170);
}
Primero, incluimos la librería estándar Servo (no es necesario instalar una librería). Luego creamos el objeto servo y definimos el pin al que está conectado el servo (servoPin).
En la función setup conectamos el servo al pin correspondiente y orientamos el servo inicialmente a 90°. En la función loop reemplazamos las llamadas a la función print por comandos write al servo. En caso de un gesto hacia arriba o abajo, movemos el servo a la posición de 90°. Un gesto a la izquierda mueve el servo a 10° y un gesto a la derecha lo mueve a 170°. El siguiente vídeo corto muestra el código en acción:

Con esto ya tienes un control por gestos sencillo para un pequeño servo, que podrías usar, por ejemplo, para abrir o cerrar una caja sin tocarla. En el siguiente ejemplo de código probamos el sensor de color del APDS-9960
Midiendo colores con el APDS-9960
El siguiente código utiliza el sensor de color del APDS-9960 para medir los valores de color rojo, verde, azul y claro, y los muestra en el Monitor Serie.
Comenzamos incluyendo la librería de Adafruit y creando el objeto del sensor. En la función setup inicializamos el sensor como siempre con sensor.begin(), y luego llamamos a sensor.enableColor(true) para activar el sensor de color.
#include "Adafruit_APDS9960.h"
Adafruit_APDS9960 sensor;
void setup() {
Serial.begin(9600);
if (!sensor.begin()) {
Serial.println("failed to initialize device!.");
}
sensor.enableColor(true);
}
void loop() {
uint16_t r, g, b, c, tmp, lux;
while (!sensor.colorDataReady()) {
delay(5);
}
sensor.getColorData(&r, &g, &b, &c);
Serial.print("red:");
Serial.println(r);
Serial.print("green:");
Serial.println(g);
Serial.print("blue:");
Serial.println(b);
Serial.print("clear:");
Serial.println(c);
tmp = sensor.calculateColorTemperature(r, g, b);
Serial.print("tmp:");
Serial.println(tmp);
lux = sensor.calculateLux(r, g, b);
Serial.print("lux:");
Serial.println(lux);
Serial.println();
delay(1000);
}
En la función loop, llamamos a sensor.colorDataReady() para obtener los valores de color rojo (r), verde (g), azul (b) y claro (c), y luego los mostramos en el Monitor Serie.
La librería Adafruit_APDS9960 tiene dos funciones adicionales que te permiten calcular la temperatura de color y el brillo en lux a partir de los valores de color medidos. También mostramos estos valores en el Monitor Serie.
Si cambias la intensidad de la luz ambiental o colocas LEDs de diferentes colores frente al sensor, verás que los valores de color cambian.
Probando la detección de color del APDS-9960
Para probar la detección de color del APDS-9960, utilicé LEDs rojos, verdes y azules. Los valores de abajo son los que medí al colocar un LED rojo cerca del sensor:
red:329 green:26 blue:47 clear:342 tmp:24902 lux:65436
Como era de esperar, el valor rojo es mucho más alto que los valores verde y azul. También observa que los valores de temperatura de color y brillo en lux son extremadamente altos. Parece que la luz del LED rojo confunde estas mediciones.
Después, utilicé un LED verde. El LED verde era relativamente débil y el valor verde solo aumentó un poco. También el valor rojo subió. Puedes ver en el valor de lux que el brillo de mi LED verde era bajo.
red:15 green:16 blue:6 clear:42 tmp:3045 lux:15
Finalmente, probé con un LED azul y obtuve los valores de color que se muestran abajo. El valor azul fue muy alto, pero también hubo un aumento en el componente verde.
red:40 green:561 blue:2507 clear:2751 tmp:1754 lux:64574
La respuesta del sensor de color obviamente depende del brillo y la longitud de onda de la luz de color. Mis LEDs no estaban necesariamente en el rango más sensible, lo que podría explicar la reacción débil al LED azul. Pero también puedes ver en el gráfico de respuesta espectral de abajo que el APDS-9960 generalmente tiene una sensibilidad mucho menor para la luz azul (B).

Reaccionando a interrupciones con el APDS-9960
Como último ejemplo, quiero mostrarte cómo usar el pin de interrupción del APDS-9960. Para ello, necesitamos conectar la salida INT del APDS-9960 a un pin de interrupción del Arduino. En el caso de un Arduino Uno, solo los pines 2 y 3 son pines de interrupción. Para los pines de interrupción de otras placas de microprocesador consulta aquí (link).
En el diagrama de conexiones de abajo, conecto la salida INT del APDS-9960 al pin 3 del Arduino.

El siguiente código activa una señal de interrupción si un objeto se acerca al sensor y luego muestra el valor de proximidad.
#include "Adafruit_APDS9960.h"
Adafruit_APDS9960 sensor;
const int intPin = 3;
void setup() {
Serial.begin(9600);
if (!sensor.begin()) {
Serial.println("failed to initialize device!");
}
sensor.enableProximity(true);
sensor.setProximityInterruptThreshold(0, 100);
sensor.enableProximityInterrupt();
pinMode(intPin, INPUT_PULLUP);
}
void loop() {
if (!digitalRead(intPin)) {
Serial.println(sensor.readProximity());
sensor.clearInterrupt();
}
}
Comenzamos el código incluyendo la librería, creando el objeto del sensor y definiendo el pin de interrupción. En la función setup activamos la detección de proximidad, configuramos los umbrales de proximidad y activamos la interrupción de proximidad. También necesitamos poner el pin de interrupción intPin en modo INPUT.
En la función loop comprobamos el estado del intPin. Si su estado pasa a bajo significa que se ha activado una interrupción, leemos el valor de proximidad y lo mostramos.
Los valores de proximidad van de 255 (más cerca) a 0 (más lejos). Como configuramos un umbral de proximidad de 100, el código empieza a mostrar valores de proximidad si un objeto se acerca a menos de 100, lo que corresponde a una distancia de unos 10mm.
Atenuando un LED proporcionalmente a la proximidad
Puedes usar este código para controlar el brillo de un LED dependiendo de la proximidad de un objeto. Para ello, añadimos un LED a nuestro circuito. Conecta el cátodo (pata corta) del LED a GND y el ánodo (pata larga) mediante una resistencia de 220Ω al pin 11. Cualquier otro pin PWM también funcionará.

A continuación, ampliamos un poco el código. Definimos el ledPin y lo configuramos en modo OUTPUT en la función setup. En la función loop leemos el valor de proximidad prox, y como es un valor entre 0 y 255, podemos usarlo directamente para controlar el brillo del LED llamando a analogWrite(ledPin, prox):
#include "Adafruit_APDS9960.h"
Adafruit_APDS9960 sensor;
const int intPin = 3;
const int ledPin = 11;
void setup() {
Serial.begin(9600);
if (!sensor.begin()) {
Serial.println("failed to initialize device!");
}
sensor.enableProximity(true);
sensor.setProximityInterruptThreshold(0, 0);
sensor.enableProximityInterrupt();
pinMode(intPin, INPUT_PULLUP);
pinMode(ledPin, OUTPUT);
}
void loop() {
if (!digitalRead(intPin)) {
uint8_t prox = sensor.readProximity();
analogWrite(ledPin, prox);
sensor.clearInterrupt();
}
}
El siguiente vídeo corto muestra cómo cambia el brillo del LED dependiendo de la proximidad de la mano al sensor:

¡Y eso es todo por hoy! Espero que te hayas divertido experimentando con el sensor APDS-9960.
Conclusiones
En este tutorial has aprendido a usar el sensor de gestos y color APDS-9960 con un Arduino para detectar gestos y medir valores de color y brillo.
En comparación con el sensor de proximidad APDS-9930, el APDS-9960 puede detectar cuatro gestos integrados (arriba, abajo, izquierda, derecha) y tiene un sensor de color RGB, mientras que el APDS-9930 solo tiene sensor de proximidad y de luz ambiental. Ambos sensores están diseñados específicamente para aplicaciones en teléfonos móviles o tabletas para activar funciones (como encender altavoces, micrófonos, pantallas) y controlar el brillo de la pantalla.
Si necesitas más gestos, échale un vistazo al PAJ7620U2, que puede detectar hasta 13 gestos y su hermano pequeño, el PAJ7620, que aún puede detectar 9 gestos.
El rango del sensor de proximidad en el APDS-9930 y APDS-9960 es intencionadamente muy limitado. Si quieres medir distancias más largas con precisión, por ejemplo para aplicaciones de robótica, es mejor usar sensores de distancia por infrarrojos como el GP2Y0A710K0F que usan triangulación para determinar la distancia a un objeto. O sensores de distancia láser Time-of-Flight (ToF) como el TOF10120 o la librería VL53L1X.
Si tienes alguna pregunta, no dudes en dejarla en los comentarios.
¡Feliz cacharreo ; )

