In questo tutorial imparerai come utilizzare il sensore di gesti e colore RGB APDS-9960 con un Arduino o altri microcontrollori comuni come ESP32 o ESP8266.
L’APDS-9960 è un sensore molto piccolo che utilizza luce IR e fotodiodi per riconoscere quattro diversi gesti (da sinistra a destra, da destra a sinistra, dall’alto verso il basso, dal basso verso l’alto). Ha anche rilevatori integrati per la luce ambientale, la misurazione dei colori (rosso, verde, blu) e la prossimità.
Componenti necessari
Per questo progetto ti serviranno un sensore APDS-9960 e un microcontrollore. Io ho usato un Arduino Uno, ma qualsiasi altro Arduino o anche un ESP32/ESP8266 andrà bene, purché fornisca un’uscita a 3.3V. Uno degli esempi utilizza anche un servo, ma non è essenziale per questo progetto.

Sensore APDS-9960

Arduino Uno

Cavo USB per Arduino UNO

Set di cavi 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.
Caratteristiche del sensore di gesti e colore RGB APDS-9960
L’APDS-9960 è un chip minuscolo (3.94×2.36×1.35 mm) che offre funzioni avanzate di rilevamento gesti, rilevamento prossimità, Digital Ambient Light Sensing (ALS) e rilevamento colore (RGBC). L’immagine qui sotto mostra il chip APDS-9960:

Il rilevamento dei gesti avviene tramite quattro fotodiodi direzionali che rilevano la luce IR riflessa (emessa dal LED integrato), che viene poi convertita in informazioni digitali di movimento (cioè velocità, direzione e distanza). Si possono rilevare gesti semplici SU-GIÙ-DESTRA-SINISTRA o anche gesti più complessi.
La funzione di rilevamento colore e ALS dell’APDS-9960 fornisce dati di intensità per luce rossa, verde, blu e chiara. Ognuno dei canali R, G, B, C ha un filtro che blocca UV e IR e un convertitore dati dedicato che produce dati a 16 bit simultaneamente.
Schema a blocchi funzionale dell’APDS-9960
L’immagine qui sotto mostra lo schema a blocchi funzionale dell’APDS-9960. Puoi facilmente identificare il diodo LED emettitore IR, i quattro fotodiodi per il rilevamento colore (Clear, Red, Green, Blue) e i quattro fotodiodi per il rilevamento gesti (Up, Down, Left, Right).

L’APDS-9960 comunica tramite interfaccia I2C (SCL, SDA) e ha un’uscita di interrupt aggiuntiva (INT) che si attiva quando viene superata una soglia programmabile (ad esempio, la prossimità).
La tensione di funzionamento dell’APDS-9960 è 2.4V-3.6V, il range di rilevamento dei gesti è 10-20cm e l’indirizzo I2C è 0x39. Per informazioni più dettagliate consulta il datasheet linkato qui sotto:
Breakout board per APDS-9960
Il chip APDS-9960 è troppo piccolo per collegarlo direttamente ad Arduino. Di solito, serve una breakout board come quella mostrata qui sotto:

La maggior parte delle breakout board per APDS-9960 ha i seguenti sei pin:
- VCC : Alimentazione (2.4 – 3.6V)
- GND : Massa
- VL : Alimentazione LED IR
- SDA : Segnale dati I2C
- SCL : Segnale clock I2C
- INT : Pin di interrupt
Di solito servono solo i pin di alimentazione (VCC, GND), i pin per la comunicazione I2C (SCL, SDA) e il pin di interrupt (INT). VL permette di fornire alimentazione esterna al LED IR, ma normalmente non serve.
Nota che l’APDS-9960 funziona a 3.3V e che la maggior parte delle breakout board di solito non ha un regolatore di tensione.
Collegare l’APDS-9960 ad Arduino
Grazie all’interfaccia I2C dell’APDS-9960, collegarlo ad Arduino è semplice. Prima collega il pin SCL della breakout board APDS-9960 ad A5 di Arduino. Allo stesso modo, collega SDA ad A4 di Arduino. Poi collega GND a GND e 3.3V a VCC dell’APDS-9960.

