DIY Human Sensor L12 Base on HLK-LD2412

The HLK-LD2412 has some nice enhancements to the LD2410 (we use it for a range of our radars, such as the 1U, 1WX, 1MS, etc.):

  • Better antenna design
  • Larger coverage area
  • Better static capability
  • The included light module is also better at performing in low light.
  • Up to 12 gate detections means you can fine-tune the sensitivity of certain gates by filtering them.
  • With three resolutions (0.25m, 0.5m, 0.75m), compared to the LD2410, there are 0.5m more.

In our tests, we also found some shortcomings:

  • The shortest detection distance showed a large numerical error, and the HLK developers explained that the ranging aspect of the radar was weakened in favour of enhanced overall radar detection.





We share our sensors on eBay and we can send them all over the world, so feel free to explore.

We will share our yaml at a later date, for now we are still tweaking them.

1 Like

How does this differ from the F2? I’m very happy with the 3 F2 sensors I purchased, but if I was looking to expand my sensor network, how would you describe the use case for the F2 versus the new L12?

1 Like

Things are still just getting started, and it’s hard to specify how much of a difference it makes, but there are some nice enhancements relative to the LD2410. For the F2, it’s great, but the price is higher.
I think with all these radar modules, even hlk probably can’t figure out how exactly they are any different.
So it’s subtle and we’ll gather more user opinions after our initial testing.

For our first impressions, the ld2412 has a nice relative ld2410 boost, and our sense is that it’s more stable. But the f2 has low heat and strong antennae, it’s nice and one of those don’t worry about it radars. And the ld2412, ld2410 is like one of those manual cars that can be a lot of fun to operate for complex situations where you want to fine-tune (especially with the increase in the number of adjustable doors from 8 to 13, and the addition of 0.5m which is an intermediate resolution between 0.2m and 0.75m). I think it belongs to the kind of people who love to toss it around.

2 Likes

I have one of those LD2412 - would very much like to see your current ESPHome configuration, even if it’s not perfect!

2 Likes

There has been some feedback from the initial L12 users and so far it looks positive, we will be releasing the source code in 1-2 weeks and as time is running out we will get this done as soon as possible. We’ll post an announcement in the screek community when we do, so you can keep an eye out for that.

4 Likes

Love to see your code, once its ready.

Hi, quick question on the mmwave sensors you’ve tested.

I have built my own “assistant” based on the 2450 and esp32, so it includes light sensor, LED, speaker, microphone, temp sensor etc and sits in the corner of my lounge.

One of the main problems I find with the 2450 is that if there are 2 people in the room, and 1 person leaves, it marks the as no occupancy. It also isn’t very good at tracking stationary people as we already know.

I like the gimmick of tracking location in the room, but honestly, I’d rather more accurate presence detection. So with the 2410b (or the 2412 which seems like it’s better?), how does it handle the scenario where one person leaves a room?

Thanks

2 Likes

it’s here now.

3 Likes

Hi, sorry just saw this reply. For ld2410 or 2412, they just think there’s someone or no one, and when there’s no one it’s just that they don’t exist.

the project is cook:)

Was patiently waiting for you code, but I am having issues compiling

INFO ESPHome 2024.8.3
INFO Reading configuration /config/esphome/kitchen-controller.yaml...
INFO Generating C++ source...
INFO Compiling app...
Processing kitchen-controller (board: esp32-s3-devkitc-1; framework: arduino; platform: platformio/[email protected])
--------------------------------------------------------------------------------
HARDWARE: ESP32S3 240MHz, 320KB RAM, 8MB Flash
 - toolchain-riscv32-esp @ 8.4.0+2021r2-patch5 
 - toolchain-xtensa-esp32s3 @ 8.4.0+2021r2-patch5
