Dans ce tutoriel, vous allez apprendre à utiliser le capteur de gestes et de couleurs RGB APDS-9960 avec un Arduino ou d’autres microcontrôleurs courants comme l’ESP32 ou l’ESP8266.
L’APDS-9960 est un capteur très compact qui utilise la lumière infrarouge et des photodiodes pour reconnaître quatre gestes différents (de gauche à droite, de droite à gauche, de haut en bas, de bas en haut). Il possède également des détecteurs intégrés pour la lumière ambiante, la mesure des couleurs (rouge, vert, bleu) et la proximité.
Matériel nécessaire
Pour ce projet, il vous faut un capteur APDS-9960 et un microcontrôleur. J’ai utilisé un Arduino Uno mais n’importe quel autre Arduino ou un ESP32/ESP8266 fera l’affaire, tant qu’il fournit une sortie 3,3V. Un des exemples utilise aussi un servo, mais ce n’est pas indispensable pour ce projet.

Capteur APDS-9960

Arduino Uno

Câble USB pour Arduino UNO

Jeu de fils Dupont

Breadboard

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.
Caractéristiques du capteur de gestes et de couleurs RGB APDS-9960
L’APDS-9960 est une puce minuscule (3,94×2,36×1,35 mm) qui offre une détection avancée des gestes, la détection de proximité, la mesure numérique de la lumière ambiante (ALS) et la détection des couleurs (RGBC). L’image ci-dessous montre la puce APDS-9960 :

La détection des gestes est réalisée grâce à quatre photodiodes directionnelles qui captent la lumière infrarouge réfléchie (émise par la LED intégrée), laquelle est ensuite convertie en informations numériques de mouvement (vitesse, direction et distance). Des gestes simples HAUT-BAS-DROITE-GAUCHE ou des gestes plus complexes peuvent être détectés.
La fonction de détection des couleurs et de la lumière ambiante (ALS) de l’APDS-9960 fournit des données d’intensité lumineuse pour le rouge, le vert, le bleu et le canal clair. Chacun des canaux R, G, B, C possède un filtre bloquant les UV et l’IR ainsi qu’un convertisseur de données dédié produisant des données 16 bits simultanément.
Schéma fonctionnel de l’APDS-9960
L’image ci-dessous montre le schéma fonctionnel de l’APDS-9960. Vous pouvez facilement identifier la LED émettrice IR, les quatre photodiodes pour la détection des couleurs (Clair, Rouge, Vert, Bleu), et les quatre photodiodes pour la détection des gestes (Haut, Bas, Gauche, Droite).

L’APDS-9960 communique via une interface I2C (SCL, SDA) et dispose d’une sortie d’interruption supplémentaire (INT) qui s’active lorsqu’un seuil programmable est dépassé (par exemple, la proximité).
La tension de fonctionnement de l’APDS-9960 est de 2,4V à 3,6V, la plage de mesure des gestes est de 10 à 20 cm et l’adresse I2C est 0x39. Pour plus de détails, consultez la fiche technique ci-dessous :
Breakout board pour APDS-9960
La puce APDS-9960 est trop petite pour être connectée directement à un Arduino. En général, vous aurez besoin d’une breakout board comme celle-ci :

La plupart des breakout boards pour l’APDS-9960 possèdent les six broches suivantes :
- VCC : Alimentation (2,4 – 3,6V)
- GND : Masse
- VL : Alimentation LED IR
- SDA : Signal de données I2C
- SCL : Signal d’horloge I2C
- INT : Broche d’interruption
En général, seules les broches d’alimentation (VCC, GND), les broches pour la communication I2C (SCL, SDA) et la broche d’interruption (INT) sont nécessaires. VL permet d’alimenter la LED IR séparément, ce qui n’est généralement pas utile.
Notez que l’APDS-9960 fonctionne en 3,3V et que la plupart des breakout boards n’ont généralement pas de régulateur de tension.
Connexion de l’APDS-9960 à l’Arduino
Grâce à l’interface I2C de l’APDS-9960, la connexion à un Arduino est simple. Commencez par connecter la broche SCL de la breakout board APDS-9960 à A5 de l’Arduino. De même, connectez SDA à A4 de l’Arduino. Ensuite, reliez GND à GND et 3,3V à VCC de l’APDS-9960.

