Projects / Proximity

Touchless Doorbell with Light Ring

Wave at it — no button to touch. A chime and a glowing ring welcome your visitor.

Beginner⏱ 1 hour4 ElectroTrical boards

Overview

The ET-S65 VCNL4040 sends out invisible infrared light and measures how much bounces back, detecting a hand up to about 20 cm away. Wave in front of it and the ET-M04 plays a two-tone chime on the ET-A16 buzzer and runs an animation on the ET-D07 12-LED ring.

No mechanical button means nothing to wear out and nothing to touch. The same sensor reads ambient light, so the ring glows softly at night as a house-number light.

  • Hand-wave detection up to ~20 cm
  • Two-tone chime
  • 12-LED colour animation
  • Night-light mode using the built-in light sensor

What you need

ElectroTrical boards

ET-M04RP2040 Dev BoardController
Coming soon
ET-S65VCNL4040 Proximity + Light SensorDetects a hand and measures ambient light
Coming soon
ET-A16Passive Buzzer BoardChime
Coming soon
ET-D0712-LED RGB RingLight animation
Coming soon

You'll also need

  • 1 Qwiic cable
  • Jumper wires
  • USB-C 5 V supply
  • Enclosure with a clear window for the sensor (thin glass or acrylic)

Wiring

Sensor

FromToNote
ET-M04 QwiicET-S65 QwiicVCNL4040 at 0x60

ET-A16 buzzer → ET-M04

FromToNote
VBUSVIN
GNDGND
GPIO6SIG

ET-D07 ring → ET-M04

FromToNote
VBUS5V
GNDGND
GPIO7DINThe ring's input buffer accepts 3.3 V logic

Build it

  1. 01

    Set up the Arduino IDE

    In Preferences, add the Arduino-Pico board URL (https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json), install “Raspberry Pi Pico/RP2040” in Boards Manager and select “Generic RP2040”. Install the libraries listed above the sketch.

  2. 02

    First upload

    If the IDE can't find the board, hold the BOOT button while plugging in USB; it appears as a drive and the upload goes through. After that, uploads work normally.

  3. 03

    Wire and test

    Wire as in the tables. Open Serial Monitor and move your hand in front of the sensor: the proximity number rises as you get closer.

  4. 04

    Set the threshold

    Note the value with no hand and with a hand at 10 cm, and set TRIGGER halfway between. Behind a window, the baseline is higher.

  5. 05

    Mount it

    Behind glass or acrylic, press the sensor flat against the window, or add a small foam ring so infrared doesn't reflect inside the window straight back into the sensor.

Arduino code

Written for the ET-M04 RP2040 Dev Board. Install these libraries from the Arduino Library Manager:

  • Adafruit VCNL4040
  • Adafruit NeoPixel
touchless_doorbell.ino
#include <Wire.h>
#include <Adafruit_VCNL4040.h>
#include <Adafruit_NeoPixel.h>

const int BUZZER = 6, RING_PIN = 7, LEDS = 12;
const int TRIGGER = 60;                  // proximity counts above baseline
const unsigned long COOLDOWN_MS = 4000;
const float DARK_LUX = 15;

Adafruit_VCNL4040 vcnl;
Adafruit_NeoPixel ring(LEDS, RING_PIN, NEO_GRB + NEO_KHZ800);
int baseline = 0;
unsigned long lastRing = 0;

void chime() {
  tone(BUZZER, 1319, 300); delay(320);   // E6
  tone(BUZZER, 1047, 500);               // C6
  for (int r = 0; r < 3; r++)            // colour wipe x3
    for (int i = 0; i < LEDS; i++) {
      ring.clear();
      for (int k = 0; k < 4; k++) ring.setPixelColor((i + k) % LEDS, ring.Color(0, 80, 255));
      ring.show(); delay(40);
    }
}

void setup() {
  Serial.begin(115200);
  Wire.begin();                          // Qwiic on GP4 / GP5
  ring.begin(); ring.setBrightness(80); ring.clear(); ring.show();
  if (!vcnl.begin()) { Serial.println("VCNL4040 not found (0x60)"); while (1) delay(100); }
  vcnl.setProximityLEDCurrent(VCNL4040_LED_CURRENT_200MA);
  vcnl.setProximityIntegrationTime(VCNL4040_PROXIMITY_INTEGRATION_TIME_8T);

  long sum = 0;                          // learn the no-hand baseline
  for (int i = 0; i < 20; i++) { sum += vcnl.getProximity(); delay(25); }
  baseline = sum / 20;
}

void loop() {
  int prox = vcnl.getProximity();
  float lux = vcnl.getLux();

  if (prox - baseline > TRIGGER && millis() - lastRing > COOLDOWN_MS) {
    Serial.println("Ding dong!");
    chime();
    lastRing = millis();
  }

  // night light: soft warm glow when dark
  uint32_t idle = lux < DARK_LUX ? ring.Color(40, 20, 4) : 0;
  ring.fill(idle); ring.show();

  Serial.printf("prox %d (base %d)  lux %.1f\n", prox, baseline, lux);
  delay(50);
}

Troubleshooting

Rings by itself

Light reflects inside the window back into the sensor. Press the sensor against the glass or add a foam gasket, then raise TRIGGER.

Doesn't trigger in sunlight

Strong sunlight adds infrared. Shade the window, or mount the doorbell under a cover.

Ring shows wrong colours

Check the 5V wire and that the strip type is NEO_GRB; a weak supply makes LEDs flicker or turn red.

Take it further

  • Send a phone notification with an ESP32 board such as the ET-M01
  • Add the ET-S56 light sensor to adjust ring brightness
  • Count visitors per day in the ET-A14 FRAM

Turning this into a product?

We design custom boards that combine these sensors on one PCB, with firmware and production.