Human Presence Detection with Millimeter Wave Sensors

In this article, I'm explaining how to use the LD2410 millimeter wave sensor to detect human presence and control an LED with an ESP32 board.
Jul 27, 2024 — 7 mins read — Electronics

Human Presence Detection with Millimeter Wave Sensors

One of the classic challenges for detecting human presence in electronics projects is the detection of stationary people.

A PIR sensor will only look at the temperature change in the covered area over time, so when someone is sitting or sleeping in a room, after the set threshold, the sensor will report no presence until a new movement is detected.

This is a problem for smart home applications where we have cases where we need to know if someone is present in the room or not no matter if they are moving or sleeping in a bed.

That is why a new sensor has been developed that uses radio waves at 24GHz to detect even the slightest movement of the human body at distances of up to 5 meters. In the video below, I'm providing an overview of the sensor and an example of how to use it with ESP32.


This video is sponsored by Altium 365. Click here to get a free trial and try it out!


Understanding the LD2410 Millimeter Wave Sensor

The LD2410 is an advanced sensor designed specifically for detecting human presence with millimeter waves. Unlike traditional passive infrared (PIR) sensors that rely on detecting motion to sense presence, the LD2410 can detect both moving and stationary individuals. This makes it incredibly versatile, as it can pick up on someone sitting, standing still, or even sleeping.

The LD2410C variant of the sensor features a nearly square form factor and is equipped with five pins: TX and RX for UART communication, VCC and GND for power, and an output pin that can provide a digital signal. There are additional variants like the LD2410B with a different form factor so you can select the one that best suits your need.

A key advantage of the LD2410 is its ability to operate at 24 GHz and detect targets up to 5-6 meters away, depending on the environment. It allows for the definition of up to eight zones within this range, each with different sensitivity levels for detecting motion or stationary targets.


Tools and materials needed

On the links below you have all of the hardware used or mentioned in the video. By buying through the links, you are supporting the channel and my work, without any additional cost to you!


Connecting the LD2410 to a USB to Serial Adapter

By connecting the sensor directly to a USB to serial adapter, we will be able to connect the sensor to a computer and visualize its data using some of the available programs, like the LD2410 Configurator and the LD2410 Tool from the sensor manufacturer.

The connections are done using the following schema:

  • TX Pin (LD2410) to RX Pin (USB Adapter)
  • RX Pin (LD2410) to TX Pin (USB Adapter)
  • VCC Pin (LD2410) to 5V Pin (USB Adapter)
  • GND Pin (LD2410) to GND Pin (USB Adapter)


Visualizing the Sensor Data

By using any of the provided tools for the LD2410 sensor, once we establish a serial connection to it, we can graphically view the output data. In it, we have general information if there is a presence or not, whether that presence is stationary or moving, and we also get information about the confidence score of the received signal in each of the 8 zones of the sensor.

The tools also allow us to adjust the gains for each of the zones, so we can adjust the sensitivity of the sensor based on our needs and application.

Keep in mind that a serial connection can only be established in one place and with one tool at a time so if you have one of the tools opened or you are viewing data in the Arduino serial monitor, you will need to close that connection before opening it with another tool.


Connecting the LD2410 and LED to the ESP32

Next, we’ll connect the LD2410 sensor and an LED to the ESP32 board using the schema below:

  • TX Pin (LD2410) to GPIO 16 (ESP32)
  • RX Pin (LD2410) to GPIO 17 (ESP32)
  • VCC Pin (LD2410) to 5V (Vin) Pin (ESP32)
  • GND Pin (LD2410) to GND Pin (ESP32)
  • OUT Pin (LD2410) – not connected, as we will use the UART interface for data

The LD2410 sensor can work from 5 to 12V on its VCC pin. With the FireBeetle 2, the Vin pin is not connected to the input 5V supply because of the battery charging circuit so I connected the sensor to the 3.3V pin. Even thou this is out of specs for the sensor, it seems to be working but further testing needs to be done to verify the accuracy of the provided data.

For the output LED, we need to connect the long leg (anode) of the LED to GPIO 15 on the ESP32 with a 100-ohm resistor in between. The short leg of the LED is then connected to the GND pin on the ESP32.


Arduino Code

To interact with the sensor, we will be using the MyLD2410 Library. The library provides an example sketch called `sensor_data.ino` that i slightly modified to use the correct serial port on the ESP32 board as well as adding the code that controls the LED.

The full code of the sketch is available below.