Assurez-vous d’utiliser du 3,3V comme alimentation. Le capteur APDS-9960 n’est pas prévu pour du 5V et les breakout boards pour l’APDS-9960 n’ont généralement pas de régulateur de tension.
Installer la bibliothèque pour APDS-9960
Il existe deux principales bibliothèques Arduino pour l’APDS-9960. La Adafruit_APDS9960 bibliothèque et la SparkFun_APDS-9960_Sensor_Arduino_Library. J’utiliserai la bibliothèque Adafruit_APDS9960 dans ce projet.
Pour installer la bibliothèque Adafruit_APDS9960, ouvrez le LIBRARY MANAGER, cherchez « APDS9960 », trouvez la bibliothèque d’Adafruit et installez-la, comme montré ci-dessous :

L’installateur peut vous demander d’installer des dépendances. Pas de souci, cliquez simplement sur « INSTALL ALL »

Une fois la bibliothèque installée, écrivons un petit code de test pour essayer le capteur. Téléversez le code suivant et passez votre main devant le capteur à environ 5 cm.
#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 vous voyez le message « Movement detected » affiché dans le Serial Monitor, tout fonctionne. Par contre, si vous voyez « failed to initialize device! », cela se complique un peu et il faut lire la section suivante. Si tout va bien, vous pouvez passer à la suite.
Adafruit_APDS9960: failed to initialize device!
Commencez par vérifier que le câblage est correct (SCL->A5, SDA->A4, VCC->3V3, GND->GND). Si le câblage est bon et que le capteur n’est pas défectueux, il y a principalement deux raisons pour lesquelles sensor.begin() peut échouer. Une adresse I2C différente ou un identifiant de puce différent. Vérifions d’abord l’adresse I2C.
Adresse I2C différente de l’APDS9960
L’adresse I2C habituelle de l’APDS9960 est 0x39 et la bibliothèque Adafruit_APDS9960 attend cette adresse I2C. Pour vérifier cela, installez et lancez le code I2C scanner suivant :
#include "I2CScanner.h"
I2CScanner scanner;
void setup() {
Serial.begin(9600);
scanner.Init();
}
void loop() {
scanner.Scan();
delay(5000);
}
Le scanner I2C devrait trouver un périphérique I2C à l’adresse 0x39 et l’afficher dans le Serial Monitor.
I2C device found at address 0x39 ! --- Scan finished ---
Si vous voyez une adresse I2C différente, il faut alors modifier le code dans la fonction setup comme suit et remplacer « addr » par l’adresse I2C que vous voyez.
void setup() {
...
if (!sensor.begin(10, APDS9960_AGAIN_4X, addr, &Wire)) {
Serial.println("failed to initialize device!");
}
...
}
Si votre adresse I2C est 0x39 ou si vous avez changé l’adresse I2C comme décrit ci-dessus mais que sensor.begin() échoue toujours, alors le prochain suspect est un identifiant de puce différent. Si le scanner I2C ne trouve aucun périphérique, il est probable que votre capteur soit défectueux (ou que le câblage soit encore incorrect).
Identifiant de puce différent pour l’APDS9960
Si vous regardez dans le code de la fonction begin() dans la bibliothèque Adafruit_APDS9960, vous verrez que le code utilise d’abord l’adresse I2C addr. Il vérifie ensuite l’identifiant de la puce et s’attend à ce qu’il soit 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;
}
Cependant, j’ai un APDS9960 avec l’identifiant de puce 0xA8 (et non 0xAB) et la SparkFun_APDS-9960_Sensor_Arduino_Library indique un autre identifiant de puce, qui est 0x9C.
Comme l’identifiant de la puce est codé en dur, il faut modifier le code. Le plus simple est de télécharger deux fichiers Adafruit_APDS9960.h et Adafruit_APDS9960.cpp dans votre dossier de projet, à côté de votre sketch, par exemple MySketch.ino :

Vous verrez alors ces deux nouveaux fichiers apparaître comme des onglets dans l’IDE Arduino :

