How to Build a Gesture-Controlled Mood Lamp with ESP32
Wave to cycle colors, hold to dim, and save your favorite lighting scenes
Updated

What you'll build
In this guide you will build a gesture-controlled mood lamp powered by an ESP32 microcontroller, an APDS-9960 proximity and gesture sensor, and a strip of individually addressable WS2812B LEDs. A simple wave of your hand cycles through color palettes, holding your hand near the sensor smoothly dims or brightens the output, and a double-swipe gesture saves the current color and brightness as a favorite scene you can recall later. The result is an ambient light that feels almost magical to interact with -- no buttons, no app, just natural hand movements.
The APDS-9960 is one of the most versatile low-cost sensors available to makers. It packs gesture detection, ambient light sensing, and proximity measurement into a single breakout board, making it perfect for beginner-friendly projects that still feel polished. You will learn how to initialize the sensor over I2C, interpret its gesture interrupts inside the ESP32's main loop, and translate those events into smooth LED animations using the FastLED library. Along the way you will pick up foundational skills in I2C communication, interrupt-driven programming, and non-blocking animation timing that transfer directly to more advanced ESP32 projects.
By the end of the build you will have a desk-ready lamp that responds to four distinct gestures, stores up to three favorite scenes in the ESP32's non-volatile flash memory, and recovers its last state after a power cycle. The project is an excellent starting point for anyone interested in smart-home hardware because it introduces addressable LED control, persistent storage with Preferences, and sensor fusion concepts you can later extend with Wi-Fi connectivity or voice assistant integration. If you enjoy working with addressable LEDs and the FastLED library, the Plant Disco Guardian is a great next build that adds soil moisture sensing into the mix.
Wiring diagram
Wiring diagram
Components needed
| Component | Type | Qty | Buy |
|---|---|---|---|
| APDS-9960 Gesture Sensor | sensor | 1 | €4.35 |
| WS2812B LED Strip | actuator | 1 |
Prices and availability are indicative and may have been updated by the supplier. Schematik may earn a commission from purchases made through affiliate links.
Assembly
Wire sensors and LEDs
Connect APDS-9960 SDA/SCL to GPIO21/GPIO22, INT to GPIO27, and WS2812B DIN to GPIO4.
- Use a common ground between LED strip and ESP32.
- Power the LED strip from a stable 5V source when using many LEDs.
Upload and test gestures
Upload the sketch, then swipe left/right to change colors and up/down to adjust brightness.
- Keep your hand 5-10 cm above the APDS-9960 for reliable gesture detection.
Pin assignments
| Pin | Connection | Type |
|---|---|---|
| GPIO 21 | apds9960-1 SDA | I2C |
| GPIO 22 | apds9960-1 SCL | I2C |
| GPIO 27 | apds9960-1 INT | DIGITAL |
| GPIO 4 | ws2812b-1 DIN | DATA |
Code
#include <Wire.h>
#include <SparkFun_APDS9960.h>
#include <FastLED.h>
#define APDS_INT_PIN 27
#define LED_PIN 4
#define NUM_LEDS 16
#define SDA_PIN 21
#define SCL_PIN 22
SparkFun_APDS9960 apds;
CRGB leds[NUM_LEDS];
uint8_t hue = 0;
uint8_t brightness = 140;
void setup() {
Wire.begin(SDA_PIN, SCL_PIN);
pinMode(APDS_INT_PIN, INPUT_PULLUP);
FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
FastLED.setBrightness(brightness);
apds.init();
apds.enableGestureSensor(true);
}
void loop() {
if (apds.isGestureAvailable()) {
int g = apds.readGesture();
if (g == DIR_LEFT || g == DIR_RIGHT) hue += 24;
if (g == DIR_UP && brightness < 245) brightness += 10;
if (g == DIR_DOWN && brightness > 25) brightness -= 10;
FastLED.setBrightness(brightness);
}
fill_rainbow(leds, NUM_LEDS, hue, 4);
FastLED.show();
delay(20);
}
// Run this and build other cool things at schematik.ioReady to build this?
Open this project in Schematik to get the full wiring diagram, pin assignments, and deployable code for the Gesture-Controlled Mood Lamp.
Open in Schematik →