Dependency Graph
|-- AsyncTCP-esphome @ 2.1.3
|-- WiFi @ 2.0.0
|-- FS @ 2.0.0
|-- Update @ 2.0.0
|-- ESPAsyncWebServer-esphome @ 3.2.2
|-- DNSServer @ 2.0.0
|-- ESPmDNS @ 2.0.0
|-- noise-c @ 0.1.6
|-- Wire @ 2.0.0
Compiling .pioenvs/kitchen-controller/src/esphome/components/uart/uart_component_esp32_arduino.cpp.o
Compiling .pioenvs/kitchen-controller/src/esphome/components/wifi/wifi_component_esp8266.cpp.o
Compiling .pioenvs/kitchen-controller/src/esphome/components/wifi/wifi_component_esp_idf.cpp.o
Compiling .pioenvs/kitchen-controller/src/esphome/components/wifi/wifi_component_libretiny.cpp.o
Compiling .pioenvs/kitchen-controller/src/esphome/components/wifi/wifi_component_pico_w.cpp.o
Compiling .pioenvs/kitchen-controller/src/esphome/core/application.cpp.o
src/esphome/components/uart/uart_component_esp32_arduino.cpp: In member function 'virtual void esphome::uart::ESP32ArduinoUARTComponent::setup()':
src/esphome/components/uart/uart_component_esp32_arduino.cpp:103:25: error: cannot convert 'HWCDC*' to 'HardwareSerial*' in assignment
     this->hw_serial_ = &Serial;
                         ^~~~~~
Compiling .pioenvs/kitchen-controller/src/esphome/core/bytebuffer.cpp.o
*** [.pioenvs/kitchen-controller/src/esphome/components/uart/uart_component_esp32_arduino.cpp.o] Error 1
========================= [FAILED] Took 10.61 seconds =========================

Configuration:

esphome:
  name: kitchen-controller
  friendly_name:  Kitchen Controller
  platformio_options:
    board_build.flash_mode: dio


esp32:
  board: esp32-s3-devkitc-1
  framework:
    type: arduino

# Enable logging
logger:
  baud_rate: 0

# Enable Home Assistant API
api:
  encryption:
    key:

ota:
  - platform: esphome
    password: 

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid:
    password:

captive_portal:

external_components:
  - source:
      type: git
      url: https://github.com/screekworkshop/custom_components_support_for_screek_l12
      ref: main
    components: [esp32, uart, ld2412]

uart:
- id: uart_bus
  rx_pin: 
    number: GPIO14
    mode:
      input: true
      pullup: true
  tx_pin: 
    number: GPIO13
    mode:
      input: true
      pullup: true
  baud_rate: 115200

- id: UART02
  rx_pin: GPIO6
  tx_pin: GPIO7
  baud_rate: 256000
  parity: NONE
  stop_bits: 1
  data_bits: 8

i2c:
  - id: bus_a
    sda: GPIO12
    scl: GPIO11
    scan: true

  - id: bus_b
    sda: GPIO5
    scl: GPIO4
    scan: true

ld2410:    
  - uart_id: UART02


ld2412:
  - id: ld2412_radar
    uart_id: uart_bus

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: Outside Presence

  - platform: ld2412
    has_target:
      name: Presence
    has_moving_target:
      name: Moving Target
    has_still_target:
      name: Still Target

sensor:
  - platform: bmp280
    i2c_id: bus_a
    temperature:
      name: "Kitchen Temperature"
      oversampling: 16x
    pressure:
      name: "Kitchen Pressure"
    address: 0x77
    update_interval: 10s

  - platform: aht10
    i2c_id: bus_a  
    address: 0x38
    variant: AHT20
    temperature:
      name: "Kitchen Temperature AHT10"
    humidity:
      name: "Kitchen Humidity"
    update_interval: 10s

  - platform: bh1750
    i2c_id: bus_a  
    name: "Kitchen Illuminance"
    address: 0x23
    update_interval: 10s

  - platform: bmp280
    i2c_id: bus_b
    temperature:
      name: "Outside Temperature"
      oversampling: 16x
    pressure:
      name: "Outside Pressure"
    address: 0x77
    update_interval: 10s

  - platform: aht10
    i2c_id: bus_b
    address: 0x38
    variant: AHT20
    temperature:
      name: "Outside Temperature AHT10"
    humidity:
      name: "Outside Humidity"
    update_interval: 10s

  - platform: bh1750
    i2c_id: bus_b 
    name: "Outside Illuminance"
    address: 0x23
    update_interval: 10s

  - platform: ld2410
    light:
      name: light
    moving_distance:
      name : Moving Distance
    still_distance:
      name: Still Distance
    moving_energy:
      name: Move Energy
    still_energy:
      name: Still Energy
    detection_distance:
      name: Detection Distance
    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:
  - platform: esp32_rmt_led_strip
    rgb_order: GRB
    pin: GPIO48
    num_leds: 1
    rmt_channel: 0
    chipset: ws2812
    name: "ESP RGB"

