In diesem Tutorial lernst du, wie du den APDS-9960 Gesten- und RGB-Farbsensor mit einem Arduino oder anderen gängigen Mikrocontrollern wie dem ESP32 oder ESP8266 verwendest.
Der APDS-9960 ist ein sehr kleiner Sensor, der IR-Licht und Fotodioden nutzt, um vier verschiedene Gesten zu erkennen (von links nach rechts, von rechts nach links, von oben nach unten, von unten nach oben). Außerdem verfügt er über integrierte Sensoren für Umgebungslicht, Farbmessungen (Rot, Grün, Blau) und Annäherung.
Benötigte Teile
Für dieses Projekt benötigst du einen APDS-9960 Sensor und einen Mikrocontroller. Ich habe einen Arduino Uno verwendet, aber jeder andere Arduino oder auch ein ESP32/ESP8266 funktioniert ebenfalls, solange er eine 3,3V Stromversorgung bereitstellt. Eines der Beispiele nutzt zusätzlich einen Servo, dieser ist aber kein zwingend notwendiger Bestandteil für das Projekt.

APDS-9960 Sensor

Arduino Uno

USB-Kabel für Arduino UNO

Dupont-Kabelset

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.
Eigenschaften des APDS-9960 Gesten- und RGB-Farbsensors
Der APDS-9960 ist ein winziger Chip (3,94×2,36×1,35 mm), der fortschrittliche Gestenerkennung, Annäherungserkennung, digitale Umgebungslichtmessung (ALS) und Farberkennung (RGBC) bietet. Das Bild unten zeigt den APDS-9960 Chip:

Die Gestenerkennung erfolgt über vier gerichtete Fotodioden, die reflektiertes IR-Licht (ausgesendet von der integrierten LED) erfassen und in digitale Bewegungsinformationen (z.B. Geschwindigkeit, Richtung und Entfernung) umwandeln. Einfache Hoch-Runter-Rechts-Links-Gesten oder auch komplexere Gesten können erkannt werden.
Die Farb- und ALS-Erkennung des APDS-9960 liefert Intensitätsdaten für Rot, Grün, Blau und Klar. Jeder der R-, G-, B-, C-Kanäle verfügt über einen UV- und IR-Blockfilter sowie einen eigenen Datenwandler, der gleichzeitig 16-Bit-Daten erzeugt.
Funktionsblockdiagramm des APDS-9960
Das folgende Bild zeigt das Funktionsblockdiagramm des APDS-9960. Du kannst leicht die IR-Emitter-LED, die vier Fotodioden für die Farberkennung (Clear, Red, Green, Blue) und die vier Fotodioden für die Gestenerkennung (Up, Down, Left, Right) erkennen.

Der APDS-9960 kommuniziert über eine I2C-Schnittstelle (SCL, SDA) und verfügt über einen zusätzlichen Interrupt-Ausgang (INT), der aktiviert wird, wenn ein programmierbarer Schwellenwert überschritten wird (z.B. bei Annäherung).
Die Betriebsspannung des APDS-9960 liegt bei 2,4V-3,6V, der Messbereich für Gesten beträgt 10-20cm und die I2C-Adresse ist 0x39. Für weitere Details schau dir das unten verlinkte Datenblatt an:
Breakout-Board für APDS-9960
Der APDS-9960 Chip ist zu klein, um ihn direkt an einen Arduino anzuschließen. In der Regel benötigst du ein Breakout-Board wie unten gezeigt:

Die meisten Breakout-Boards für den APDS-9960 haben die folgenden sechs Pins:
- VCC : Stromversorgung (2,4 – 3,6V)
- GND : Masse
- VL : IR-LED-Stromversorgung
- SDA : I2C-Datensignal
- SCL : I2C-Taktsignal
- INT : Interrupt-Pin
In der Regel benötigst du nur die Stromversorgungspins (VCC, GND), die Pins für die I2C-Kommunikation (SCL, SDA) und den Interrupt-Pin (INT). VL ermöglicht es dir, die IR-LED extern zu versorgen, was normalerweise nicht nötig ist.
Beachte, dass der APDS-9960 mit 3,3V betrieben wird und die meisten Breakout-Boards üblicherweise keinen Spannungsregler haben.
APDS-9960 mit Arduino verbinden
Dank der I2C-Schnittstelle des APDS-9960 ist der Anschluss an einen Arduino einfach. Verbinde zuerst den SCL-Pin des APDS-9960 Breakout-Boards mit A5 des Arduino. Ebenso verbindest du SDA mit A4 des Arduino. Danach verbindest du GND mit GND und 3,3V mit VCC des APDS-9960.

Achte darauf, dass du 3,3V als Stromversorgung verwendest. Der APDS-9960 Sensor ist nicht für 5V ausgelegt und Breakout-Boards für den APDS-9960 haben normalerweise keinen Spannungsregler.
Bibliothek für APDS-9960 installieren
Es gibt zwei Hauptbibliotheken für den APDS-9960 für Arduino. Die Adafruit_APDS9960 Bibliothek und die SparkFun_APDS-9960_Sensor_Arduino_Library. Ich verwende in diesem Projekt die Adafruit_APDS9960 Bibliothek.
Um die Adafruit_APDS9960 Bibliothek zu installieren, öffne den LIBRARY MANAGER, suche nach „APDS9960“, finde die Bibliothek von Adafruit und installiere sie wie unten gezeigt:

Der Installer kann dich auffordern, Abhängigkeiten zu installieren. Das ist in Ordnung. Drücke einfach auf „INSTALL ALL“

Mit installierter Bibliothek können wir nun etwas Testcode schreiben, um den Sensor auszuprobieren. Lade den folgenden Code hoch und bewege deine Hand in etwa 5cm Abstand vor dem Sensor.
#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");
}
}
Wenn du die Meldung „Movement detected“ im Serial Monitor siehst, ist alles in Ordnung. Falls jedoch „failed to initialize device!“ erscheint, wird es etwas kniffliger und du solltest den nächsten Abschnitt lesen. Wenn alles funktioniert, kannst du ihn überspringen.
Adafruit_APDS9960: failed to initialize device!
Überprüfe zuerst, ob die Verdrahtung korrekt ist (SCL->A5, SDA->A4, VCC->3V3, GND->GND). Wenn die Verkabelung stimmt und der Sensor nicht defekt ist, gibt es zwei Hauptgründe, warum sensor.begin() fehlschlagen kann. Eine andere I2C-Adresse oder eine andere Chip-ID. Prüfen wir zuerst die I2C-Adresse.
Andere I2C-Adresse des APDS9960
Die übliche I2C-Adresse des APDS9960 ist 0x39 und die Adafruit_APDS9960 Bibliothek erwartet diese I2C-Adresse. Um das zu überprüfen, installiere und starte folgenden I2C scanner Code:
#include "I2CScanner.h"
I2CScanner scanner;
void setup() {
Serial.begin(9600);
scanner.Init();
}
void loop() {
scanner.Scan();
delay(5000);
}
Der I2C-Scanner sollte ein I2C-Gerät mit der Adresse 0x39 finden und dies im Serial Monitor ausgeben.
I2C device found at address 0x39 ! --- Scan finished ---
Wenn du eine andere I2C-Adresse siehst, musst du den Code in der setup-Funktion wie folgt ändern und „addr“ durch die von dir gefundene I2C-Adresse ersetzen.
void setup() {
...
if (!sensor.begin(10, APDS9960_AGAIN_4X, addr, &Wire)) {
Serial.println("failed to initialize device!");
}
...
}
Wenn deine I2C-Adresse 0x39 ist oder du die I2C-Adresse wie oben beschrieben geändert hast, aber sensor.begin() immer noch fehlschlägt, ist der nächste Kandidat eine andere Chip-ID. Wenn der I2C-Scanner kein Gerät findet, ist dein Sensor höchstwahrscheinlich defekt (oder die Verkabelung ist immer noch falsch).
Andere Chip-ID des APDS9960
Wenn du in den Code der begin() Funktion in der Adafruit_APDS9960 Bibliothek schaust, siehst du, dass der Code zuerst die I2C-Adresse addr verwendet. Dann prüft er die Chip-ID und erwartet 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;
}
Ich habe jedoch einen APDS9960 mit der Chip-ID 0xA8 (nicht 0xAB) und die SparkFun_APDS-9960_Sensor_Arduino_Library listet eine weitere Chip-ID auf, nämlich 0x9C.
Da die Chip-ID fest im Code steht, müssen wir den Code anpassen. Am einfachsten ist es, zwei Dateien Adafruit_APDS9960.h und Adafruit_APDS9960.cpp in deinen Projektordner neben dein Sketch, z.B. MySketch.ino, zu kopieren:

Du siehst dann diese beiden neuen Dateien als Tabs in deiner Arduino IDE:

Öffne nun den Tab mit der Adafruit_APDS9960.cpp Datei, finde die begin Funktion und entferne oder kommentiere einfach den Block, der mit /* Make sure we're actually connected * / markiert ist, wie unten gezeigt:
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;
// }
Alternativ kannst du auch „x“ ausgeben lassen, um die ID deines Chips herauszufinden und den Test if (x != 0xAB) entsprechend anpassen.
Wenn du den Code nicht selbst ändern möchtest, habe ich eine angepasste Version der beiden Dateien erstellt, die du hier herunterladen kannst (link). Du musst die Dateien aber trotzdem entpacken und in dein Projekt kopieren. Mit diesem Fix sollte der obige Testcode jetzt laufen.
Gesten mit dem APDS-9960 erkennen
Der folgende Code ist eine kleine Erweiterung des obigen Testcodes. Wie zuvor initialisieren wir im setup die Sensoren mit sensor.begin() und aktivieren dann die Annäherungs- und Gestenerkennung:
#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");
}
In der loop-Funktion rufen wir sensor.readGesture() auf und geben je nach Rückgabewert die erkannte Geste im Serial Monitor aus.
Bewege jetzt deine Hand in etwa 5-10 cm Abstand über den Sensor. Je nach Richtung solltest du die erkannte Geste im Serial Monitor angezeigt bekommen, wie unten gezeigt:

Anstatt die Ausgabe im Serial Monitor anzuzeigen, kannst du den Code jetzt so anpassen, dass je nach Geste LEDs geschaltet, Servos gesteuert oder andere Aktionen ausgelöst werden. Die folgenden Abschnitte zeigen ein einfaches Beispiel, wie man einen Servo mit Gesten steuert.
Servo mit APDS-9960 Gestensensor steuern
Zuerst müssen wir den Servo mit dem Arduino verbinden. Wenn du einen dieser kleinen SG90 Micro Servos hast, kannst du ihn direkt an den Arduino anschließen (keine separate Stromversorgung nötig). Verbinde einfach das rote Kabel (mittlerer Pin) des Servos mit 5V, das braune Kabel mit Masse (GND) und das orange/gelbe Kabel mit Pin 13, wie unten gezeigt.

Wenn du mehr Infos zum Anschluss und zur Verwendung dieser Servos brauchst, schau dir das How to control servo motors with Arduino Tutorial an.
Der Code zur Steuerung des Servos per Geste ist eine einfache Abwandlung des vorherigen Codes zur Gestenerkennung.
#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);
}
Zuerst binden wir die Standard- Servo Bibliothek ein (keine Installation nötig). Dann erstellen wir das servo Objekt und definieren den Pin, an dem der Servo angeschlossen ist (servoPin).
In der setup Funktion verbinden wir den Servo mit dem Servo-Pin und stellen ihn initial auf 90°. In der loop-Funktion ersetzen wir die print Funktionsaufrufe durch write Befehle an den Servo. Bei einer Hoch- oder Runter-Geste bewegt sich der Servo auf 90°, eine Links-Geste auf 10° und eine Rechts-Geste auf 170°. Das kurze Video unten zeigt den Code in Aktion:

Damit hast du jetzt eine einfache Gestensteuerung für einen kleinen Servo, mit der du zum Beispiel eine Box berührungslos öffnen oder schließen kannst. Im nächsten Codebeispiel probieren wir den Farbsensor des APDS-9960 aus.
Farben messen mit dem APDS-9960
Der folgende Code nutzt den Farbsensor im APDS-9960, um die Farbwerte für Rot, Grün, Blau und Klar zu messen und im Serial Monitor auszugeben.
Wir beginnen damit, die Adafruit-Bibliothek einzubinden und das Sensorobjekt zu erstellen. In der setup-Funktion initialisieren wir den Sensor wie gewohnt mit sensor.begin() und aktivieren dann mit sensor.enableColor(true) den Farbsensor.
#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);
}
In der loop-Funktion rufen wir sensor.colorDataReady() auf, um die Farbwerte für Rot (r), Grün (g), Blau (b) und Klar (c) zu erhalten, und geben sie dann im Serial Monitor aus.
Die Adafruit_APDS9960 Bibliothek bietet zwei zusätzliche Funktionen, mit denen du die Farbtemperatur und die Helligkeit in Lux basierend auf den gemessenen Farbwerten berechnen kannst. Diese Werte geben wir ebenfalls im Serial Monitor aus.
Wenn du die Helligkeit des Umgebungslichts änderst oder LEDs mit verschiedenen Farben vor den Sensor hältst, wirst du sehen, dass sich die Farbwerte ändern.
Farberkennung des APDS-9960 testen
Um die Farberkennung des APDS-9960 zu testen, habe ich rote, grüne und blaue LEDs verwendet. Die unten stehenden Werte habe ich gemessen, als ich eine rote LED nah an den Sensor gehalten habe:
red:329 green:26 blue:47 clear:342 tmp:24902 lux:65436
Wie erwartet ist der Rotwert deutlich höher als die Grün- und Blauwerte. Beachte auch, dass die Werte für Farbtemperatur und Lux-Helligkeit extrem hoch sind. Offenbar verwirrt das rote LED-Licht diese Messungen.
Als nächstes habe ich eine grüne LED verwendet. Die grüne LED war vergleichsweise schwach und der Grünwert stieg nur wenig an. Auch der Rotwert ging nach oben. Am Lux-Wert sieht man, dass die Helligkeit meiner grünen LED gering war.
red:15 green:16 blue:6 clear:42 tmp:3045 lux:15
Zum Schluss habe ich eine blaue LED ausprobiert und die unten stehenden Farbwerte erhalten. Der Blauwert war sehr hoch, aber auch der Grünanteil stieg an.
red:40 green:561 blue:2507 clear:2751 tmp:1754 lux:64574
Die Reaktion des Farbsensors hängt offensichtlich von der Helligkeit und der Wellenlänge des farbigen Lichts ab. Meine LEDs lagen vermutlich nicht im optimalen Bereich, was die schwache Reaktion auf die blaue LED erklären könnte. Aber auch im Spektral-Response-Diagramm unten sieht man, dass der APDS-9960 generell eine deutlich geringere Empfindlichkeit für blaues Licht (B) hat.

Auf Interrupts mit dem APDS-9960 reagieren
Als letztes Beispiel möchte ich dir zeigen, wie du den Interrupt-Pin des APDS-9960 verwendest. Dafür müssen wir den INT-Ausgang des APDS-9960 mit einem Interrupt-fähigen Pin des Arduino verbinden. Beim Arduino Uno sind das nur die Pins 2 und 3. Für Interrupt-Pins anderer Mikrocontroller-Boards siehe hier (link).
Im Schaltplan unten verbinde ich den INT-Ausgang des APDS-9960 mit Pin 3 des Arduino.

Der folgende Code löst ein Interrupt-Signal aus, wenn sich ein Objekt dem Sensor nähert, und gibt dann den Annäherungswert aus.
#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();
}
}
Wir starten den Code, indem wir die Bibliothek einbinden, das Sensorobjekt erstellen und den Interrupt-Pin definieren. In der setup Funktion aktivieren wir die Annäherungserkennung, setzen die Schwellenwerte und aktivieren den Annäherungs-Interrupt. Außerdem müssen wir den Interrupt-Pin intPin auf INPUT-Modus setzen.
In der loop Funktion fragen wir den Zustand des intPin ab. Wenn der Zustand auf LOW geht, wurde ein Interrupt ausgelöst und wir lesen den Annäherungswert aus und geben ihn aus.
Die Annäherungswerte reichen von 255 (nächste Entfernung) bis 0 (weiteste Entfernung). Da wir einen Schwellenwert von 100 gesetzt haben, beginnt der Code mit der Ausgabe der Annäherungswerte, wenn sich ein Objekt näher als 100 befindet, was etwa 10mm entspricht.
LED proportional zur Annäherung dimmen
Du kannst diesen Code nutzen, um die Helligkeit einer LED abhängig von der Annäherung eines Objekts zu steuern. Dafür fügen wir eine LED zu unserer Schaltung hinzu. Verbinde die Kathode (kurzes Bein) der LED mit GND und die Anode (langes Bein) über einen 220Ω Widerstand mit Pin 11. Jeder andere PWM-Pin funktioniert ebenfalls.

Als nächstes erweitern wir den Code etwas. Wir definieren die ledPin und setzen sie im OUTPUT Modus in der setup Funktion. In der loop Funktion lesen wir den Annäherungswert prox aus, und da dieser zwischen 0 und 255 liegt, können wir ihn direkt nutzen, um die Helligkeit der LED mit analogWrite(ledPin, prox) zu steuern:
#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();
}
}
Das kurze Video unten zeigt, wie sich die Helligkeit der LED je nach Abstand der Hand zum Sensor verändert:

Und das war’s für heute! Ich hoffe, du hattest Spaß beim Ausprobieren des APDS-9960 Sensors.
Fazit
In diesem Tutorial hast du gelernt, wie du den APDS-9960 Gesten- und Farbsensor mit einem Arduino verwendest, um Gesten zu erkennen und Farb- sowie Helligkeitswerte zu messen.
Im Vergleich zum APDS-9930 Annäherungssensor kann der APDS-9960 vier eingebaute Gesten erkennen (hoch, runter, links, rechts) und verfügt über einen RGB-Farbsensor, während der APDS-9930 nur einen Annäherungs- und Umgebungslichtsensor hat. Beide Sensoren sind speziell für den Einsatz in Mobiltelefonen oder Tablets entwickelt, um Funktionen zu aktivieren (wie Lautsprecher, Mikrofone, Displays einschalten) und die Displayhelligkeit zu steuern.
Wenn du mehr Gesten brauchst, schau dir den PAJ7620U2 an, der bis zu 13 Gesten erkennen kann. Sein kleiner Bruder, der PAJ7620, erkennt immerhin noch 9 Gesten.
Die Reichweite des Annäherungssensors im APDS-9930 und APDS-9960 ist absichtlich sehr begrenzt. Wenn du größere Entfernungen zu Objekten genau messen möchtest, z.B. für Robotik-Anwendungen, bist du mit Infrarot-Abstandssensoren wie dem GP2Y0A710K0F besser beraten, die per Triangulation die Entfernung bestimmen. Oder Time-of-Flight (ToF) Laser-Entfernungssensoren wie dem TOF10120 oder der VL53L1X Bibliothek.
Wenn du Fragen hast, schreib sie gerne in die Kommentare.
Viel Spaß beim Tüfteln ; )

