fshr

The musings of a grumpy hairless ape




ESPHome Presence Sensor - Part 3 - LD2420 Config

This guide is presented as-is with no guarantee or warranty as to it’s correctness, accuracy, or suitability for purpose. You use the information presented here at your own risk. Please see my general disclaimer for further details.

Introduction

This is the third part in my mini guide to setting up a basic presence sensor using ESPHome, Home Assistant, and some (cheap) off the shelf components. If you haven’t already looked at Part 1 and Part 2, go take a look now as it sets up some of the pre-reqs and configuration needed to do part 3.

So in Part 1, we set out what we’re going to be making, and what we need to make it. Then in Part 2 we created, built, and installed a basic ESPHome config onto the ESP32 board and got it connected to Home Assistant. In Part 3 we’ll add on an LD2420 presence sensor and get it reporting into Home Assistant.

If you’re planning on following along and making your own sensor, then I’ll assume now that you’ve done both previous parts, have everything in place and you’re ready to go! If you’re just reading along for the fun of it, then that’s fine too and “Hi!

Again I’m going to assume a basic level of technical ability for anyone following this, I’m not going to do detailed step-by-step of “click here”, type this, “click there”, etc

(Re)Introducing the Sensor

Before we do anything else, let’s quickly revisit the sensor we’re going to be connecting.

LD2420
LD2420

For the purposes of this guide, we’re going to be using the Hi-Link LD2420. This is a mmWave presence sensor, or in other words it bounces “radar” signals around the room to detect whether there’s anybody “present” within it’s field of view. That field of view is rated up to a distance of around 8m, with a detection angle of ±60°, and while not ideal for covering an entire room, for basic presence detection (e.g. is someone sat in front of it) it’s fine, and it’s simple enough to implement for what we’re doing here.

Connecting the Sensor

Based on the LD2420 documentation, the sensor can be used with either GPIO and UART interfaces, however ESPHome only supports the LD2420 via UART connections, so that’s what we’re going to be using (UART is essentially an RS232 style serial interface).

LD2420 Pins
LD2420 Pins

We’ll be connecting the LS2420 to our ESP32 via a set of Dupont Jumper Wires (Female-Female), and we’ll need 4 cables for the collection (joined or separated):

  • Power 3.3V (marked as 3V3)
  • Power Ground (marked as GND)
  • Serial TX (marked on the LD2420 as OT1)
  • Serial RX (marked on the LD2420 as RX)

As noted in the ESPHome documentation, the module pinouts for the LD2420 vary depending on the firmware version installed. So far, all of the boards I’ve had have been on a firmware later than 1.5.3 have have had Serial TX on OT1, so that is the connectivity I’ll be using here. If you end up with a board with an older firmware you may need to change your wiring.

Connecting the ESP32

Excepting the USB-C connector, the pad based GPIO pins, and the onboard LED and buttons, the ESP32-S3-Zero comes with 16 multipurpose connectors we can use for a variety of purposes, whether as UART, PWN, I2S, ADC, I2C, SPI, or GPIO.

ESP32-S3-Zero Pinout
ESP32-S3-Zero Pinout

The board does have a pair of preset UART0 pins (TX/RX), however as these can be useful for connecting a serial console for debugging we won’t use them for our sensor connection. In addition, the board has 5V, 3V3, and GND pins available for use. As the LS2420 is quite a light power draw we will use the 3V3 and GND pins to provide power to the sensor.

As noted above, we’ll be using the Dupont Jumper Wires to connect to the sensor, and we’ll use GPIOs 1 & 2 for the UART:

  • Power 3.3V (marked as 3V3)
  • Power Ground (marked as GND)
  • Serial TX (marked on the ESP32 as 1 / GP1 / GPIO1)
  • Serial RX (marked on the ESP32 as 2 / GP2 / GPIO2)

You can use any pair of the GPIO pins for TX/RX, I’ve chosen GP1/GP2 only as they’re close to the 3V3 & GND pins and so makes cabling easier.

Plugging Stuff In

Note/Warning 1 - Take care with the 3V3 & GND connections! While it’s only 3.3v DC it’s still possible to damage either the sensor or ESP32 if you connect them incorrectly! If the sensor doesn’t work, and starts to get warm/hot to the touch, you’ve probably got things hooked up wrong and you’re at risk of letting the white smoke out.

Note 2 - You need to cross connect the TX/RX pins between the boards. i.e. the TX on one side goes to RX on the other and vice versa. If you connect TX-TX and RX-RX it won’t work!

Note 3 - The board/sensor pinouts are sometimes shown and/or labelled from the other side of the board from side with the pins. Make sure you mentally flip the pins around in your head when connecting cables so you’re connected to the right pins!

