LD2410Async
Asynchronous Arduino ESP32 library for the LD2410 mmWave radar sensor
Loading...
Searching...
No Matches
tortureTest.ino
Go to the documentation of this file.
1/**
2 * @file tortureRequestCommands.ino
3 * @brief
4 * LD2410Async torture test: endlessly executes random *request* commands,
5 * measures execution time, tracks stats, and prints a summary every 10 minutes
6 * or when the spacebar is pressed in the terminal window (will not work in a
7 * purely monitor window).
8 *
9 * Important!
10 * Adjust RADAR_RX_PIN and RADAR_TX_PIN to your wiring.
11 */
12
13#include <Arduino.h>
14#include <Ticker.h>
15#include "LD2410Async.h"
16
17 // ========================= USER CONFIGURATION =========================
18 // UART pins for the LD2410 sensor (ESP32 UART1 example)
19#define RADAR_RX_PIN 32 // ESP32 pin that receives data from the radar (radar TX)
20#define RADAR_TX_PIN 33 // ESP32 pin that transmits data to the radar (radar RX)
21
22// UART baudrate for the radar sensor (factory default is often 256000)
23#define RADAR_BAUDRATE 256000
24
25#define LED_PIN 2 //GPIO for internal LED (adjust if needed)
26// =====================================================================
27
28// Create a HardwareSerial instance bound to UART1
29HardwareSerial RadarSerial(1);
30
31// Create the LD2410Async instance
33
34// --------------------------- Stats ----------------------------
35//@cond Hid_this_from_the_docu
36struct CommandStats {
37 const char* name;
38 unsigned long minMs;
39 unsigned long maxMs;
40 unsigned long totalMs;
41 unsigned long runs;
42 unsigned long failures; // any non-SUCCESS
43 unsigned long timeouts;
44 unsigned long failed;
45 unsigned long canceled;
46};
47// @endcond
48
59
60CommandStats stats[REQ_COUNT] = {
61 { "requestGateParametersAsync", ULONG_MAX, 0, 0, 0, 0, 0, 0, 0 },
62 { "requestFirmwareAsync", ULONG_MAX, 0, 0, 0, 0, 0, 0, 0 },
63 { "requestBluetoothMacAddressAsync",ULONG_MAX, 0, 0, 0, 0, 0, 0, 0 },
64 { "requestDistanceResolutionAsync", ULONG_MAX, 0, 0, 0, 0, 0, 0, 0 },
65 { "requestAuxControlSettingsAsync", ULONG_MAX, 0, 0, 0, 0, 0, 0, 0 },
66 { "requestAllConfigSettingsAsync", ULONG_MAX, 0, 0, 0, 0, 0, 0, 0 },
67 { "requestAllStaticDataAsync", ULONG_MAX, 0, 0, 0, 0, 0, 0, 0 },
68};
69
70volatile bool commandInFlight = false;
72unsigned long cmdStartMs = 0;
73
74// We use a Ticker to retry quickly when a send is rejected (busy)
76
77//Just to delay the next command a bit
79
80// Stats printing
81unsigned long lastStatsPrintMs = 0;
82const unsigned long STATS_PRINT_PERIOD_MS = 300000;
83
84// ----------------------- Forward decls ------------------------
85void runRandomCommand();
87
88// ------------------------ Helpers ----------------------------
90 const unsigned long dur = millis() - cmdStartMs;
91 CommandStats& s = stats[cmd];
92
94 if (dur < s.minMs) s.minMs = dur;
95 if (dur > s.maxMs) s.maxMs = dur;
96 s.totalMs += dur;
97 s.runs++;
98 }
99 else {
100 s.failures++;
101 switch (result) {
102 case LD2410Async::AsyncCommandResult::TIMEOUT: s.timeouts++; break;
103 case LD2410Async::AsyncCommandResult::FAILED: s.failed++; break;
104 case LD2410Async::AsyncCommandResult::CANCELED: s.canceled++; break;
105 default: break;
106 }
107 }
108}
109
111 Serial.println();
112 Serial.println("===== LD2410Async Torture Test (REQUEST COMMANDS) =====");
113
114 unsigned long totalRuns = 0;
115 unsigned long totalFailures = 0;
116 unsigned long totalTimeouts = 0;
117 unsigned long totalFailed = 0;
118 unsigned long totalCanceled = 0;
119
120 for (int i = 0; i < REQ_COUNT; i++) {
121 const CommandStats& s = stats[i];
122 const unsigned long minShown = (s.minMs == ULONG_MAX) ? 0 : s.minMs;
123 const unsigned long avg = (s.runs > 0) ? (s.totalMs / s.runs) : 0;
124
125 Serial.printf("%-32s | runs: %lu | failures: %lu", s.name, s.runs, s.failures);
126 Serial.printf(" (timeouts:%lu failed:%lu canceled:%lu)", s.timeouts, s.failed, s.canceled);
127 Serial.printf(" | min:%lums max:%lums avg:%lums\n", minShown, s.maxMs, avg);
128
129 // accumulate totals
130 totalRuns += s.runs;
131 totalFailures += s.failures;
132 totalTimeouts += s.timeouts;
133 totalFailed += s.failed;
134 totalCanceled += s.canceled;
135 }
136
137 // minutes since program start
138 unsigned long minutes = millis() / 60000;
139
140 Serial.println("-------------------------------------------------------");
141 Serial.printf("TOTALS | runs: %lu | failures: %lu",
142 totalRuns, totalFailures);
143 Serial.printf(" (timeouts:%lu failed:%lu canceled:%lu)\n",
144 totalTimeouts, totalFailed, totalCanceled);
145 Serial.printf("Uptime: %lu minute(s)\n", minutes);
146 Serial.println("=======================================================");
147}
148
149
151 // Retry very soon without blocking
152 retryTicker.once_ms(1, []() { runRandomCommand(); });
153}
154
155// --------------------- Command driver ------------------------
157 // Start timing *only* when we are about to send.
158 digitalWrite(LED_PIN, HIGH);
159
160 cmdStartMs = millis();
161 bool accepted = false;
162
163 switch (cmd) {
164 case REQ_GATE_PARAMS:
166 break;
167 case REQ_FIRMWARE:
169 break;
170 case REQ_BT_MAC:
172 break;
173 case REQ_DIST_RES:
175 break;
176 case REQ_AUX:
178 break;
179 case REQ_ALL_CONFIG:
181 break;
182 case REQ_ALL_STATIC:
184 break;
185 default:
186 accepted = false;
187 break;
188 }
189
190 return accepted;
191}
192
198
200 if (commandInFlight) return; // safety
201
203 //Need to diable config mode first
204 Serial.print("!");
206 return;
207 }
208 }
209
210
211 currentCmd = static_cast<RequestCommand>(random(REQ_COUNT));
212 commandInFlight = true;
213
214
215 if (!sendCommand(currentCmd)) {
216 // Library said "no" (likely busy) — back off and try again
217 commandInFlight = false;
219 }
220}
221
223 switch (random(4)) {
224 case 0:
226 break;
227 case 1:
228 delayNextCommandTicker.once_ms(random(10) + 1, runRandomCommand);
229 break;
230 case 2:
231 delayNextCommandTicker.once_ms((random(10) + 1) * 10, runRandomCommand);
232 break;
233 default:
234 delayNextCommandTicker.once_ms((random(30) + 1) * 100, runRandomCommand);
235 break;
236 }
237}
238
239
241 digitalWrite(LED_PIN, LOW);
243 Serial.print(".");
244 }
245 else {
246 Serial.print("x");
247 }
248
249 recordResult(currentCmd, result);
250 commandInFlight = false;
251
252
254
255}
256
257// --------------------- Arduino lifecycle ---------------------
258void setup() {
259 Serial.begin(115200);
260 delay(500);
261 Serial.println("LD2410Async torture test starting...");
262
263
264 pinMode(LED_PIN, OUTPUT);
265 digitalWrite(LED_PIN, LOW);
266
267 // Setup UART to the radar
269
270 // Start LD2410Async background task (required for async operation)
271 if (!ld2410.begin()) {
272 Serial.println("ERROR: ld2410.begin() failed (already running?)");
273 }
274
275
276
277 // Kick off the first command
279
280 lastStatsPrintMs = millis();
281}
282
283void loop() {
284 // Print stats every 10 minutes
285 const unsigned long now = millis();
287 printStats();
288 lastStatsPrintMs = now;
289 }
290
291 // Print stats immediately if user presses spacebar
292 if (Serial.available()) {
293 int c = Serial.read();
294 if (c == ' ') {
295 printStats();
296 }
297 }
298
299
300 // Nothing else to do: LD2410Async runs its own FreeRTOS task after begin()
301 // Keep loop() lean to maximize timing accuracy for callbacks.
302}
Asynchronous driver class for the LD2410 human presence radar sensor.
Definition LD2410Async.h:38
bool requestGateParametersAsync(AsyncCommandCallback callback)
Requests the current gate parameters from the sensor.
bool begin()
Starts the background task that continuously reads data from the sensor.
AsyncCommandResult
Result of an asynchronous command execution.
Definition LD2410Async.h:47
@ TIMEOUT
No ACK received within the expected time window.
@ FAILED
Command failed (sensor responded with negative ACK).
@ SUCCESS
Command completed successfully and ACK was received.
@ CANCELED
Command was canceled by the user before completion.
bool requestAllStaticDataAsync(AsyncCommandCallback callback)
Requests all static information from the sensor.
bool disableConfigModeAsync(AsyncCommandCallback callback)
Disables config mode on the radar.
bool isConfigModeEnabled() const
Detects if config mode is enabled.
bool requestDistanceResolutionAsync(AsyncCommandCallback callback)
Requests the current distance resolution setting from the sensor.
bool requestFirmwareAsync(AsyncCommandCallback callback)
Requests the firmware version of the sensor.
bool requestBluetoothMacAddressAsync(AsyncCommandCallback callback)
Requests the Bluetooth MAC address.
bool requestAllConfigSettingsAsync(AsyncCommandCallback callback)
Requests all configuration settings from the sensor.
bool requestAuxControlSettingsAsync(AsyncCommandCallback callback)
Requests the current auxiliary control settings.
void printStats()
void runRandomCommandAfterDelay()
Ticker retryTicker
HardwareSerial RadarSerial(1)
void setup()
unsigned long lastStatsPrintMs
volatile bool commandInFlight
RequestCommand currentCmd
unsigned long cmdStartMs
void disableConfigModeCallback(LD2410Async *, LD2410Async::AsyncCommandResult result)
void scheduleRetry()
#define RADAR_BAUDRATE
#define RADAR_RX_PIN
bool sendCommand(RequestCommand cmd)
LD2410Async ld2410(RadarSerial)
CommandStats stats[REQ_COUNT]
Ticker delayNextCommandTicker
void runRandomCommand()
void commandCallback(LD2410Async *sender, LD2410Async::AsyncCommandResult result)
#define LED_PIN
RequestCommand
@ REQ_GATE_PARAMS
@ REQ_COUNT
@ REQ_ALL_STATIC
@ REQ_DIST_RES
@ REQ_ALL_CONFIG
@ REQ_BT_MAC
@ REQ_FIRMWARE
@ REQ_AUX
#define RADAR_TX_PIN
const unsigned long STATS_PRINT_PERIOD_MS
void recordResult(RequestCommand cmd, LD2410Async::AsyncCommandResult result)
void loop()