/*
  This program reads all data received from
  the HLK-LD2410 presence sensor and periodically
  prints the values to the serial monitor.
  
  Several #defines control the behavior of the program:
  #define SERIAL_BAUD_RATE sets the serial monitor baud rate
  #define ENHANCED_MODE enables the enhanced (engineering)
  mode of the sensor. Comment that line to switch to basic mode.
  #define DEBUG_MODE enables the printing of debug information
  (all reaceived frames are printed). Comment the line to disable
  debugging.

  Communication with the sensor is handled by the 
  "MyLD2410" library Copyright (c) Iavor Veltchev 2024

  Use only hardware UART at the default baud rate 256000,
  or change the #define LD2410_BAUD_RATE to match your sensor.
  For ESP32 or other boards that allow dynamic UART pins,
  modify the RX_PIN and TX_PIN defines

  Connection diagram:
  Arduino/ESP32 RX  -- TX LD2410 
  Arduino/ESP32 TX  -- RX LD2410
  Arduino/ESP32 GND -- GND LD2410
  Provide sufficient power to the sensor Vcc (200mA, 5-12V) 
*/
#ifdef ESP32
#define sensorSerial Serial1
#define RX_PIN 16
#define TX_PIN 17
#define INDICATOR_PIN 15
#elif defined(ARDUINO_SAMD_NANO_33_IOT)
#define sensorSerial Serial1
#else
#error "This sketch only works on ESP32 or Arduino Nano 33IoT"
#endif

// User defines
#define SERIAL_BAUD_RATE 115200
#define ENHANCED_MODE
// #define DEBUG_MODE

//Change the communication baud rate here, if necessary
//#define LD2410_BAUD_RATE 256000
#include "MyLD2410.h"

#ifdef DEBUG_MODE
MyLD2410 sensor(sensorSerial, true);
#else
MyLD2410 sensor(sensorSerial);
#endif

unsigned long nextPrint = 0, printEvery = 1000;  // print every second

void printValue(const byte &val) {
  Serial.print(' ');
  Serial.print(val);
}

void printData() {
  Serial.print(sensor.statusString());
  if (sensor.presenceDetected()) {

    digitalWrite(INDICATOR_PIN, HIGH);

    Serial.print(", distance: ");
    Serial.print(sensor.detectedDistance());
    Serial.print("cm");
  } else {
    digitalWrite(INDICATOR_PIN, LOW);
  }
  Serial.println();

  if (sensor.movingTargetDetected()) {
    Serial.print(" MOVING    = ");
    Serial.print(sensor.movingTargetSignal());
    Serial.print("@");
    Serial.print(sensor.movingTargetDistance());
    Serial.print("cm ");
    if (sensor.inEnhancedMode()) {
      Serial.print("\n signals->[");
      sensor.getMovingSignals().forEach(printValue);
      Serial.print(" ] thresholds:");
      sensor.getMovingThresholds().forEach(printValue);
    }
    Serial.println();
  }
  if (sensor.stationaryTargetDetected()) {
    Serial.print(" STATIONARY= ");
    Serial.print(sensor.stationaryTargetSignal());
    Serial.print("@");
    Serial.print(sensor.stationaryTargetDistance());
    Serial.print("cm ");
    if (sensor.inEnhancedMode()) {
      Serial.print("\n signals->[");
      sensor.getStationarySignals().forEach(printValue);
      Serial.print(" ] thresholds:");
      sensor.getStationaryThresholds().forEach(printValue);
    }
    Serial.println();
  }
  Serial.println();
}

void setup() {
  Serial.begin(SERIAL_BAUD_RATE);
#ifdef ESP32
  sensorSerial.begin(LD2410_BAUD_RATE, SERIAL_8N1, RX_PIN, TX_PIN);
#else
  sensorSerial.begin(LD2410_BAUD_RATE);
#endif
  pinMode(INDICATOR_PIN, OUTPUT);
  delay(2000);
  Serial.println(__FILE__);
  if (!sensor.begin()) {
    Serial.println("Failed to communicate with the sensor.");
    while (true)
      ;
  }

#ifdef ENHANCED_MODE
  sensor.enhancedMode();
#endif

  delay(nextPrint);
}

void loop() {
  if ((sensor.check() == MyLD2410::Response::DATA) && (millis() > nextPrint)) {
    nextPrint = millis() + printEvery;
    printData();
  }
}


Conclusion and Next Steps

With the demo of the LD2410 millimeter wave sensor and the ESP32 board, you now have the tools to create advanced presence detection systems that go beyond the limits of traditional PIR sensors.

I hope this tutorial has given you a solid foundation to start your project for the application that you need. The applications are endless, from smart lighting systems to occupancy monitoring in commercial spaces and whatever you choose to create, feel free to share it with me in the comments below or in the video comments.

If you found this tutorial helpful, don't forget to hit the like button and subscribe for more DIY electronics projects in the future. Your feedback is invaluable, so feel free to leave comments or ask questions below. For all the tools, code, and additional resources mentioned in this guide, check out the links provided above and in the video description.

Stay tuned for more exciting projects and tutorials, and happy building!

esp32 mmwave arduino presence movement
Read next

Voice-Controlled LED Using ESP32 and Arduino Cloud with Google Assistant

Picture a smart home from the movies. You come in from the front door and are immediately greeted by a voice telling you your home's latest...

You might also enojy this

I made a BLE receiver for my garage door

I wanted to be able to control my garage door from my phone so I created a custom BLE receiver for it with the RYBG211_Lite module from Reya...