So, with the ESP32 unplugged from power, go ahead and cable up the ESP32 and sensor. For my cabling I’ll be using Dupont wires with Brown, Red, Orange, & Yellow cables, but feel free to use whatever you have available. I’ll be connecting the boards as follows:

ESP32 Pin ESP32 Use Cable Colour LD2420 Use LD2420 Pin
GND Ground Brown Ground GND
3V3 3.3v Red 3.3v 3V3
1 TX Orange RX RX
2 RX Yellow TX OT1

If you’ve followed my colours and cabling your two boards should look like this:

LD2420 Cabling
LD2420 Cabling
ESP32 Cabling
ESP32 Cabling

Assuming you’re happy with your cabling, go ahead and plug the ESP32 into power and wait for it to start up.

To check that all is ok, open a browser page to your HomeAssistant install where you’ve installed ESPHome. Go to the “ESPHome Builder” page and check that your device is still present and is now “Online”".

ESPHome Device 3
ESPHome Device 3

If it shows as “Offline” and/or the ESP32 or LD2420 seem to be getting warm, you’ve possibly connected the cables incorrectly. Unplug the ESP32 and check all cabling before trying again. If you still have issues, unplug the jumper wires completely, and just try the ESP32 on it’s own. If it still doesn’t connect you may need to work through Part 2 again to reset the device.

To check the install has worked correctly, in ESPHome Builder click the “Logs” option on the “ESP Device” card. You should hopefully see a whole bunch of device and ESPHome logs rush past, including seeing it connect to your WiFi, and hopefully at some point:

[11:57:50][I][safe_mode:041]: Boot seems successful; resetting boot loop counter
[11:57:50][D][esp32.preferences:114]: Saving 1 preferences to flash...
[11:57:50][D][esp32.preferences:142]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failed

If you get this far we’re ready to add some new config.

Updating The Config

As part of running through Part 2 we created a basic configuration for the ESP32 which got it booted, connected to WiFi, and talking to Home Assistant. However we’re now going to modify that configuration to include the pieces required for the LD2420 and presence detection.

So in the ESPHome UI, on your new device card, click the “Edit” button to open the configuration editor. In the editor, delete the current configuration and replace with the following (we’ll go through what it does at the end):

###############################################################################

substitutions:
  name: waveshare-mini-guide
  friendly_name: Waveshare Mini Guide Presence

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  name_add_mac_suffix: false
  platformio_options:
    board_build.flash_mode: dio

esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  framework:
    type: esp-idf
    version: recommended
    sdkconfig_options:
      CONFIG_ESP32_S3_BOX_BOARD: "y"
   
psram:
  mode: quad
  speed: 80MHz

################################################################################

# Wifi information
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: ${name}
    password: ${name}

captive_portal:

# Enable Home Assistant API
api:

ota:
  platform: esphome

# Enable logging
logger:

###############################################################################

uart:
  id: ld2420_uart
  tx_pin: GPIO1
  rx_pin: GPIO2
  baud_rate: 115200
  parity: NONE
  stop_bits: 1

ld2420:

###############################################################################

number:
  - platform: ld2420
    presence_timeout:
      name: Detection Presence Timeout
    min_gate_distance:
      name: Detection Gate Minimum
    max_gate_distance:
      name: Detection Gate Maximum

###############################################################################

button:
  - platform: shutdown
    name: "Shutdown"
  - platform: restart
    name: "Restart"
  - platform: safe_mode
    name: "Restart (Safe Mode)"

  - platform: factory_reset
    disabled_by_default: True
    name: "Factory Reset ESP"
    id: factory_reset_all

  - platform: ld2420
    apply_config:
      name: Apply Config
    factory_reset:
      name: Factory Reset
    restart_module:
      name: Restart Module
    revert_config:
      name: Undo Edits

select:
  - platform: ld2420
    operating_mode:
      name: Operating Mode

###############################################################################

binary_sensor:
  - platform: ld2420
    has_target:
      name: Presence

text_sensor:
  - platform: ld2420
    fw_version:
      name: LD2420 Firmware

sensor:
  - platform: ld2420
    moving_distance:
      name : Moving Distance

################################################################################

“Save” the new configuration, and click the “X” in the top left to go back to the main UI. You should see the name on the device card update to reflect the new “friendly_name” we set above.

The New Firmware

We’re now going to build and upload our updated firmware. In the UI on the device card, click the “three dots” and select “Install”. You’ll be prompted as to how you want to install the firmware on your device. As we’re now on the network we can choose “Wirelessly”. ESPHome will then build the firmware using the new config and deploy it to the ESP32 “OTA” (over the air).

To avoid issues with code dependencies, whenever you add or remove components from a configuration (e.g. the LD2420 component) ESPHome will force a clean of the build files and do a full (i.e. long) build from scratch.

