ESPHome servo.detach not work

I have a problem with the servo.detach command.
I am using a AZ delivery D1 Mini V3 NodeMCU board

When I release the Switch 1, which is connected digital port D1, the servo does not stop, it moves to the end position (-100 or 100)

Does anyone else have the same problem?
Is there any way to stop the servo?

on_release code looks like this (I tried all the different ways I know):

    on_release:
      then:
      - servo.detach: servo1
      - lambda: |-
         id(servo1).detach();
      - logger.log: "done1"

Debug log look like this, on_release seems to work, but servo.detach not:

[21:47:11][D][binary_sensor:036]: 'Switch 1': Sending state ON
[21:47:11][D][servo:062]: Servo new target: -1.000000
[21:47:12][D][binary_sensor:036]: 'Switch 1': Sending state OFF
[21:47:12][D][main:155]: done1
[21:47:16][D][servo:050]: Servo reached target

Here is full code

esphome:
  name: pwm-4servo
  friendly_name: pwm-4servo

esp8266:
  board: d1_mini

# Enable logging
logger:
  level: DEBUG

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Pwm-4Servo Fallback Hotspot"
    password: "NOJGD83JUJIV"

captive_portal:
    
# Define global variables
globals:
  - id: my_global_int1
    type: int
    restore_value: no
  - id: my_global_int2
    type: int
    restore_value: no
  - id: my_global_int3
    type: int
    restore_value: no
  - id: my_global_int4
    type: int
    restore_value: no

# Configure API and OTA
api:
  services:
    - service: control_servo1
      variables:
        level: float
      then:
        - servo.write:
            id: servo1
            level: !lambda 'return level / 100.0;'
    - service: control_servo2
      variables:
        level: float
      then:
        - servo.write:
            id: servo2
            level: !lambda 'return level / 100.0;'
    - service: control_servo3
      variables:
        level: float
      then:
        - servo.write:
            id: servo3
            level: !lambda 'return level / 100.0;'
    - service: control_servo4
      variables:
        level: float
      then:
        - servo.write:
            id: servo4
            level: !lambda 'return level / 100.0;'

ota:

# Configure outputs and servo
output:
  - platform: esp8266_pwm
    id: pwmout1
    pin: D5
    frequency: 50 Hz

  - platform: esp8266_pwm
    id: pwmout2
    pin: D6
    frequency: 50 Hz

  - platform: esp8266_pwm
    id: pwmout3
    pin: D7
    frequency: 50 Hz

  - platform: esp8266_pwm
    id: pwmout4
    pin: D8
    frequency: 50 Hz

servo:
  - id: servo1
    output: pwmout1
    transition_length: 5s
    auto_detach_time: 1s

  - id: servo2
    output: pwmout2
    transition_length: 5s
    auto_detach_time: 1s

  - id: servo3
    output: pwmout3
    transition_length: 5s
    auto_detach_time: 1s

  - id: servo4
    output: pwmout4
    transition_length: 5s
    auto_detach_time: 1s

# Configure binary sensor and switch
binary_sensor:
  - platform: gpio
    pin: 
      number: D1
      inverted: true
      mode:
        input: true
        pullup: true
    name: "Switch 1"
    filters:
      - delayed_on: 10ms
    on_press:
      then:
        - servo.write:
           id: servo1
           level: !lambda |-
             if (id(my_global_int1) == 1) {
             id(my_global_int1) = 2;
             return -1.0;
              } else {
             id(my_global_int1) = 1;
             return 1.0;
              }
    on_release:
      then:
      - servo.detach: servo1
      - lambda: |-
         id(servo1).detach();
      - logger.log: "done1"

  - platform: gpio
    pin: 
      number: D2
      inverted: true
      mode:
        input: true
        pullup: true
    name: "Switch 2"
    filters:
      - delayed_on: 10ms
    on_press:
      then:
        - servo.write:
           id: servo2
           level: !lambda |-
             if (id(my_global_int2) == 1) {
             id(my_global_int2) = 2;
             return -1.0;
              } else {
             id(my_global_int2) = 1;
             return 1.0;
              }
    on_release:
      then:
      - servo.detach: servo2
      - logger.log: "done2"

  - platform: gpio
    pin: 
      number: D3
      inverted: true
      mode:
        input: true
        pullup: true
    name: "Switch 3"
    filters:
      - delayed_on: 10ms
    on_press:
      then:
        - servo.write:
           id: servo3
           level: !lambda |-
             if (id(my_global_int3) == 1) {
             id(my_global_int3) = 2;
             return -1.0;
              } else {
             id(my_global_int3) = 1;
             return 1.0;
              }
    on_release:
      then:
      - servo.detach: servo3
      - logger.log: "done3"

  - platform: gpio
    pin: 
      number: D4
      inverted: true
      mode:
        input: true
        pullup: true
    name: "Switch 4"
    filters:
      - delayed_on: 10ms
    on_press:
      then:
        - servo.write:
           id: servo4
           level: !lambda |-
             if (id(my_global_int4) == 1) {
             id(my_global_int4) = 2;
             return -1.0;
              } else {
             id(my_global_int4) = 1;
             return 1.0;
              }
    on_release:
      then:
      - servo.detach: servo4
      - logger.log: "done4"

