Skip to content

Instantly share code, notes, and snippets.

@kdorff
Last active March 3, 2024 16:11
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save kdorff/245ff51463b4845de6239deaaa21445e to your computer and use it in GitHub Desktop.
Save kdorff/245ff51463b4845de6239deaaa21445e to your computer and use it in GitHub Desktop.
Break beam sensor using VL53L0X for Home Assistant using ESPHome
##
## A standard "break beam sensor" uses a laser or LED with a device on both
## sides of an opening and is triggered when something breaks the beam
## (such as a customer walking through the beam). Some garage doors use them.
## Stores often use them at the entrace to ring a chime when a customer enters
## or leaves.
##
## This is my attempt at using a VL53L0X i2c Time of Flight sensor
## as a break beam sensor in Home Assistant using ESPHome.
##
## The binary sensor 'breakbeam_sensor' is
## * A synthetic break beam that is controlled by changes
## to 'breakbeam_sensor_dist'.
## * Should only send changes when the 'beam is broken':
## * 'breakbeam_sensor_dist' becomes < 'minTripDistance' (or)
## * 'breakbeam_sensor_dist' becomes to greater than 'minTripDistance'
##
## The sensor 'breakbeam_sensor_dist' is the actual VL53L0X sensor.
## * The maximum reliable "open" distance seems to be to about 1.5 meters.
## * This sensor is marked intnernal as to not send distance data to HA.
## * When distance first falls less that 'minTripDistance',
## 'breakbeam_sensor' will turned on.
## * When the distance is first greater than 'minTripDistance', the
## 'breakbeam_sensor' will be turned off.
## * This will poll at 0.1s. This seems fast enough, but 1s was not.
##
esphome:
name: distance-sensor-0
esp8266:
board: esp01_1m
# Logging (DEBUG is the standard level)
logger:
level: INFO
# Enable Home Assistant API
api:
ota:
password: "XXXXX"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
fast_connect: true
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Distance-Sensor-0"
password: "XXXXX"
captive_portal:
# the vl53l0x is i2c
i2c:
scan: true
##
## The virutal break beam sensor.
## The state of this will be controlled
## by breakbeam_sensor_dist's lambda as necessary.
##
binary_sensor:
- name: "Breakbeam Sensor"
id: breakbeam_sensor
platform: template
device_class: motion
##
## The actual sensor.
## This sensor's lambda will control the state of our
## virtual break beam sensor, breakbeam_sensor.
##
sensor:
- name: "Breakbeam Sensor Dist"
id: breakbeam_sensor_dist
platform: vl53l0x
address: 0x29
update_interval: 0.1s
long_range: true
internal: true
#
# Only send a value back if breakbeam_sensor changes.
#
filters:
- lambda: !lambda |-
/**
* YOU MIGHT WANT TO CONFIGURE THIS.
* Distance below which to trip the virtual break beam sensor.
* '0.5' meters is about 20 inches.
*/
static double minTripDistance = 0.5;
if (x <= minTripDistance) {
if (id(breakbeam_sensor).state == true) {
// Beam was already broken
return {};
}
// Beam was just broken
id(breakbeam_sensor).publish_state(true);
ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Detected");
return {};
}
else {
if (id(breakbeam_sensor).state == false) {
// Beam was already un-broken
return {};
}
// Beam was just un-broken
id(breakbeam_sensor).publish_state(false);
ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Cleared");
return {};
}
@kdorff
Copy link
Author

kdorff commented Nov 7, 2022

I am using this code for my project. It works great as-is on my D1 mini. I am new to YAML and trying to mod the code to add an LED to light-on on detect and off on cleared, but can't figure it out. Any ideas?

I think you'd use something like a GPIO output https://esphome.io/components/output/gpio.html
or possibly a GPIO switch https://esphome.io/components/switch/gpio.html

And then turn the switch/output on and off when there is motion / motion stops. If you name your output light_1, you should be able to turn on with id(light_1).turn_on(); or with YAML - output.turn_on: light_1.

