Projects / Proximity
Touchless Doorbell with Light Ring
Wave at it — no button to touch. A chime and a glowing ring welcome your visitor.
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
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
| From | To | Note |
|---|---|---|
| ET-M04 Qwiic | ET-S65 Qwiic | VCNL4040 at 0x60 |
ET-A16 buzzer → ET-M04
| From | To | Note |
|---|---|---|
| VBUS | VIN | |
| GND | GND | |
| GPIO6 | SIG |
ET-D07 ring → ET-M04
| From | To | Note |
|---|---|---|
| VBUS | 5V | |
| GND | GND | |
| GPIO7 | DIN | The ring's input buffer accepts 3.3 V logic |
Build it
- 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.
- 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.
- 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.
- 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.
- 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
#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.