[WIP] An experiment in building Direction of Travel (DoT) sensors using photoresistors and ESPHome

Hi all,

In my quest to improve presence and occupancy detection, I was thinking about a sensor device that can detect which direction a person is moving. Basically it’s two photoresistors spaced about 8cm apart on one side of a doorway, with either lasers or bright LEDs or something pointed directly at them from the other side.

When a person walks through the doorway, they break the beams in a particular order that indicates if they are entering or leaving the room. This would be super useful, because you can assume a room is occupied if someone walked into it but hasn’t left, even if there’s no motion (eg they sat down and read a book).

Now, I’ve mocked up a prototype on a breadboard, and it works quite well. To pass WAF I will need to 3D print a nice acetone-smoothed case and somehow come up with a method of mounting it in the doorframe that is not ugly.

However, I’m struggling with the code.

I can think of how I might code it up in the Arduino IDE. Far easier, I can think of how I’d do it in Node-RED. But I can’t for the life of me think how I’d do it in ESPHome, because to my knowledge, ESPHome doesn’t have the equivalent of a loop method.

The logic is something like this.

Wait for one of the sensors to change from ON to OFF. On state change, check to see if the other sensors changes state too, within about a second. If it does, report direction of travel. If it doesn’t, it’s either a false alarm or someone lurking in the doorway without actually going through, and we don’t need to report anything.

In the IDE I’d probably do it by having two methods called checkSensorOne() and checkSensorTwo(), basically identical but for the sensor names, and call the methods one after the other on loop. I could probably do the checking in a lambda, but I can’t think how I’d loop it.

Is there a way to do this in ESPhome? I really like the API integration, and otherwise I’ll have to do this with MQTT, which I have mostly forgotten. Can you point me at any code examples, even if they are for doing other things, that have a loop-style functionality in ESPHome?

There is interval: . My own testing and confirmation from Otto is that 15-20ms is about the lowest practical interval. Was this the same scenario as on Discord ?

Couldn’t you just do the 2 sensors as binary switches with a “delayed_off”-filter for maybe 1 sec, and then a switch with some lambda code, that defines that if binary_sensor 2 is comes on, when binary_sensor 1 is already active, someone is in the room, and vice versa?

I do something similar with a pair of zwave PIR sensors. One of each side of the stair railing.
I only care about one direction of travel - coming up the stairs. All it takes is a simple condition statement in the automation.

- id: '3'
  alias: Welcome Home light in kitchen
  trigger:
  - entity_id: binary_sensor.stairwell_motion_sensor
    from: 'off'
    platform: state
    to: 'on'
  condition:
  - condition: state
    entity_id: binary_sensor.basement_motion_sensor
    state: 'on'
  - after: sunset
    condition: sun
  action:
  - scene: scene.kitchen_light_on
1 Like

This is not tested in reality, but this is what I would try in ESPHome:

binary_sensor:
  - platform: gpio
    internal: true
    pin: D2
    name: one
    id: one
    filters:
      - delayed_off: 1s
    on_press:
      then:
        - if:
            condition:
              binary_sensor.is_on: two
            then:
              - binary_sensor.template.publish:
                  id: presence
                  state: ON
              - lambda: id(one).publish_state(false);
              - lambda: id(two).publish_state(false);

  - platform: gpio
    internal: true
    pin: D4
    name: two
    id: two
    filters:
      - delayed_off: 1s
    on_press:
      then:
        - if:
            condition:
              binary_sensor.is_on: one
            then:
              - binary_sensor.template.publish:
                  id: presence
                  state: OFF
              - lambda: id(one).publish_state(false);
              - lambda: id(two).publish_state(false);

  - platform: template
    name: "Room presence"
    id: presence
1 Like

Interesting, so you’re doing the logic within Home Assistant itself. That’s a good approach, and I can see how well it works for your scenario.

Mine is a little different, in that if I can get this prototype to work, I would end up putting them in as many doorways as possible, and would then add that data to a Bayesian sensor group for better accuracy. So the direction matters a lot.

Thank you for your mockup example, this could be way simpler than I was initially anticipating. I also had them set up as binary sensors.

Your on_press statement had me confused for a second until my brain caught up and pointed out that, yeah, these are basically just two buttons.

You’ve given me a good direction to move in, I’ll report back after some testing.

EDIT: mixed success. The problem is that it’s very twitchy right now. I think I need to move to the next phase of prototyping, which will involve making a board and 3D printing an enclosure, to try and ensure that the photoresistors don’t respond to as much ambient light as they do just shoved into a breadboard.

I’ll report back again when I’ve built something a little more robust, but, it looks like we might be winning here.

1 Like

Direction matters for me as well. I only act if the direction is up the stairs. I don’t know how this would scale, since I am only doing this for a single entry point. I do have the advantage here in that there is about 3 feet between the sensors as you wrap around the staircase going down or up. So I have zero false positives. It was the second automation I did in HA about 3 years ago before some of the newer features and has been solid.

Yeah that’s going to be the fun part for me: I have 6cm between the sensors. But I’m recessing them into tubes to minimise false positives.

But assuming this works, I’m going to need to implement some kind of counter system, probably in NodeRED, so that HA can be aware of how many people are in a space by virtue of how many people entered it. Could be a pipe dream, though. Let’s see how well version 2 works first.

1 Like

I’m going to use this thread to post progress updates, as this looks to be about hardware for a bit, and I’ve edited the title accordingly.

Imgur

This is version 2 of the sensor plate. From this I figured out that the tubes are actually too deep for practical use. They do filter out most false positives, but they require deadly accurate light sources which will be tricky to install.

Also the plate bends. So for version 3 (currently printing), I’m going with tubes half as long, and some support struts along the back of the plate to prevent bending.

Next step is to create an emitter plate to match, and experiment with the best light sources. Honestly I would love to use IR so that the thing will be invisible, but a doorway is usually 850cm wide, and I’m not sure your standard hobby IR LED can throw strong enough light across that gap. I may have to use little lasers instead. If anyone has ideas about cheap, powerful, invisible, low-voltage light sources, please chime in.

What about using ultrasonic sensors to do the same thing? That way it only requires equipment on one side of the door. It could even be mounted over top of the doorway. I suspect with any of these, you need to account for doors opening/closing.

1 Like

The reason I can’t use ultrasonics is because they’re very large (comparatively speaking) and very visible. With this device, I’m hoping to be able to install it flush with the doorframe - WAF is a very relevant issue, but if I’m honest, I care about how the end product looks too.

I mean, you could have an ultrasonic on each side of a doorway, but again, big, obvious sensor, plus on one side you have to control for the door swing itself. Whereas, by installing inside the doorframe, I don’t have to worry about picking up the door because doors open out of the frame, not into it, so it’s not an issue.

I do, however, really like the idea of not having to install from two sides. What might workis two PIR sensors with their caps off, with tubes to narrow their focus. I’ll do a test, but I rather suspect it won’t work. We need two side by side, but the extent to which we’ll need to narrow their view means they might not notice body heat because it’s covered in clothes or whatnot.

What I like about light sensors is the absoluteness: the technique really needs something to physically break the beams.

Version 3 is working well with LEDs , so I’m probably going to tinker with the code a bit now. @CMDK’s code above is a good jumping off point, but I need to refine it a bit because this sensor isn’t actually for indicating presence as it is for indicating something moved in a particular direction (L to R, or, R to L). This means turning on a presence sensor isn’t actually as helpful as it first appears.