fan:
  - platform: binary
    output: fan1
    name: "Controller fan"

output:
  - platform: gpio
    pin: GPIO19
    id: fan1

switch:
  - platform: gpio
    pin: GPIO15
    id: lockremote
    name: "Lock Remote"
    on_turn_on:
    - delay: 500ms
    - switch.turn_off: lockremote

  - platform: ld2410
    engineering_mode:
      name: "engineering mode"
    bluetooth:
      name: "control bluetooth"

number:
  - platform: ld2410
    timeout:
      name: timeout
    light_threshold:
      name: light threshold
    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

button:
  - platform: ld2410
    factory_reset:
      name: "factory reset"
    restart:
      name: "restart"
    query_params:
      name: query params

  - platform: template
    name: "LD2412 BLE Enable"
    # disabled_by_default: True
    entity_category: "config"
    icon: mdi:bluetooth
    on_press:
      lambda: |-
        id(ld2412_radar) -> ble_control(true);
  - platform: template
    name: "LD2412 BLE Disable"
    # disabled_by_default: True
    entity_category: "config"
    icon: mdi:bluetooth-off
    on_press:
      lambda: |-
        id(ld2412_radar) -> ble_control(false);
  - platform: template
    name: "LD2412 Reboot"
    icon: mdi:radar
    entity_category: "config"
    on_press:
      lambda: |-
        id(ld2412_radar) -> reboot();
  - platform: template
    name: "LD2412 Factory Reset"
    icon: mdi:restart
    entity_category: "config"
    on_press:
      - lambda: |-
          id(ld2412_radar) -> factoryReset();


text_sensor:
  - platform: ld2410
    version:
      name: "firmware version"
    mac_address:
      name: "mac address"

  - platform: ld2412
    version:
      name: LD2412 FM Version
      id: ld2412_fm_version
    mac_address:
      name: LD2412 Mac
      id: ld2412_mac


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      

Since the code is primarily designed for the ESP32-C3 DIO mode of the L12, you can remove it:
components: [esp32, uart, ld2412] inside libraries other than ld2412.
On esp32-c3 the serial port logging functionality is lost, so the patch is used.

Hi @screek-workshop ,
I used your code as reference to adapt the current official code for LD2410. I don’t have to much time to work on this so I removed the engineering part because is way to much for me. One think is missing is the distance resolution which I consider important. Since you wrote that you are working with the production company, do you have more info about this? There is no documented command to read or write this configuration

1 Like

Information about the distance resolution can be found in the final hlk protocol documentation!

Hi @screek-workshop,
I can’t find it. In the official product page, the drive folder linked has only one file about the protocol and is dated 21 may. Is the same file that I used until now and I didn’t find any information about the distance resolution

try this version HLK-LD2412-24G - 资料下载 - 海凌科电子

Hi @screek-workshop,
thanks for your help! I managed to add the resolution picklist with the provided document. It was a pain to translate the chinese document in English! :smiley:

I uploaded all my code to github if someone need it:

Rihan9/LD2412 (github.com)

2 Likes

amazing, nice work, I’ll give it a try later.
Is there any chance this could be packaged up as a remote component, would be good to benefit from any improvements, rather than downloading files.

Hi,
the repository should be ready to be used as source for external components*.
If it doesn’t work, post here the error and I’ll try to fix it

*External Components — ESPHome

Sorry, I was being dim! Thanks for that.
You might want to add the example code for how to integrate it, just for anyone following along months after. Cheers!

I’m assuming the components would be…
components: [ld2412]

1 Like