Automating Coffee Bar Lighting with a C4002 Presence Detector
Description of the project
This project describes an upgrade of an existing PIR (Passive Infrared) motion detection system to a presence detection system using the DFRobot C4002 mmWave Human Presence Sensor. The existing system activates under cabinet 24 VDC LED strip lights that illuminate a coffee bar countertop when someone approaches the coffee bar.
Although the existing system works, it suffers from a common problem associated with PIR detector activated lighting. If the sensor does not detect sufficient motion after a set delay time, it deactivates the lights. This happens often when there is a lack of large scale motion at the coffee bar. For example, when someone is preparing coffee beans in the grinder, they may be motionless, or nearly motionless, for a minute or more. When the lights go out, the most common response is to wave ones hand under the sensor to reactivate the lights.
My motivations for this project
In addition to finding a better way to automate the coffee bar under cabinet lighting, I had a few more motivations that led me to undertake this design and build project. I retired a few years ago after a 40 year career working as an electronics engineering technologist and polytechnic instructor. Retirement did not mean abandoning my interest in electronics technology by any means. I intend to continue learning, making, and tinkering for as long as I can.
Electronics technology advances and changes rapidly. Reading about new developments is one way to stay current, but for me, actually applying technology to a project provides much deeper understanding, and usually, a lot of fun. I saw an opportunity with the DFRobot C4002 to dive into three branches of rapidly developing technology that hold interest for me.
First, Internet of Things (IoT) devices as they apply to home automation.
Second, Artificial Intelligence (AI), as an assistant in code development, design refinement, and troubleshooting.
Third, 3D printing, as a tool to fabricate functional parts for enclosures.
This one project would allow me to explore and learn more about all three branches. The question lingering in my mind as I began this journey was: Can a fellow in this late 60's keep up with all this stuff and make a working IoT project? Short answer: Yes he can!
Quick Summary of Project Outcomes
Years of experience have taught me that reality can force revision of even well developed plans. This project was no different. A few key highlights:
Biggest Success: Everything works! The coffee bar cabinet lights activate when someone approaches the counter. They stay on as long as someone is standing at the counter. The lights turn off when there is no one standing at the counter.
Biggest challenge: Sorting out numerous home network issues that caused the FireBeetle 2 to disappear randomly. These issues had nothing to do with any of the technology used in this project. These issues are now resolved.
Second Biggest Challenge: Figuring out how to best position and tweak the C4002 sensor. For its size and cost the C4002 packs a lot of capability. Working with reflected 24 GHz radar signals in an enviroment that includes metallic backsplash and a granite countertop coupled with a sensor that can detect very small movements (breathing, for example) caused a lot of headaches. Many of my mounting ideas resulted in heaps of false triggers.
Biggest surprise: The C4002 can actually detect motion through a standard residential interior wall. Verified during my bench tests. Cool…and kind of creepy.
Biggest disappointment: AI does actually make mistakes. Sometimes pretty significant mistakes. I found AI to be very useful for the most part, but I had to stay vigilant and judge responses through the lens of 40 years of experience in this field. I found there was a tendency for my AI-bot to blindly jump down rabbit holes.
Biggest delay to progress: I spent a good amount of time struggling to understand why my bench tested breadboard design, which worked correctly, failed to work when the parts were assembed into the 3D enclosures and wired together. After checking EVERYTHING, I stepped back and checked my assumptions. One assumption I made was that the manufacturer specifications for all of the parts were actually correct. This turned out to be not true for the sensor cable running between the C4002 sensor and the FireBeetle 2. The documented pinout for the cable was wrong. Once I rewired with the correct pinout, the system came back to life.
Minor annoyance: nearly every “how to” video I viewed on You Tube about configuring Home Assistant, installing a VM on a Windows desktop, or using ESPBuilder was several versions out of date. I eventually got it all straight.
Greatest benefit: I now know more about the DFRobot product line, Home Assistant and ESP Builder and how relatively easy it is to integrate IoT devices into a home environment. I want to do so much more.
Overview of my development process
I have developed many prototype projects for classroom teaching, for industrial clients, and for home brew projects. Here is a point list of the steps I went through to turn this idea into a prototype. Keep in mind that there tends to be a lot of looping back to previous steps based on findings and the occasional late night jolt of inspiration.
| 1 | Conceptualize the design |
| 2 | Source parts |
| 3 | Breadboard for bench test |
| 4 | Code Development |
| 4 | Design/Fabricate Enclosures |
| 5 | System integration and test |
Conceptualize the design
I begin by thinking about the problem at hand and researching available technologies that can be applied to solve the problem. For this problem (keep the lights on at the coffee bar when someone is standing still), the DFRobot C4002 presence sensor paired with a FireBeetle 2 ESP32-C6 IoT Development Board seemed like a great combination.
The C4002 is a mmWave presence sensor that can sense very small movements over a range appropriate for my coffee bar application. It is small, low power, and reasonably priced. The FireBeetle 2 ESP32-C6 is also small, low power, and reasonably priced. My research included reading the DFRobot Wiki pages for both devices. I was also interested in learning about available Integrated Development Environments (IDE) for these platforms. This journey introduced me to the world of Home Assistant, ESPBuilder, and YAML coding.
Because I wasn't sure where the C4002 should be mounted for best performance I decided to house the sensor and controller in separate enclosures and connect them together via a 2m long 4 conductor sensor cable.
There are two strips of 24 VDC COB LED lights mounted under the cupboards above the coffee bar. I have installed a 24 VDC LED driver power supply and have routed a fused supply line to the top of the cupboards. This is where I installed the FireBeetle 2 ESP32-C6. The FireBeetle is a low voltage microcontroller that can not directly drive 24 VDC LED strips that draw about 2.3 A at full brightness. For this reason I incorporated a simple MOSFET switch board that can be activated with a 5 VDC control signal from the FireBeetle.
Source the parts
For those interested, a Bill of Materials (BOM) for this project is provided below with links to the retailers where I obtained the parts. Ancillary materials and and equipment were used to complete this project including a Bambu Lab X1 Carbon printer, Shapr3D design software, a solder rework station, and several pieces of electronic test equipment.
Breadboard for Bench Test

