Motion Sensor (PIR) with ESP8266 and MQTT

Separate LED and PIR

This is where using MQTT to replay the motion status shines. The motion sensor published to one specific topic, and other clients, either LED light or a database, to listen in. This approach does not limit the number clients can be controlled by one motion sensor. The drawback is at least two MCUs needed, one for motion sensor, and the other for light.

pir esp01

The concept is similar to the previous tutorial (as in step 1) using a control terminal, but instead of manually pushing the message, the PIR client will automatically publish a message in JSON format to the desired topic such as sensor/door/pir.

Customize the topic in the provided code as you wish, only to make sure that both the publisher and subscribers share the same topic. Here is how I defined a topic on the publisher side. The entire code is posted on GitHub.

#define light_state_topic "sensor/door/pir"
#define SENSORNAME "pirOne"

Prepare a client to publish the message and another as subscriber to turn on/off. The message is transferred through MQTT protocol.

mqtt publisher

And on the subscriber side, and the full code to upload to ESP8266 on GitHub

#define mqtt_port 1883
#define subscribe_topic "sensor/door/pir"
#define SENSORNAME "One1W"

In the video, you can see that the HIGH status of PIR retained about 5-6 seconds after the last motion while the subscriber (LEDs) is ON for 12 seconds. To change the duration for the LED to be on, change the value of DELAYS variable in the code of the subscriber:

#define DELAYS  12 //delay 12 second after the PIR sensor OFF

The DELAYS variable is fed to a function to keep track of the HIGH status of the PIR publisher. Calling the client.loop() during the delay is what I came up with the update the status of PIR sensor while counting up to the max delays by DELAYS.

void setLeds(int onSeconds){
    float prev = 0;
    if (stateOn==1){
    brightness = 1000;
    analogWrite(controlPin, brightness);
    analogWrite(ledPin, brightness);
    Serial.print("\t>>  analogWrite:\t");
    for (int i=0; i 10)) {
        prev = millis()/1000;
        Serial.printf("\nstateON is %i \t", stateOn);
        Serial.printf("\t Counting on i: %d \n", i);
    } else {
    brightness = 0;
    analogWrite(controlPin, brightness);
    analogWrite(ledPin, brightness);

And finally, call this function up on the MAIN LOOP:


And here is a video of PIR and LED interacting:

This would be it. In the next step, we will work with a database and a web server.