Yes, you must install sensor and when you finish (and that’s how it will be) leave the sensing area of sensor and hit “auto”. Then wait a couple of minutes until it says “complete”. If you move sensor later, you just repeat auto calibration.
After that you only make small adjustments if needed.
Would be great to be able to specify a default value in the ESP device yaml though…
I don’t really see the benefit of having default values set in the ESP device yaml as you can setup the values via the HLKRadarTool app or via the HA interface and this integration just uses what is already configured on the LD2410.
If defaults were set in the ESP device yaml, any updates to the yaml as well as ESPHome updates will then overwrite any customisations made with the defaults again.
Fair point that any updates would overwrite the custom values with the defaults…
The reason why I think/thought this is useful is because the yaml can be stored in source control (kind of like infrastructure as code), so you never loose it. The Home Assistant config on the other hand tends to get corrupted, etc and when that happens, you loose you custom LD2410 configuration values and then you have to experiment all over again to find the correct thresholds. For now I decided to store the configured custom values as comments in the yaml.
I’m not sure if the HA config getting corrupted would impact the LD2410 as the values are stored on the LD2410 itself and not in HA.
The other option for config backup is to use the HLKRadarTool app. You can save the settings as a Template and then reload them if they need resetting. As you can save multiple templates, you can use that for experimentation so you don’t loose a working config.
Thank you!
If the values are stored in the LD2410 itself, than that’s less likely to be lost. Unlessyou accidentally or willingly factory reset it.
Good morning everyone…
I am thinking of getting some, but there seems to be a dispute here which one to use.
Which sensore is easiest/fail proof and why did u chose it?
And what are actually use cases. Right now it seems to be just a cool toy but not peactical
I think i’m gonna use only 2410 from now on. 2411 doesn’t have zones, as it seems, so you can’t set it as precise as 2410, 2420 doesn’t have BT, so you can’t adjust zones with phone app (which is the easiest)…
And, btw… i managed to use output pin only on 2410, on other two it doesn’t work, so “standalone” use is not possible,
Does anyone know of a way with the LD2410 to detect when the “timeout” has started? The output pin, and the presence sensors, all just go “away” after the configured timeout. I’d like to have a way to know if it’s lost sight but is waiting before reporting it - so I can display a telltail light e.g. “move now or i’m turning the lights off!”
I know I can do this separately with a separate timeout in my automations, but i’d like my magic box to be self-sufficient in that regard.
Thanks.
Hi all, I’m just posting my card YAML for the engineering mode energy readouts because I found a way to have it update live. Took me a good few hours to find a solution so I’m hoping this can save someone else some time
If you use just custom:bar-card
by itself it redraws the card live with updated data without needing to refresh the page but you cant use number.
threshold entities to set the target:
for each graph, which you need to see when your energy readout crosses the threshold.
To convert those number.
threshold entities to something usable by custom:bar-card
you can wrap the whole thing in a custom:config-template-card
to convert the number entities to variables that you then put in the target fields. However this breaks custom:bar-card
redrawing for some reason.
If you then wrap the whole thing, again, in a custom:card-templater
and specifiy some entities it will redraw the card when those entities update. I’ve specified all of the energy readouts in mine because if I only specify one it seems buggy, but I have not done any extensive testing as it was 3am by the time a figured this out. However I think it puts quite a load on the browser and home assistant itself as it may be redrawing 9 times every update instead of just once? It seems to be very taxing on a phone but it anyway here it is.
type: custom:card-templater #force a redraw when any of the specified entities update their data.
entities:
- sensor.ld2410b_71b5e8_g0_move_energy
- sensor.ld2410b_71b5e8_g1_move_energy
- sensor.ld2410b_71b5e8_g2_move_energy
- sensor.ld2410b_71b5e8_g3_move_energy
- sensor.ld2410b_71b5e8_g4_move_energy
- sensor.ld2410b_71b5e8_g5_move_energy
- sensor.ld2410b_71b5e8_g6_move_energy
- sensor.ld2410b_71b5e8_g7_move_energy
- sensor.ld2410b_71b5e8_g8_move_energy
card:
type: custom:config-template-card #convert number. entities to vars for the target: fields
variables:
g0_threshold: states['number.ld2410b_71b5e8_g0_move_threshold'].state
g1_threshold: states['number.ld2410b_71b5e8_g1_move_threshold'].state
g2_threshold: states['number.ld2410b_71b5e8_g2_move_threshold'].state
g3_threshold: states['number.ld2410b_71b5e8_g3_move_threshold'].state
g4_threshold: states['number.ld2410b_71b5e8_g4_move_threshold'].state
g5_threshold: states['number.ld2410b_71b5e8_g5_move_threshold'].state
g6_threshold: states['number.ld2410b_71b5e8_g6_move_threshold'].state
g7_threshold: states['number.ld2410b_71b5e8_g7_move_threshold'].state
g8_threshold: states['number.ld2410b_71b5e8_g8_move_threshold'].state
entities:
- ${g0_threshold}
- ${g1_threshold}
- ${g2_threshold}
- ${g3_threshold}
- ${g4_threshold}
- ${g5_threshold}
- ${g6_threshold}
- ${g7_threshold}
- ${g8_threshold}
card:
type: custom:bar-card #draw the bars
direction: right
height: 44px
width: 100%
positions:
icon: "off"
name: inside
indicator: inside
value: inside
animation:
state: "off"
entities:
- entity: sensor.ld2410b_71b5e8_g0_move_energy
target: ${g0_threshold}
name: g0
severity:
- color: green
from: ${g0_threshold}
to: 100
- entity: sensor.ld2410b_71b5e8_g1_move_energy
target: ${g1_threshold}
name: g1
severity:
- color: green
from: ${g1_threshold}
to: 100
- entity: sensor.ld2410b_71b5e8_g2_move_energy
target: ${g2_threshold}
name: g2
severity:
- color: green
from: ${g2_threshold}
to: 100
- entity: sensor.ld2410b_71b5e8_g3_move_energy
target: ${g3_threshold}
name: g3
severity:
- color: green
from: ${g3_threshold}
to: 100
- entity: sensor.ld2410b_71b5e8_g4_move_energy
target: ${g4_threshold}
name: g4
```
Hi, I’ve started using these sensors, and I’m an ESPHome newbie too. It’s my first project with all of it.
I’ve fully followed the config set here and have a couple questions.
- Can someone explain me what is the OUT pin for? I currently have it connected, but I don’t understand the documentation about it. I already have presence detection using the TX and RX pins, so I don’t get why I’d want the OUT connected too.
- Following the docs, this is my binary_sensor config:
binary_sensor:
- platform: ld2410
has_target:
name: Presence
has_moving_target:
name: Moving Target
has_still_target:
name: Still Target
out_pin_presence_status:
name: out pin presence status
- platform: gpio
pin: GPIO2
name: gpio out pin presence
device_class: presence
I don’t understand the difference or if both “out pin presence” sensors are necessary at all. They return different values, so they don’t seem to be the same thing.
Many thanks.
Out pin is… well, output. It’s active if presence is detected (either moving or static). For instance, i have connected solid state relay on one of LD’s and i use it as standalone sensor for lights. If you connect it to esphome you have some kind of monitor of this output. How is that usefull… couldn’t tell, since there’s another sensors saying that (moving target, static target, presence), so you can safely omit that connection and delete that sensor from yaml.
I have one or these devices and it had been great. Do you have updated ESPHome config for them as i would life to update it to 2025.2.2?
I’m lost! Using an ESP32 S3 trying to get it work with an LD2410C.
Don’t know, how to Connect the Pins
Today i made it - but then i changed something in the yaml config and all is gone.
My ESP-Board Layout:
My last try was LD2410 TX → GPIO9 / RX → GPIO10
uart:
id: uart_1
rx_pin: GPIO9
tx_pin: GPIO10
baud_rate: 256000
#data_bits: 8
stop_bits: 1
parity: NONE
NO results, all Sensors are ‘unknown’.
Please help
I was able to run the built-in auto calibration by sending the packets manually:
button:
- platform: ld2410
query_params:
name: "Force Query"
- platform: template
name: "Calibrate LD2410 Sensor"
id: calibrate_ld2410
on_press:
then:
# 1. Enable Configuration Mode
- logger.log: "INFO: Starting LD2410 calibration sequence... You have 10 seconds to clear the room!"
- logger.log: "DEBUG: Sending Enable Configuration command (0x00FF)"
- uart.write:
id: ld2410_uart
# Data: HDR | LEN=4 | CMD=0xFF | VAL=0x01 | FTR
data: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x04, 0x03, 0x02, 0x01]
- delay: 1000ms
# 2. Start the auto-calibration
- logger.log: "DEBUG: Sending Start Calibration command (0x000B, 60s)"
- uart.write:
id: ld2410_uart
# Data: HDR | LEN=4 | CMD=0x0B | VAL=0x3C00 | FTR
data: [0xFD, 0xFC, 0xFB, 0xFA, 0x04, 0x00, 0x0B, 0x00, 0x3C, 0x00, 0x04, 0x03, 0x02, 0x01]
- delay: 1000ms
# 3. Disable Configuration Mode
- logger.log: "DEBUG: Sending End Configuration command (0x00FE)"
- uart.write:
id: ld2410_uart
# Data: HDR | LEN=2 | CMD=0xFE | FTR (No value needed)
data: [0xFD, 0xFC, 0xFB, 0xFA, 0x02, 0x00, 0xFE, 0x00, 0x04, 0x03, 0x02, 0x01]
- logger.log: "INFO: LD2410 calibration sequence sent. Ensure room is empty for 70 seconds!"
- delay: 70000ms
- logger.log: "INFO: LD2410 calibration finished. Force a query to download new parameters."
This runs the auto-calibration for 60 seconds after a 10 second delay for clearing the room.
Same here, any progress on the engineering mode switching off after a few seconds?
My less than 6 month old LD2410b sensor decided to stop working randomly. It is not relaying any data (checked on 2 different esphome devices and a usb-uart ttyl device) and is not detected in HLKRadarTools app. It is heating up to extreme levels such that holding it for merely a second will burn my fingertips.
Has this happened with anyone else?
Interesting. I have one that’s just running connected to the dev board and an ESP32 Bluetooth proxy. Yea…set it up a couple years ago when everyone was still playing games figuring out how to get working on an ESP32 or 8266…LOL. Down and dirty but … works fine.
Mine does run pretty hot as well. But, I have it on the wall in the garage to control a Fan on/off and …I live in Phoenix lol. So, it made it through last summer and the garage topping out around 125° F… Wasn’t all that uncommon.
If you look at the ESPs, their operational temps can be fairly high. I’ve seen from 158° F to as high as 221° F for an ESP32S3. So, I suspect the LD2410s aren’t far off.
But …with that said…I’ve had ESP8266 D1 mini boards just up and die. The MTBF isn’t all that long compared to say…common PC parts. They were typically like 50K hours MTBF. I think the datasheet for an ESP32S3 I was just looking at was only 1k hours. Not a lot really. So… I wouldn’t consider your failure all that unusual. They cost what …a few bucks just for the sensor? When I buy things like this…I always get 3-5 at a time just for this reason. Or…I might fry one…lol. Chuck it in the trash, pop a new one on…and don’t sweat it brother.
Showcasing - LD2410C Multiple Threshold Profiles
Usecases
- Different sensing threshold when ceiling fan is On or Off
- In Windy scenarios where curtains or window glasses moves or vibrates with wind which causes false triggers.
Implementation
I’ve made 2 separate profiles for the LD2410C tied to a wemos d1 mini with esphome.
I’ve added a dashboard toggle with mushroom template tile that allows me to flip the toggle and based on the toggle value, I typically change all static thresholds of g0 to g8 of the sensor.
Code
Mushroom template tile:
type: custom:mushroom-template-card
primary: Motion Setting
secondary: |-
{% if is_state("input_boolean.motion_sensitivity", "off") %}
Normal Sensitivity
{% else %}
Reduced Sensitivity
{% endif %}
icon: mdi:cursor-move
entity: input_boolean.motion_sensitivity
icon_color: |-
{% if is_state("input_boolean.motion_sensitivity", "off") %}
green
{% else %}
deep-orange
{% endif %}
badge_icon: |-
{% if is_state("input_boolean.motion_sensitivity", "off") %}
mdi:check-bold
{% else %}
mdi:alert-circle
{% endif %}
badge_color: |-
{% if is_state("input_boolean.motion_sensitivity", "off") %}
green
{% else %}
deep-orange
{% endif %}
fill_container: false
multiline_secondary: false
double_tap_action:
action: none
hold_action:
action: none
This triggers my automation which uses a template to add an offset value (20) in my case based on the state of the boolean
alias: When Motion Sensitivity changes
description: When Motion sensitivity is changed
triggers:
- trigger: state
entity_id:
- input_boolean.motion_sensitivity
conditions: []
actions:
- choose:
- conditions:
- condition: state
entity_id: input_boolean.motion_sensitivity
state: "on"
sequence:
- repeat:
count: 9
sequence:
- variables:
entities: >-
{{ state_attr('group.all_ld2410_still_thresholds',
'entity_id') | list }}
- repeat:
for_each: "{{ entities }}"
sequence:
- variables:
current: "{{ states(repeat.item) | float(0) }}"
new_value: "{{ [current + 20, 100] | min }}"
- target:
entity_id: "{{ repeat.item }}"
data:
value: "{{ new_value }}"
action: number.set_value
- conditions:
- condition: state
entity_id: input_boolean.motion_sensitivity
state: "off"
sequence:
- repeat:
count: 9
sequence:
- variables:
entities: >-
{{ state_attr('group.all_ld2410_still_thresholds',
'entity_id') | list }}
- repeat:
for_each: "{{ entities }}"
sequence:
- variables:
current: "{{ states(repeat.item) | float(0) }}"
new_value: "{{ [current - 20, 0] | max }}"
- target:
entity_id: "{{ repeat.item }}"
data:
value: "{{ new_value }}"
action: number.set_value
enabled: true
mode: single
Also note that I created a group of all static values of the gates in groups.yaml
file to templatize this inside my automation easily
# groups.yaml
all_ld2410_still_thresholds:
name: "All LD2410 Still Thresholds"
entities:
- number.presence_bedroom_g0_still_threshold
- number.presence_bedroom_g1_still_threshold
- number.presence_bedroom_g2_still_threshold
- number.presence_bedroom_g3_still_threshold
- number.presence_bedroom_g4_still_threshold
- number.presence_bedroom_g5_still_threshold
- number.presence_bedroom_g6_still_threshold
- number.presence_bedroom_g7_still_threshold
- number.presence_bedroom_g8_still_threshold
Context
- Image: Me in the room, breathing, on my laptop taking the screenshot
- Sensor: LD2410B (firmware v2.44.24073110)
- Integration: ESPHome 2025.4.1 via Home Assistant add-on
- MCU: ESP32 (240 MHz, 4 MB Flash)
- Distance to user: 275 cm
- Mounting: Inside a 1 mm plastic case with antenna cutouts
- Environment: No motion sources; quiet room
Observed Problem
I’m attempting to use the LD2410B for simple presence detection (turn on light when someone is in the room). However, I’m experiencing signal ambiguity between an empty room and an occupied room with a person sitting still.
Signal Levels
Condition | g3–g5 Still Energy (%) | g3–g5 Move Energy (%) | Notes |
---|---|---|---|
Empty Room | 4–15% | 3–15% | Possibly reflections or EMI |
Person Sitting (275 cm) | 5–18% | 6–20% | Varies per second |
Person Moving | 10–40% | 15–40% | Transient spike only |
As seen, the “still” energy while seated overlaps the baseline noise, and fluctuates frequently around thresholds. This results in:
- False negatives: presence not detected while seated
- False positives: presence detected when room is empty
The internal binary sensor presence
toggles inconsistently, and I have not found stable thresholds.
Attempted Solutions
- Ensured no fans/EMI; sensor has line of sight
Questions
- How can I increase the signal-to-noise ratio for “still” presence at ~2.75 m?
- How can I make an automation when an empty room reads similar to a room with somebody in it?
- Are there known minimum amplitude thresholds for reliable “still” detection per firmware version?
- Would moving the sensor out of the enclosure make a significant difference (RCS increase)?