My recommendation is get the LED working independently in the ESPHome project, verifying that you know how to turn it on and off. After you are confident with that, then apply what you've learned about using the LED to the motion lambda.

Good luck!
Kevin

@ZixZeven
Copy link

ZixZeven commented Nov 8, 2022

Kevin, thanks you very much. You have provided me the hint and made it worked. Attached is the added code in bold.

...
if (x <= minTripDistance) {
if (id(breakbeam_sensor).state == true) {
id(gpio_d7).turn_on();
return {};
}
id(breakbeam_sensor).publish_state(true);
ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Detected");
return {};
}
else {
if (id(breakbeam_sensor).state == false) {
id(gpio_d7).turn_off();
return {};
}
id(breakbeam_sensor).publish_state(false);
ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Cleared");
return {};
}

output:
- platform: gpio
pin: D7
id: gpio_d7

@kdorff
Copy link
Author

kdorff commented Nov 8, 2022

Kevin, thanks you very much. You have provided me the hint and made it worked. ...

So glad to hear it!! Have fun on your ESPHome adventure! You can do lots of cool things with it.

@rcientista
Copy link

Hi,

I have set up this and it is working. Thank you.

However, I would like to add a max distance also for the sensor to be triggered.

For example, it would only trigger if between 0.2 and 0.5.
I am not a coder or anything of the sort and was wondering if you could help with this.

Thank you.

@rcientista
Copy link

rcientista commented Nov 30, 2022

Hi again,

So I did some googling and learned a bit and got it to work with the following in case someone wants to do the same:

