The APDS9960 is a compact I2C sensor that combines proximity sensing, RGB/ambient light sensing, and built-in touchless gesture detection (left/right/up/down/near/far). It’s commonly used for non-contact, “intangible” interactions like wake-on-approach, simple hand-gesture controls, and light/color-aware behaviors.

I2C setup (APDS9960 + Nano 33 IoT)

What I2C is (principle)

Wiring (Nano 33 IoT → APDS9960 breakout)

3742e3d484a4b65ca25a0ba55dd5a9c3.jpg

I2C Scanning

Confirm the sensor is actually “visible” on the I2C bus.

#include <Wire.h>

void setup() {
  Wire.begin();
  Serial.begin(115200);
  while (!Serial) {}

  Serial.println("I2C scan...");
  byte count = 0;

  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.print("Found 0x");
      if (addr < 16) Serial.print("0");
      Serial.println(addr, HEX);
      count++;
      delay(5);
    }
  }

  Serial.print("Done. Devices found: ");
  Serial.println(count);
}

void loop() {}

image.png

Problem I met and how to fix it?

Q: The missing 0x39 was the APDS9960 I2C address.

A: At first it didn’t show up in the I2C scanner because the breakout wasn’t properly soldered, so SDA/SCL/VCC/GND weren’t actually connected electrically. After soldering, 0x39 appeared, meaning the hardware I2C connection was OK.

Q: Then the SparkFun library still failed init() because it does a strict ID-register check. A: We fixed it by editing the library code to bypass/relax that ID check (so it would proceed with normal I2C reads/writes).

It was like the sensor didn’t even show up on the “guest list” (no 0x39) because the pins weren’t soldered, and after it finally entered the venue, the library’s “ID check at the door” rejected it—so we bypassed that check in the code.

Demo 1 — Measuring “nearest” and “farthest” detection

Principle