Once the firmware is built and deployed you should hopefully see a whole bunch of device and ESPHome logs rush past, including seeing it connect to your WiFi, including hopefully at some point:

[11:08:55][C][uart.idf:159]: UART Bus 0:
[11:08:55][C][uart.idf:160]:   TX Pin: GPIO1
[11:08:55][C][uart.idf:161]:   RX Pin: GPIO2
[11:08:55][C][uart.idf:163]:   RX Buffer Size: 256
[11:08:55][C][uart.idf:165]:   Baud Rate: 115200 baud
[11:08:55][C][uart.idf:166]:   Data Bits: 8
[11:08:55][C][uart.idf:167]:   Parity: NONE
[11:08:55][C][uart.idf:168]:   Stop bits: 1

to show that it’s successfully configured the UART on the ESP32, and:

[11:08:55][C][ld2420:068]: LD2420:
[11:08:55][C][ld2420:069]:   Firmware Version :  v1.6.1

to show that it’s successfully found the LD2420 sensor.

If you instead see the following:

[11:05:05][W][ld2420:090]: LD2420 Firmware Version v0.0.0 and older are only supported in Simple Mode
[11:05:05][E][component:082]:   Component ld2420 is marked FAILED

then that (in my experience) tends to mean that the serial connections aren’t correct, so check your cabling and try again.

You should also start to see entries along the lines of:

[11:12:39][D][sensor:093]: 'Moving Distance': Sending state 59.00000 cm with 0 decimals of accuracy
[11:12:47][D][sensor:093]: 'Moving Distance': Sending state 105.00000 cm with 0 decimals of accuracy
[11:12:49][D][sensor:093]: 'Moving Distance': Sending state 36.00000 cm with 0 decimals of accuracy
[11:12:53][D][sensor:093]: 'Moving Distance': Sending state 86.00000 cm with 0 decimals of accuracy
[11:13:02][D][sensor:093]: 'Moving Distance': Sending state 21.00000 cm with 0 decimals of accuracy
[11:13:03][D][sensor:093]: 'Moving Distance': Sending state 50.00000 cm with 0 decimals of accuracy

This is the sensor detecting movement (probably yours) and sending a state with the (estimated) distance back to Home Assistant.

Home Assistant

If you’ve got this far and everything has worked, Congratulations!!.

The next step is to see what’s been updated on the Home Assistant side. If you open a new browser tab/page to your Home Assistant instance, and go to “Settings - Devices & services - ESPHome - Waveshare Mini Guide” (click the “1 device” link), you should see the device page for your ESP32 with (hopefully) some updates.

Under the “Sensors” section you should now see 2 new sensors for “Moving Distance” and “Presence”:"

HA Device Sensors
HA Device Sensors

  • Moving Distance - This is an estimate by the sensor of how far away the last seen movement was. Generally I’ve found that this is best taken as a general distance rather than an accurate number, in particular movement which is very close to, or very far from the sensor can confuse it and give inaccurate readings.
  • Presence - This is a true/false style flag as to whether the sensor has detected someone in it’s sensor zone. Note that unlike a motion sensor this isn’t motion detected, but true presence detected (i.e. it will only change with presence, not with motion).

Also under the “Configuration” section you should see a set of new controls:

HA Device Configuration
HA Device Configuration

  • Apply Config - Apply any configuraiton changes made below to the LD2420 (any changes made in HA won’t apply until you click this)
  • Detection Gate Maximum - The maximum distance for movement or presence detection. This is done in 70cm increments (i.e. 1 = 70cm, 2 = 1m40cm, etc.). Defaults to 12, i.e. 8.64m.
  • Detection Gate Minimum - The minimum distance for movement or presence detection. This is done in 70cm increments (i.e. 1 = 70cm, 2 = 1m40cm, etc.). Defaults to 0, i.e. 0cm.
  • Detection Presence Timeout - How long to wait after presence is “lost” before reporting presence as “clear”. Defaults to 30s.
  • Factory Reset - Reset the LD2420 to factory defaults.
  • Operating Mode - Can be used to change the mode of the sensor, e.g. for calibration. I’ve never set this to anything other than “Normal”. See ESPHome Docs for more details.
  • Undo Edits - Undo any changed you’ve made in the HA UI before you’ve done an “Apply Config”

The main controls of interest here are Detection Gate Maximum & Minimum. The sensor is quite sensitive to presence, and if pointing at a doorway or window will happily detect people walking past. Setting the “Detection Gate Maximum” to a lower number (remember multiples of 70cm) can help limit presence to just the area closer to the sensor.

Here’s a quick video showing the sensor in Home Assistant updating as I leave, wait, and then re-enter the room:

