Community project

Presence And Environment Monitor

ESP32
Photo of Presence And Environment Monitor
Generated with AI

stevetzor

Published October 24, 2026

This guide builds a dual-radar presence and environment monitor using an ESP32-S3 that detects occupancy and motion in a room while measuring light and temperature. The project combines two Hi-Link radar modules—the LD2410 for still-target detection and the LD2450 for tracking—with environmental sensors to create a comprehensive room awareness system. The result integrates seamlessly with Home Assistant for automation and monitoring.

The guide provides a complete parts list, wiring diagram showing all sensor connections, step-by-step assembly instructions, and pre-configured ESPHome firmware ready to deploy. Builders will learn how to wire multiple UART devices and I2C sensors to a single microcontroller, calibrate the radar modules for their space, and set up the web interface and Home Assistant integration for real-time presence and environmental data.

Wiring diagram

Wiring diagram for Presence And Environment Monitor

Gather all the parts

QtyComponent
1

Hi-Link HLK-LD2410 (original 5V model)

5V powered radar with 3.3V TTL UART at 256000 baud, per Hi-Link serial protocol V1.02. Not the LD2410S.

1

Hi-Link HLK-LD2450

5V supply rated above 200mA; 3.3V TTL UART, factory 256000 baud 8N1. Hi-Link serial protocol V1.03.

1

BH1750

Rohm BH1750FVI 16-bit digital ambient light sensor with I2C interface. Measures illuminance from 1 to 65535 lux. Two selectable I2C addresses (0x23 / 0x5C) via ADDR pin.

1

DS18B20+ temperature sensor (TO-92)

Genuine Analog Devices DS18B20, externally powered at 5V; open-drain DQ pulled up to 3.3V. Replaces BME280; temperature only.

1

4.7 kΩ resistor

4.7 kΩ

Pulls the DS18B20 open-drain data line to 3.3V, never 5V.

1

Regulated isolated USB 5V supply, 2A

Certified enclosed 5V USB wall adapter with USB-C cable to the XIAO. Both radars use the XIAO 5V USB-output pad; no separate external 5V injection. Use a good cable and test for voltage drop with both radars active.

1

XIAO ESP32-S3 supplied external 2.4GHz antenna

Use the standard XIAO supplied antenna and U.FL cable. Connect to the board antenna socket with power off. Its printed enclosure envelope is adjustable; check the actual antenna dimensions.

Assemble it in 7 steps

1. Gather the modules and disconnect power

Use a standard Seeed XIAO ESP32-S3 (8MB flash / 8MB PSRAM), an original 5V HLK-LD2410, an HLK-LD2450, a BH1750 breakout, a genuine DS18B20+ TO-92 temperature sensor, a 4.7 kΩ resistor and a certified enclosed regulated 5V 2A USB wall adapter and USB-C cable. Use suitable jumper cables. The DS18B20 replaces the BME280 and does not measure humidity. The original LD2410 needs a matching 1.27mm connector cable or careful soldering.

  • Unplug USB and the wall adapter before wiring. Never work on mains wiring; power enters only through USB-C. This design is not for the 3.3V LD2410S or newer 115200-baud variants.

2. Distribute USB power with everything unplugged

The only power input is the XIAO USB-C socket. Connect its 5V output pad to LD2410 VCC, LD2450 5V and DS18B20 VDD. Connect all sensor grounds to XIAO GND. Do not wire the adapter directly to the 5V pad; its positive and negative connections in the circuit diagram represent the USB cable. Use the regulated 5V 2A USB adapter for normal operation. Connect the XIAO supplied external antenna before powering up.

  • Never connect 5V to 3V3 or a GPIO. Do not connect a second external power supply or a battery. Check voltage under radar load and stop if the connector gets warm or the board resets; adapter current capacity does not guarantee board passthrough capacity.

3. Connect each radar's data wires

LD2410 TX → D1 (GPIO2) (readings into ESP32), RX → D0 (GPIO1) (commands from ESP32). Leave OUT disconnected. LD2450 TX → D9 (GPIO8) (readings into ESP32), RX → D10 (GPIO9) (commands from ESP32). Both use the factory 256000 baud setting.

4. Connect light and temperature sensors