line 94

          static double minTripDistance = 0.5;         
             static double maxTripDistance = 0.1;

             if ((x <= minTripDistance) & (x >= maxTripDistance)) {

I am not sure if this is the best way but it worked.

Kind Regards.

@kdorff
Copy link
Author

kdorff commented Apr 24, 2023

Hi @didi767 - first thing is that you should use code blocks when posting YAML code. The above isn't terribly readable, especially if you are asking for help with it.

If your questions are all still about the concepts, ask me those specific questions. I'll assume you aren't just asking me to write this, as I don't do that. I'm happy to try to help, but this is your project not mine.

The next thing to know is the vl53l0x isn't a PIR sensor, it's a time of flight sensor. A PIR sensor (passive infrared) looks for a heat and then trips if it sees heat. They generally have a "cool down" period of time where they will not trip again. I found them less than useful for these and other reasons.

A Time of flight (TOF) sensors continuously measures distance between itself and whatever surface is in front of it. It will be useful for you to read the specs of the vl53l0x as well as the ESPHome documentation page for it to understand how it works and it's limitations, such as only supporting relatively small distances. Read all the comments in my code to better understand what it is doing. If you have specific questions about what my code is doing, ask those. But in summary: my code just watches the TOF sensor for distances less than minTripDistance and then sets a template binary sensor named breakbeam_sensor accordingly.

I don't see that you've included the template sensor named breakbeam_sensor but you do seem to be using it in the filter so your code probably won't compile.

For your above "not even sure if this would work" -- well, then neither am I, especially if you haven't mentioned specific concerns. What is it doing right? What is it doing wrong? You have logging enabled and I see some logging messages in the lambda code, that should give you lots of information about what it is doing right or wrong. Once connected the vl53l0x will also output logging messages with the current distance, which should help with debugging.

If it's functionality you wonder about, for this and any other project I'd recommend using a breadboard and wiring it up so you can see how things actually are working. You really cannot code ESPHome projects in a vacuum. You need to wire it up, see how the code works, and most importantly write the thing iteratively. Get one small thing running. Once you are satisfied, wire up and get the next thing running. The way I would approach it is get the functionality you had before running before adding in new features, like the TOF sensor. Once the actuator 100% working, then add the ToF sensor to the mix. But FIRST just see that ESPHome can see the distances values from the ToF (in debugging messages that will automatically start appearing once the ToF sensor is connected into ESPHome). Once that works, add in the filter and the binary sensor so it can set the binary sensor based on the distance being below a threshhold.

@kdorff
Copy link
Author

kdorff commented Apr 26, 2023

If the purpose of the TOF sensor is to verify the dog isn't occupying the area on either side of the door, I wonder if you need one on both sides - as the dog could be coming OR going. But I may be misunderstanding. If you need to use two TOF sensors in your configuration, you'll need to change the i2c address of of them. See this article.

You should be able to edit your posting above to fix the formatting. On your messages click ... (top right) and select Edit. Then do one of the following

  • Above your .yaml code on it's own line, place three back-tics. Also put three back-ticks on the line after the code. This is how you specify a multi-line code block in Markdown.
  • Select the .yaml code and click the Add Code tool (from the tool bar at the top of the comment text editor).
  • Select the .yaml code and press control-e (the same as clicking the "Add Code" tool.)

In general, this document will show you how to edit Markdown text to get rich formatting. See the section titled Quoting code.

Next, I'd suggest using more descriptive variable and sensor names. win_1 and win_2 don't tell me much.

Finally, I'd suggest adding more comments describing what things are happening in the comments - describe the state and what you are doing in a detailed manner.

@kdorff
Copy link
Author

kdorff commented Apr 28, 2023

@didi767 First, if you are using a VL53L0X, it isn't a PIR sensor, it's a TOF sensor. PIR and TOF sensors do completely different things and you will confuse yourself and others if you try to use them interchangably. The code in this gist that we are discussing uses a TOF sensor to try to emulate yet another kind of sensor, a Breakbeam sensor. A Breakbeam sensor will trigger if something moves in front of the beam.

As I cannot help you with your door opening and closing (I have no idea how any of that is working,) I can try to help you understand the code in this gist and what it does.

In my code, you will find the configuration of the i2c hardware TOF device in the sensor: platform: vl53l0x the stanza.

sensor:
  - name: "Breakbeam Sensor Dist"
    id: breakbeam_sensor_dist
    platform: vl53l0x
    address: 0x29
    update_interval: 0.1s
    internal: true

If you just add this stanza to your configuration and monitor the esphome logging, you will see that once every tenth of a second the sensor breakbeam_sensor_dist will report the current distance it observes between itself and the nearest object. But I didn't want to send this updated sensor information back to Home Assistant 10 times a second, so I marked the sensor internal: true. This way the sensor state is stored only on the esphome device.

Before we go any further, let's look at the associated binary_sensor: that is critical to this all working.

binary_sensor:
  - name: "Breakbeam Sensor"
    id: breakbeam_sensor
    platform: template
    device_class: motion

This is a template binary_sensor which means (a) It will report its On or Off state back to home assistant (because it is a binary_sensor) and (b) being a template sensor, it has no value of it's own - something else has to give it a value.

Next, we look at breakbeam_sensor_dist's filters: lambda:, noting the syntax change from yaml to C. The lambda is C code that will run every update_interval: (every 0.1 seconds, in this case), allowing us to process the currently observed distance. In my case, I use these to activate my stair lights. So normally, the vl53l0x is observing the distance to the nearest wall. But when I walk in front of it, that distance will change (to less than minTripDistance).

When the lambda executes, it will have the current distance from the vl53l0x / breakbeam_sensor in the variable named x (this is convention). In my lambda: code, x (the current distance) is compared with the unchanging (static) valued stored in minTripDistance. You should read and understand the actual logic, but effectively if something has JUST made the distance less than minTripDistance, then the binary_sensor breakbeam_sensor will be turned On with id(breakbeam_sensor).publish_state(true);. If something has JUST returned the distance to more than minTripDistance the binary_sensor breakbeam_sensor will be turned Off id(breakbeam_sensor).publish_state(false);. In all cases the lambda will return {} indicating there is no additional state change on the breakbeam_sensor_dist state.

I'd recommend you get this configuration running so you can see breakbeam_sensor changing based on the changing distance.

Once you have this working, you can observe the state of binary_sensor.breakbeam_sensor to see if something is "breaking the beam".

@kdorff
Copy link
Author

kdorff commented Apr 28, 2023

@didi767 In genreal, esphome is event drive and you wouldn't (couldn't and shouldn't) do a while like this, IMO. I believe you want to tie into events that are happening.

After you have the TOF working as a breakbeam, my best guess is maybe to

  • Before you close use a condition to verify that binary_sensor.breakbeam_sensor is false/off.
  • put a filter on breakbeam_sensor (I assume you can do this) and detect if the sensor changes to true/on WHILE the cover is closing: If so, change the cover to open? I've not used covers, but it seems like this should be an option.

@darknessblade
Copy link

darknessblade commented May 30, 2023

When flashing it with the ESP-home flash tool for windows I keep getting the following error:
Unexpected error: The firmware binary is invalid (magic byte=23, should be E9)

Already tried flashing tasmota/a newer firmware to the Wemos-D1 first.

It is not a driver issue, as I already installed all nodeMCU drivers

Any suggestions on what I can try to resolve the issue??

@kdorff
Copy link
Author

kdorff commented May 30, 2023

When flashing it with the ESP-home flash tool for windows I keep getting the following error: Unexpected error: The firmware binary is invalid (magic byte=23, should be E9)

Already tried flashing tasmota/a newer firmware to the Wemos-D1 first.

It is not a driver issue, as I already installed all nodeMCU drivers

Any suggestions on what I can try to resolve the issue??

Do you have the board defined correctly? In this gist I have

esp8266:
  board: esp01_1m

because I am running this project on an ESP8266. Other projects where I've used an ESP32 I find:

esp32:
  board: esp32dev
  framework:
    type: arduino

because it is an ESP32.

But if you are getting this error right when you plug in the device and try to flash it from "+New Device" then I'm not sure.

I've never seen it before and don't really use Tasmoto, so I'm not sure how any of that mixes in. I see some discussion about it here that you might read.

If none of the above is helpful, maybe the device is just bad.

@kdorff
Copy link
Author

kdorff commented May 30, 2023

When flashing it with the ESP-home flash tool for windows I keep getting the following error: Unexpected error: The firmware binary is invalid (magic byte=23, should be E9)

Already tried flashing tasmota/a newer firmware to the Wemos-D1 first.

It is not a driver issue, as I already installed all nodeMCU drivers

Any suggestions on what I can try to resolve the issue??

Do you have the board defined correctly? In this gist I have

esp8266:
  board: esp01_1m

because I am running this project on an ESP8266. Other projects where I've used an ESP32 I find:

esp32:
  board: esp32dev
  framework:
    type: arduino

because it is an ESP32.

But if you are getting this error right when you plug in the device and try to flash it from "+New Device" then I'm not sure.

I've never seen it before and don't really use Tasmoto, so I'm not sure how any of that mixes in. I see some discussion about it here that you might read.

Or maybe you are trying to flash the wrong file, another post suggests the same?

If none of the above is helpful, maybe the device is just bad.

@darknessblade
Copy link

I have the board defined correctly, based on the pinout/looks I should have the identical board as you have [wemos D1 pro [esp8266] ]

The device being bad would be quite weird, since its new out of box. and has never been used.

I have not altered anything in the YAML file. so the file itself should be fine.

As for those suggestions I will try them tomorrow

@darknessblade
Copy link

darknessblade commented May 31, 2023

I tried the suggestions you gave me
but none worked.

When I try to flash the YAML, it gives me the following info:

Chip Info:
 - Chip Family: ESP8266
 - Chip Model: ESP8266EX
 - Chip ID: 004EF837
 - MAC Address: XX:XX:XX:XX:XX
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
 - Flash Size: 4MB 

It might just be that I have wrongly defined the ESP8266 chip/board details

@kdorff
Copy link
Author

kdorff commented Jun 1, 2023

You mention trying to flash the YAML file. Is this a typo? I assume you are trying to flash the firmware.bin file or similar that you previously compiled. I always let the ESPHome Add-on for Home Assistant do the firmware compilation (of the yaml) and flash the firmware for me. I've never needed to use a separate tool for flashing.

You might want to open a ticket with the esphome-flasher tool team, as it seems that is the program that is giving this error when it tries to upload the compiled firmware file you are supplying. Since the YAML file compiled correctly, for you to try to flash it, I don't think it is my code that is causing the problem.

If you are trying to directly flash the YAML file, this isn't possible. YAML files need to be compiled to a file like firmware.bin which IS outside of the scope of this discussion. I'd direct you to the ESPHome documentation regarding compiling and flashing firmware.

@darknessblade
Copy link

My mistake, I was trying to flash the YAML

First time using the ESP chips for my smarthome, so wasn't sure on what to do, or how to do it.

@kdorff
Copy link
Author

kdorff commented Jun 1, 2023

@darknessblade I'm not sure what guide you've been following, but if your goal is to run ESPHome by itself, outside of Home Assistant as an Arduino alternative, I'd suggest you connect with like minded people in the ESPHome Discord - I imagine they exist. They might be able to provide you will a better guide to get it going. I have no interest in running ESPHome outside of the Home Assistant context, so I'm the wrong person to help you with that. You can find a link to their Discord on the ESPHome home page under "Keeping Up."

I'd personally suggest running the ESPHome add-on for Home Assistant. It will manage your devices, do the compilation and installation, etc. and I'm sure you can find a guides on Youtube for setting it all up... such as but not limited to (I don't endorse these, but they seem to be about what you might want):

https://www.youtube.com/watch?v=CYvTLw_Wn6I
https://www.youtube.com/watch?v=5DHoLGgouCo

Best of luck.

@kdorff
Copy link
Author

kdorff commented Jun 1, 2023

@darknessblade That said, Home Assistant is not for the meek or technically disinclined. If you aren't sure you want to take on Home Assistant and it's monthly maintenance, care and feeding, I'm not completely sure you want to use ESPHome.

I'm a big fan of ESPHome, BUT! While I do prefer ESPHome coding over straight Arduino code, it's only by a relatively small margin. If I didn't have the Home Assistant integration, I'm not sure that I'd be using ESPHome. Everything you can do in ESPHome can be done in with C/C++ in Arduino (optionally using platform.io). There are just as many, if not more, Arduino coding examples for every facet.

Mostly I want you to question why you are using ESPHome if you aren't using Home Assistant.

@kdorff
Copy link
Author

kdorff commented Jun 1, 2023

@darknessblade you might also do well to investigate the devices that run CircuitPython, such as those sold by Adafruit. Adafruit is a fantastic resources for someone new to microcontroller programming as they tend to provide learning resources, including code (often both Arduino and CircuitPython code) for all of the microcontrollers, sensors, and other devices they sell. If you are just getting into Microcontroller programming, Adafruit is a fantastic resource. CircuitPython is probably an easier introduction than Arduino's C/C++ code if you are new to programming.

@wizardnl
Copy link

wizardnl commented Nov 13, 2023

@kdorff First of all, thank you for uploading your code. It works perfectly and it's exactly what I was looking for to use within a project I'm doing for my home automation. I only need some help, if possible. I want to use your code with two sensors connected to the ESP. I got this part working by modifying your code to add the second sensor and an enable pin for each sensor.
binary_sensor:

  • name: "Breakbeam Sensor"
    id: breakbeam_sensor
    platform: template
    device_class: motion

  • name: "Breakbeam Sensor2"
    id: breakbeam_sensor2
    platform: template
    device_class: motion

sensor:

  • name: "Breakbeam Sensor Dist"
    id: breakbeam_sensor_dist
    platform: vl53l0x
    address: 0x41
    enable_pin: D3
    update_interval: 500ms
    long_range: true
    internal: true

  • name: "Breakbeam Sensor Dist2"
    id: breakbeam_sensor_dist2
    platform: vl53l0x
    address: 0x42
    enable_pin: D4
    update_interval: 500ms
    long_range: true
    internal: true

This works perfectly. However, I just can't get the filters part to work. When I add a second filter, I get errors. When I use just one filter, it works with the first sensor. I'm new to this and dont understand how to add several filters. i tried to add them per sensor but it did not work.. Could you guide me in the right direction to get the second filter working?
filters:
- lambda: !lambda |-
/**
* YOU MIGHT WANT TO CONFIGURE THIS.
* Distance below which to trip the virtual break beam sensor.
* '0.5' meters is about 20 inches.
*/
static double minTripDistance = 0.1;
if (x <= minTripDistance) {
if (id(breakbeam_sensor).state == true) {
// Beam was already broken
return {};
}
// Beam was just broken
id(breakbeam_sensor).publish_state(true);
ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Detected");
return {};
}
else {
if (id(breakbeam_sensor).state == false) {
// Beam was already un-broken
return {};
}
// Beam was just un-broken
id(breakbeam_sensor).publish_state(false);
ESP_LOGI("breakbeam_sensor_dist", "Set breakbeam_sensor to Cleared");
return {};

  - lambda: !lambda |-
      /**
       * YOU MIGHT WANT TO CONFIGURE THIS.
       * Distance below which to trip the virtual break beam sensor.
       * '0.5' meters is about 20  inches.
       */
      static double minTripDistance = 0.1;
      if (x <= minTripDistance) {
        if (id(breakbeam_sensor2).state == true) {
          // Beam was already broken
          return {};
        }
        // Beam was just broken
        id(breakbeam_sensor2).publish_state(true);
        ESP_LOGI("breakbeam_sensor_dist2", "Set breakbeam_sensor2 to Detected");
        return {};
      }
      else {
        if (id(breakbeam_sensor2).state == false) {
          // Beam was already un-broken
          return {};
        }
        // Beam was just un-broken
        id(breakbeam_sensor2).publish_state(false);
        ESP_LOGI("breakbeam_sensor_dist2", "Set breakbeam_sensor2 to Cleared");
        return {};
      }

@kdorff
Copy link
Author

kdorff commented Nov 13, 2023

@wizardnl I cannot quite tell what you have and where it is in your code because you're not using code blocks in all places. For most effective assistance, try to submit pretty complete code samples use please use code blocks around all code so I can see exactly where things are, the formatting you've used, etc.

I see a code in text with lost formatting that I think is the same as my code sample for breakbeam_sensor_dist. Then I see a code block, which I believe you say is problematic, but I'm lacking the larger context of where this is in your file.

For what it's worth: the filters.lamba for breakbeam_sensor_dist2 will need to be part of the breakbeam_sensor_dist2 stanza. It kind of looks like you've tacked it on after the breakbeam_sensor_dist lambda. Each breakbeam sensor will need have it's own filters.lambda block. When you look at the value x in the lambda, that is the current distance reading for a single sensor. So that filters.lambda needs to be part of that sensor.

@kdorff
Copy link
Author

kdorff commented Nov 13, 2023

@wizardnl additionally you mention address: 0x41 and address: 0x42 for your breakbeams where mine is address: 0x29 (which is the default for vl53l0x). If you changed the addresses, I'm not sure why you'd need the enable_pin.

Did you change the address on both of your vl53l0x? These seem like odd addresses.

@wizardnl
Copy link

@wizardnl additionally you mention address: 0x41 and address: 0x42 for your breakbeams where mine is address: 0x29 (which is the default for vl53l0x). If you changed the addresses, I'm not sure why you'd need the enable_pin.

Did you change the address on both of your vl53l0x? These seem like odd addresses.

Sorry that my previous message wasn't clear. After posting, I did some more testing and, stupidly, I didn't add the filter correctly per sensor as in your example. I got it working later in the afternoon.

To answer your question, if you want to use more than one sensor, you need to change the default 0x29 address and assign an address per sensor. Also, you need to connect the enable pin (Xshunt) per sensor (https://esphome.io/components/sensor/vl53l0x.html).

I now have your code working with 3 sensors on one wemos D1. This is amazing and just what I needed. I want to automate the LED lights for my stairs, and I needed a good way to detect someone who will step on the stairs at the bottom, top, and in the middle part where I have a small platform. With your solution, I can now detect if and where the person is, and based on that, I can automate the LED lights per stair step, so the lights "walk" with you. when you go up and when you go down.

@kdorff
Copy link
Author

kdorff commented Nov 13, 2023

@wizardnl AWESOME! I'm glad you got it all running! Thanks for the heads up about changing address - very useful! I don't think the ESPHome driver did that when I first implemented this (or I missed it). I would have loved to have used just one.

@kerimtrn
Copy link

Hello

Thank you so much for your work! It makes a great DIY sensor for my smart home. I have built 2 of them so far and plan on doing more. One of them is working flawlessly but the other one has a small issue. I use the exact code you have published on a Wemos D1 Mini. It works most of the time with no issues. The only issue comes up when there is to much light in the room. The sensor is pointing to the window. Even though it is very low and does not see the window directly, it affects its reliability. I tired to make the reading interval 0.2 seconds and it did the same. I did make it 0.05 seconds to see how long it detects false readings. The result is for just 1 reading. So, I have the idea to keep it 0.05 seconds but create a filter to only make the virtual sensor "detected" if the reading is consistent for 0.2 seconds. This way I can prevent false "detected". The problem is I do not know how to do that. Is there any chance you are able to do this? I looked for it on the internet but I have too little knowledge to understand the things on there. Yes, I could do it in the automation in HA, but it would still have a lot of traffic in my wifi. I rather solve it in the ESP controller.

Thank you so much again!

@kdorff
Copy link
Author

kdorff commented Nov 27, 2023

@kerimtrn
It sounds like you want to remember the last 3 readings and only trigger if the current and the previous 3 entries are correct.
I'd keep an array of readings, and keep track where you are writing in the array so you write to the array over and over. Do some reading about creating a circular buffer using an array.

Alternatively, you could look at what I did with data-smoothing.h in https://github.com/kdorff/esphome/blob/main/cat-water-sensor/cat-water-sensor.yaml. My code in data-smoothing.h assumes the data is an int and would need to be changed to double, I imagine.

@kerimtrn
Copy link

Hello

Thank you for your quick answer. I actually think about simpler solution if it is possible to do. Just like a button filtering, can I use a filter to activate the virtual sensor after 0.2 seconds of activity? I use delay_on on my buttons to prevent fluctuations but it did not work for this one when I tried. Maybe I did something wrong or maybe it is not possible for this kind of entity.

@kdorff
Copy link
Author

kdorff commented Nov 30, 2023

The lamda, itself, is a filter. Look at other filtering you can do on sensor https://esphome.io/components/sensor/index.html
Perhaps sliding_window_moving_average could be helpful? or median or quantile? I'm not entirely sure how they would interact with the lambda but the docs may say or just experimentation.

@wizardnl
Copy link

@wizardnl AWESOME! I'm glad you got it all running! Thanks for the heads up about changing address - very useful! I don't think the ESPHome driver did that when I first implemented this (or I missed it). I would have loved to have used just one.

Had to try it to see if it would work with 14 sensors. ;-) In theory, I can now control every step on my stairs individually. I still need to do some intensive testing, but for now, it works. Thanks again for sharing your code.
20231212_223816 (Klein)

@photonclock
Copy link

@wizardnl Looks like you picked up the ball and ran with it. Sure would be appreciated if you shared the code you came up with in a new gist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment