Is there a blocking version of the delay action?

I have a piezo buzzer hooked up to a nodemcu and the code below works just fine. My problem is that sometimes the tones or the delay between them are slightly too long. This is not a huge issue, but is very noticeable and slightly annoying. I understand that the delay action is non-blocking and so the variance in timing is likely due to other processes happening in the loop, but am wondering whether there is a way in ESPHome to implement a blocking version of delay so that the timing will be more consistent and if so, whether that is a good idea or if it will screw up the rest of the loop.

api:
  services:
    - service: notify_open_door
      then:
        - output.esp8266_pwm.set_frequency:
            id: passive_buzzer
            frequency: 800Hz
        - output.set_level:
            id: passive_buzzer
            level: 50%
        - delay: 120ms
        - output.turn_off: passive_buzzer
        - delay: 100ms
        - output.esp8266_pwm.set_frequency:
            id: passive_buzzer
            frequency: 1000Hz
        - output.set_level:
            id: passive_buzzer
            level: 50%
        - delay: 120ms
        - output.turn_off: passive_buzzer

Try adding a short delay at the beginning

Also are you sure the action isn’t triggered many times concurrently from ha?

Your ms delays won’t work
Minimum resolution on outputs is 1sec
So 120ms may be in the same second - no delay
Or cross the ‘second’ boundary - 1 second delay

Thanks for the suggestion @glmnet but the short delay didn’t help.

Thanks for the info @Mutt. What defines the resolution of the outputs? Couldn’t this be circumvented with a blocking version of the delay action?

I have no idea what you mean about a blocking version of anything.
No the 1 second updates on output can not be circumvented

Blocking refers to whether something runs asynchronously or not. The ESPHome version of delay is non-blocking, meaning that other code will run during that delay. As the website says:

This is a “smart” asynchronous delay - other code will still run in the background while the delay is happening.

In regular arduino code, the delay function is blocking, meaning that no other code will run during the delay.

Well that doesn’t exist in HA
I don’t use esphome
Generally I answer issues on z-wave, duckdns, general configuration including packages, automations and scripts. Though I’m starting on jinja templates

If you can offload the timing to one of your sub processes maybe you can achieve your timings

Ahhh yeah I was abatir to ask where did you read delay doesn’t support millisecond

FYI this esphome subforum and that is esphome code.

Yes, but the actions are requested and written from the HA State Machine.
So your point is ?

Nope. Everything in that config after then: is local to the ESP processor and its GPIO.

Also Home Assistant does support millisecond delays but suffers from this load dependant variable timing problem too. Script Syntax - Home Assistant

In home assistant I was using this work around for a while:

It was better but still not great. If the processor was really loaded up the timing was still way off.

So the only thing I can say regarding blocking calls on the ESP is to avoid them as much as possible. You run the risk of tripping one of the two watchdog timers (1 hardware wdt, 1 software wdt). That will cause the ESP to reset. Additionally you run the risk of causing WiFi issues and potential memory corruption if the the processor is held up running user code.

That being said, there is a configuration in ESPHome that allows you to write your own code within the YAML configuration and it is compiled and run directly on the ESP. However, that custom code does not get compiled and tested by ESPHome so any unhandled error or bug in the code will cause it to fail when executing.

So you are saying that the code in the OP 1 is a data package sent in 1 chunk and is thus handed off to another processor ?
So where is the variability in percieved tone sequence coming from ?
(haven’t read your link yet (I will) but now I’m going to bed :yawning_face: )

You’re trolling here. Read docs or open another thread

As pointed out earlier this is the ESPhome forum category. It is for talking about configuring ESP8266 and ESP32 wifi microprocessor boards that are configured using a system called ESPhome.

ESPhome uses YAML for device configuration which is compiled and uploaded to the ESP boards. This YAML configuration is not in any way interpreted by home assistant. It is all compiled and run on the ESP board. I think is what is confusing you.

OPs YAML is compiled and the code runs on the ESP board. It listens for a notification from home assistant then does some PWM pulses on a GPIO pin - all handled on the ESP board.

I highly suggest you have a read about ESPhome. It is a very easy and cheap way to roll your own mulit-sensors that communicate via wifi with home assistant. It can also be used to replace Tasmota. It uses a configuration system you are already familiar with (YAML) so no need to learn Arduino coding.

As for a practical solution to the original problem…

The best I have come up with (but not yet implemented) is to hand off the timing to dedicated hardware. A few 555 timer ICs or a PIC12F683 which has PWM and interrupts.

I saw in the ESPHome docs, @squirtbrnr, that the lambdas can be any arbitrary C++ code but I have no idea how to implement a delay in C++. I haven’t done any C++ in years and I think you’re right that it would likely cause more issues than it’s worth.

I think @tom_l is right that I would have to use some other hardware to really nail down the timing.

Thanks for all the help everyone. If anyone has any other ideas, though, I would love to hear them.