first commit

This commit is contained in:
admin committed 2026-09-11 12:02:40 +07:00
commit 3eaff3a647
1 file changed
+173
+173
View File
@@ -0,0 +1,173 @@
# ESP32-S3 + HLK-LD2453 — Zone Presence Detection (port of ESP32-LD2450)
Ported from [thanhtantran/ESP32-LD2450](https://github.com/thanhtantran/ESP32-LD2450),
targeting:
- **MCU:** ESP32-S3 (Arduino framework, plain Arduino IDE — no PlatformIO)
- **Radar:** Hi-Link **HLK-LD2453** (24 GHz, 1TX+2RX, up to 3 targets)
## ⚠️ Current status: radar parser is a stub
`LD2453Parser.cpp`'s byte-level frame decoding is **not implemented yet**.
The official HLK-LD2453 "Communication Protocol" manual section (frame
header/tail, per-target byte layout, sign convention, speed encoding)
could not be sourced from a verifiable source at the time this was
written — see "Confirming the protocol" below. Everything else (Wi-Fi,
REST API, WebSocket, zone logic, non-blocking UART acquisition, raw hex
capture) is fully implemented and ready to go.
## What's reused from the original ESP32-LD2450 project
- The zone model: up to 3 rectangles in millimeters, `GET /zones` /
`POST /updateZones` REST endpoints, `ArduinoJson` for
(de)serialization — see `ZoneManager.cpp`.
- The WebSocket broadcast pattern (`AsyncWebSocket` on `/ws`,
`ws.textAll()` per frame) — see `WebServerManager.cpp`.
- The overall setup()/loop() shape and Wi-Fi reconnect handling.
## What changed
- LD2450's `rbegamer/HLK-LD2450` library dependency is gone; parsing is
now our own `LD2453Parser`, because the byte format is different for
this sensor.
- `Serial2` with fixed pins → `HardwareSerial` on **configurable**
pins (`RADAR_RX_PIN` / `RADAR_TX_PIN` in `config.h`).
- Blocking `delay()`-based sensor "reopen on failure" hack removed;
radar acquisition is now a non-blocking ring-buffer state machine
that tolerates partial/corrupted frames without ever calling
`delay()` in the acquisition path.
- Every frame now carries `node_id` and a `sequence_number`, so this
node can later feed a multi-radar fusion setup (`RADAR_A/B/C` → UDP
→ Orange Pi) without touching the parser again.
- Plain PlatformIO `.cpp`/lib_deps project → standard Arduino IDE
sketch folder.
## Wiring
```
LD2453 ESP32-S3
V -> 3V3
G -> GND
T/TX -> RADAR_RX_PIN (default GPIO18)
R/RX -> RADAR_TX_PIN (default GPIO17)
```
Change `RADAR_RX_PIN` / `RADAR_TX_PIN` in `config.h` to match your
wiring — any two free GPIOs that support UART on your ESP32-S3 board
will work, since the ESP32 Arduino core remaps UART pins in software.
Do **not** use SoftwareSerial — `HardwareSerial` is required at
256000 baud.
## Required Arduino libraries
Install via Library Manager (exact names to search for):
| Library | Used for | Notes |
|---|---|---|
| `ArduinoJson` (by Benoit Blanchon) | REST API + WebSocket JSON | v7.x |
| `ESP Async WebServer` (by me-no-dev / ESP32Async fork) | HTTP + WebSocket server | Only needed for stage 2 (`DIAGNOSTIC_MODE 0`). Check current ESP32-S3/Arduino-core-3.x compatibility for whichever fork you install — this ecosystem has had breaking forks; if it doesn't build, the `ESP32Async/ESPAsyncWebServer` fork is the actively maintained one as of this writing. |
| `AsyncTCP` | dependency of ESP Async WebServer | matching fork/version to the WebServer library above |
Board package: **esp32 by Espressif Systems**, board = your specific
ESP32-S3 dev board.
## Project layout
```
ESP32_LD2453/
ESP32_LD2453.ino - setup()/loop(), diagnostic printing
LD2453Parser.h/.cpp - UART acquisition + frame parsing (STUBBED, see above)
ZoneManager.h/.cpp - rectangular zone occupancy logic
WebServerManager.h/.cpp - Wi-Fi, REST API, WebSocket broadcast
config.example.h - copy to config.h and edit
README.md
```
## Stage 1: diagnostic mode (do this first)
1. Copy `config.example.h` to `config.h`.
2. Leave `DIAGNOSTIC_MODE 1` (the default). This disables Wi-Fi/web
entirely — Serial-only.
3. Flash, open Serial Monitor at 115200.
4. You should see:
```
LD2453 connected
UART: 256000
...
```
Target lines will currently always print `INVALID` — expected,
since the parser is stubbed. This stage exists so you can validate
wiring/baud/board bring-up independent of the parser.
## Confirming the protocol
Until `LD2453Parser`'s real frame format is filled in, use it as a
raw-capture tool:
1. In `config.h`, set `DEBUG_RADAR_RAW 1`.
2. Flash, open Serial Monitor at 115200, and let the LD2453 see some
motion. You'll get a hex dump of every raw byte the module sends,
e.g.:
```
[RAW] AA FF 03 00 4B 01 36 08 0C 00 ... (len=30)
```
3. Share that capture (and, if you can get it, the actual "5.
Communication Protocol" section of the official HLK-LD2453 user
manual — Hi-Link's own download link for it is currently
mislabeled and points at the LD2450 manual instead) so the header,
tail, per-target byte layout, and sign/speed encoding can be
confirmed and dropped into `tryParseFrame()` in `LD2453Parser.cpp`.
The exact insertion point is marked with a comment block.
## Stage 2: full firmware (once the parser is confirmed)
1. Set `DIAGNOSTIC_MODE 0` in `config.h`.
2. Fill in `WIFI_SSID` / `WIFI_PASSWORD`.
3. Flash. The board connects to Wi-Fi, starts the HTTP server, and
broadcasts one JSON message per radar frame over `/ws`.
### WebSocket data format (`ws://<ESP32_IP>/ws`)
```json
{
"sensor": "LD2453",
"node_id": "RADAR_A",
"sequence": 12345,
"timestamp": 12345678,
"targets": [
{ "id": 1, "valid": true, "x": -820, "y": 2840, "speed": 12 },
{ "id": 2, "valid": true, "x": 1350, "y": 4120, "speed": -4 }
]
}
```
`id` is the radar's target *slot* (1–3), not a persistent person
identity — a target disappearing and reappearing may land in a
different slot.
### REST API
- `GET /zones` — current zone rectangles + live occupancy
- `POST /updateZones` — update one or more zones (same shape as
`GET /zones`, partial updates supported)
- `GET /status` — basic health check (uptime)
## Multi-radar future work (not implemented yet)
Every `RadarFrame` already carries `node_id` and `sequence_number` so
that, later, this same parser output can be forwarded over UDP to an
Orange Pi doing sensor fusion across `RADAR_A/B/C`, without touching
`LD2453Parser` again. No UDP/MQTT/cloud code has been added — this
firmware only does local Wi-Fi + WebSocket, as requested.
## Code quality notes
- No `delay()` in the radar acquisition path (`LD2453Parser::update()`,
`feedByte()`) — only the one-time Wi-Fi connect retry in
`WebServerManager::begin()`, which runs once during `setup()` before
acquisition starts.
- No dynamic allocation in the parser (fixed-size ring buffer).
- Radar acquisition, zone logic, and networking are in separate
classes/files and don't call into each other directly — the `.ino`
wires them together.