Hack a PIR Motion Sensor with an ESP8266

In this project we’ll modify a commercial motion sensor (powered with mains voltage) with an ESP8266 to log data whenever motion is detected. The data will be sent to Node-RED using MQTT communication protocol. The ESP8266 will be powered through the motion sensor phase out wire using the HLK-PM03 AC/DC converter.

Hack a PIR Motion Sensor with an ESP8266


Before continuing with this project, we recommend taking a look at the following resources:

Parts Required:

Here’s a list of the parts needed for this project:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Project Overview

This project is divided into three parts:

  1. Building the circuit
  2. Writing and uploading the ESP8266 code
  3. Creating the Node-RED flow

The following image shows a high-level overview of the project we’ll build.

ESP8266 PIR Motion Sensor HLK-PM03

Motion Sensor

We’ll hack a commercial motion sensor that has enough space to put an ESP-01 and the HLK-PM03 AC/DC converter module inside. We bought our motion sensor for $5 in a local store.

When the PIR sensor detects motion, there’s power coming out from the red hot wire that can turn on a lamp or a device. Your motion sensor should have a similar wiring diagram on the lid or printed in the instructions manual.


In our project, the motion sensor output load is the HLK-PM03 AC/DC converter module that will power the ESP8266.

Hi-Link HLK-PM03

Related: Power ESP8266 with AC voltage using HLK-PM03 Converter

The HLK-PM03 module AC/DC converter supplies 3.3V from either 110VAC or 220VAC. This makes it perfect to power the ESP8266 from mains voltage.

In summary, when motion is detected there is power reaching the ESP8266. The ESP8266 can execute tasks for as long as the motion sensor is triggered.

You may need to adjust the time duration that the sensor stays on, so your ESP8266 has enough time to execute its tasks. The sensor should have a knob to adjust the time (and another to adjust luminosity).

In our example, whenever the ESP8266 powers up, it runs a sketch that sends information to Node-RED via MQTT to log the date and time that motion was detected.

Instead of sending information to Node-RED, you can execute other tasks, such as:

These tasks can be easily done using IFTTT.

1. Building the Circuit

The following schematic diagram shows the circuit for this project.

Remove your PIR motion sensor lid. Inside, it should have three wires: phase in, neutral, and phase out. Follow these steps:

  • Wire phase in (brown) and neutral (blue) to the motion sensor
  • Wire neutral (blue) and phase out (red) to the HLK-PM03 input

It’s recommended to add a slow blow fuse right before the HKL-PM03 converter and a capacitor to the output.

Note: if you’re using an ESP8266 that is always powered on with the HLK-PM03, we recommend using this protection circuit.

The HLK-PM03 outputs 3.3V and GND. These are connected to the ESP8266 VCC and GND pin to power it.

We’ve built the HLK-PM03 and ESP8266 circuit on a small protoboard to save space. We’ve also added some header pins to place the ESP8266-01. This way you can plug and unplug the board every time you need to upload new code.

Recommended reading: ESP8266 GPIOs and Pinout refence guide

2. Writing and Uploading the ESP8266 Code

We’ll program the ESP8266 using the Arduino IDE. In order to upload code to your ESP8266, you need to install the ESP8266 add-on first, if you haven’t already (Install the ESP8266 Board in Arduino IDE).

You’ll also need to install the PubSubClient library to create an MQTT client with the ESP8266. The PubSubClient library provides a client for doing simple publish/subscribe messaging with a server that supports MQTT (basically allows your ESP8266 to talk with Node-RED).

  • Click here to download the PubSubClient library. You should have a .zip folder in your Downloads folder
  • Unzip the .zip folder and you should get pubsubclient-master folder
  • Rename your folder from pubsubclient-master to pubsubclient
  • Move the pubsubclient folder to your Arduino IDE installation libraries folder

Then, copy the following code to your Arduino IDE, but don’t upload it yet. You need to make a few modifications to make it work for you.

You need to edit the code with your own SSID, password and MQTT Broker IP Address (Raspberry Pi IP Address).

  Rui Santos
  Complete project details at https://randomnerdtutorials.com  

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// Replace with your SSID, password and MQTT broker IP address
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
const char* mqtt_server = "REPLACE_WITH_YOUR_MQTT_BROKER_IP";
//For example
//const char* mqtt_server = "";

WiFiClient espClient;
PubSubClient client(espClient);

void setup_wifi() {

  // We start by connecting to a WiFi network
  Serial.print("Connecting to ");

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {


  Serial.println("WiFi connected");
  Serial.println("IP address: ");

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
    } else {
      Serial.print("failed, rc=");
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  digitalWrite(BUILTIN_LED, HIGH);
  client.setServer(mqtt_server, 1883);
  while (!client.connected()) {
  Serial.print("Motion Detected");
  // Publish MQTT message
  String mqttMessage = "Motion Detected";  
  client.publish("esp/pir", mqttMessage.c_str());

void loop() {

View raw code

Include your network credentials

You need to include your network credentials in the following lines.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

Include your MQTT broker IP address

You also need to include your MQTT broker IP address.

const char* mqtt_server = "REPLACE_WITH_YOUR_MQTT_BROKER_IP"; 

To find your MQTT broker IP address, it should be configured first. We’re using Mosquitto broker hosted on a Raspberry Pi. Follow the next resources if you haven’t done that yet:

How the code works

The code is very simple. It simply publishes a message on a topic. For testing purposes, we’re also turning the on-board LED on every time the ESP8266 is powered. This is done on the setup() because it will only be executed once (when motion is detected and while the ESP8266 is powered).

void setup() {
   pinMode(BUILTIN_LED, OUTPUT); // BUILTIN_LED pin as an output
   digitalWrite(BUILTIN_LED, HIGH);
   client.setServer(mqtt_server, 1883);
   while (!client.connected()) {
   Serial.print("Motion Detected");
   // Publish MQTT message
   String mqttMessage = "Motion Detected";  
   client.publish("esp/pir", mqttMessage.c_str());

Uploading the code

After modifying the code with your network credentials, you can upload it to your board. To upload the code to the ESP8266-01 you need a serial adapter or an FTDI programmer.

3. Creating the Node-RED Flow

Before creating the flow, you need to have installed in your Raspberry Pi:

Importing the Node-RED flow

To import the provided Node-RED flow, go to the GitHub repository or click the figure below to see the raw file, and copy the code provided.

Next, in the Node-RED window, at the top right corner, select the menu, and go to Import  > Clipboard.

Then, paste the code provided and click Import.

Here’s the imported flow. It receives the ESP8266 MQTT messages and logs the time whenever motion is detected.

We’ve also added two buttons to clear and refresh the log.

Node-RED Dashboard

After making all the necessary changes, click the Deploy button to save all the changes.

Now, your Node-RED application is ready. To access Node-RED Dashboard and see how your application looks, access any browser in your local network and type:



Now, you can test your project. Whenever motion is detected, the ESP8266 powers up and sends a message via MQTT to Node-RED.

If you go to your Node-RED Dashboard you can see all the logs of when motion was detected. Your application should look as in the following figure.

The dashboard shows the last time motion was detected and all previous logs. You also have the option to refresh the log, and clear the log. Please note that clearing the log is irreversible.

Wrapping Up

This project showed how you can hack a commercial motion sensor with an ESP8266 to make it smarter. You can easily power the ESP8266 with the HLK-PM03 from mains voltage and make a compact circuit that can fit in the motion sensor.

Whenever motion is detected the ESP8266 is powered and executes a task. In this case, it publishes an MQTT message to log the time motion was detected, but you can easily write code to execute any other task.

We hope you’ve found this project useful. If you liked this project, you may also be interested in one the following resources:

Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »
Learn how to build a home automation system and we’ll cover the following main subjects: Node-RED, Node-RED Dashboard, Raspberry Pi, ESP32, ESP8266, MQTT, and InfluxDB database DOWNLOAD »

Enjoyed this project? Stay updated by subscribing our newsletter!

22 thoughts on “Hack a PIR Motion Sensor with an ESP8266”

    • Hi Nigel.
      Take a look at this PubSubClient library example: github.com/knolleary/pubsubclient/blob/f029640ee6365c58ebfe66ebf6bf1733d322f2ec/examples/mqtt_auth/mqtt_auth.ino
      It connects to an MQTT server, providing username and password.

  1. It appears that the node-red flow cannot be imported? If I go to github it goes immidiately to raw and when I copy this raw code to clipboard and try to import from there it is not recognized as a correct flow? pls advice 😉

  2. the flow is not recognized to be valid when I try to import it. (The red install button does not show up when I paste the flow from the clipboard.

  3. something wrong with my github on win10? ……. Tried the same on my Linuxbox and it works like a charm 😉 thanks for your support /Henk

  4. Excellent Solution. Hadn’t thought of this. Now used this with some timer code to create motion lights that are not wired to the sensor.
    Used Peter Scargils Big timer node.
    Thanks to the Santos’s.

  5. Hello Sara or Rui,

    I downloaded the sketch from the url above, but when I try to compile the sketch. But then I get some errors:

    sketch_feb09a:63:11: error: ‘BUILTIN_LED’ was not declared in this scope

    pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
    exit status 1
    ‘BUILTIN_LED’ was not declared in this scope

  6. Hi, how fast does the motion sensor react?
    I mean, powering up the ESP8266 already takes some time.


    • Hi Stefan.
      In our experiments it was almost instantaneous. But I think it depends on the motion sensor you use.
      We didn’t notice much delay in the response.

      • Hi Sara,

        Thanks for your comment!
        This sounds very promising.
        And thanks a lot for this great article!


  7. This is a great step by step description, as many others on this site. I think the circuit is somewhat overcomplicated with double ac to dc convertion: first on PIR itself and second is by HLK-PM03 unit. Is it not easier to connect to PIR’s low voltage circuit (and convert it if needed to 3.3V)? Definitely safer as you wouldnt be connecting mains voltage to your prototype pcb in such case (with 5mm clearance between neutral and load!)

  8. Thank you for sharing this interesting custom solution. How long does it take from the moment the PIR sensor is turned on to the indication on the MQTT server? How long does the ESP8266 boot up?

  9. Question – just getting started with messing around with some builds so very new to this. Is it possible to have the board tied to the line voltage so it is always powered and then just have it sense when the red is triggered? Any advantages to it always being online? I’m thinking something along the lines of Home Assistant integration.


    • Edit – just to be clear I mean have the tap the line voltage with the HLK-PM03, not deliver line voltage to the board. Then I would imagine another HLK tapped off the red. That way you could still allow the lights to function as normal but make them “smart”.


Leave a Reply to Nigel Holland Cancel reply

Download Our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.