BH1750 VCC → ESP32 3V3 (power), GND → GND, SDA → D4 (GPIO5) (data), SCL → D5 (GPIO6) (clock), ADDR → GND for address 0x23. DS18B20 VDD (pin 3) → USB-derived 5V, GND (pin 1) → common GND, DQ (pin 2) → D3 (GPIO4) (temperature data). Connect one end of the 4.7 kΩ resistor to DQ and the other to ESP32 3V3. For the TO-92 sensor, identify pins from its package pin diagram; do not use probe wire colors as pin identification. Keep the data cable short for this build.

  • The DS18B20 gets 5V power, but its resistor must pull data to 3.3V, never 5V. Use the bare three-pin sensor, not a module with a built-in pull-up to 5V. The BH1750 remains at 3.3V; do not move its VCC to 5V.

5. Position the sensors and test the room

Face both radar antenna surfaces toward the room, with the LD2450 upright per its manufacturer orientation. Start with the radars separated rather than touching; compare each radar's readings alone and together, then adjust spacing or direction if simultaneous operation causes false detections. Keep metal away from their antenna faces. Place the light sensor where it sees room light and the temperature sensor away from the ESP32 and warm radar modules, with airflow.

  • Allow about 30 seconds to settle after power-on. Test walking, sitting still and leaving the room. Fans, curtains, walls and adjacent rooms can cause false detections; tune detection range and sensitivity using the radar maker's tools if needed.
  • Occupancy turns on when either radar reports presence, then holds for 10 seconds after both report clear (in addition to radar timeouts). Radar states can remain stale if a module is disconnected; Device Online refers only to the ESP32 connection. LD2450 target slots are not a guaranteed people count. The LD2450 needs firmware V2.02.23090617 or later; update it with the maker's HLKRadarTool app if needed.

6. Deploy ESPHome and connect to Home Assistant

With power unplugged, check wiring. Plug the XIAO into the computer using a USB data cable and press Deploy. Use a port capable of powering the whole circuit or temporarily disconnect radar power while deploying. For normal operation move that cable to the 5V USB wall adapter. Join Presence-Sensor using password RoomSense42, open http://192.168.4.1 and enter home Wi-Fi details. Add the discovered Room Presence device using Home Assistant ESPHome integration.

  • The native API encryption key is in src/device.yaml under api.encryption.key; copy it into Home Assistant if prompted. The web readings use username admin and password RoomSense42 at the device's home-network address. The old custom /api endpoint is replaced by ESPHome entities.
  • Wireless ESPHome updates use password RoomSenseUpdate42. These are starter passwords and a project-visible API key; change them and the key in src/device.yaml before deploying on an untrusted network. No cloud account is needed.
  • Only one DS18B20 is configured, so ESPHome finds it automatically. Wi-Fi credentials entered through setup are saved on the ESP32, not in this project.

7. Print and fit-check the compact enclosure

Open data/enclosure/presence_case.scad in OpenSCAD and follow data/enclosure/README.md. Print the lid-fit and board-clip tests before the 120 × 100 × 34 mm base and lid. This revision fits the standard XIAO ESP32-S3, not the old DevKit. The radars and light board clip into the lid; the XIAO and temperature sensor fit into the base. Measure populated boards and inspect edge clearances first. No rendered STL or physical fit validation is supplied.

  • Test all printed retainers before wall mounting; adjust loose clips and the antenna guides. Keep all screw heads, wires and clips clear of antennas and components. Keep USB cable slack and secure the cable externally.
  • Indoor use only. Test detection with lid off and on and compare temperature after warm-up. The temperature bay reduces direct heating but is not thermally isolated.

Review all connections

1. Connections between "still_radar" and "ESP32"

Functionstill_radarESP32
powerVCC5V
groundGNDGND
uartTXGPIO 2
uartRXGPIO 1

2. Connections between "tracking_radar" and "ESP32"

Functiontracking_radarESP32
power5V5V
groundGNDGND
uartTXGPIO 8
uartRXGPIO 9

3. Connections between "light" and "ESP32"

FunctionlightESP32
powerVCC3V3
groundGNDGND
i2cSDAGPIO 5
i2cSCLGPIO 6
groundADDRGND

4. Connections between "climate" and "ESP32"

FunctionclimateESP32
powerVDD5V
groundGNDGND
digitalDQGPIO 4