Congratulations! You’ve now got an ESPHome based presence sensor built and integrated into Home Assistant. It may be very rough and ready, and not something you would want to hang in your hallway, but hopefully this should give an idea of how to get into building your own ESPHome based devices:

  • If you have a 3D printer, why not design a case to take the ESP32 and LD2420 and sit it on a desk or table somewhere. The mmWave signal will happily work through a couple of mm of plastic, so it could easily be hidden away somewhere.
  • Add a mmWave sensor onto another ESPHome based device. For example, I pair them with ESP32 based eInk or LCD displays to trigger dynamic updates based on whether I’m in front of them or not.

And if you’ve got this far, thanks for reading, and maybe give some feedback via Mastodon!


Config Walkthrough

If you want to know a little more about the config you just applied, here’s another quick walkthrough:

substitutions:
  name: waveshare-mini-guide
  friendly_name: Waveshare Mini Guide Presence

Substitutions are like variables, you can define them once and then reference them elsewhere in the file. Here we’re defining a device name, and a friendly name.

esphome:
  name: ${name}
  friendly_name: ${friendly_name}
  name_add_mac_suffix: false
  platformio_options:
    board_build.flash_mode: dio

This sets up the basics of ESPHome on the device, including setting a device name and friendly name. The device name set here is what’s used to generate the device mDNS name. The “platformio_options” are board specific options relating to how ESPHome builds and flashes the firmware.

esp32:
  board: esp32-s3-devkitc-1
  variant: esp32s3
  framework:
    type: esp-idf
    version: recommended
    sdkconfig_options:
      CONFIG_ESP32_S3_BOX_BOARD: "y"
   
psram:
  mode: quad
  speed: 80MHz

This sets the details of the board itself, including the board type (board & variant), as well as which framework we’re using (arduino or esp-idf), and options for that framework. ESP-IDF is the newer framework, but Arduino seems to have better device support in some areas.

# Wifi information
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: ${name}
    password: ${name}

captive_portal:

Here we set our WiFi details (pulling SSID and password from the Secrets configuration), as well as enabling the backup AP and captive portal in case we can#t connect to WiFi (see the ESPHome docs for more details)

# Enable Home Assistant API
api:

ota:
  platform: esphome

# Enable logging
logger:

Here we’re enabling both the Home Assistant API (api:) and ESPHome Over-The-Air (OTA) support. These are needed if you want to manage the device over the LAN from Home Assistant and/or ESPHome respectively. We also enable the logger here so that we can view logs from the board wirelessly or over USB Serial.

All the new config is now after this point:

uart:
  id: ld2420_uart
  tx_pin: GPIO1
  rx_pin: GPIO2
  baud_rate: 115200
  parity: NONE
  stop_bits: 1

Configure the UART to talk to the LD2420. We give it a unique “id”, tell it the GPIO pins to use for TX/RX, and give it the required serial configuration.

ld2420:

Enable the LD2420 component

number:
  - platform: ld2420
    presence_timeout:
      name: Detection Presence Timeout
    min_gate_distance:
      name: Detection Gate Minimum
    max_gate_distance:
      name: Detection Gate Maximum

Add the controls for configuration of the detection gate and timeout. These will be visible in Home Assistant.

button:
  - platform: shutdown
    name: "Shutdown"
  - platform: restart
    name: "Restart"
  - platform: safe_mode
    name: "Restart (Safe Mode)"

  - platform: factory_reset
    disabled_by_default: True
    name: "Factory Reset ESP"
    id: factory_reset_all

  - platform: ld2420
    apply_config:
      name: Apply Config
    factory_reset:
      name: Factory Reset
    restart_module:
      name: Restart Module
    revert_config:
      name: Undo Edits

Here we define a set of buttons to display in Home Assistant. We have the previous buttons from the prior config (Shutdown, Restart, Safe Mode), plus some new buttons for the LD2420 and a main Factory Reset button (disabled).

select:
  - platform: ld2420
    operating_mode:
      name: Operating Mode

Add the control for selecting the LD2420 operating mode. This will be visible in Home Assistant.

binary_sensor:
  - platform: ld2420
    has_target:
      name: Presence

Add a binary (on/off) sensor for the presence detection. This will be visible in Home Assistant.

text_sensor:
  - platform: ld2420
    fw_version:
      name: LD2420 Firmware

Add a text sensor for the LD2420 firmware. This will be visible in Home Assistant.

sensor:
  - platform: ld2420
    moving_distance:
      name : Moving Distance

Add a generic sensor for the moving distance. This will be visible in Home Assistant.

Note: Any number/button/sensor defined with a platform of “ld2420” will automatically get linked back to that item in the LD2420 component, e.g. the binary Presence sensor will link into the presence state in the sensor and make it available in ESPHome and to Home Assistant.


Posted 12 February 2025

In HomeAutomation SmartHome HomeAssistant ESPHome