The first parts to arrive were the DFRobot C4002 and the FireBeetle 2 ESP32-C6. There is also an ESP32-S3 AI Camera that will be featured in my next project post. I brought the package of parts to my test bench and got to work on breadboarding a proof of concept design.
The initial breadboard design incorporated the 24 VDC to 5 VDC step down regulator, the MOSFET driver, the C4002, and the FireBeetle 2, and a short test strip of COB LED lights. A bench supply provided the raw 24 VDC to run the system.

A block diagram of the hardware components is provided below.

Code Development
Hardware doesn't do much useful without firmware. I have written a lot of firmware over the span of my career. However, because I am retired, and because effective AI coding tools are available, I now focus on getting my projects up and running without having to learn Yet Another Markup Language (YAML). Many of my friends that are still in the tech world have told me stories about the wonders of AI coding tools. When I tried AI coding tools I too was stunned at how helpful they were…generally…most of the time.
To get this project up and running on the bench I relied heavily on set up steps and example code provided in a series of DFRobot project blogs by auroraAA and Jaychouu on the C4002 pages of the DFRobot website. Thier posts were very helpful in setting up ESPHome within Home Assistant.
Even though their posts are from the spring of 2026 many of the detailed software related steps have been impacted by recent ESPHome updates. This is the nature of rapidly evolving software.
First step though was to load a Virtual Machine version of Home Assistant on my Windows PC. I used Oracle's Virtual Box Manager to do this. To set up a VM, the SVM switch in my PC's BIOS had to be enabled. Once that was done, everything installed nicely.
All of the new YAML code developed for this project was generated through interactions with Google Gemini. With sufficient interaction and several rounds of testing, the YAML code provided by Gemini appears to be functioning as expected. I do not guarantee it to be error free or structured to any established coding standard. The code below contains sections that support testing and troubleshooting in addition to the core functions.
# Board: DFRobot FireBeetle 2 ESP32-C6
# Definition: definitions/boards/dfrobot_firebeetle2_esp32c6/manifest.yaml
esphome:
name: coffee-bar-presence-detector
friendly_name: Coffee Bar Presence Detector
esp32:
variant: esp32c6
logger:
api:
encryption:
key: "xxxxxxxxxxxxxxxxxxxxxxxxx"
#Prevent the FireBeetle from rebooting if Home Assistant is offline
reboot_timeout: 0s #Disables API-loss reboots.
ota:
- platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: Coffee Bar Pres Fallback Hotspot
password: "xxxxxxxx"
use_address: 192.168.x.xx
power_save_mode: NONE #Disable WiFi radio sleep mode for max ping stability.
reboot_timeout: 15min #Reboot the ESP32 if WiFi stack locks up.
captive_portal:
web_server:
port: 80
version: 2
# UART Configuration
uart:
id: uart_bus
tx_pin: GPIO5
rx_pin: GPIO4
baud_rate: 115200
# External components
external_components:
- source:
type: git
url: https://github.com/cdjq/esphome.git
ref: dev
components:
- dfrobot_c4002
refresh: 0s
# C4002 Component Configuration
dfrobot_c4002:
id: my_c4002
uart_id: uart_bus # Specify UART bus explicitly
# Sensor Configuration Section
sensor:
# C4002 Sensors
- platform: dfrobot_c4002
c4002_id: my_c4002
movement_distance:
name: "Motion Distance"
id: movement_distance_sensor
unit_of_measurement: "m"
accuracy_decimals: 2
icon: "mdi:ruler"
device_class: "distance"
state_class: "measurement"
existing_distance:
name: "Presence Distance"
id: existing_distance_sensor
unit_of_measurement: "m"
accuracy_decimals: 2
icon: "mdi:account"
device_class: "distance"
state_class: "measurement"
movement_speed:
name: "Motion Speed"
id: movement_speed_sensor
unit_of_measurement: "m/s"
accuracy_decimals: 2
icon: "mdi:speedometer"
device_class: "speed"
state_class: "measurement"
movement_direction:
name: "Motion Direction"
id: movement_direction_sensor
icon: "mdi:compass"
internal: true # Comment out temporarily for data testing
target_status:
name: "Target Status"
id: target_status_sensor
icon: "mdi:target"
# internal: true # Comment out temporarily for data testing
on_value:
then:
- if:
condition:
lambda: 'return x > 0;'
then:
# Instant fade-up to full brightness upon human detection
- light.turn_on:
id: cob_led_strip
brightness: 100%
transition_length: 0.2s
else:
# Wait 10 seconds before acting
- delay: 10s
# Double-check that the room is still empty
- if:
condition:
lambda: 'return id(target_status_sensor).state == 0;'
then:
# Elegant, slow fade to black over 4 seconds
- light.turn_off:
id: cob_led_strip
transition_length: 4.0s
# WiFi Signal Sensor
- platform: wifi_signal
name: "WiFi Signal Strength"
update_interval: 30s
unit_of_measurement: "dBm"
accuracy_decimals: 0
device_class: "signal_strength"
entity_category: "diagnostic"
text_sensor:
- platform: template
name: "Movement Direction Text"
id: movement_direction_text
icon: "mdi:directions"
lambda: |-
if (id(movement_direction_sensor).has_state()) {
int d = id(movement_direction_sensor).state;
if (d == 0) return {"Away"};
else if (d == 1) return {"No Direction"};
else if (d == 2) return {"Approaching"};
else return {"Unknown"};
}
return {"No Data"};
update_interval: 1s
- platform: template
name: "Target Status Text"
id: target_status_text
icon: "mdi:human-greeting"
lambda: |-
if (id(target_status_sensor).has_state()) {
int d = id(target_status_sensor).state;
if (d == 0) return {"No Target"};
else if (d == 1) return {"Static Presence"};
else if (d == 2) return {"Motion"};
else return {"Unknown"};
}
return {"No Data"};
update_interval: 1s
- platform: dfrobot_c4002
c4002_id: my_c4002
c4002_text_sensor:
name: "C4002 Log"
icon: "mdi:message-text-outline"
# Switch Configuration Section
switch:
- platform: dfrobot_c4002
c4002_id: my_c4002
switch_out_led:
name: "Out LED Switch"
icon: "mdi:led-on"
switch_run_led:
name: "Run LED Switch"
icon: "mdi:led-on"
switch_factory_reset:
name: "Factory Reset"
icon: "mdi:restart"
entity_category: "config"
switch_environmental_calibration:
name: "Sensor Calibration"
icon: "mdi:calibration"
entity_category: "config"
- platform: template
name: "COB Relay Switch"
id: manual_cob_switch
icon: "mdi:lightbulb-switch"
# This line mirrors the actual light state on your dashboard icon
lambda: 'return id(cob_led_strip).remote_values.is_on();'
turn_on_action:
- light.turn_on:
id: cob_led_strip
brightness: 100%
transition_length: 0.2s
turn_off_action:
- light.turn_off:
id: cob_led_strip
transition_length: 4.0s
- platform: dfrobot_c4002
c4002_id: my_c4002
switch_factory_reset:
name: "C4002 Factory Reset"
icon: "mdi:restart"
switch_environmental_calibration:
name: "C4002 Sensor Calibration"
icon: "mdi:calibration"
# Select Configuration Section - Fixed operating_mode
select:
- platform: dfrobot_c4002
c4002_id: my_c4002
operating_mode:
name: "OUT Mode"
icon: "mdi:account"
entity_category: "config"
options:
- "Mode_1"
- "Mode_2"
- "Mode_3"
# Number Configuration Section
number:
- platform: dfrobot_c4002
c4002_id: my_c4002
max_range:
name: "Max Detection Distance"
unit_of_measurement: "m"
icon: "mdi:ruler"
entity_category: "config"
min_range:
name: "Min Detection Distance"
unit_of_measurement: "m"
icon: "mdi:ruler"
entity_category: "config"
light_threshold:
name: "Light Threshold"
unit_of_measurement: "lx"
icon: "mdi:lightbulb"
entity_category: "config"
area1_min:
name: "Area 1 Min"
unit_of_measurement: "m"
icon: "mdi:ruler"
entity_category: "config"
area1_max:
name: "Area 1 Max"
unit_of_measurement: "m"
icon: "mdi:ruler"
entity_category: "config"
area2_min:
name: "Area 2 Min"
unit_of_measurement: "m"
icon: "mdi:ruler"
entity_category: "config"
area2_max:
name: "Area 2 Max"
unit_of_measurement: "m"
icon: "mdi:ruler"
entity_category: "config"
area3_min:
name: "Area 3 Min"
unit_of_measurement: "m"
icon: "mdi:ruler"
entity_category: "config"
area3_max:
name: "Area 3 Max"
unit_of_measurement: "m"
icon: "mdi:ruler"
entity_category: "config"
target_disappeard_delay_time:
name: "Target Disappear Delay"
unit_of_measurement: "s"
icon: "mdi:timer"
entity_category: "config"
# 3. Define the hardware PWM pin at our clean, silent 4kHz frequency
output:
- platform: ledc
pin: GPIO8
id: led_pwm_output
frequency: 4000Hz
# 4. Create the dimmable Light component (hidden from HA dashboard UI)
light:
- platform: monochromatic
id: cob_led_strip
output: led_pwm_output
internal: true # Keeps the raw light entity hidden so it doesn't clutter your HA Design/Fabricate Enclosures
As mentioned, this project allowed me to produce functional 3D prints using my new (well used, but new to me) 3D printer. Designs of the enclosures went through a few iterations and rethinks. For the proof of concept prototype, I ended up designing and printing three parts.
| 1 | Transparent PETG window |
| 2 | C4002 and window enclosure |
| 3 | FireBeetle 2 and MOSFET switch enclosure |
Transparent PETG window
To protect the C4002 from spills and splashes that might occur at an active coffee bar, I wanted to put some sort of window in front of it. My AI inquiries suggested a 1 mm thick window made of transparent PETG would not significantly attenuate the 24 GHz signal. AI suggested the window be placed 5 mm in front of the sensor. I followed this recommendation. The window was mounted above the C4002 with 5 mm M2 standoffs as shown in the photographs below.


