The HLK LD2420 is a sophisticated 24GHz radar sensor that brings professional-grade human presence detection to your Arduino projects. Unlike PIR sensors that only detect motion, the LD2420 can detect stationary human presence, making it perfect for smart home automation, security systems, and IoT applications.
- True Human Presence Detection: Detects both moving and stationary humans
- No Blind Zones: Works from 0.2m to 8m range
- High Accuracy: Β±35cm precision within detection range
- Wide Coverage: Wide detection angle
- Real-time Data: 10Hz refresh rate for responsive applications
- Download from GitHub
- Extract the ZIP file
- Copy to Arduino/libraries folder
- Restart Arduino IDE
- Download from GitHub
- Open Arduino IDE
- Go to Sketch β Include Library β Add.ZIP Library...
- Select the downloaded ZIP file
Create a new sketch and add:
#include "LD2420.h"
If no errors appear, the library is installed correctly.
Basic Interface Tutorial
For the simplest possible radar detection that only shows distance changes, use the provided SimpleMotionDetection example:
#include <SoftwareSerial.h>
#include "LD2420.h"
// Define RX and TX pins for SoftwareSerial
#define RX_PIN 8
#define TX_PIN 9
// Create instances
SoftwareSerial sensorSerial(RX_PIN, TX_PIN);
LD2420 radar; // Use default constructor
// Track last distance to detect changes
int lastDistance = -1;
bool wasDetecting = false;
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
while (!Serial) {
delay(10);
}
Serial.println("=== Simple Motion Detection ===");
// Initialize SoftwareSerial for LD2420
sensorSerial.begin(115200);
// Initialize the radar sensor
if (radar.begin(sensorSerial)) {
Serial.println("Radar ready. Waiting for motion...");
} else {
Serial.println("Failed to initialize radar!");
while (1) delay(1000);
}
// Configure sensor
radar.setDistanceRange(0, 600);
radar.setUpdateInterval(50); // 20Hz update rate
}
void loop() {
radar.update(); // Update radar readings
// Check if motion is detected
bool isDetecting = radar.isDetecting();
int currentDistance = radar.getDistance();
if (isDetecting) {
// Only print when distance changes
if (currentDistance != lastDistance) {
Serial.print("Motion detected at ");
Serial.print(currentDistance);
Serial.println("cm");
lastDistance = currentDistance;
wasDetecting = true;
}
} else {
// Motion stopped - reset for next detection
if (wasDetecting) {
lastDistance = -1;
wasDetecting = false;
}
}
delay(10);
}
This Tutorial demonstrates:
- β Basic sensor initialization
- β Simple motion detection with distance output
- β No repeated messages for the same distance
- β Clean, minimal code structure
Expected Output:
For comprehensive radar functionality with callbacks, zones, and data filtering, use the AdvancedUsage example:
#include <SoftwareSerial.h>
#include "LD2420.h"
// Define RX and TX pins for SoftwareSerial
#define RX_PIN 8
#define TX_PIN 9
// Create instances
SoftwareSerial sensorSerial(RX_PIN, TX_PIN);
LD2420 radar; // Use default constructor
// Detection zones
struct DetectionZone {
int minDistance;
int maxDistance;
String name;
bool isActive;
unsigned long lastDetection;
};
DetectionZone zones[] = {
{0, 50, "Close Range", false, 0},
{51, 150, "Medium Range", false, 0},
{151, 300, "Far Range", false, 0}
};
const int NUM_ZONES = sizeof(zones) / sizeof(zones[0]);
// Data filtering
const int FILTER_SIZE = 5;
int distanceFilter[FILTER_SIZE];
int filterIndex = 0;
bool filterFull = false;
// Configuration
unsigned long statusInterval = 5000; // Print status every 5 seconds
unsigned long lastStatusPrint = 0;
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
while (!Serial) {
delay(10);
}
Serial.println("=== LD2420 Advanced Example ===");
// Initialize SoftwareSerial for LD2420
sensorSerial.begin(115200);
Serial.println("SoftwareSerial initialized on RX:8, TX:9");
// Initialize the radar sensor
if (radar.begin(sensorSerial)) {
Serial.println("β LD2420 initialized successfully!");
} else {
Serial.println("β Failed to initialize LD2420!");
while (1) delay(1000);
}
// Configure sensor
radar.setDistanceRange(0, 400);
radar.setUpdateInterval(50);
// Set up callbacks
radar.onDetection(onDetectionEvent);
radar.onStateChange(onStateChangeEvent);
radar.onDataUpdate(onDataUpdateEvent);
// Initialize filter
initializeFilter();
Serial.println("Setup complete. Monitoring detection zones...");
printZoneInfo();
}
void loop() {
radar.update(); // Update radar readings
// Check zone status
updateZones();
// Print periodic status
if (millis() - lastStatusPrint > statusInterval) {
printDetailedStatus();
lastStatusPrint = millis();
}
delay(10);
}
// Initialize the distance filter
void initializeFilter() {
for (int i = 0; i < FILTER_SIZE; i++) {
distanceFilter[i] = 0;
}
filterIndex = 0;
filterFull = false;
}
// Add a value to the filter and return the filtered result
int addToFilter(int newValue) {
distanceFilter[filterIndex] = newValue;
filterIndex = (filterIndex + 1) % FILTER_SIZE;
if (!filterFull && filterIndex == 0) {
filterFull = true;
}
// Calculate average
int sum = 0;
int count = filterFull ? FILTER_SIZE : filterIndex;
for (int i = 0; i < count; i++) {
sum += distanceFilter[i];
}
return count > 0 ? sum / count : 0;
}
// Update detection zones
void updateZones() {
bool isDetecting = radar.isDetecting();
int currentDistance = radar.getDistance();
for (int i = 0; i < NUM_ZONES; i++) {
bool wasActive = zones[i].isActive;
// Check if object is in this zone
if (isDetecting &&
currentDistance >= zones[i].minDistance &&
currentDistance <= zones[i].maxDistance) {
zones[i].isActive = true;
zones[i].lastDetection = millis();
// Print zone activation
if (!wasActive) {
Serial.print("π― Zone activated: ");
Serial.print(zones[i].name);
Serial.print(" (");
Serial.print(currentDistance);
Serial.println(" cm)");
}
} else {
zones[i].isActive = false;
}
}
}
// Callback functions
void onDetectionEvent(int distance) {
int filteredDistance = addToFilter(distance);
Serial.print("π‘ Raw: ");
Serial.print(distance);
Serial.print(" cm, Filtered: ");
Serial.print(filteredDistance);
Serial.println(" cm");
}
void onStateChangeEvent(LD2420_DetectionState oldState, LD2420_DetectionState newState) {
Serial.print("π State change: ");
Serial.print(stateToString(oldState));
Serial.print(" β ");
Serial.println(stateToString(newState));
// Reset all zones when no detection
if (newState == LD2420_NO_DETECTION) {
for (int i = 0; i < NUM_ZONES; i++) {
zones[i].isActive = false;
}
Serial.println("π All zones cleared");
}
}
void onDataUpdateEvent(LD2420_Data data) {
// This callback gets called for every data update
// Use it for continuous monitoring or logging
static unsigned long updateCounter = 0;
updateCounter++;
// Print data rate every 100 updates
if (updateCounter % 100 == 0) {
static unsigned long lastRateCheck = 0;
unsigned long now = millis();
if (lastRateCheck > 0) {
float rate = 100000.0 / (now - lastRateCheck); // Updates per second
Serial.print("π Data rate: ");
Serial.print(rate, 1);
Serial.println(" Hz");
}
lastRateCheck = now;
}
}
// Convert detection state to string
String stateToString(LD2420_DetectionState state) {
switch (state) {
case LD2420_NO_DETECTION: return "No Detection";
case LD2420_DETECTION_ACTIVE: return "Active Detection";
case LD2420_DETECTION_LOST: return "Detection Lost";
default: return "Unknown";
}
}
// Print zone information
void printZoneInfo() {
Serial.println("\\n=== Detection Zones ===");
for (int i = 0; i < NUM_ZONES; i++) {
Serial.print(zones[i].name);
Serial.print(": ");
Serial.print(zones[i].minDistance);
Serial.print("-");
Serial.print(zones[i].maxDistance);
Serial.println(" cm");
}
Serial.println("=====================\\n");
}
// Print detailed status
void printDetailedStatus() {
Serial.println("\\n--- Detailed Status ---");
LD2420_Data currentData = radar.getCurrentData();
Serial.print("Target detected: ");
Serial.println(radar.isDetecting() ? "Yes" : "No");
Serial.print("Distance: ");
Serial.print(radar.getDistance());
Serial.println(" cm");
Serial.print("State: ");
Serial.println(stateToString(radar.getState()));
Serial.print("Data valid: ");
Serial.println(radar.isDataValid() ? "Yes" : "No");
Serial.print("Last update: ");
Serial.print(radar.getLastUpdateTime());
Serial.println(" ms ago");
Serial.println("\\nZone Status:");
for (int i = 0; i < NUM_ZONES; i++) {
Serial.print(" ");
Serial.print(zones[i].name);
Serial.print(": ");
if (zones[i].isActive) {
Serial.print("ACTIVE (");
Serial.print(millis() - zones[i].lastDetection);
Serial.println(" ms ago)");
} else {
Serial.println("Inactive");
}
}
Serial.println("---------------------\\n");
}
This Tutorial demonstrates:
- β Multiple detection zones (Close, Medium, Far range)
- β Real-time callbacks for detection events
- β Data filtering for noise reduction
- β State change monitoring
- β Detailed status reporting
- β Performance metrics
Expected Output:
Configure the sensor to detect objects only within specific ranges:
#include <SoftwareSerial.h>
#include "LD2420.h"
SoftwareSerial radarSerial(8, 9);
LD2420 radar;
void setup() {
Serial.begin(115200);
radarSerial.begin(115200);
if (radar.begin(radarSerial)) {
// Set detection range: 50cm to 100cm
radar.setDistanceRange(50, 100);
// Set faster update rate
radar.setUpdateInterval(50); // Check every 50ms
radar.onDetection(onDetection);
Serial.println("π Detection range: 50cm - 300cm");
Serial.println("β‘ Update rate: 20Hz");
}
}
void loop() {
radar.update();
delay(10);
}
void onDetection(int distance) {
// This will only trigger for distances between 50-300cm
Serial.print("β
Valid detection: ");
Serial.print(distance);
Serial.println(" cm");
}
Expected Output:
This comprehensive tutorial has covered everything you need to know about interfacing the HLK LD2420 radar sensor with Arduino. From basic detection to advanced smart home automation, the LD2420 offers unprecedented capabilities for human presence detection.
Support and Community:- GitHub repository: https://github.com/cyrixninja/LD2420
- Submit issues and feature requests
- Contribute to the library development
Happy building! π
Comments