I have an improoved version of HLK-LD2420 running on ESP32 with SSD1306 display. It also has a diagnostic. I'm not a programmer (my expertise is hardware/IoT), so I had help form Artificial Inteligence.
Code: Select all
/*
* BasicUsage.ino - Basic example for LD2420 Radar Sensor Library - ESP32 Version
*
* This example demonstrates the basic usage of the LD2420 library on ESP32.
* It shows how to initialize the sensor, read distance data, and use callbacks.
*
* Hardware connections for ESP32:
* - LD2420 VCC -> 3.3V
* - LD2420 GND -> GND
* - LD2420 TX -> Pin 16 (RX2)
* - LD2420 RX -> Pin 17 (TX2)
* - SSD1306 SDA -> GPIO 21
* - SSD1306 SCL -> GPIO 22
*
* Author: cyrixninja
* Date: July 22, 2025
* Adapted for ESP32: [Mauro Miyashiro/DeepSeek/Qwen]
*/
#include <HardwareSerial.h>
#include "LD2420.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// For ESP32, we can use HardwareSerial instead of SoftwareSerial
#define RX_PIN 16
#define TX_PIN 17
// OLED Display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
// Create HardwareSerial instance (UART2 on ESP32)
HardwareSerial sensorSerial(2);
LD2420 radar;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Variables for display update timing
unsigned long lastDisplayUpdate = 0;
const unsigned long DISPLAY_UPDATE_INTERVAL = 500; // Update display every 500ms
// Test variables
bool rxTestPassed = false;
bool txTestPassed = false;
bool communicationTested = false;
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
while (!Serial) {
delay(10); // Wait for Serial Monitor
}
Serial.println("=== LD2420 Radar Sensor Example - ESP32 ===");
// Initialize OLED display
if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
Serial.println("✓ SSD1306 display initialized!");
// Display startup message
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20,0);
display.println("LD2420 Radar");
display.setCursor(20,25);
display.println("Inicializing...");
display.display();
delay(3000);
// Initialize HardwareSerial for sensor communication
sensorSerial.begin(115200, SERIAL_8N1, RX_PIN, TX_PIN);
// Test radar sensor communication with RX/TX verification
bool radarInitialized = initializeRadarWithTest();
if (radarInitialized) {
Serial.println("LD2420 initialized successfully!");
Serial.println(radar.getVersionInfo());
display.clearDisplay();
display.setCursor(0,0);
display.println("LD2420: OK");
display.setCursor(0,20);
display.println("RX: " + String(rxTestPassed ? "OK" : "FAIL"));
display.setCursor(0,35);
display.println("TX: " + String(txTestPassed ? "OK" : "FAIL"));
display.display();
delay(3000);
} else {
Serial.println("Failed to initialize LD2420!");
display.clearDisplay();
display.setCursor(0,0);
display.println("LD2420: FAIL");
display.setCursor(0,20);
display.println("RX: " + String(rxTestPassed ? "OK" : "FAIL"));
display.setCursor(0,35);
display.println("TX: " + String(txTestPassed ? "OK" : "FAIL"));
display.setCursor(0,50);
display.println("Verify connections!");
display.display();
while (1) {
delay(1000);
// Blink display to indicate error
display.invertDisplay(true);
delay(500);
display.invertDisplay(false);
delay(500);
}
}
// Configure distance range (optional)
radar.setDistanceRange(0, 400); // 0-400 cm range
// Set update interval (optional)
radar.setUpdateInterval(50); // Update every 50ms
Serial.println("Setup complete. Waiting for detections...");
Serial.println("----------------------------------------");
// Initial display setup
updateDisplay("Testing...", "Waiting", 0, false);
}
bool initializeRadarWithTest() {
Serial.println("Starting LD2420 communication...");
// Test 1: Basic initialization
display.clearDisplay();
display.setCursor(0,0);
display.println("Test LD2420:");
display.setCursor(0,20);
display.println("1. Initializing...");
display.display();
if (!radar.begin(sensorSerial)) {
Serial.println("Basic initialization fail");
return false;
}
Serial.println("Basic initializations is OK");
delay(3000);
// Test 2: RX Test - Check if we can read data from sensor
display.clearDisplay();
display.setCursor(0,0);
display.println("Test LD2420:");
display.setCursor(0,20);
display.println("1. OK");
display.setCursor(0,35);
display.println("2. Test RX");
display.display();
rxTestPassed = testRXCommunication();
Serial.println(rxTestPassed ? "RX test is OK" : "RX test fail");
delay(3000);
// Test 3: TX Test - Check if we can write commands to sensor
display.clearDisplay();
display.setCursor(0,0);
display.println("Test LD2420:");
display.setCursor(0,20);
display.println("1. OK");
display.setCursor(0,35);
display.println("2. " + String(rxTestPassed ? "OK" : "FAIL"));
display.setCursor(0,50);
display.println("3. Test TX");
display.display();
txTestPassed = testTXCommunication();
Serial.println(txTestPassed ? "Teste TX OK" : "Test TX FAIL");
delay(3000);
// Only proceed with data validation if both RX and TX are working
bool dataTestPassed = false;
if (rxTestPassed && txTestPassed) {
// Test 4: Data validation test
display.clearDisplay();
display.setCursor(0,0);
display.println("Test LD2420:");
display.setCursor(0,20);
display.println("1. OK");
display.setCursor(0,30);
display.println("2. " + String(rxTestPassed ? "OK" : "FAIL"));
display.setCursor(0,40);
display.println("3. " + String(txTestPassed ? "OK" : "FAIL"));
display.setCursor(0,50);
display.println("4. Validating dataset");
display.display();
dataTestPassed = testDataValidation();
Serial.println(dataTestPassed ? "Test dataset is OK" : "Test dataset FAIL");
delay(3000);
} else {
Serial.println("Sking test dataset - RX ou TX fail");
dataTestPassed = false;
}
communicationTested = true;
return rxTestPassed && txTestPassed && dataTestPassed;
}
bool testRXCommunication() {
Serial.println("Testing comunication RX...");
// First, check if we're receiving any data at all on the serial port
Serial.println("checking dataset in the serial port...");
int bytesAvailable = 0;
for (int i = 0; i < 10; i++) {
bytesAvailable = sensorSerial.available();
if (bytesAvailable > 0) {
Serial.println("Dataset detected in the serial port: " + String(bytesAvailable) + " bytes");
break;
}
delay(100);
}
if (bytesAvailable == 0) {
Serial.println("No dataset received in the serial port");
return false;
}
// Try to read version info multiple times
for (int i = 0; i < 5; i++) {
String versionInfo = radar.getVersionInfo();
if (versionInfo.length() > 0 && versionInfo != "Unknown") {
Serial.println("RX OK: " + versionInfo);
return true;
}
// Try to read basic data
radar.update();
delay(100);
if (radar.isDataValid()) {
LD2420_Data data = radar.getCurrentData();
Serial.println("RX OK - Dataset received: " + String(data.distance) + "cm");
return true;
}
delay(200);
}
return false;
}
bool testTXCommunication() {
Serial.println("Testing omunication TX...");
// Test 1: Check if we can reset the sensor configuration
// This requires actual TX communication
Serial.println("Test 1: Restarting configuration...");
// Save current state
bool hadValidDataBefore = radar.isDataValid();
int previousDistance = 0;
if (hadValidDataBefore) {
LD2420_Data data = radar.getCurrentData();
previousDistance = data.distance;
}
// Send reset command (change settings significantly)
radar.setDistanceRange(20, 300); // Change range
delay(200);
radar.setUpdateInterval(100); // Change interval
delay(200);
// Now try to restore original settings
radar.setDistanceRange(0, 400);
delay(200);
radar.setUpdateInterval(50);
delay(200);
// Test 2: Verify the sensor responds to our commands
// by checking if we can still get data after configuration changes
Serial.println("Test 2: Checking return from commands...");
int successfulReads = 0;
for (int i = 0; i < 8; i++) {
radar.update();
delay(150);
if (radar.isDataValid()) {
successfulReads++;
LD2420_Data data = radar.getCurrentData();
Serial.println("Leitura " + String(i+1) + ": " + String(data.distance) + "cm");
}
// If we get several successful reads, TX is working
if (successfulReads >= 2) {
Serial.println("TX OK - Sensor answer comands");
return true;
}
}
// Test 3: Alternative test - check if sensor stops responding when we send bad commands
Serial.println("Test 3: Resiliance test...");
// If we have RX working but no response to TX commands, TX might be broken
if (rxTestPassed && successfulReads == 0) {
Serial.println("TX FAIL - RX is working but no answer from comands");
return false;
}
// If we get any successful reads, TX is working
if (successfulReads > 0) {
Serial.println("TX OK - " + String(successfulReads) + " valid reading");
return true;
}
Serial.println("TX FAIL - No answer from comands");
return false;
}
bool testDataValidation() {
Serial.println("Validating dataset from sensor...");
// Collect multiple data samples to validate
int validSamples = 0;
int totalSamples = 10;
for (int i = 0; i < totalSamples; i++) {
radar.update();
delay(100);
if (radar.isDataValid()) {
LD2420_Data data = radar.getCurrentData();
// Validate data ranges and consistency
if (data.distance >= 0 && data.distance <= 400 && data.isValid) {
validSamples++;
Serial.println("Amostra " + String(i+1) + ": " + String(data.distance) + "cm - VALID");
} else {
Serial.println("Amostra " + String(i+1) + ": " + String(data.distance) + "cm - Out of range");
}
} else {
Serial.println("Amostra " + String(i+1) + ": Invalid dataset");
}
delay(100);
}
// Consider test passed if we get at least 50% valid samples
bool testPassed = (validSamples >= (totalSamples / 2));
Serial.println("Valid samples: " + String(validSamples) + "/" + String(totalSamples));
return testPassed;
}
void loop() {
// Update the radar sensor (call this regularly)
radar.update();
// You can also read data directly
if (radar.isDataValid()) {
LD2420_Data data = radar.getCurrentData();
// Print status every 2 seconds to Serial
static unsigned long lastPrint = 0;
if (millis() - lastPrint > 2000) {
printStatus(data);
lastPrint = millis();
}
// Update display more frequently (every 500ms)
if (millis() - lastDisplayUpdate > DISPLAY_UPDATE_INTERVAL) {
updateDisplayFromData(data);
lastDisplayUpdate = millis();
}
} else {
// No valid data available
if (millis() - lastDisplayUpdate > DISPLAY_UPDATE_INTERVAL) {
updateDisplay("No dataset", communicationTested ? "Verify sensor" : "Testing...", 0, false);
lastDisplayUpdate = millis();
}
}
delay(10);
}
// Update display with radar data
void updateDisplayFromData(LD2420_Data data) {
String distanceStr = String(data.distance) + " cm";
String stateStr = stateToString(data.state);
updateDisplay(distanceStr, stateStr, data.distance, data.isValid);
}
// Main display update function
void updateDisplay(String distance, String state, int distanceValue, bool isValid) {
display.clearDisplay();
// Header
display.setTextSize(1);
display.setCursor(0, 0);
display.println("LD2420 Radar Sensor");
// Distance information
display.setCursor(0, 16);
display.setTextSize(1);
display.print("Distance: ");
display.println(distance);
// State information
display.setTextSize(1);
display.setCursor(0, 29);
display.print("Status: ");
display.println(state);
// Data validity and age
display.setCursor(0, 41);
display.print("Dataset: ");
display.println(isValid ? "Valid" : "Invalid");
// Visual indicator based on distance
if (isValid && distanceValue > 0) {
// Draw a simple radar-like visualization
int indicatorWidth = map(constrain(distanceValue, 0, 400), 0, 400, 5, 120);
display.fillRect(0, 55, indicatorWidth, 8, SSD1306_WHITE);
// Add distance markers
display.setCursor(0, 55);
display.print("0");
display.setCursor(120, 55);
display.print("4m");
}
display.display();
}
// Helper function to print current status to Serial
void printStatus(LD2420_Data data) {
Serial.println("--- Current Status ---");
Serial.print("Distance: ");
Serial.print(data.distance);
Serial.println(" cm");
Serial.print("State: ");
Serial.println(stateToString(data.state));
Serial.print("Last update: ");
Serial.print(millis() - data.timestamp);
Serial.println(" ms ago");
Serial.print("Data valid: ");
Serial.println(data.isValid ? "Yes" : "No");
Serial.print("Communication: RX=");
Serial.print(rxTestPassed ? "OK" : "FAIL");
Serial.print(", TX=");
Serial.println(txTestPassed ? "OK" : "FAIL");
Serial.println("---------------------");
}
// Helper function to convert state to string
String stateToString(LD2420_DetectionState state) {
switch (state) {
case LD2420_NO_DETECTION:
return "No detection";
case LD2420_DETECTION_ACTIVE:
return "Detection OK";
case LD2420_DETECTION_LOST:
return "Detection lost";
default:
return "Unknow";
}
}