Assicurati di usare 3.3V come alimentazione. Il sensore APDS-9960 non è progettato per 5V e le breakout board per APDS-9960 di solito non hanno un regolatore di tensione.
Installare la libreria per APDS-9960
Esistono due principali librerie Arduino per l’APDS-9960. La Adafruit_APDS9960 libreria e la SparkFun_APDS-9960_Sensor_Arduino_Library. In questo progetto userò la Adafruit_APDS9960 libreria.
Per installare la Adafruit_APDS9960 libreria, apri il LIBRARY MANAGER, cerca “APDS9960”, trova la libreria di Adafruit e installala, come mostrato qui sotto:

Durante l’installazione potrebbero essere richieste delle dipendenze. Nessun problema, basta premere “INSTALL ALL”

Con la libreria installata, scriviamo un po’ di codice di test per provare il sensore. Carica il seguente codice e muovi la mano davanti al sensore a circa 5cm di distanza.
#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");
}
}
Se vedi il messaggio “Movement detected” stampato sul Serial Monitor, tutto funziona. Se invece vedi “failed to initialize device!” la situazione è un po’ più complicata e devi leggere la prossima sezione. Se tutto va bene puoi saltarla.
Adafruit_APDS9960: failed to initialize device!
Per prima cosa, controlla che i collegamenti siano corretti (SCL->A5, SDA->A4, VCC->3V3, GND->GND). Se i collegamenti sono giusti e il sensore non è difettoso, ci sono due motivi principali per cui sensor.begin() potrebbe fallire. Un indirizzo I2C diverso o un chip ID diverso. Controlliamo prima l’indirizzo I2C.
Indirizzo I2C diverso dell’APDS9960
Il solito indirizzo I2C dell’APDS9960 è 0x39 e la Adafruit_APDS9960 libreria si aspetta questo indirizzo I2C. Per verificarlo installa ed esegui il seguente I2C scanner codice:
#include "I2CScanner.h"
I2CScanner scanner;
void setup() {
Serial.begin(9600);
scanner.Init();
}
void loop() {
scanner.Scan();
delay(5000);
}
Lo scanner I2C dovrebbe trovare un dispositivo I2C con indirizzo 0x39 e stamparlo sul Serial Monitor.
I2C device found at address 0x39 ! --- Scan finished ---
Se vedi un indirizzo I2C diverso, allora devi cambiare il codice nella funzione setup come segue e sostituire “addr” con l’indirizzo I2C che vedi.
void setup() {
...
if (!sensor.begin(10, APDS9960_AGAIN_4X, addr, &Wire)) {
Serial.println("failed to initialize device!");
}
...
}
Se il tuo indirizzo I2C è 0x39 o hai cambiato l’indirizzo I2C come descritto sopra ma sensor.begin() fallisce ancora, allora il prossimo indiziato è un chip ID diverso. Se lo scanner I2C non trova nessun dispositivo, probabilmente il sensore è rotto (o i collegamenti sono ancora sbagliati).
Chip ID diverso dell’APDS9960
Se guardi nel codice della funzione begin() nella libreria Adafruit_APDS9960 vedrai che il codice usa prima l’indirizzo I2C addr. Poi controlla il chip ID e si aspetta che sia 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;
}
Tuttavia, io ho un APDS9960 con chip ID 0xA8 (non 0xAB) e la SparkFun_APDS-9960_Sensor_Arduino_Library elenca un altro chip ID, che è 0x9C.
Poiché il chip ID è hard-coded dobbiamo modificare il codice. Il modo più semplice è scaricare due file Adafruit_APDS9960.h e Adafruit_APDS9960.cpp nella cartella del tuo progetto, accanto al tuo sketch, ad esempio MySketch.ino:

Vedrai quindi questi due nuovi file apparire come tab nell’Arduino IDE:

Ora apri la tab con il file Adafruit_APDS9960.cpp, trova la funzione begin e semplicemente rimuovi o commenta il blocco annotato con /* Make sure we're actually connected * / come mostrato qui sotto:
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;
// }
In alternativa, puoi anche stampare “x” per scoprire l’ID del tuo chip e modificare il test if (x != 0xAB), di conseguenza.
Se non vuoi modificare il codice da solo, ho creato una versione modificata dei due file che puoi scaricare qui (link). Devi comunque estrarre i file e copiarli nella cartella del tuo progetto. Con questa modifica, il codice di test sopra dovrebbe ora funzionare.
Riconoscere i gesti con APDS-9960
Il codice seguente è una piccola estensione del codice di test precedente. Come prima, nella funzione setup inizializziamo il sensore con sensor.begin() e poi abilitiamo il rilevamento di prossimità e gesti:
#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");
}
Nel loop chiamiamo sensor.readGesture() e, a seconda del valore restituito, stampiamo il gesto rilevato sul Serial Monitor.
Ora, muovi la mano sopra il sensore a una distanza di circa 5-10 cm e, a seconda della direzione, dovresti vedere il gesto rilevato stampato sul Serial Monitor come mostrato qui sotto:

Invece di stampare sul Serial Monitor puoi ora modificare il codice per accendere LED, controllare servomotori o eseguire qualsiasi altra azione tu voglia, a seconda del gesto. Le prossime sezioni contengono un semplice esempio su come controllare un servo tramite i gesti.
Controllare un servo con il sensore di gesti APDS-9960
Per prima cosa dobbiamo collegare il servo ad Arduino. Se hai uno di quei piccoli SG90 Micro Servo puoi collegarlo direttamente ad Arduino (non serve un’alimentazione separata). Collega semplicemente il filo rosso (pin centrale) del servo a 5V, il filo marrone a GND e il filo arancione/giallo al pin 13, come mostrato qui sotto.

Se ti serve più info su come collegare e usare questi servo dai un’occhiata al tutorial How to control servo motors with Arduino.
Il codice per controllare il servo con un gesto è una semplice variazione del codice precedente per il rilevamento dei gesti.
#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);
}
Per prima cosa includiamo la libreria standard Servo (non serve installare una libreria). Poi creiamo l’oggetto servo e definiamo il pin a cui è collegato il servo (servoPin).
Nella funzione setup agganciamo il servo al pin e inizialmente lo orientiamo a 90°. Nel loop sostituiamo le chiamate alla funzione print con i comandi write al servo. In caso di gesto su o giù, muoviamo il servo a 90°. Un gesto a sinistra lo porta a 10° e un gesto a destra a 170°. Il breve video qui sotto mostra il codice in azione:

Con questo ora hai un semplice controllo gestuale per un piccolo servo, che puoi usare, ad esempio, per aprire o chiudere una scatola senza toccarla. Nel prossimo esempio di codice proviamo il sensore di colore integrato nell’APDS-9960
Misurare i colori con APDS-9960
Il codice qui sotto utilizza il sensore di colore dell’APDS-9960 per misurare i valori di rosso, verde, blu e clear, e li stampa sul Serial Monitor.
Iniziamo includendo la libreria Adafruit e creando l’oggetto sensore. Nella funzione setup inizializziamo il sensore come al solito con sensor.begin(), poi chiamiamo sensor.enableColor(true) per abilitare il sensore di colore.
#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);
}
Nel loop chiamiamo sensor.colorDataReady() per recuperare i valori di colore per rosso (r), verde (g), blu (b) e clear (c), e poi li stampiamo sul Serial Monitor.
La libreria Adafruit_APDS9960 ha due funzioni aggiuntive che permettono di calcolare la temperatura colore e la luminosità in lux in base ai valori misurati. Stampiamo anche questi valori sul Serial Monitor.
Se cambi la luminosità della luce ambientale o metti LED di colori diversi davanti al sensore, vedrai che i valori di colore cambiano.
Testare il rilevamento colore dell’APDS-9960
Per testare il rilevamento colore dell’APDS-9960, ho usato LED rossi, verdi e blu. I valori qui sotto sono quelli che ho misurato quando ho posizionato un LED rosso vicino al sensore:
red:329 green:26 blue:47 clear:342 tmp:24902 lux:65436
Come previsto il valore rosso è molto più alto rispetto a verde e blu. Nota anche che i valori di temperatura colore e luminosità in lux sono altissimi. Sembra che la luce del LED rosso confonda queste misurazioni.
Poi ho usato un LED verde. Il LED verde era relativamente debole e il valore verde è aumentato solo di poco. Anche il valore rosso è salito. Dal valore lux si vede che la luminosità del mio LED verde era bassa.
red:15 green:16 blue:6 clear:42 tmp:3045 lux:15
Infine, ho provato un LED blu e ho ottenuto i valori di colore mostrati qui sotto. Il valore blu era molto alto ma c’è stato anche un aumento della componente verde.
red:40 green:561 blue:2507 clear:2751 tmp:1754 lux:64574
La risposta del sensore di colore ovviamente dipende dalla luminosità e dalla lunghezza d’onda della luce colorata. I miei LED non erano necessariamente nella gamma più sensibile, il che potrebbe spiegare la debole reazione al LED blu. Ma puoi vedere anche dal grafico della risposta spettrale qui sotto che l’APDS-9960 ha generalmente una sensibilità molto più bassa per la luce blu (B).

Reagire agli interrupt con APDS-9960
Come ultimo esempio, voglio mostrarti come usare il pin di interrupt dell’APDS-9960. Per questo dobbiamo collegare il pin INT dell’APDS-9960 a un pin di Arduino abilitato agli interrupt. Nel caso di Arduino Uno solo i pin 2 e 3 sono pin di interrupt. Per i pin di interrupt di altre schede microprocessore guarda qui (link).
Nel diagramma di collegamento qui sotto collego l’uscita INT dell’APDS-9960 al pin 3 di Arduino.

Il codice seguente genera un segnale di interrupt se un oggetto si avvicina al sensore e poi stampa il valore di prossimità.
#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();
}
}
Iniziamo il codice includendo la libreria, creando l’oggetto sensore e definendo il pin di interrupt. Nella funzione setup abilitiamo il rilevamento di prossimità, impostiamo le soglie di prossimità e abilitiamo l’interrupt di prossimità. Dobbiamo anche impostare il pin di interrupt intPin in modalità INPUT.
Nella funzione loop interroghiamo lo stato del intPin. Se il suo stato va basso significa che è stato generato un interrupt, quindi leggiamo il valore di prossimità e lo stampiamo.
I valori di prossimità vanno da 255 (più vicino) a 0 (più lontano). Poiché abbiamo impostato una soglia di prossimità a 100, il codice inizia a stampare i valori di prossimità se un oggetto si avvicina a meno di 100, che corrisponde a una distanza di circa 10mm.
Regolare la luminosità di un LED in base alla prossimità
Puoi usare questo codice per controllare la luminosità di un LED in base alla prossimità di un oggetto. Per questo aggiungiamo un LED al circuito. Collega il catodo (gamba corta) del LED a GND e l’anodo (gamba lunga) tramite una resistenza da 220Ω al pin 11. Qualsiasi altro pin PWM va bene.

Ora estendiamo un po’ il codice. Definiamo il ledPin e lo impostiamo in modalità OUTPUT nella funzione setup. Nella funzione loop leggiamo il valore di prossimità prox, e dato che è un valore tra 0 e 255, possiamo usarlo direttamente per controllare la luminosità del LED chiamando 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();
}
}
Il breve video qui sotto mostra come la luminosità del LED cambia in base alla distanza della mano dal sensore:

E questo è tutto per oggi! Spero ti sia divertito a sperimentare con il sensore APDS-9960.
Conclusioni
In questo tutorial hai imparato come usare il sensore di gesti e colore APDS-9960 con Arduino per rilevare gesti e misurare valori di colore e luminosità.
Rispetto al APDS-9930 sensore di prossimità, l’APDS-9960 può rilevare quattro gesti integrati (su, giù, sinistra, destra) e ha un sensore di colore RGB, mentre l’APDS-9930 ha solo un sensore di prossimità e di luce ambientale. Entrambi i sensori sono progettati specificamente per applicazioni su smartphone o tablet per attivare funzioni (come accendere altoparlanti, microfoni, display) e controllare la luminosità del display.
Se ti servono più gesti dai un’occhiata al PAJ7620U2, che può rilevare fino a 13 gesti, e al suo fratello minore PAJ7620 che può comunque rilevare 9 gesti.
La portata del sensore di prossimità negli APDS-9930 e APDS-9960 è volutamente molto limitata. Se vuoi misurare con precisione distanze maggiori, ad esempio per applicazioni di robotica, è meglio usare sensori di distanza a infrarossi come il GP2Y0A710K0F che usano la triangolazione per determinare la distanza da un oggetto. Oppure sensori di distanza laser Time-of-Flight (ToF) come il TOF10120 o la VL53L1X libreria.
Se hai domande sentiti libero di lasciarle nei commenti.
Buon divertimento con i tuoi esperimenti ; )

