LD2410Async
Asynchronous Arduino ESP32 library for the LD2410 mmWave radar sensor
Loading...
Searching...
No Matches
Async Commands & Processing

Why asynchronous processing matters for the LD2410

The LD2410 radar sensor continuously streams detection frames and requires explicit configuration commands to adjust its behavior. If the library were implemented with blocking (synchronous) calls, every command would have to wait for the sensor’s response before the application could continue. Since enabling config mode or requesting data can take several seconds, blocking calls would freeze the main program loop and would disrupt other tasks.

An asynchronous approach avoids this problem. Commands are sent non-blocking, and the library reports back via callbacks when acknowledgements or data arrive. This has several benefits:

  • Responsiveness - the main loop and other tasks keep running while waiting for the sensor.
  • Efficiency - incoming data frames are parsed in the background without polling or busy-waiting.
  • Scalability - multiple sensors or other asynchronous components (Wi-Fi, MQTT, UI updates) can run in parallel without interfering with each other.
  • Robustness - timeouts and retries can be handled cleanly without stalling the system.

Detection Data Callback

Whenever the LD2410 sensor transmits a valid data frame, the library automatically parses it and invokes the detection data callback. This allows your application to react immediately to sensor input without the need for polling.

Use onDetectionDataReceived() to register a callback function for detection events.

The callback delivers two parameters:

  • A pointer to the LD2410Async instance that triggered the event. This allows convenient access to members of that instance.
  • A simple presenceDetected flag (true if presence is detected, false otherwise).
Note
The callback is triggered for every received frame, not only when presenceDetected changes. This means you can always rely on it to reflect the most recent sensor state.

For applications that need more than just the quick presence flag, the library provides full access to the updated DetectionData struct. This struct contains distances, signal strengths and other info.

Detection Data Callback Example

#include "LD2410Async.h"
HardwareSerial RadarSerial(1);
void onDetection(LD2410Async* sender, bool presenceDetected) {
if (presenceDetected) {
Serial.println("Presence detected!");
} else {
Serial.println("No presence.");
}
}
void setup() {
Serial.begin(115200);
RadarSerial.begin(256000, SERIAL_8N1, 32, 33); // RX=Pin 32, TX= Pin 33
}
void loop() {
// Nothing needed here - data is processed asynchronously.
}
HardwareSerial RadarSerial(1)
void setup()
Arduino setup function which initializes the radar and registers the callback.
LD2410Async radar(RadarSerial)
Creates LD2410Async object bound to the serial port defined in RadarSerial.
void loop()
Arduino loop function which does nothing.
Asynchronous driver class for the LD2410 human presence radar sensor.
Definition LD2410Async.h:38
bool begin()
Starts the background task that continuously reads data from the sensor.
void onDetectionDataReceived(DetectionDataCallback callback)
Registers a callback for new detection data.

Configuration Callbacks

Whenever the LD2410 sensor executes or reports configuration changes, the library provides two separate callback mechanisms to keep your application informed.

Use onConfigChanged() to register a callback that is invoked whenever the sensor acknowledges and applies a configuration-changing command (for example, after setting sensitivities or timeouts). This event serves as a notification that the sensor has accepted a change, but it does not mean that the local configuration data has been refreshed. If you need updated values, you must explicitly request them from the sensor (e.g. with requestAllConfigSettingsAsync()).

Use onConfigDataReceived() to register a callback that is invoked whenever new configuration data has actually been received from the sensor. This happens after request commands such as requestAllConfigSettingsAsync() or requestGateParametersAsync(). Within this callback, the library guarantees that the internal ConfigData structure has been updated, so you can safely access it via getConfigData() or getConfigDataRef().

Note
Configuration data is not sent automatically by the sensor and is not updated automatically when internal changes occur. To refresh the local configuration structure, you must explicitly request the latest values from the sensor. The recommended way is to call requestAllConfigSettingsAsync(), which retrieves the complete configuration in one operation.

Configuration Callbacks Example

// Define the callback function
void onConfigChanged(LD2410Async* sender) {
Serial.println("Sensor acknowledged a configuration change.");
// If you want the latest config values, explicitly request them
}
// Define a helper callback for when config data arrives
Serial.print("No one timeout: ");
Serial.println(cfg.noOneTimeout);
}
}
// Somewhere in setup():
radar.onConfigChanged(onConfigChanged);
void onConfigReceived(LD2410Async *sender, LD2410Async::AsyncCommandResult result)
Callback after receiving the config data.
AsyncCommandResult
Result of an asynchronous command execution.
Definition LD2410Async.h:47
@ SUCCESS
Command completed successfully and ACK was received.
LD2410Types::ConfigData getConfigData() const
Returns a clone of the current configuration data of the radar.
void onConfigChanged(GenericCallback callback)
Registers a callback that is invoked whenever the sensor's configuration has been changed successfull...
bool requestAllConfigSettingsAsync(AsyncCommandCallback callback)
Requests all configuration settings from the sensor.
void print() const
Debug helper: print configuration contents to Serial.
unsigned short noOneTimeout
Timeout (seconds) until "no presence" is declared.

Async Commands Basics

The LD2410 sensor can be configured and queried using a large set of commands.

All commands that need to communicate with the sensor are implemented as asynchronous operations:

  • They return immediately without blocking the main loop.
  • Each command call itself returns a simple true or false:
    • true means the command was accepted for processing.
    • false means it could not be started (for example, because another command is already pending).
  • When the sensor sends back an acknowledgement (ACK) or a response, the library automatically calls the user-provided callback with a result of type AsyncCommandResult.
  • Callbacks allow your application to handle SUCCESS, FAILED, TIMEOUT, or CANCELED in a clean and non-blocking way.

List of Asynchronous Commands

Async Command Example

#include "LD2410Async.h"
HardwareSerial RadarSerial(1);
// Callback method gets triggered when all config data has been received
// Access latest config via getConfigData()
Serial.print("Max moving gate: ");
Serial.println(cfg.maxMotionDistanceGate);
Serial.print("No one timeout: ");
Serial.println(cfg.noOneTimeout);
} else {
Serial.println("Failed to retrieve config settings.");
}
}
void setup() {
Serial.begin(115200);
RadarSerial.begin(256000, SERIAL_8N1, 32, 33); // RX=Pin 32, TX=Pin 33
if (!radar.begin()) {
Serial.println("Failed to initialize the LD2410Async library");
return;
}
// Query all configuration parameters and register callback
Serial.println("Could not send config request (busy or failed).");
}
}
void loop() {
// Nothing required here – everything runs asynchronously
}
byte maxMotionDistanceGate
Furthest gate used for motion detection.

Best Practices for Async Commands

  • Check the return value - all async methods return true if the command is getting executed or false when execution of the commands is not possible for some reason (e.g. another async command pending or a para is inavlid/out of range)
  • Check the result of the callback - handle AsyncCommandResult values such as SUCCESS, FAILED, TIMEOUT, or CANCELED as necessary.
  • Be aware of busy state – before sending a command, ensure the library is not already executing another one.
    Use asyncIsBusy() if needed. All async commands check the busy state internally and will return false if another command is already pending.
  • Don’t block in callbacks - keep callbacks short and non-blocking; offload heavy work to the main loop or a task.
  • Config mode handling – you usually don’t need to manually enable or disable config mode; the library automatically handles this for commands that require it.
    Only call enableConfigModeAsync() or disableConfigModeAsync() directly if you explicitly want to keep the sensor in config mode across multiple operations.
  • Avoid overlapping commands – sending a new command while another one is still pending can cause failures.
    Always wait for the callback to complete before sending the next command, or call asyncCancel() if you need to abort the current operation.