Testing confirmed that a 1 mm thick transparent PETG window does not seem to adversely affect the 24 GHz signals departing from or arriving at the C4002 sensor.
C4002 and window enclosure
Discussions with Gemini suggested it would be a bad idea to mount the C4002 under the cabinets pointing straight down at the granite countertop. Granite apparently is pretty much a mirror for 24 GHz signals and the strong reflections could be problematic. Instead, I designed an enclosure with a 45 degree front edge with a slot to hold the PETG window and C4002 sensor. The enclosure was also fitted with a hole to accommodate a 4 pin M8 sensor connector. Photographs of the sensor enclosure are below.



FireBeetle 2 and MOSFET switch enclosure
The final enclosure design needed to hold the FireBeetle 2, the MOSFET switch board, and connectors for power supplies and the sensor cable going to the C4002. I set up mounting holes for brass inserts to hold the MOSFET switch board on the bottom of the case, with the FireBeetle 2 mounted above. I did not incorporate room for heat sinks on the MOSFETs because the current draw going through the MOSFETs to the LED strips was not enormous, and the duty cycle on the MOSFETs would usually be quite low. So far, after a week of testing, this decision appears to be working.
I went with 5.5 mm x 2.1 mm plugs and jacks for the +5 VDC supply and the +24 VDC IN and OUT connections to the LED strips. For the sensor cable I went with a hard wire (soldered) connection to the FireBeetle to save the cost of another pair of connectors (the 2 m long sensor cable was unterminated at one end). I added access holes for the RESET and BOOT buttons on the FireBeetle and a recessed access hole for the USB-C connector. Photographs of the case in various states of assembly are below.