Ouvrez maintenant l’onglet avec le fichier Adafruit_APDS9960.cpp, trouvez la fonction begin et supprimez ou commentez simplement le bloc annoté avec /* Make sure we're actually connected * / comme montré ci-dessous :
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;
// }
Sinon, vous pouvez aussi afficher « x » pour connaître l’ID de votre puce et adapter le test if (x != 0xAB) en conséquence.
Si vous ne souhaitez pas modifier le code vous-même, j’ai créé une version modifiée des deux fichiers, que vous pouvez télécharger ici (link). Il faudra quand même décompresser les fichiers et les copier dans votre projet. Avec cette correction, le code de test ci-dessus devrait maintenant fonctionner.
Reconnaître les gestes avec l’APDS-9960
Le code suivant est une légère extension du code de test précédent. Comme avant, dans la fonction setup, on initialise le capteur avec sensor.begin() puis on active la détection de proximité et de gestes :
#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");
}
Dans la fonction loop, on appelle sensor.readGesture() et selon la valeur retournée, on affiche le geste détecté dans le Serial Monitor.
Maintenant, passez votre main devant le capteur à une distance d’environ 5 à 10 cm et selon la direction, vous devriez voir le geste détecté affiché dans le Serial Monitor comme ci-dessous :

Au lieu d’afficher dans le Serial Monitor, vous pouvez maintenant modifier le code pour allumer des LEDs, contrôler des servos ou déclencher toute autre action selon le geste. Les sections suivantes montrent un exemple simple pour contrôler un servo avec des gestes.
Contrôler un servo avec le capteur de gestes APDS-9960
D’abord, il faut connecter le servo à l’Arduino. Si vous avez un de ces petits Micro Servos SG90, vous pouvez les brancher directement à un Arduino (pas besoin d’alimentation séparée). Connectez simplement le fil rouge (broche du milieu) du servo au 5V, le fil marron à la masse (GND) et le fil orange/jaune à la broche 13, comme ci-dessous.

Si vous avez besoin de plus d’infos sur la connexion et l’utilisation de ces servos, consultez le tutoriel How to control servo motors with Arduino.
Le code pour contrôler le servo avec un geste est une simple variante du code précédent pour la détection des gestes.
#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);
}
D’abord, on inclut la bibliothèque standard Servo (pas besoin d’installation). Ensuite, on crée l’objet servo et on définit la broche à laquelle le servo est connecté (servoPin).
Dans la fonction setup, on attache le servo à la broche et on l’oriente initialement à 90°. Dans la fonction loop, on remplace les appels à la fonction print par des commandes write pour le servo. Un geste haut ou bas place le servo à 90°, un geste gauche à 10° et un geste droite à 170°. Le court extrait vidéo ci-dessous montre le code en action :

Voilà, vous avez maintenant un contrôle gestuel simple pour un petit servo, que vous pouvez utiliser, par exemple, pour ouvrir ou fermer une boîte sans contact. Dans l’exemple suivant, nous allons tester le capteur de couleur intégré à l’APDS-9960.
Mesurer les couleurs avec l’APDS-9960
Le code ci-dessous utilise le capteur de couleur de l’APDS-9960 pour mesurer les valeurs de couleur rouge, vert, bleu et clair, et les affiche dans le Serial Monitor.
On commence par inclure la bibliothèque Adafruit et créer l’objet capteur. Dans la fonction setup, on initialise le capteur comme d’habitude avec sensor.begin(), puis on appelle sensor.enableColor(true) pour activer le capteur de couleur.
#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);
}
Dans la fonction loop, on appelle sensor.colorDataReady() pour récupérer les valeurs de couleur rouge (r), vert (g), bleu (b) et clair (c), puis on les affiche dans le Serial Monitor.
La bibliothèque Adafruit_APDS9960 propose deux fonctions supplémentaires qui permettent de calculer la température de couleur et la luminosité en lux à partir des valeurs mesurées. On affiche aussi ces valeurs dans le Serial Monitor.
Si vous changez la luminosité de la lumière ambiante ou placez des LEDs de différentes couleurs devant le capteur, vous verrez que les valeurs de couleur changent.
Test de la détection des couleurs de l’APDS-9960
Pour tester la détection des couleurs de l’APDS-9960, j’ai utilisé des LEDs rouges, vertes et bleues. Voici les valeurs mesurées lorsque j’ai placé une LED rouge près du capteur :
red:329 green:26 blue:47 clear:342 tmp:24902 lux:65436
Comme prévu, la valeur rouge est bien plus élevée que les valeurs verte et bleue. Notez aussi que les valeurs de température de couleur et de luminosité (lux) sont très élevées. Il semble que la lumière de la LED rouge perturbe ces mesures.
Ensuite, j’ai utilisé une LED verte. Elle était relativement faible et la valeur verte n’a augmenté que légèrement. La valeur rouge a aussi augmenté. On voit à la valeur lux que la luminosité de ma LED verte était faible.
red:15 green:16 blue:6 clear:42 tmp:3045 lux:15
Enfin, j’ai essayé une LED bleue et obtenu les valeurs ci-dessous. La valeur bleue était très élevée mais il y a aussi eu une augmentation du composant vert.
red:40 green:561 blue:2507 clear:2751 tmp:1754 lux:64574
La réponse du capteur de couleur dépend évidemment de la luminosité et de la longueur d’onde de la lumière colorée. Mes LEDs n’étaient pas forcément dans la plage la plus sensible, ce qui peut expliquer la faible réaction à la LED bleue. Mais on voit aussi sur le graphique de réponse spectrale ci-dessous que l’APDS-9960 a généralement une sensibilité bien plus faible pour la lumière bleue (B).

Réagir aux interruptions avec l’APDS-9960
Pour finir, je vais vous montrer comment utiliser la broche d’interruption de l’APDS-9960. Pour cela, il faut connecter la sortie INT de l’APDS-9960 à une broche d’interruption de l’Arduino. Sur un Arduino Uno, seules les broches 2 et 3 sont prévues pour les interruptions. Pour les broches d’interruption des autres cartes microcontrôleurs, voir ici (link).
Sur le schéma de câblage ci-dessous, je connecte la sortie INT de l’APDS-9960 à la broche 3 de l’Arduino.

Le code suivant déclenche un signal d’interruption si un objet s’approche du capteur, puis affiche la valeur de proximité.
#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();
}
}
On commence le code en incluant la bibliothèque, en créant l’objet capteur et en définissant la broche d’interruption. Dans la fonction setup, on active la détection de proximité, on règle les seuils de proximité et on active l’interruption de proximité. Il faut aussi passer la broche d’interruption intPin en mode INPUT.
Dans la fonction loop, on interroge l’état de la broche intPin. Si son état passe à LOW, cela signifie qu’une interruption a été déclenchée, on lit alors la valeur de proximité et on l’affiche.
Les valeurs de proximité vont de 255 (plus proche) à 0 (plus éloigné). Comme on a fixé un seuil de proximité à 100, le code commence à afficher les valeurs de proximité si un objet s’approche à moins de 100, ce qui correspond à une distance d’environ 10 mm.
Faire varier l’intensité d’une LED en fonction de la proximité
Vous pouvez utiliser ce code pour contrôler la luminosité d’une LED selon la proximité d’un objet. Pour cela, ajoutez une LED à votre montage. Connectez la cathode (patte courte) de la LED au GND et l’anode (patte longue) via une résistance de 220Ω à la broche 11. Toute autre broche PWM fonctionnera aussi.

Ensuite, on étend un peu le code. On définit la ledPin et on la passe en mode OUTPUT dans la fonction setup. Dans la fonction loop, on lit la valeur de proximité prox, et comme c’est une valeur entre 0 et 255, on peut l’utiliser directement pour contrôler la luminosité de la LED en appelant 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();
}
}
Le court extrait vidéo ci-dessous montre comment la luminosité de la LED varie selon la distance de la main par rapport au capteur :

Et voilà pour aujourd’hui ! J’espère que vous vous êtes amusé avec le capteur APDS-9960.
Conclusions
Dans ce tutoriel, vous avez appris à utiliser le capteur de gestes et de couleurs APDS-9960 avec un Arduino pour détecter des gestes et mesurer des valeurs de couleur et de luminosité.
Comparé au capteur de proximité APDS-9930, l’APDS-9960 peut détecter quatre gestes intégrés (haut, bas, gauche, droite) et possède un capteur de couleur RGB, alors que l’APDS-9930 n’a qu’un capteur de proximité et de lumière ambiante. Les deux capteurs sont spécialement conçus pour les applications mobiles (téléphones, tablettes) pour activer des fonctions (comme allumer haut-parleurs, micros, écrans) et contrôler la luminosité de l’écran.
Si vous avez besoin de plus de gestes, regardez du côté du PAJ7620U2, qui peut détecter jusqu’à 13 gestes, et son petit frère, le PAJ7620, peut en détecter 9.
La portée du capteur de proximité dans l’APDS-9930 et l’APDS-9960 est volontairement très limitée. Si vous voulez mesurer précisément des distances plus longues, par exemple pour la robotique, il vaut mieux utiliser des capteurs de distance infrarouge comme le GP2Y0A710K0F qui utilisent la triangulation pour déterminer la distance à un objet. Ou des capteurs de distance laser Time-of-Flight (ToF) comme le TOF10120 ou la bibliothèque VL53L1X.
Si vous avez des questions, n’hésitez pas à les poser dans les commentaires.
Bon bricolage ; )

