Presence Sensor Part 1

Monday, Mar 24, 2025 | 7 minute read | Updated at Monday, Mar 24, 2025

Squwal
Presence Sensor Part 1

In this first blog article, we will see how to develop a zigbee presence sensor for home assistant.

In this article, which will surely be in several parts, we will see together how to obtain a zigbee presence sensor. This base will eventually serve me later to develop new sensors, I already have several ideas in mind.

Introduction

First of all, it’s good to know that to detect the presence of a person in a room, the most commonly used solution is the use of a PIR motion detector. This type of sensor (very often battery-powered) detects moving people by measuring variations in infrared radiation emitted by the human body. It’s very effective for passage rooms (such as corridors or stairs), but it can no longer detect you once you’re static sitting on the couch. For this use case, millimeter wave presence detectors have become more common. In principle, they emit millimeter waves that will reflect off a person, and are sensitive enough to detect micro-movements such as breathing or heartbeats.

There are several models from the usual home automation manufacturers, and for my part, I notably have the FP-2 model from Aqara installed in my living room. This works perfectly as long as I am standing, navigating between the living room and the dining room as well as when I am sitting at the table, but unfortunately, it cannot detect my presence when I am on the couch, being quite far from its mounting location. Rather than buying a second one (still sold at around €90 excluding promotions) and also for the challenge, I decided to try to make one myself.

Aqara FP2 Presence Sensor

Aqara FP2 Presence Sensor

Layout of my dining room, the aqara sensor is behind a curtain

Layout of my dining room, the aqara sensor is behind a curtain

Use Cases

I wanted to be able to detect the presence of at least 2 people in a room, for example to pause a video playback when my partner gets up from the couch. I also wanted to be able to know the distance of a person from the sensor. In my kitchen, the credenza is on the wall opposite the hob. So I only wanted to turn on the credenza when I was in front of the sink. And since when I’m doing the dishes I’m too static for a motion detector, I wanted a solution based on millimeter waves. The last use case, detecting when I leave my PC, again the presence detector is the most suitable sensor.

Chosen Material and Environment

Initially, I experimented with an ESP32-D1 mini and a LD2410 millimeter sensor. I used ESPHome to configure everything, which is an opensource project allowing to quickly configure a set of sensors around an ESP microcontroller. ESPHome There are several tutorials for this use case that you can easily find on the internet.

But for my part, I was not satisfied with these choices:

  • The LD2410 sensor is a sensor that can only detect one person at a time.
  • The code generated by ESPHome is quite opaque compared to the configuration that is passed to it as input. On another project (which I will surely redo later), I was not satisfied with the consumption of the sensor, and it was impossible to easily know if ESPHome was using the Low Power capabilities of the ESP.
  • The protocol used, bluetooth or wifi in the case of ESPs supported by ESP-Home did not please me. My bluetooth dongle is quite far away in my home automation installation, and I don’t like to overload my wifi network.

So I opted for the following choices:

  • An ESP32-C6 microcontroller (for its ability to integrate a Zigbee chip)
  • A LD2450 millimeter sensor (the big brother of the LD2410, more sensitive and allowing to detect up to 3 people)
  • a BH1750 light sensor (to know the brightness of the room for light control scenarios)
  • The use of the ESP-IDF framework from the microcontroller manufacturer

Presentation of the Code Architecture

The entry point of the code is the app_main() function in the main.c file. Its purpose is to initialize the flash as early as possible, then launch the zigbee task which will be the main task of the application.

The zigbee task initializes the zigbee stack, defines the clusters of our sensor (I will develop in more detail the principle of zigbee clusters in a future part), starts the zigbee message processing task. In a callback function associated with the good association to the zigbee network, a sensor management task is launched.

The sensor task initializes the i2c (for the light sensor) then initializes the BH1750 driver, it then configures the uart (for the presence sensor) then initializes the LD2450 driver. The data from the 2 sensors are received continuously and reported directly using the zigbee APIs. The clusters are configured not to emit zigbee messages if the values have not changed or have changed little (example: a movement of 10 cm, or a brightness that changes by 5 lux will not cause a new message to be sent on the zigbee network).

Installation

For the complete installation of the application, I advise you to follow the instructions on github: README It is necessary to configure an ESP-IDF environment on your computer, and I advise you to install the ESP-IDF extension on your code editor (Visual Studio Code recommended). Once our sensor is ready, it needs to be paired with Zigbee2mqtt.

Zigbee2mqtt (and home assistant)

In order for home assistant to retrieve data from our sensor, it must be paired with zigbee2mqtt. The problem is that our DIY module is not a commercial module, so it does not appear in the database of modules supported by Z2M. We need to create a file that will allow Z2M to recognize and interpret the data sent by our sensor. This file is called an external converter and must be located at this location in our home assistant installation: /homeassistant/zigbee2mqtt/external_converters/squwalinc_esp32c6.js I spent a lot of time making this file work, finding very little documentation on creating an external converter for a custom cluster. Feel free to reuse it!

Once the external converter is added, just restart zigbee2mqtt, activate inclusion mode, and restart the sensor. It should then correctly report to home assistant.

Location Display (home assistant)

There are several examples for displaying the location of people on a radar-type map. So I adapted one for my case. The LOVELACE CARD is also available on github. Pay attention to the card dependencies (vertical stack and plotly).

People location map

People location map

Making a Case

To finalize the prototyping of this sensor, I decided to make a case allowing me to position it in a room. I wanted initially a simple shape, allowing to keep all the elements in place, removable, and easily usable regardless of the orientation (flat on the desk for testing, then in the correct orientation of the LD2450).

Case modeling in fusion 360

Case modeling in fusion 360

A 3D print later, we do the placement tests.

Tests before connection

Tests before connection

Everything fits perfectly, the different sensors are well maintained in horizontal position. I can possibly add a bit of non-conductive tape to allow me to turn the case in all directions.

I am not distributing the case on github because this version is not optimal. Indeed it is not designed to allow the ideal orientation of the sensor, even if it works. I will model a more optimized version later, if possible adjustable, and I will distribute it on github.

In testing phase

In testing phase

Improvements

I still have several points to optimize. First, regarding the code, it happens that when a target is no longer detected, the last coordinates are not erased. Regarding the hardware, I find that the LD2450 does not work at the distance announced in the datasheet (6 meters). I don’t think I managed to detect beyond 3 meters. I need to do new tests, with another power supply and perhaps a better orientation. Regarding the case, I want to make an adjustable version, as well as a more compact version. Indeed I will try to use an ESP32-C6 mini to make the whole much more compact. Moreover, the hole for the BH1750 for my case is not big enough, which means that it does not receive enough light to obtain a range of values more consistent with the brightness of the room.

TL;DR

To make this presence sensor you need:

  • ESP32-C6 x1
  • LD2450 x1
  • BH1750 x1

Connect the 2 sensors to the ESP32-C6 Get the code on my github Configure the ESP-IDF extension on your code editor (Visual Studio Code recommended) Connect the ESP32-C6 to your computer via a USB cable and select the corresponding port Click on the “ESP-IDF Build, Flash & Monitor” button

© 2025

🌱 Powered by Hugo with theme Dream.

About me

Welcome to Squwal’s blog ! This blog is dedicated to domotique, electronics and embedded software, with a focus on the design and development of sensors. I am an engineer in embedded software, and I share my projects here to keep track of my work and allow others to inspire themselves.

Do not hesitate to ask questions in the comments, by email or by exploring my GitHub for more information! 🚀