5. Connections between "temp_pullup" and "ESP32"

Functiontemp_pullupESP32
data1 → DS18B20+ temperature sensor (TO-92) DQEXT
power23V3

6. Connections between "supply" and "ESP32"

FunctionsupplyESP32
powerPOS → Via the XIAO USB-C socket and cable only; do not also wire adapter positive to the 5V pad.5V
groundNEG → Ground carried by the same USB-C cable.GND

7. Connections between "antenna" and "ESP32"

FunctionantennaESP32
dataRF → XIAO built-in U.FL antenna socketEXT

Deploy the firmware

esphome:
  name: presence-sensor
  friendly_name: Room Presence

esp32:
  variant: esp32s3
  flash_size: 8MB
  framework:
    type: arduino

logger:
  baud_rate: 0

# Join the setup network to enter your home Wi-Fi details.
wifi:
  ap:
    ssid: Presence-Sensor
    password: RoomSense42

captive_portal:

api:
  reboot_timeout: 0s
  encryption:
    key: "A91dH3Twq8l+CZpOvKxj2eUX6rMY0bIa5QhsNGf7S4c="

ota:
  - platform: esphome
    password: RoomSenseUpdate42

web_server:
  port: 80
  version: 2
  local: true
  auth:
    username: admin
    password: RoomSense42

i2c:
  sda: GPIO5
  scl: GPIO6
  scan: true
  frequency: 100kHz

one_wire:
  - platform: gpio
    pin: GPIO4
    id: temperature_bus

uart:
  - id: still_uart
    rx_pin: GPIO2
    tx_pin: GPIO1
    baud_rate: 256000
    parity: NONE
    stop_bits: 1
  - id: tracking_uart
    rx_pin: GPIO8
    tx_pin: GPIO9
    baud_rate: 256000
    parity: NONE
    stop_bits: 1

ld2410:
  id: still_radar
  uart_id: still_uart

ld2450:
  id: tracking_radar
  uart_id: tracking_uart

binary_sensor:
  - platform: ld2410
    ld2410_id: still_radar
    has_target:
      id: still_presence
      name: LD2410 Presence
      filters: []
    has_moving_target:
      name: LD2410 Moving Target
    has_still_target:
      name: LD2410 Still Target
  - platform: ld2450
    ld2450_id: tracking_radar
    has_target:
      id: tracking_presence
      name: LD2450 Presence
      filters: []
    has_moving_target:
      name: LD2450 Moving Target
    has_still_target:
      name: LD2450 Still Target
  - platform: template
    id: room_presence
    name: Occupancy
    device_class: occupancy
    lambda: |-
      if ((id(still_presence).has_state() && id(still_presence).state) ||
          (id(tracking_presence).has_state() && id(tracking_presence).state)) {
        return true;
      }
      if (!id(still_presence).has_state() || !id(tracking_presence).has_state()) {
        return {};
      }
      return false;
    filters:
      - delayed_off: 10s
  - platform: status
    name: Device Online

sensor:
  - platform: bh1750
    name: Illuminance
    address: 0x23
    update_interval: 2s
  - platform: dallas_temp
    one_wire_id: temperature_bus
    name: Temperature
    resolution: 12
    update_interval: 10s
  - platform: ld2410
    ld2410_id: still_radar
    detection_distance:
      name: LD2410 Detection Distance
    moving_distance:
      name: LD2410 Moving Distance
    still_distance:
      name: LD2410 Still Distance
  - platform: ld2450
    ld2450_id: tracking_radar
    target_count:
      name: LD2450 Target Count
    target_1:
      x:
        name: Target 1 X
      y:
        name: Target 1 Y
      speed:
        name: Target 1 Speed
    target_2:
      x:
        name: Target 2 X
      y:
        name: Target 2 Y
      speed:
        name: Target 2 Speed
    target_3:
      x:
        name: Target 3 X
      y:
        name: Target 3 Y
      speed:
        name: Target 3 Speed

switch:
  - platform: ld2450
    ld2450_id: tracking_radar
    multi_target:
      name: LD2450 Multi Target Tracking

text_sensor:
  - platform: ld2450
    ld2450_id: tracking_radar
    version:
      name: LD2450 Firmware

button:
  - platform: restart
    name: Restart Device

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik