ProtoCore v0.0.1
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
ld2410.h File Reference

HLK-LD2410 24 GHz mmWave presence / motion radar codec (PC_ENABLE_LD2410). More...

#include <stddef.h>
#include <stdint.h>

Go to the source code of this file.

Classes

struct  Ld2410State
 Target presence state (report payload byte 2). More...
 
struct  Ld2410Report
 A decoded LD2410 target report. Engineering fields are 0 unless engineering. More...
 
struct  Ld2410Stream
 Byte-by-byte report-frame reassembler (fixed buffer, resyncs on noise). More...
 
struct  Ld2410Ack
 A decoded command-ACK frame. payload points into the caller's frame (not copied). More...
 

Macros

#define LD2410_MAX_GATES   9
 Range gates the LD2410 reports energy for in engineering mode (gate 0..8).
 
#define LD2410_FRAME_MAX   72
 Largest assembled frame: header(4) + len(2) + payload(<=60) + footer(4), rounded up.
 

Functions

bool pc_ld2410_parse_report (const uint8_t *frame, size_t len, Ld2410Report *out)
 Decode one whole LD2410 report frame (header F4 F3 F2 F1 .. footer F8 F7 F6 F5). Pure - no I/O. Validates the header/footer, the intra-frame length, the data-type byte (0x02 basic / 0x01 engineering), the 0xAA head marker and the 0x55 tail.
 
void pc_ld2410_stream_reset (Ld2410Stream *s)
 Reset a stream to the syncing state.
 
bool pc_ld2410_stream_push (Ld2410Stream *s, uint8_t byte, Ld2410Report *out)
 Feed one received byte. When it completes a valid report frame, fills out and returns true; otherwise returns false (still syncing / mid-frame / bad frame - it resyncs).
 
bool pc_ld2410_present (const Ld2410Report *r)
 true if r shows any target (moving or stationary).
 
uint16_t pc_ld2410_distance_cm (const Ld2410Report *r)
 Best available target distance (cm): the moving distance if moving, else stationary.
 
size_t pc_ld2410_cmd_config_enable (uint8_t *buf, size_t cap)
 "Enable configuration" (word 0x00FF, value 0x0001).
 
size_t pc_ld2410_cmd_config_end (uint8_t *buf, size_t cap)
 "End configuration" (word 0x00FE).
 
size_t pc_ld2410_cmd_engineering (uint8_t *buf, size_t cap, bool on)
 Enable (0x0062) or disable (0x0063) engineering mode.
 
size_t pc_ld2410_cmd_restart (uint8_t *buf, size_t cap)
 Restart the module (word 0x00A3).
 
size_t pc_ld2410_cmd_bluetooth (uint8_t *buf, size_t cap, bool on)
 LD2410B: turn the Bluetooth radio on (value 0x0001) or off (0x0000). Word 0x00A4.
 
size_t pc_ld2410_cmd_get_mac (uint8_t *buf, size_t cap)
 LD2410B: query the module's Bluetooth MAC address (word 0x00A5, value 0x0001).
 
size_t pc_ld2410_cmd_set_bt_password (uint8_t *buf, size_t cap, const char password[6])
 LD2410B: set the 6-octet Bluetooth control password (word 0x00A9). Takes effect after a restart and survives power loss. password is exactly 6 octets, sent in natural order (the factory default is the ASCII "HiLink" -> 48 69 4C 69 6E 6B); it is not NUL-terminated and is not padded, so pass 6 octets.
 
bool pc_ld2410_parse_ack (const uint8_t *frame, size_t len, Ld2410Ack *out)
 Decode one command-ACK frame (header, intra-frame length, footer and length agreement all checked).
 
bool pc_ld2410_ack_ok (const Ld2410Ack *ack)
 True if ack reports success (Ld2410Ack::status == 0).
 
bool pc_ld2410_ack_mac (const Ld2410Ack *ack, uint8_t mac[6])
 Extract the 6-octet MAC from a get-MAC ACK (word 0x01A5) into mac, in wire order.
 
bool pc_ld2410_begin (int rx_pin, int tx_pin)
 Open UART2 at PC_LD2410_BAUD on rx_pin / tx_pin.
 
bool pc_ld2410_poll ()
 Pump the UART through the stream.
 
const Ld2410Reportpc_ld2410_last ()
 The most recently decoded report, or nullptr before the first one arrives.
 
bool pc_ld2410_set_engineering (bool on)
 Enable/disable engineering mode (brackets the command with enable/end).
 
bool pc_ld2410_restart ()
 Restart the module (brackets the command with enable/end).
 

Detailed Description

HLK-LD2410 24 GHz mmWave presence / motion radar codec (PC_ENABLE_LD2410).

The LD2410 streams a framed serial report at 256000 baud: header F4 F3 F2 F1, a little-endian intra-frame length, the payload, and footer F8 F7 F6 F5. The payload carries the target state (none / moving / stationary / both), the moving and stationary target distance (cm) and energy (0-100), the overall detection distance, and - in "engineering mode" - the per-gate energy of all nine range gates. Configuration is a second frame kind (header FD FC FB FA, footer 04 03 02 01) carrying a 2-byte command word.

This codec is pure and host-tested: pc_ld2410_parse_report decodes one report frame, and Ld2410Stream reassembles frames byte-by-byte from a UART with resync on noise (no heap, fixed buffer). The command encoders build the config frames. On an ESP32 the binding pumps a HardwareSerial and keeps the latest report; only that read/write touches hardware.

A cheap solder-and-bench-test breakout: wire it to a UART, wave a hand, watch presence.

Author
Douglas Quigg (dstroy0)
Date
2026

Definition in file ld2410.h.

Macro Definition Documentation

◆ LD2410_MAX_GATES

#define LD2410_MAX_GATES   9

Range gates the LD2410 reports energy for in engineering mode (gate 0..8).

Definition at line 33 of file ld2410.h.

◆ LD2410_FRAME_MAX

#define LD2410_FRAME_MAX   72

Largest assembled frame: header(4) + len(2) + payload(<=60) + footer(4), rounded up.

Definition at line 36 of file ld2410.h.

Function Documentation

◆ pc_ld2410_parse_report()

bool pc_ld2410_parse_report ( const uint8_t *  frame,
size_t  len,
Ld2410Report out 
)

Decode one whole LD2410 report frame (header F4 F3 F2 F1 .. footer F8 F7 F6 F5). Pure - no I/O. Validates the header/footer, the intra-frame length, the data-type byte (0x02 basic / 0x01 engineering), the 0xAA head marker and the 0x55 tail.

Returns
true on a valid frame; false on any mismatch or a short buffer.

◆ pc_ld2410_stream_reset()

void pc_ld2410_stream_reset ( Ld2410Stream s)

Reset a stream to the syncing state.

◆ pc_ld2410_stream_push()

bool pc_ld2410_stream_push ( Ld2410Stream s,
uint8_t  byte,
Ld2410Report out 
)

Feed one received byte. When it completes a valid report frame, fills out and returns true; otherwise returns false (still syncing / mid-frame / bad frame - it resyncs).

◆ pc_ld2410_present()

bool pc_ld2410_present ( const Ld2410Report r)

true if r shows any target (moving or stationary).

◆ pc_ld2410_distance_cm()

uint16_t pc_ld2410_distance_cm ( const Ld2410Report r)

Best available target distance (cm): the moving distance if moving, else stationary.

◆ pc_ld2410_cmd_config_enable()

size_t pc_ld2410_cmd_config_enable ( uint8_t *  buf,
size_t  cap 
)

"Enable configuration" (word 0x00FF, value 0x0001).

◆ pc_ld2410_cmd_config_end()

size_t pc_ld2410_cmd_config_end ( uint8_t *  buf,
size_t  cap 
)

"End configuration" (word 0x00FE).

◆ pc_ld2410_cmd_engineering()

size_t pc_ld2410_cmd_engineering ( uint8_t *  buf,
size_t  cap,
bool  on 
)

Enable (0x0062) or disable (0x0063) engineering mode.

◆ pc_ld2410_cmd_restart()

size_t pc_ld2410_cmd_restart ( uint8_t *  buf,
size_t  cap 
)

Restart the module (word 0x00A3).

◆ pc_ld2410_cmd_bluetooth()

size_t pc_ld2410_cmd_bluetooth ( uint8_t *  buf,
size_t  cap,
bool  on 
)

LD2410B: turn the Bluetooth radio on (value 0x0001) or off (0x0000). Word 0x00A4.

◆ pc_ld2410_cmd_get_mac()

size_t pc_ld2410_cmd_get_mac ( uint8_t *  buf,
size_t  cap 
)

LD2410B: query the module's Bluetooth MAC address (word 0x00A5, value 0x0001).

◆ pc_ld2410_cmd_set_bt_password()

size_t pc_ld2410_cmd_set_bt_password ( uint8_t *  buf,
size_t  cap,
const char  password[6] 
)

LD2410B: set the 6-octet Bluetooth control password (word 0x00A9). Takes effect after a restart and survives power loss. password is exactly 6 octets, sent in natural order (the factory default is the ASCII "HiLink" -> 48 69 4C 69 6E 6B); it is not NUL-terminated and is not padded, so pass 6 octets.

The companion "obtain Bluetooth access" command (0x00A8) is deliberately absent: the protocol document states it answers only over Bluetooth and not the serial port, so it belongs to the BLE control channel, which this wired driver does not cover.

◆ pc_ld2410_parse_ack()

bool pc_ld2410_parse_ack ( const uint8_t *  frame,
size_t  len,
Ld2410Ack out 
)

Decode one command-ACK frame (header, intra-frame length, footer and length agreement all checked).

Returns
false if frame is not a well-formed ACK.

◆ pc_ld2410_ack_ok()

bool pc_ld2410_ack_ok ( const Ld2410Ack ack)

True if ack reports success (Ld2410Ack::status == 0).

◆ pc_ld2410_ack_mac()

bool pc_ld2410_ack_mac ( const Ld2410Ack ack,
uint8_t  mac[6] 
)

Extract the 6-octet MAC from a get-MAC ACK (word 0x01A5) into mac, in wire order.

Returns
false unless ack is a successful get-MAC ACK carrying at least 6 payload octets.

◆ pc_ld2410_begin()

bool pc_ld2410_begin ( int  rx_pin,
int  tx_pin 
)

Open UART2 at PC_LD2410_BAUD on rx_pin / tx_pin.

Returns
true on ESP32.

◆ pc_ld2410_poll()

bool pc_ld2410_poll ( )

Pump the UART through the stream.

Returns
true if a fresh report was decoded.

◆ pc_ld2410_last()

const Ld2410Report * pc_ld2410_last ( )

The most recently decoded report, or nullptr before the first one arrives.

◆ pc_ld2410_set_engineering()

bool pc_ld2410_set_engineering ( bool  on)

Enable/disable engineering mode (brackets the command with enable/end).

◆ pc_ld2410_restart()

bool pc_ld2410_restart ( )

Restart the module (brackets the command with enable/end).