Documentation

LD1125H 24GHz mmWave Human Presence Radar Sensor Module | ShillehTek Product Manual
Documentation / LD1125H 24GHz mmWave Human Presence Radar Sensor Module | ShillehTek Product Manual

LD1125H 24GHz mmWave Human Presence Radar Sensor Module | ShillehTek Product Manual

ArduinoESP32ld1125h-24ghz-mmwave-human-presence-radar-sensor-modulemanualmmWavePresence SensorRadarshillehtek

Overview

The LD1125H is a 24GHz millimeter-wave human presence radar from Hi-Link. It is a compact 4-pin module that outputs human-readable ASCII strings over a 3.3V UART, reporting both moving and stationary targets along with their distance. Because it streams plain text frames like mov, dis=1.23 and occ, dis=0.85, it is one of the easiest mmWave radars to integrate - no binary parser required.

Inside, the LD1125H uses FMCW radar at 24GHz to measure micro-movements down to chest rise from breathing. This lets it hold presence even when a person sits perfectly still, something a PIR sensor simply cannot do. Detection works through plastic enclosures, drywall, glass, and most fabrics, and is largely immune to temperature, light, and humidity changes.

Typical projects: occupancy-based lighting, bathroom and stairwell automation, smart desks that know you're still there, bed/sleep presence sensors, hidden security trip-wires behind drywall, and ESPHome/Home Assistant nodes.

At a Glance

Technology
24GHz FMCW Radar
Output Format
ASCII over UART
Detection Range
Up to ~8 m
Operating Voltage
5V DC
UART Baud
115200 (8N1)
Best For
Static + moving presence

Specifications

Parameter Value
Module HLK-LD1125H
Operating Frequency 24GHz ISM band
Operating Voltage 5V DC (4.5V - 5.5V)
Average Current ~85 mA
Moving Target Range 0.4 m - 8 m (configurable)
Static Target Range 0.4 m - 6 m (configurable)
Distance Resolution ~0.05 m
Detection Angle ±60deg horizontal / ±45deg vertical
UART Baud Rate 115200, 8N1
UART Logic Level 3.3V TTL
Connector 2.0 mm pitch, 4-pin
Operating Temperature -20degC to +65degC
Dimensions ~22 mm x 15 mm

Pinout Diagram

LD1125H 24GHz mmWave radar pinout labeling the 2.0mm 4-PIN interface as VCC (5V), GND, URX (TTL receive) and UTX (TTL send)

Wiring Guide

Arduino Wiring

The Uno's only hardware UART is used by the Serial Monitor, so we read the radar with SoftwareSerial on D2/D3. SoftwareSerial handles 115200 unreliably on a Uno - if you see garbled frames, switch to a Mega (use Serial1) or an ESP32.

Sensor Pin Arduino Pin
VCC 5V
GND GND
UTX D2 (SoftwareSerial RX)
URX D3 (SoftwareSerial TX)
Warning: URX is the module's RECEIVE pin - it must go to the Arduino's TX (D3). UTX is the module's TRANSMIT pin and goes to the Arduino's RX (D2). Crossing them swapped will simply produce silence.
Tip: If 115200 SoftwareSerial is unstable, send the config command uart_baud 9600\r\n followed by save to drop the radar to a Uno-friendly baud rate.

ESP32 Wiring

The ESP32 is the recommended host - 3.3V logic, three hardware UARTs, and plenty of buffer. We use UART2 on GPIO16/17.

Sensor Pin ESP32 Pin
VCC 5V (VIN)
GND GND
UTX GPIO16 (RX2)
URX GPIO17 (TX2)
Tip: Mount the LD1125H away from the ESP32's antenna and any switching regulators - 24GHz radar is sensitive to RF interference. A 5 cm gap is usually enough.

Raspberry Pi Wiring

Disable the serial login shell with sudo raspi-config -> Interface Options -> Serial Port -> Login shell: No, Hardware serial: Yes. Reboot, then read the radar from /dev/serial0.

Sensor Pin Raspberry Pi Pin
VCC Pin 2 (5V)
GND Pin 6 (GND)
UTX Pin 10 (GPIO15 / RXD)
URX Pin 8 (GPIO14 / TXD)
Warning: The Pi's GPIO is 3.3V. Never connect the radar pins to anything 5V tolerant only - it's fine here because the LD1125H also runs 3.3V TTL.

Raspberry Pi Pico Wiring

We use UART0 on GP0/GP1.

Sensor Pin Pico Pin
VCC VBUS (Pin 40)
GND GND (Pin 38)
UTX GP1 (Pin 2, UART0 RX)
URX GP0 (Pin 1, UART0 TX)
Tip: The Pico's 3.3V output is too weak to power the radar - use VBUS (5V) for VCC, not 3V3(OUT).

Code Examples

Arduino

Reads ASCII frames from the LD1125H, splits them on commas, and prints the human-readable status and distance.

ld1125h_arduino.ino
// LD1125H ASCII reader for Arduino Uno
// Wiring: UTX->D2, URX->D3, VCC->5V, GND->GND
// Frames look like:   mov, dis=1.23   or   occ, dis=0.85

#include <SoftwareSerial.h>
SoftwareSerial RadarSerial(2, 3); // RX, TX

String line;

void setup() {
  Serial.begin(115200);
  RadarSerial.begin(115200);
  Serial.println("LD1125H reader ready");
}

void loop() {
  while (RadarSerial.available()) {
    char c = RadarSerial.read();
    if (c == '\n') {
      line.trim();
      if (line.length()) {
        if (line.startsWith("mov")) {
          Serial.print("MOVING  ");
        } else if (line.startsWith("occ")) {
          Serial.print("STATIC  ");
        } else {
          Serial.print(line);
          Serial.println();
          line = "";
          continue;
        }
        int eq = line.indexOf('=');
        if (eq > 0) Serial.print(line.substring(eq + 1));
        Serial.println(" m");
      }
      line = "";
    } else if (c != '\r') {
      line += c;
    }
  }
}

ESP32

Same parser on a hardware UART. Includes a helper that sends configuration commands like th1=120 (moving sensitivity) or rmax=6 (max range in meters).

ld1125h_esp32.ino
// LD1125H on ESP32 - ASCII reader + config helper
#include <HardwareSerial.h>
HardwareSerial RadarSerial(2);

String line;

void sendCmd(const String &cmd) {
  RadarSerial.print(cmd);
  RadarSerial.print("\r\n");
}

void setup() {
  Serial.begin(115200);
  RadarSerial.begin(115200, SERIAL_8N1, 16, 17);
  delay(500);
  // Example config: 6 m max, moderate sensitivity
  sendCmd("rmax=6");
  sendCmd("mth1=80");
  sendCmd("mth2=50");
  sendCmd("mth3=30");
  sendCmd("save");
  Serial.println("LD1125H ESP32 reader ready");
}

void loop() {
  while (RadarSerial.available()) {
    char c = RadarSerial.read();
    if (c == '\n') {
      line.trim();
      if (line.length()) {
        bool moving = line.startsWith("mov");
        bool stat   = line.startsWith("occ");
        int eq = line.indexOf('=');
        float d = (eq > 0) ? line.substring(eq + 1).toFloat() : -1;
        if (moving)      Serial.printf("MOVING  %.2f m\n", d);
        else if (stat)   Serial.printf("STATIC  %.2f m\n", d);
        else             Serial.println(line);
      }
      line = "";
    } else if (c != '\r') {
      line += c;
    }
  }
}

Raspberry Pi (Python)

A clean Python reader that prints state + distance and exposes a callable for your own automations. Install pyserial with pip install pyserial.

ld1125h_pi.py
#!/usr/bin/env python3
"""LD1125H ASCII reader for Raspberry Pi."""
import serial, re, time

PORT = "/dev/serial0"
BAUD = 115200

ser = serial.Serial(PORT, BAUD, timeout=1)
print("LD1125H Pi reader started")

pattern = re.compile(r"^(mov|occ)\s*,\s*dis\s*=\s*([0-9.]+)", re.IGNORECASE)

def handle(state, distance_m):
    label = "MOVING" if state.lower() == "mov" else "STATIC"
    print(f"{label}  {distance_m:.2f} m")

while True:
    raw = ser.readline()
    if not raw:
        continue
    try:
        text = raw.decode("ascii", errors="ignore").strip()
    except UnicodeDecodeError:
        continue
    m = pattern.match(text)
    if m:
        handle(m.group(1), float(m.group(2)))

Raspberry Pi Pico (MicroPython)

The Pico version uses UART0. A tiny line buffer keeps it RAM-friendly.

ld1125h_pico.py
# LD1125H on Raspberry Pi Pico (MicroPython)
from machine import UART, Pin
import time

uart = UART(0, baudrate=115200, tx=Pin(0), rx=Pin(1))
buf = ""

print("LD1125H Pico reader ready")

while True:
    if uart.any():
        chunk = uart.read(uart.any())
        try:
            buf += chunk.decode("ascii")
        except UnicodeError:
            buf = ""
            continue
        while "\n" in buf:
            line, buf = buf.split("\n", 1)
            line = line.strip()
            if not line:
                continue
            if line.startswith("mov") or line.startswith("occ"):
                label = "MOVING" if line.startswith("mov") else "STATIC"
                eq = line.find("=")
                if eq > 0:
                    try:
                        d = float(line[eq + 1:])
                        print(label, "%.2f m" % d)
                    except ValueError:
                        pass
    time.sleep_ms(20)

Frequently Asked Questions

What's the difference between "mov" and "occ" output?
mov = a moving target (walking, waving). occ = an occupied/static target (sitting, sleeping). Either one is a confirmed human presence.
How do I change the maximum detection distance?
Send rmax=N over UART where N is meters (e.g. rmax=4) followed by save. The setting is stored in non-volatile memory.
My radar reports false detections - how do I tune it?
Raise the sensitivity thresholds for the affected distance bands using mth1, mth2, mth3 for moving targets and oth1, oth2, oth3 for static targets. Higher numbers = less sensitive. Always finish with save.
Does it work behind drywall?
Yes. 24GHz penetrates drywall, wood, plastic, and glass well. Metal, foil-backed insulation, and thick concrete will block it.
Is a level shifter needed for 5V boards?
No. The module's TX is 3.3V, which is a valid HIGH for AVR Arduinos. The module's RX tolerates 5V signals on its input safely. Power VCC with 5V.
Will it work with ESPHome / Home Assistant?
Yes - there are community ESPHome custom components for the LD1125H that expose presence and distance as Home Assistant entities. The ASCII protocol makes it especially easy to integrate.
Can I run it from a 3.3V supply?
No. The module requires 5V on VCC. Its internal regulator drops that to 3.3V for the RF front-end. Powering with 3.3V will cause unreliable detection.