The LD2410C is a mmWave presence/movement sensor that is really cheap, widely available and with a little help and unserstanding, makes a GREAT alternative to infra-red and ultrasonic detectors – and at the price is suitable for everything from human presence/movement detection in farly large rooms right down to light controls for storage rooms and cabinets.
I’ve spent AGES getting to grips with this device, not helped by projects that don’t actually work, other projects with code behind paywalls and more. Finally this week I stumbled on a video by an American chap who has done a great job of explaining the sensor and how to get started using it.
Commercial pre-built units
So, I started this quest using Apollo Automation devices like the Apollo Pro-1 mm Sensor and others from the same company and they are GREAT, but not cheap. Depending where you live and your budget, they could end up being just too expensive for widespread use throughout the home. I love the Apollo stuff – see my various articles – just search “Apollo”.
Then I started looking at the LD2450 and finally decided to try out the LD2410C after seeing various YouTube videos on the subject… but I hit so many dead ends – until now.
Here we are… I have a few LD2410C boards from AliExpress… simply put, they generally have a 5-way connector which includes ground, serial RX, serial TX, an output for a LED and VCC. For now we can ignore the output and focus on the 4 pins – ground is obvious, Vcc to 5v, RX and TX.
Stand-alone use of the LD2410C – no ESP
Next I grabbed an FTDI – a small board which plugs into your computer’s serial port (or a hub) and gives you 3v3 volt level serial RX and TX as well as 3v3 and 5v outputs – again available for next to nothing from AliExpress. Going to their CHOICE items it shoud be possible to get a couple of LD2410C devices and an FTDI for around 10 Euros including postage. Today I generally choose serial devices like FTDIs with USB-C as I’m trying to standardise on USB-C but I tend to keep a few USB-A to C adaptors around as not all of my USB Hubs have USB-C connectors.
Anyway here is an older USB-A FTDI connected to an LD2410C sensor… the FTDI is providing the 5V power (around 79ma needed) and also serial RX and TX (connected to the LD2410c REVERSED – i.e. RX to TX, TX to RX.

And some detail… looking at the LD2410C, on the right you see the device – sensor side visible. Of interest, my device is about 20mm by 15mm. As you see I’ve connected TX, TX, ground and VCC. That’s it – for a mere couple of euros, this device, talking to an APP or a PC for example, can reliably detect human presence and movement. Doing something useful takes a little more work but one thing at a time.
On the active face you are viewing on the right here, the device senses from straight out for maybe a 60 degree angle and can work from a few cm to several metres distance- though my experience so far suggests that maybe 20cm outwards works best. Oh and yes the LD2410c gets warm in use. Below is a better view of my FTDI and the connections.
Hopefully the images above make the connections quite clear. I’ve done a video (below – embedded) to go with this article and hopefully between the two you’ll get a start on using these devices. As an aside, the LD2410C has a light sensor. Could be handy when used as a room presence sensor for lighting control to avoid turning on lights when it’s already bright out there. I’m not going into that here.
Don’t be cheap – An ESP32 S3 Mini costs only 3 £euros or equiv. from China
So a video fron Dronebot Workshop is what finally got me going – thanks to the owner for that – here’s his video for reference. There are two basic ways to talk to the LD2410C, Bluetooth or the serial pins. I’ll start with the latter. In a blog entry accompanying the above video, the writer mentions a free EXE tool available from the LD2410C manufacturer which uses Bluetooth. Here’s a 3-year-old Google Drive version of that tool. See the last item in the link above.
On my PC I tried this tool and it works – see image on the right.
But that assumes you are using a PC… and it’s only SO useful – so I prefer the web-based online tool also described in the video. But first – the tool to the right and the web tool both need to talk to your FTDI via the serial port it creates when connected to your PC or whatever. Getting FTDIs to work is beyond the scope of this article – for me, they always seem to work “out of the box”.
I just plug them into a USB hub connected to my PC and a new serial port magically appears. That’s the port you’d connect to on the single .EXE program shown above right – and given the wiring arrangement I showed above, on hitting CONNECT at the default baud rate of 25600, you would immediately start seeing something happening.
However, I’m going to go straight to the web tool instead as I didn’t find the above THAT intuitive – similarly the web tool needs to connect to the serial port created by the FTDI. Here’s the link, this time not for a download but directly to the web-based LD2410 Configurator. And here it is in action – my video shows this all graphically and hopefully between this and the video you’ll see how easy it is to start with the LD2410C.
On loading up the page – and with your FTDI plugged into your computing device and to the LD2450C – this is what you should see.
I didn’t use the “Display Advanced connection options” box, I just picked a port as I showed above – and connected.
At this point I was up and running. Now we have the full main page of the LD2410 Configurator – showing live presence detection in the top left blue box and movement in the red box next to it – all as below. I go into detail in the video.
Simply watching the panel above and maybe playing with the controls on the sbove right, hopefully you should start to see what the LD2410C device is capable of (and it’s limits – the values do tend to jump about a bit so in practice a little filtering will be useful).
The next step which I’ll go into later (as not everyone uses ESPHOME and Home Assistant) is to get that data out into a form that is useful. On DronebotWorkshop’s article he goes into using Arduino with the LD2410C device and also refers to the HLKRadarTool App for Android. If you look at the control screen above you can see that you can turn Bluetooth on and off in the device from that web page. Turning it on I found the LD2410C device appear in the APP which I’d grabbed from the Android Playstore, but personally I decided to stick with the above web page and go off looking at the official ESPHOME web page where they go into code for the LD2410C.
See my video below – and try to avoid noticing that I’m not looking at the camera… I was too busy trying to get to grips with using OBSBOT Studio’s multi-window facilities.
Basics over – now for something real
NOW, if you’ve waded through that lot !!!! CONGRATULATIONS !!!!, you backed the right horse because after wasting over a day on an ESP32-C3 board which worked with slightly modded standard ESP-HOME LD2410 code – exciting in itself, today I tried an ESP32-S3 and after realising I’d randomly picked pins GPIO9 and 10 for RX and TX and not only got them the wrong way around, but also physically connected pins 8 and 9, I finally not only got the code working in ESP-HOME but it ALSO magically appeared in Home Assistant and that’s where the REAL magic starts…
Choice of ESP, Opportunities and Limits
Couple of things first, I’m sure there’s a reason the C3 is being awkward, we’ll get to that – my pal Antonio and I will work on that, secondly on the ESP32 boards it is important you realise you can’t use the standard UART1. In the end I just picked gpio9 and gpio10 as they are among a list of pins that can be used as UARTS. I did NOTHING more than specify gpio9 and gpio10 and lo and behold, an ESP32-S3 mini talking to the LD2410C and as it happens, the S3 Mini has a WS2812B LED on pin 48. Thats my next job… visual indication of distance as I use on my Apollo units.
So, in my case I also had problems (and I’ve had it for ages) trying to create projects using my main PC while Home Assistant and hence ESP-HOME are sitting on another machine… all of that went away when I continued as before but for the first flash, told the controls to compile to the machine running ESP-HOME – and plugging the board into the same machine – voila. Oh and attaching a fixed IP (any spare address) to the chip guarantees a better flashing experience.
I’m going to put the lot up here, no pay walls, no missing bits – bear with me…
Meanwhile as a teaser – the code… not done anything with the blue light.. and that encryption key your installation will have to generate it’s own (automatically)..
esphome:
name: s3-radar
friendly_name: s3-radar
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "the_esp-home-provided_api_key"
ota:
- platform: esphome
password: "the_esp-home-provided_ota_key"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
# Static IP settings
static_ip: 192.168.1.226 # Your desired static IP address
gateway: 192.168.1.1 # Your router's IP address
subnet: 255.255.255.0 # Your network's subnet mask
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "S3-Radar Fallback Hotspot"
password: "the_esp-home-provided_fallback_key"
captive_portal:
web_server:
port: 80
include_internal: true
# ---------------------------------------------------------------------------------
light:
- platform: binary
name: "Blue Status Light"
output: light_output
id: led_light
restore_mode: ALWAYS_OFF
output:
- platform: gpio
pin: GPIO2
id: light_output
uart:
id: ld2410_uart
tx_pin: GPIO10 # TX
rx_pin: GPIO9 # RX
baud_rate: 256000
parity: NONE
stop_bits: 1
ld2410:
uart_id: ld2410_uart
id: ld2410_comp
select:
- platform: ld2410
distance_resolution:
name: distance resolution
baud_rate:
name: baud rate
light_function:
name: light function
out_pin_level:
name: out pin level
button:
- platform: ld2410
factory_reset:
name: "factory reset"
restart:
name: "restart"
query_params:
name: query params
number:
- platform: ld2410
timeout:
name: timeout
max_move_distance_gate:
name: max move distance gate
max_still_distance_gate:
name: max still distance gate
g0:
move_threshold:
name: g0 move threshold
still_threshold:
name: g0 still threshold
g1:
move_threshold:
name: g1 move threshold
still_threshold:
name: g1 still threshold
g2:
move_threshold:
name: g2 move threshold
still_threshold:
name: g2 still threshold
g3:
move_threshold:
name: g3 move threshold
still_threshold:
name: g3 still threshold
g4:
move_threshold:
name: g4 move threshold
still_threshold:
name: g4 still threshold
g5:
move_threshold:
name: g5 move threshold
still_threshold:
name: g5 still threshold
g6:
move_threshold:
name: g6 move threshold
still_threshold:
name: g6 still threshold
g7:
move_threshold:
name: g7 move threshold
still_threshold:
name: g7 still threshold
g8:
move_threshold:
name: g8 move threshold
still_threshold:
name: g8 still threshold
light_threshold:
name: light threshold
text_sensor:
- platform: ld2410
version:
name: "presence sensor version"
mac_address:
name: "presence sensor mac address"
switch:
- platform: ld2410
engineering_mode:
name: "engineering mode"
bluetooth:
name: control Bluetooth
sensor:
- platform: internal_temperature
name: "Internal Temperature"
- platform: ld2410
moving_distance:
name: "Moving distance (cm)"
still_distance:
name: "Still Distance (cm)"
moving_energy:
name: "Move Energy (%)"
still_energy:
name: "Still Energy (%)"
detection_distance:
name: "Distance Detection (cm)"
g0:
move_energy:
name: g0 move energy
still_energy:
name: g0 still energy
g1:
move_energy:
name: g1 move energy
still_energy:
name: g1 still energy
g2:
move_energy:
name: g2 move energy
still_energy:
name: g2 still energy
g3:
move_energy:
name: g3 move energy
still_energy:
name: g3 still energy
g4:
move_energy:
name: g4 move energy
still_energy:
name: g4 still energy
g5:
move_energy:
name: g5 move energy
still_energy:
name: g5 still energy
g6:
move_energy:
name: g6 move energy
still_energy:
name: g6 still energy
g7:
move_energy:
name: g7 move energy
still_energy:
name: g7 still energy
g8:
move_energy:
name: g8 move energy
still_energy:
name: g8 still energy
light:
name: light
binary_sensor:
- platform: ld2410
has_target:
name: Presence
has_moving_target:
name: Moving Target
has_still_target:
name: Still Target
The code above was my first attempt ands had no WS2812B code – just the LD2450C.
And now with the aid of ChatGPT I’ve just LEAPFROGGED my previous attempts – the code below – for the ESP32-S3 with RGB LED on GPIO48 – and the LD2410C….. now the onboard RGB LED changes colour depending on presence distance…. ALL WITHIN the ESP32-S3 board with ESP-HOME – not relying on Home Assistant at all. MAGIC. Here it is… I disconnected the blue LED, may as well scrap that first LED platform eventually…
- platform: binary
name: “Blue Status Light”
output: light_output
id: led_light
restore_mode: ALWAYS_OFF
esphome:
name: s3-radar
friendly_name: s3-radar
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "the_esp-home-provided_api_key"
ota:
- platform: esphome
password: "the_esp-home-provided_ota_key"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.1.226
gateway: 192.168.1.1
subnet: 255.255.255.0
ap:
ssid: "S3-Radar Fallback Hotspot"
password: "the_esp-home-provided_fallback_key"
captive_portal:
web_server:
port: 80
include_internal: true
# ---------------------------------------------------------------------------------
light:
- platform: binary
name: "Blue Status Light"
output: light_output
id: led_light
restore_mode: ALWAYS_OFF
- platform: neopixelbus
type: GRB
variant: WS2812
pin: GPIO48
num_leds: 1
name: "NeoPixel Light"
id: neo_pixel_light
output:
- platform: gpio
pin: GPIO2
id: light_output
uart:
id: ld2410_uart
tx_pin: GPIO10
rx_pin: GPIO9
baud_rate: 256000
parity: NONE
stop_bits: 1
ld2410:
uart_id: ld2410_uart
id: ld2410_comp
select:
- platform: ld2410
distance_resolution:
name: distance resolution
baud_rate:
name: baud rate
light_function:
name: light function
out_pin_level:
name: out pin level
button:
- platform: ld2410
factory_reset:
name: "factory reset"
restart:
name: "restart"
query_params:
name: query params
number:
- platform: ld2410
timeout:
name: timeout
max_move_distance_gate:
name: max move distance gate
max_still_distance_gate:
name: max still distance gate
g0:
move_threshold:
name: g0 move threshold
still_threshold:
name: g0 still threshold
g1:
move_threshold:
name: g1 move threshold
still_threshold:
name: g1 still threshold
g2:
move_threshold:
name: g2 move threshold
still_threshold:
name: g2 still threshold
g3:
move_threshold:
name: g3 move threshold
still_threshold:
name: g3 still threshold
g4:
move_threshold:
name: g4 move threshold
still_threshold:
name: g4 still threshold
g5:
move_threshold:
name: g5 move threshold
still_threshold:
name: g5 still threshold
g6:
move_threshold:
name: g6 move threshold
still_threshold:
name: g6 still threshold
g7:
move_threshold:
name: g7 move threshold
still_threshold:
name: g7 still threshold
g8:
move_threshold:
name: g8 move threshold
still_threshold:
name: g8 still threshold
light_threshold:
name: light threshold
text_sensor:
- platform: ld2410
version:
name: "presence sensor version"
mac_address:
name: "presence sensor mac address"
switch:
- platform: ld2410
engineering_mode:
name: "engineering mode"
bluetooth:
name: control Bluetooth
sensor:
- platform: internal_temperature
name: "Internal Temperature"
- platform: ld2410
moving_distance:
name: "Moving distance (cm)"
still_distance:
name: "Still Distance (cm)"
id: still_distance_sensor
moving_energy:
name: "Move Energy (%)"
still_energy:
name: "Still Energy (%)"
detection_distance:
name: "Distance Detection (cm)"
g0:
move_energy:
name: g0 move energy
still_energy:
name: g0 still energy
g1:
move_energy:
name: g1 move energy
still_energy:
name: g1 still energy
g2:
move_energy:
name: g2 move energy
still_energy:
name: g2 still energy
g3:
move_energy:
name: g3 move energy
still_energy:
name: g3 still energy
g4:
move_energy:
name: g4 move energy
still_energy:
name: g4 still energy
g5:
move_energy:
name: g5 move energy
still_energy:
name: g5 still energy
g6:
move_energy:
name: g6 move energy
still_energy:
name: g6 still energy
g7:
move_energy:
name: g7 move energy
still_energy:
name: g7 still energy
g8:
move_energy:
name: g8 move energy
still_energy:
name: g8 still energy
light:
name: light
binary_sensor:
- platform: ld2410
has_target:
name: Presence
has_moving_target:
name: Moving Target
has_still_target:
name: Still Target
# -------------------------------------------------------------------------------
# Local LED colour control based on still distance
interval:
- interval: 2s
then:
- lambda: |-
float dist = id(still_distance_sensor).state;
ESP_LOGD("neo", "Still distance = %.1f cm", dist);
if (dist <= 0) {
// Turn off via ESPHome action
auto call = id(neo_pixel_light).make_call();
call.set_state(false);
call.perform();
return;
}
// Decide colour
float r = 0.0, g = 0.0, b = 0.0;
if (dist < 100) { r = 0.0; g = 1.0; b = 0.0; } // Green
else if (dist < 200) { r = 1.0; g = 1.0; b = 0.0; } // Yellow
else if (dist < 300) { r = 1.0; g = 0.5; b = 0.0; } // Orange
else if (dist < 400) { r = 1.0; g = 0.0; b = 0.0; } // Red
else { r = 0.0; g = 0.0; b = 1.0; } // Blue
// Turn on NeoPixel via ESPHome light action
auto call = id(neo_pixel_light).make_call();
call.set_state(true);
call.set_rgb(r,g,b);
call.set_brightness(1.0);
call.perform();
And here’s the quick and dirty video demo.. I have to work on those distances – but it’s getting there…
Did you notice I’d switched to the framework type Arduino (near the start) in the code above..
Well, that turned out to be a problem with my ESP-HOME installation having some carry-over out-of-date code – I hit the same problem with the ESP-C6 (another nice board with an RGB LED but this time on GPIO8). Eventually I we found a solution – uninstall the ESP-HOME add-in and reinstall it (trivial) though I did end up sticking with the ARDUINO framework for no particular reason. The simple uninstall and re-install clears cache and is harmless (you don’t lose your previous work) and then the ESP-IDF framework type once again works. I discovered this when I tried the C6 and was told that the Arduino framework type doesn’t support the C6. So I took the plunge – and after re-adding in ESP-HOME, I could use the C6 with esp-idf, changing the LED to GPIO8 – but then the original neopixel bus would not work with the C6 so I changed the WS2812 settings to use the esp32_rmt_led_strip platform with slightly different parameters – I suspect that will work with the earlier boards.
Here’s the code for the ESP32-C6… with a few mods to distances and that daft blue light commented out…
esphome:
name: c6-radar
friendly_name: c6-radar
esp32:
board: esp32-c6-devkitc-1
framework:
type: esp-idf
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "the_esp-home-provided_api_key"
ota:
- platform: esphome
password: "the_esp-home-provided_ota_key"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
static_ip: 192.168.1.227
gateway: 192.168.1.1
subnet: 255.255.255.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "C6-Radar Fallback Hotspot"
password: "the_esp-home-provided_fallback_key"
captive_portal:
web_server:
port: 80
include_internal: true
# ---------------------------------------------------------------------------------
light:
# - platform: binary
# name: "Blue Status Light"
# output: light_output
# id: led_light
# restore_mode: ALWAYS_OFF
- platform: esp32_rmt_led_strip
rgb_order: GRB
pin: GPIO8
num_leds: 1
chipset: WS2812
name: "NeoPixel Light"
id: neo_pixel_light
#output:
# - platform: gpio
# pin: GPIO2
# id: light_output
uart:
id: ld2410_uart
tx_pin: GPIO6
rx_pin: GPIO7
baud_rate: 256000
parity: NONE
stop_bits: 1
ld2410:
uart_id: ld2410_uart
id: ld2410_comp
select:
- platform: ld2410
distance_resolution:
name: distance resolution
baud_rate:
name: baud rate
light_function:
name: light function
out_pin_level:
name: out pin level
button:
- platform: ld2410
factory_reset:
name: "factory reset"
restart:
name: "restart"
query_params:
name: query params
number:
- platform: ld2410
timeout:
name: timeout
max_move_distance_gate:
name: max move distance gate
max_still_distance_gate:
name: max still distance gate
g0:
move_threshold:
name: g0 move threshold
still_threshold:
name: g0 still threshold
g1:
move_threshold:
name: g1 move threshold
still_threshold:
name: g1 still threshold
g2:
move_threshold:
name: g2 move threshold
still_threshold:
name: g2 still threshold
g3:
move_threshold:
name: g3 move threshold
still_threshold:
name: g3 still threshold
g4:
move_threshold:
name: g4 move threshold
still_threshold:
name: g4 still threshold
g5:
move_threshold:
name: g5 move threshold
still_threshold:
name: g5 still threshold
g6:
move_threshold:
name: g6 move threshold
still_threshold:
name: g6 still threshold
g7:
move_threshold:
name: g7 move threshold
still_threshold:
name: g7 still threshold
g8:
move_threshold:
name: g8 move threshold
still_threshold:
name: g8 still threshold
light_threshold:
name: light threshold
text_sensor:
- platform: ld2410
version:
name: "presence sensor version"
mac_address:
name: "presence sensor mac address"
switch:
- platform: ld2410
engineering_mode:
name: "engineering mode"
bluetooth:
name: control Bluetooth
sensor:
- platform: internal_temperature
name: "Internal Temperature"
- platform: ld2410
moving_distance:
name: "Moving distance (cm)"
still_distance:
name: "Still Distance (cm)"
id: still_distance_sensor
moving_energy:
name: "Move Energy (%)"
still_energy:
name: "Still Energy (%)"
detection_distance:
name: "Distance Detection (cm)"
g0:
move_energy:
name: g0 move energy
still_energy:
name: g0 still energy
g1:
move_energy:
name: g1 move energy
still_energy:
name: g1 still energy
g2:
move_energy:
name: g2 move energy
still_energy:
name: g2 still energy
g3:
move_energy:
name: g3 move energy
still_energy:
name: g3 still energy
g4:
move_energy:
name: g4 move energy
still_energy:
name: g4 still energy
g5:
move_energy:
name: g5 move energy
still_energy:
name: g5 still energy
g6:
move_energy:
name: g6 move energy
still_energy:
name: g6 still energy
g7:
move_energy:
name: g7 move energy
still_energy:
name: g7 still energy
g8:
move_energy:
name: g8 move energy
still_energy:
name: g8 still energy
light:
name: light
binary_sensor:
- platform: ld2410
has_target:
name: Presence
has_moving_target:
name: Moving Target
has_still_target:
name: Still Target
# -------------------------------------------------------------------------------
# Local LED colour control based on still distance
interval:
- interval: 2s
then:
- lambda: |-
float dist = id(still_distance_sensor).state;
ESP_LOGD("neo", "Still distance = %.1f cm", dist);
if (dist <= 0) {
// Turn off via ESPHome action
auto call = id(neo_pixel_light).make_call();
call.set_state(false);
call.perform();
return;
}
// Decide colour
float r = 0.0, g = 0.0, b = 0.0;
if (dist < 80) { r = 0.0; g = 1.0; b = 0.0; } // Green
else if (dist < 160) { r = 1.0; g = 1.0; b = 0.0; } // Yellow
else if (dist < 240) { r = 1.0; g = 0.5; b = 0.0; } // Orange
else if (dist < 320) { r = 1.0; g = 0.0; b = 0.0; } // Red
else if (dist < 400) { r = 1.0; g = 0.0; b = 1.0; } // purple
else if (dist < 480) { r = 0.0; g = 0.0; b = 1.0; } // blue
else { r = 0.0; g = 0.0; b = 0.0; } // black
// Turn on NeoPixel via ESPHome light action
auto call = id(neo_pixel_light).make_call();
call.set_state(true);
call.set_rgb(r,g,b);
call.set_brightness(1.0);
call.perform();
The ultimate solution and some limits
As it happens I did some more reading and it seems that of these small boards, the ESP32-S3 has slightly more memory so I stuck with that and armed with success, began to get ambitious – I thought it would be nice to have a BME280 temperature/pressure/humidity sensor on the same board – GREAT idea – two gadgets in one… but for one thing – the latter uses an I2C library and also pulls in code for (in this case not used) SPI.
When it came to compile my latest miracle, the ESP-HOME linker would not have it. I thought that maybe the combined code of the LD2410C and the BME280 device might be too much – and I was right. However, I’d included in the ESP-HOME code (as I usually do) the basic web server so I could see results in a browser before looking to see if the device had been added to Home Assistant. Merely commenting out the web server made everything work – ChatGPT says it uses up to 300K just for the web server and I believe it.
Here is the code as it stands today, web server commented out but the rest all works a treat. Doing a little research it seems there may be ways to minimise code use so I can have my web server back – for example no API encryption if all of this is running on a trusted internal network. The web server has the biggest impact, followed by turning off logging or minimising it, turn off OTA (erm no thanks), the API encryption and other optimisations – none of that below – just no web server so no preview in a web page.. adjust the IP address to suit and don’t just use dhcp (dynamic addressing)..
Oh, below, I’ve changed the LD2410 serial pins to acommodate the standard I2C pins for the BME280..
HAH – last minute change – instead of disabling the web server, I disabled logging by setting the logging baud rate to 0. I could then re-enable the web server. My choice.
esphome:
name: s3-bme
friendly_name: s3-bme
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
# Disable logging
logger:
level: DEBUG
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: "y82jDv7/Q3a5VP5ITf9WBwc86f+HtcBqmlK+qkPy+is="
ota:
- platform: esphome
password: "7a1e4dda0e189533af06d75347bce651"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
manual_ip:
# Static IP settings
static_ip: 192.168.1.228 # Desired static IP address
gateway: 192.168.1.1 # Your router's IP address
subnet: 255.255.255.0 # Your network's subnet mask
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "S3-Bme Fallback Hotspot"
password: "gEUATGjLMKVK"
# If logging is needed here, comment out the web server or play with a different ESP board...
web_server:
port: 80
include_internal: true
captive_portal:
i2c:
sda: GPIO8
scl: GPIO9
scan: true
id: bus_a
light:
- platform: neopixelbus
type: GRB
variant: WS2812
pin: GPIO48
num_leds: 1
name: "NeoPixel Light"
id: neo_pixel_light
output:
- platform: gpio
pin: GPIO2
id: light_output
sensor:
- platform: bme280_i2c
temperature:
name: "BME280 Temperature"
accuracy_decimals: 0
pressure:
name: "BME280 Pressure"
accuracy_decimals: 0
humidity:
name: "BME280 Humidity"
accuracy_decimals: 0
- platform: internal_temperature
name: "Internal Temperature"
- platform: ld2410
moving_distance:
name: "Moving distance (cm)"
id: moving_distance_sensor
still_distance:
name: "Still Distance (cm)"
id: still_distance_sensor
moving_energy:
name: "Move Energy (%)"
still_energy:
name: "Still Energy (%)"
detection_distance:
name: "Distance Detection (cm)"
g0:
move_energy:
name: g0 move energy
still_energy:
name: g0 still energy
g1:
move_energy:
name: g1 move energy
still_energy:
name: g1 still energy
g2:
move_energy:
name: g2 move energy
still_energy:
name: g2 still energy
g3:
move_energy:
name: g3 move energy
still_energy:
name: g3 still energy
g4:
move_energy:
name: g4 move energy
still_energy:
name: g4 still energy
g5:
move_energy:
name: g5 move energy
still_energy:
name: g5 still energy
g6:
move_energy:
name: g6 move energy
still_energy:
name: g6 still energy
g7:
move_energy:
name: g7 move energy
still_energy:
name: g7 still energy
g8:
move_energy:
name: g8 move energy
still_energy:
name: g8 still energy
light:
name: light
uart:
id: ld2410_uart
tx_pin: GPIO11
rx_pin: GPIO10
baud_rate: 256000
parity: NONE
stop_bits: 1
ld2410:
uart_id: ld2410_uart
id: ld2410_comp
select:
- platform: ld2410
distance_resolution:
name: distance resolution
baud_rate:
name: baud rate
light_function:
name: light function
out_pin_level:
name: out pin level
button:
- platform: ld2410
factory_reset:
name: "factory reset"
restart:
name: "restart"
query_params:
name: query params
number:
- platform: ld2410
timeout:
name: timeout
max_move_distance_gate:
name: max move distance gate
max_still_distance_gate:
name: max still distance gate
g0:
move_threshold:
name: g0 move threshold
still_threshold:
name: g0 still threshold
g1:
move_threshold:
name: g1 move threshold
still_threshold:
name: g1 still threshold
g2:
move_threshold:
name: g2 move threshold
still_threshold:
name: g2 still threshold
g3:
move_threshold:
name: g3 move threshold
still_threshold:
name: g3 still threshold
g4:
move_threshold:
name: g4 move threshold
still_threshold:
name: g4 still threshold
g5:
move_threshold:
name: g5 move threshold
still_threshold:
name: g5 still threshold
g6:
move_threshold:
name: g6 move threshold
still_threshold:
name: g6 still threshold
g7:
move_threshold:
name: g7 move threshold
still_threshold:
name: g7 still threshold
g8:
move_threshold:
name: g8 move threshold
still_threshold:
name: g8 still threshold
light_threshold:
name: light threshold
text_sensor:
- platform: ld2410
version:
name: "presence sensor version"
mac_address:
name: "presence sensor mac address"
switch:
- platform: ld2410
engineering_mode:
name: "engineering mode"
bluetooth:
name: control Bluetooth
binary_sensor:
- platform: ld2410
has_target:
name: Presence
has_moving_target:
name: Moving Target
has_still_target:
name: Still Target
# -------------------------------------------------------------------------------
# Local LED colour control based on still distance
interval:
- interval: 2s
then:
- lambda: |-
float dist = id(moving_distance_sensor).state;
if (dist <= 0) {
// Turn off via ESPHome action
auto call = id(neo_pixel_light).make_call();
call.set_state(false);
call.perform();
return;
}
// Decide colour
float r = 0.0, g = 0.0, b = 0.0;
if (dist < 100) { r = 0.0; g = 1.0; b = 0.0; } // Green
else if (dist < 200) { r = 1.0; g = 1.0; b = 0.0; } // Yellow
else if (dist < 300) { r = 1.0; g = 0.5; b = 0.0; } // Orange
else if (dist < 400) { r = 1.0; g = 0.0; b = 0.0; } // Red
else { r = 0.0; g = 0.0; b = 1.0; } // Blue
// Turn on NeoPixel via ESPHome light action
auto call = id(neo_pixel_light).make_call();
call.set_state(true);
call.set_rgb(r,g,b);
call.set_brightness(1.0);
call.perform();
And by magic – in Home Assistant…
I missed out the MAC address line…
That’s it for now – to take this too much further I’m going to need an ESP with more memory – or a lot more knowledge 🙂
As you can see higher up, the sensors ARE working… and that onboard single WS2812 RGB LED is being automatically controlled – the icon colour changing magically with distance. Originally I did the control in Home Assistant – and you could do that.. or not… It’s more a nicety than an essential. I like to have visual feedback as to the working of the unit.
You can use any of those sensors as needed in Home Assistant automations, I often just use “moving target” and “still target” for my needs.
Thoughts welcome.












