Saturday, December 14, 2019

Intrusion / motion / door opening detector using a NodeMCU, some sensors, and Tasmota

The Espressif Systems chip manufacturer kind of created a revolution by opening the door to the creation of dirt cheap chips for building IoT devices. Its low cost led to introduction in the market, of many types of home automation devices, such as switches, light dimmers, smart bulbs, HVAC systems and what not.

On par with that, the open source community quickly became an interested party as well, and this led to the introduction of tools for quickly allowing developers to write interesting applications for practically anything based on these chips. It is the case of the Arduino core for the ESP8266 chip - This allowed for Arduino IDE accustomed developers, to write their own code, and either replace the original firmware on commercial devices featuring the ESP8266, or use open-source board designs such as NodeMCU and build their own custom devices.

Some projects with relatively generic capabilities have as such gained popularity, as a replacement for the firmware shipped with devices branded as Sonoff, Tuya, Xiaomi and others. This is the case for Tasmota, ESPurna or ESPEasy. You may want to read the comparison between these projects.

I have personally found great use in replacing the firmware in Sonoff devices, and this led to a better and more reliable integration with other home automation tools, such as Home Assistant ( The devices themserves are cheap, and not having to depend on the cloud these originally connect to, is a plus.

Another thing that caught my attention was the price and avaliability of the generic boards such as NodeMCU, which are both useful for development and for creating custom devices.

As a starting point I aimed for building something that I could give immediate use for. That's where the Intrusion  / motion / door opening detector idea came into place.

I had a stock pile of HC-SR04 ultrasonic sensors I bought some time ago, and to which I handn't given purpose to. I also had a few HC-SR501 PIR motion sensors, to which I hadn't given a purpose to:

For a bit more that 3 euros, I bought a pack of 3 NodeMCU modules.

The idea was to place the ultrasonic sensor aiming from the top of door, downwards. With this setup, the sensor would detect a small distance while the door would be closed (the obstacle being the top of the door itself), and a distance of approximately the height of the door, while it would be open.

Putting the PIR motion sensor in the same module, would allow for simplicity of the setup, and maximize the use of the same NodeMCU device.

That is the reasoning that I have followed for building this device. The hardware task was a matter of doing some soldering on a perfboard for supporting the NodeMCU, preparing a plastic enclosure and fitting it all inside it. The plastic enclosure was a generic one, normally used for electrical installations.

In order to minimize the impact of line interferences, I have added a ferrite bead and a capacitor on the power input. Also the sensors have been shielded with aluminium foil, in order to minimize interferences originating from the NodeMCU itself (the RF field from the WiFi antenna is of course extremely close to these devices) or other sources.

The PIR sensor required some tuning: any setting other than minimum sensitivity would easily trigger false positives. It is worth noting that this PIR detector has a 3.3 Volt TTL output, so no level conversion required here, but the HC-SR04 ultrasonic sensor outputs 5 Volt TTL, as such requiring level shifting to 3.3 Volts for the Echo output signal.

For powering the device, I took advantage of the availability of an electrical wiring box above the entry door, adding a power socket in that location:

A generic USB charger featuring a 5 Volt DC output is more than enough for powering the NodeMCU and the sensors.

Given that Tasmota natively has support for the HC-SR04 sensors, It was a matter of configuring the firmware for these:

The PIR sensor is configured simply as a switch, given that it features a TTL output that goes high everytime there is a detection.

In order to efficiently trigger home automation rules in, I took advantage of the asynchronous model that is brought by MQTT. As such, I have defined a rule in Tasmota, so that everytime there is a state change in the PIR sensor, a message with the corresponding state is published in a topic:

Rule1 on switch1#state do publish cmnd/entry-door-sensors/pir/state %value% endon

For the door state, I have also defined a rule, so that when the distance from the sensor to the top of the door changes to above 15 centimeters, a message is published to another topic, with the state of the door as being open. Inversely when this distance drops to below 15 centimeters, the door is considered closed, and a message with the appropriate state is published:

Rule2 on SR04#Distance>15 do publish cmnd/entry-door-sensors/door/state OPEN endon on SR04#Distance<=15 do publish cmnd/entry-door-sensors/door/state CLOSED endon

Given that we don't want Rule2 to publish these messages all the time, but only when these thresholds are crossed, we configure Rule2 to be one shot:

Rule2 5

Finally it is a matter of enabling the rules:

Rule1 1
Rule2 1

On, we define two binary sensors, and these have as input the two topics to which we are publishing in the rules:

  - platform: mqtt
    name: entry_door_motion_detector
    state_topic: 'cmnd/entry-door-sensors/pir/state'
    device_class: motion
    payload_on: '1'
    payload_off: '0'
  - platform: mqtt
    name: entry_door_state
    state_topic: 'cmnd/entry-door-sensors/door/state'
    device_class: door
    payload_on: 'OPEN'
    payload_off: 'CLOSED'

With this, we have the basic integration done, and it is up to the user preferences, to define automations on top of it. For example I have created an automation that turns on the lights closer to the entry door, when the user enters the house at night. It (deliberately) does not turn on the lights when the user exits the house, because in that case, the motion is detected prior to the door being opened:

- id: entering_house
  alias: "Open hall lights when entering the house"
    platform: state
    entity_id: binary_sensor.entry_door_state
    to: 'on'
    condition: and
      - condition: state
        entity_id: binary_sensor.entry_door_motion_detector
        state: 'off'
      - condition: state
        entity_id: sun.sun
        state: 'below_horizon'
    service: switch.turn_on
    entity_id: group.hall_lights

On the web UI we can keep track of the state changes for these sensors:

The PIR motion sensor:

The door state detector:


bakechad said...

Great Post!
I'm new to Tasmota rules and your post is exactly what I was trying to do.

Works perfectly!

You saved me hours of trial and error.


Creation Factory said...

@bakechad, thanks. Great to know my post was helpful for your diy project.


Hardy Boyzzz said...

Nicely written !
Can you please share ferrite and capacitor details ? also diagram
i am getting many false trigger with this sensor :/

Creation Factory said...

Hi @Hardy Boyzzz, thanks. Regarding the ferrite I don't have technical details. It has about 10 cm of diameter. The capacitor is a 470 uF 16 volts electrolytic. I believe these values are not critical, any filtering is better than nothing. I later found that it was not really the DC power quality that was causing problems :)

Regarding the motion sensor, yes it is a bit tricky. You have to tune it well with the potentiometer to avoid false triggers. It ends up not being spectacularly sensitive. It is possible that in my setup (and hence the need for adding the shielding around it) this was further challenged by the proximity of the rest of the circuitry, where there are several sources of RF noise. Without the shielding I couldn't prevent false triggers from occurring.