HLK-LD6004 — UART presence flag (0x0A0A) latches "occupied" while BLE reports correctly

Viewed 55

Module: HLK-LD6004 (ADT6101P, 60 GHz)
Firmware reported by module: project 6, version 3.18.0
Interface: UART 115200 8N1, TinyFrame protocol (per "LD6004 Serial Communication Protocol")

Summary

On the UART/serial interface, the human-presence report 0x0A0A
(detection_state_area0..3) latches at "occupied" and never clears to all-zero
when the room becomes empty.
The frame stream stays live (frame IDs keep
incrementing, header/data checksums valid), but area0 stays 1 indefinitely —
observed for 2.5+ minutes with the room verifiably empty.

Critically: the same module, at the same moment, reports presence correctly over
Bluetooth (BLE).
Using your HLKRadarTool app over BLE, the occupancy flag clears to
"no person" within ~1 second of the person leaving, while the UART 0x0A0A flag on
the identical module is still reporting "occupied".
So the internal presence
computation and the BLE report are correct — only the UART 0x0A0A path reports a
stale/latched value.

We confirmed this with simultaneous observation: person leaves the room → BLE app
shows "unoccupied" immediately → our UART reader still shows areaStates=[1,0,0,0],
present=1 continuously, frame IDs advancing the whole time.

What we already ruled out

  • Not a checksum/framing error — header and data checksums validate; frame IDs advance.
  • 0x0A04 target list is no help: it freezes on a static reflection at ~2.0 m
    (identical x/y/z for minutes) whether the room is occupied or empty.
  • 0x0A08 point cloud is no help: it produces bursts of similar magnitude/density in
    both occupied and empty rooms, so it cannot distinguish them.
  • We run in "inherit on-chip configuration" mode (we do not send config at boot);
    the BLE app's view of the same chip is correct, so the on-chip config is fine.

Questions

  1. Is there a newer LD6004 firmware that fixes the UART 0x0A0A presence latch
    (so UART presence matches the BLE presence)? If so, how do we obtain and flash it
    (OTA over BLE, or over UART)?
  2. Is there a command or register (e.g. via 0x0201 / 0x0202 / a reset/clear
    command) that makes the UART 0x0A0A presence report track real occupancy the
    way the BLE report does?
  3. Is the UART 0x0A0A presence expected to behave identically to the BLE
    presence
    ? If they can differ, which one is authoritative?

Setup details (for reproduction)

  • Mounting: side / wall mount (installation = side).
  • Detection sensitivity: high. Hold/keep delay configured per protocol §6.
  • We do not send periodic keep-alive or interference-clear during the issue.
  • Read path: subscribe to the UART stream; parse 0x0A0A as 4×uint32 area flags.

Thank you — a firmware fix or a UART command that clears the latch would let us use
the serial interface; today we can only get correct presence over BLE.

3 Answers

Dear Hi-Link Support,

Thank you for your reply. Unfortunately it did not help us in practice: it referred to firmware versions (3.19.0 / 3.20.0 / 3.21.0) and a "Download Center", but every download link we were given returns HTTP 404, and no firmware file, changelog, or update tool was
actually provided. We cannot act on version numbers alone — we need the files themselves.

Our module: HLK-LD6004, firmware project 6, version 3.18.0 (as reported by the module's 0xFFFF firmware query over UART).

We have two distinct, reproducible problems on the UART interface. The BLE interface (via your HLKRadarTool app) behaves correctly on the same module:

  1. 0x0A0A presence LATCHES "occupied" when the room is empty. The detection_state area flags stay [1,0,0,0] indefinitely after the person leaves; frame IDs keep incrementing and header/data checksums are valid, so the stream is live — the module simply never clears
    the flag. At the same moment, the BLE app on the same module correctly shows "unoccupied".
  2. The UART side also drifts BLIND over time. After some hours it reports [0,0,0,0] / targetCount = 0 / no point cloud even with a person sitting directly in front of it, while frame IDs keep incrementing. Only a serial-port close/reopen followed by re-issuing
    0x0201 commands (0x17 normal mode, target-stream enable, point-cloud enable) restores detection — and the problem then recurs.

Could you please send us, as actual files/attachments or verified working links (the previously referenced links all returned HTTP 404):

  1. The latest LD6004 firmware binary (.bin) for our module (project 6).
  2. The official changelog, confirming which firmware version fixes (a) the UART 0x0A0A latch and (b) ideally the blind-drift described in point 2.
  3. The LD6004 UART firmware update tool and a step-by-step update procedure.
  4. Confirmation of whether an OTA update via HLKRadarTool (BLE) will be offered for a module currently on version 3.18.0, and if so, which version it will install.

Important: the iOS HLKRadarTool offers no firmware-update option for our module, and we do not have an Android device — so an OTA-via-app update is not available to us. We therefore specifically need the UART firmware update tool and the .bin file so we can flash
the module over UART from a PC / Raspberry Pi.

Thank you. We look forward to receiving the firmware binary and the changelog.

Hello,sorry for the late reply.
I’ve checked your issue with our engineers and have a few questions for you:

  1. How many milliseconds does UART read?
  2. Do you get the date every time when the radar transmits data?

Hello,

Q1 — How many milliseconds does the UART read?

We read with pyserial on a Raspberry Pi (Linux):

  • Port: 115200 baud, 8 data bits, no parity, 1 stop bit.
  • Read timeout = 200 ms. Each call requests up to 1024 bytes (ser.read(1024)) and returns as soon as data is available, blocking at most 200 ms.
  • It runs in a continuous loop; after each successfully parsed frame there is only a 10 ms sleep. So we drain the UART essentially continuously, ≤200 ms latency. We observe roughly 3–5 frames/second from the module (the frame-ID counter increments steadily).

Q2 — Do you get the data every time the radar transmits?

  • Yes: all received bytes are appended to a buffer, and we extract every complete TinyFrame (SOF 0x01, header length + header checksum validated per your protocol §4.3/4.4). We never poll-and-discard — every byte is buffered, every complete frame is parsed.
  • One exception: a few times we briefly stop reading to send config commands — a 0x0201 normal-mode keep-alive ~every 7 s, and a periodic "reload" where we close+reopen the serial port and re-send 0x08 / 0x17 / 0x06. During those short windows (~0.3–3 s) some frames
    may be missed.

Why we do that reload (context for your engineers):
The module otherwise drifts into a state where it keeps streaming but reports present=0, area=[0,0,0,0] and zero point-cloud even with a moving person ~1 m away. A "reload" (serial reset + re-enabling the streams) restores correct detection for ~5 minutes, then it
drifts to all-zero again.

Our questions back to you:

  1. Is 115200 baud sufficient for the full point-cloud + presence stream, or should it be higher? (e.g. the LD6002 uses 1.3824 Mbps.)
  2. What is the expected frame rate and max frame size, so we can size our reads correctly?
  3. Is there a recommended read cadence and a command sequence that prevents the module from drifting to all-zero output?
Related