Did you ever figure this out? I am having the same problem. Thanks!

I just ran across the same issue; all of my “servo.detach” actions are ignored. In my case, it’s being used as a cover and I have it set to detach whenever it reaches open or closed or is simply stopped. On a whim, I decided to also specify the auto_detach_time variable and THAT works (I was afraid maybe I was dealing with a physical issue with my servo). In my case it’s ‘good enough’, but it seems pretty clear that there’s an issue.

This is why its important to read through the Docs. It specifically tells you if you dont set auto_detach_time it will just go to its default 0s which will not allow the servo to detatch. The only problem seems to be people choose to be uninformed and then complain about something not working right.

Seems you misunderstood my post? The issue isn’t with the auto_detach_time option, but rather with the ‘servo.detach’ command being ignored. This happens for me regardless of how I specify the auto detach time.

I guess so. I only use auto detatch for mine. I have a 3 second delay and it disconnects after a move + 3 seconds.

What kind of hardware are you using? Is it a continuous rotation servo?

Yep. I have endstops and want to have it detach once it gets to an end, but it just ignores the command. The auto-detach works, but (I presume because they’re cheap) the servos have some drift that no amount of calibrating eliminates permanently, so it’s not uncommon it will move a little before the auto-detach kicks in.

I can only speak from my own experience but, once i ditched my cheap servos and bought quality ones, i stopped having servo issues. These are ones that work great for me. I realize it isnt continuous rotation but, its just an example of good quality opposed to the cheap ones that come in 4 packs.
https://www.amazon.com/LewanSoul-LDX-218-Standard-Digital-Bearing/dp/B07LF652M7/ref=mp_s_a_1_4_pp?dib=eyJ2IjoiMSJ9.VtTNDGv2sIIK354Jefdcn-aMawP_43mcI82apgmsiEwLzjqQcIo2-EZrcrKpBMSShz5-JZb8iDe-sFB6Vu4vmOyTEdYeF6ispTFgMZo_TtglZ-6JV6wozo9HOOHIVF3M-RBZTrLyP4nPgUbySbjhXg8MLZX0otEZYa3_Rma8JeeymczGj-i2G6U5S9b9k3h7Z31y9Cd3JrjVkQ1b6HLppA.htxCZO0foceJy8bPd_g47jWFir3YJtMIxE2ZQ2fXBco&dib_tag=se&keywords=servo+motor&qid=1708816909&sr=8-4

Another thing, in my experience ive had a lot of problems controlling continuous rotation servos. Im not sure why but they were always a pain in my as$. Id suggest that if you dont actually need continuous servos then dont use them if you can.

Theres little to no difference between a servo and a stepper motor too. Have you tried using a stepper?

This was for a mostly finished project that I had originally done in Arduino but decided to switch to ESPHome while finishing it up; in other circumstances I probably would have tried different hardware. Maybe someday the code will get fixed, but for now I’ve made it work.

You could always put a transistor inline with the ground and then use a gpio switch to toggle the transistor on/off which would open/close the ground on the servo.

You mind me asking what you made? Ive got a whole bunch of servos and steppers left over but nothing has peaked my interest to pursue building anything else.

Oh wtf!!! Thats flipping cool man! Im not really sure what purpose it serves but its a 10/10 for cool factor.

Is the servo in that? That sucker is really loud.

Thanks! It’s a Little Free Library, so it’s for holding books for anyone to borrow.

There’s 4 servos doing each of the movements. And yeah, they’re a little loud. Ha

aw shit thats even freaking cooler, dang. You set up a free library? Like for the neighborhood kids in the community or something? Where abouts in the world are you located?

Im not kidding. That might be one of the coolest projects ive seen in a long time and its not a project out of pure self satisfaction. A+

1 Like

Yep! We seem to get a pretty even mix of kids and adults.

I’m in Kansas City; smack-dab in the middle of the US.

Nice! I dont like to advertise because there are some dishonest people out there unfortunately but, last time i had a stockpile of books and electronics i was done with, i found a boy scout leader who was wanting to start an electronics/Arduino scout program and i donated a bunch of stuff to them.

I have some electronics books and assorted programming books if you have any kids or teens who it could hekp.

This hobby really changed my life and gave me a healthy hobby i enjoy. If i could pay that gift forward, im happy to help your library.

Im in Indiana, just north of Indianapolis so shipping wouldnt be prohibitive for me like it if you were in the UK or something.

I just cant get over what a cool thing that is. Ive never seen those. Is that something anyone can participate in? Like if i wanted to set up a little library?

That’s super-generous of you! I guarantee you there are others somewhere near you that you could just drop them off at; if you go to the website I linked, they have an interactive map. And yep, anyone can do it. To be ‘official’, you pay a few bucks for a sign and can put yours on the map too.

It’s been a lot of fun (even with someone having cleared ours out once, presumably to sell them) and would highly recommend it. I have a speaker in our house play the ‘Reading Rainbow’ theme whenever someone opens it up; our kids have a blast running to their window to see who it is. :slight_smile:

Ill check it out. I have s 9 year old daughter, she loves helping me with projects and this would be a good one to do together. I wouldnt mind putting some little esp8266 learning kits in there. Give kids something to do besides melt their brains staring at a phonr…

1 Like