How to Build a Gesture-Controlled Mood Lamp with ESP32

Wave to cycle colors, hold to dim, and save your favorite lighting scenes

ESP32Smart HomeBeginner45 minutes2 components

Updated

How to Build a Gesture-Controlled Mood Lamp with ESP32
For illustrative purposes only
On this page

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

Interactive wiring diagram

Components needed

ComponentTypeQtyBuy
APDS-9960 Gesture Sensorsensor1€4.35
WS2812B LED Stripactuator1

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

1

Wire sensors and LEDs

Connect APDS-9960 SDA/SCL to GPIO21/GPIO22, INT to GPIO27, and WS2812B DIN to GPIO4.

2

Upload and test gestures

Upload the sketch, then swipe left/right to change colors and up/down to adjust brightness.

Pin assignments

PinConnectionType
GPIO 21apds9960-1 SDAI2C
GPIO 22apds9960-1 SCLI2C
GPIO 27apds9960-1 INTDIGITAL
GPIO 4ws2812b-1 DINDATA

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.io
Libraries: SparkFun_APDS9960, FastLED