The photo above shows the MOSFET switch board mounted on the bottom of the FireBeetle enclosure. The FireBeetle PCB will be mounted above the MOSFET PCB on longer standoffs. Note that this is an early version of the enclosure that was not long or tall enough to accommodate the three power connectors that needed to be mounted on the right end of the box. The box was enlarged in the next iteration to make room for these connectors.

The photograph above shows the revised enclosure with space for both PCBs and all three power connectors.
System Integration and Test
Once I corrected dor the incorrect pinout ofon the sensor cable, all of the parts as shown above in their custom enclosures worked just fine on my test bench through several power cycles and over three days of observation. Experience has taught me that a prototype working on the bench doesn't guarantee a prototype will work in the field. So I wasn't too surprised when things didn't go perfectly to plan when the hardware was moved into position at the coffee bar.
I installed the FireBeetle 2 and 24 V to 5 V power converter up on top of the cupboards where the main fused 24 VDC feed comes into the coffee bar area.

Issues arose when trying to place the C4002 sensor enclosure. The question to be answered was: Where should the sensor be placed to obtain most reliable operation? Reliable operation in this case means human presence is correctly detected when people approach and dwell at the coffee bar anywhere along its length and humans are not detected when they are away from the coffee bar, but still in the room, and, false triggers from pets or other non-human motion are avoided.
Using controls coded into the YAML and available on the Home Assistant dashboard I was able to adjust the detection range to extend just beyond the countertop. I tried mounting the sensor on the right end of the counter, under the cupboards, facing down the long side of the coffee bar. I tried mounting it in the middle of the bar, facing toward approaching humans at 45, 55, and 65 degree inclinations (using wedges that I printed). I tried mounting it on the granite countertop in the middle of the bar facing up toward approaching humans. All of these positions suffered from occasional false triggers. I also discovered that when the sensor was mounted on the granite countertop and the countertop water distiller was running, the C4002 seemed to easily detect the tiny vibrations caused by the distiller fan and agitation from boiling water inside the vessel.
In the end, I found the best location for the sensor was under the cupboards in the middle of the coffee bar facing toward the metallic backsplash at a 45 degree downward angle.

Summary
The C4002 combined with the FireBeetle 2 ESP32-C6 and the MOSFET switch have been working well for a few days now. The YAML code includes a 4 second fade out after about 10 seconds of no target detection. This is nice feature. I also incorporated a control within Home Assistant that allows the lights to be switched on or off from the dashboard on my phone.
The lights now stay on as long as there is a human standing near the coffee bar. No more waving hands under the cupboards to get the PIR controlled lights to come back on. This alone is a nice improvement.
In my next project post I will cover my work to get the ESP32-S3 AI camera to recognize when the distiller is on the counter top and automatically set up a 3 hour timer on an Emporia smart outlet through a Home Assistant integration.
The video below describes the components in the system and illustrates operation of the C4002 presence detector








