Feedback cover, endstop based, rollback not functioning

So I have gotten my feedback cover for my gate working almost perfectly (there are a few unfinished provisions like the pulse counter). However I am running into a big issue, I have an ina260 reading forward and reverse current and its triggering a binary template sensor for obstacle detection. The cover sees the detection, issues a cover.stop. Then no rollback.

substitutions:
  devicename: gate_controller
  devicename_no_dashes: gate_controller
  friendly_devicename: "Gate Controller"
  restore_mode_setting: RESTORE_DEFAULT_OFF
  purpose: entry
  subject: gate
  # WT32-ETH01 specific pins
  open_pin: GPIO04    # Adjust based on your wiring PWM
  close_pin: GPIO02   # Adjust based on your wiring PWM
  pulse_pin: GPIO14      # Input only pin for hall effect sensor
  i2c_sda: GPIO33 
  i2c_scl: GPIO32

esphome:
  name: ${devicename}
  friendly_name: ${friendly_devicename}
  
esp32:
  board: wt32-eth01
  framework:
    type: arduino
packages:
  device_base: !include /config/esphome/common/esp32common.yaml
  
# Ethernet configuration for WT32-ETH01
# ethernet:
  # type: LAN8720
  # mdc_pin: GPIO23
  # mdio_pin: GPIO18
  # clk_mode: GPIO17_OUT
  # phy_addr: 1
  # power_pin: GPIO16
  # domain: .symtus.com
  # enable_mdns: true

# Fallback WiFi configuration
wifi:
  ssid: !secret wifi_ssid2
  password: !secret wifi_password2
  domain: .symtus.com
  ap:
    ssid: "Gate Controller Fallback"
    password: "i6D5uFh1LG1A"

# API and OTA
api:
  reboot_timeout: 0h
  encryption:
    key: !secret api_encryption_key

ota:
  platform: esphome
  password: !secret ota_password

# Enable web server
web_server:
  port: 80

logger:
  level: DEBUG  # This will show INFO and higher (WARN, ERROR)
  logs:
    sensor: WARN    # Make sensor logs less frequent
    obstacle: INFO  # Keep obstacle detection at INFO level

# I2C configuration for INA260
i2c:
  sda: ${i2c_sda}
  scl: ${i2c_scl}
  scan: true
  frequency: 400khz

mcp23017:
  - id: gate_io_expander
    # interrupt_timing: 10ms  # Debounce timing for interrupts, adjust if needed
    address: 0x20  # Default address, adjust if needed
    # interrupt: GPIO35   # Using your existing pulse_pin for interrupt
      
    

# Global state variables
globals:

  - id: last_direction
    type: int
    restore_value: yes  # Remember across reboots
    initial_value: "0"  # 0=unknown, 1=was opening, 2=was closing

  - id: soft_stop_percentage
    type: float
    restore_value: yes
    initial_value: "0.90"  # Start soft stop at 90% of travel
    
  - id: pwm_level
    type: float
    restore_value: no
    initial_value: "0.0"
  
  - id: is_soft_starting
    type: bool
    restore_value: no
    initial_value: "false"

  - id: is_soft_stoping
    type: bool
    restore_value: no
    initial_value: "false"
    
  - id: gate_close_countdown
    type: int
    restore_value: no
    initial_value: "0"

  - id: auto_close_active
    type: bool
    restore_value: no
    initial_value: "false"
  
  

#################################For possible rotation based stops##########################

  - id: last_open_rotation_count
    type: int
    restore_value: yes
    initial_value: "0"

  - id: last_close_rotation_count
    type: int
    restore_value: yes
    initial_value: "0"

  - id: current_rotation_count
    type: int
    restore_value: yes
    initial_value: "0"

#################################For possible rotation based stops##########################

# Output configuration for motor control
output:
  - platform: ledc
    pin: ${open_pin}
    frequency: 10000Hz
    id: gate_control_gate_open
    

  - platform: ledc
    pin: ${close_pin}
    frequency: 10000Hz
    id: gate_control_gate_close

# State display sensor  ONLY A DISPLAY 
text_sensor:
  - platform: template
    name: "Gate State"
    id: gate_state_sensor
    update_interval: never  #  faster update interval elsewhere
    lambda: |-
      if (id(obstacle_detected).state) return {"ERROR"};
      if (id(gate_opening).state) return {"OPENING"};
      if (id(gate_closing).state) return {"CLOSING"};
      if (id(open_gate_endstop).state) return {"OPEN"};
      if (id(close_gate_endstop).state) return {"CLOSED"};
      if (id(gate_ajar).state) return {"AJAR"};
      return {"STOPPED"};
    
# Binary sensors
binary_sensor:
  # Limit switches
  - platform: gpio
    pin:
      mcp23xxx: gate_io_expander
      number: 0   # GPA0
      mode: 
        input: true
        pullup: true
      inverted: true

    id: gate_open_switch
    name: "Gate is Fully Open"
    filters:
      - delayed_off: 50ms
    on_press:
      - logger.log: "Open endstop GPIO activated"
    on_release:
      - logger.log: "Open endstop GPIO released"

  - platform: gpio
    pin:
      mcp23xxx: gate_io_expander
      number: 1   # GPA1
      mode:
        input: true
        pullup: true
      inverted: true
    id: gate_close_switch
    name: "Gate is Fully Closed"
    filters:
      - delayed_off: 50ms
    on_press:
      - logger.log: "Close endstop GPIO activated"
    on_release:
      - logger.log: "Close endstop GPIO released"

  # Toggle button on MCP23017
  - platform: gpio
    pin:
      mcp23xxx: gate_io_expander
      number: 2   # GPA2
      mode:
        input: true
        pullup: true
      inverted: true
    id: gate_cycle_trigger
    name: "Gate Cycle Trigger"
    filters:
      - delayed_on: 100ms
      - delayed_off: 100ms
    on_press:
      - button.press: gate_cycle_button
      - logger.log: "Gate cycle button pressed"

  # OPEN button on MCP23017
  - platform: gpio
    pin:
      mcp23xxx: gate_io_expander
      number: 3   # GPA3
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate test OPEN "
    filters:
      - delayed_on: 100ms
      - delayed_off: 10ms
    on_press:
      - button.press: Test_OPEN
      - logger.log: "Gate test OPEN button pressed"
    on_release: 
     output.turn_off: gate_control_gate_open
    
   # CLOSE button on MCP23017
  - platform: gpio
    pin:
      mcp23xxx: gate_io_expander
      number: 4   # GPA
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate test CLOSE "
    filters:
      - delayed_on: 100ms
      - delayed_off: 10ms
    on_press:
      - button.press: Test_CLOSE
      - logger.log: "Gate test CLOSE button pressed"
    on_release: 
     output.turn_off: gate_control_gate_close
   
  - platform: template
    id: open_gate_endstop
    name: "Gate Open Multi Endstop Reached"
    lambda: |-
      return id(gate_open_switch).state;


  - platform: template
    id: close_gate_endstop
    name: "Gate Closed Multi Endstop Reached"
    lambda: |-
      return id(gate_close_switch).state;
    

  - platform: template
    id: gate_ajar
    name: "Gate is Ajar"
    lambda: |-
      return !(id(open_gate_endstop).state || id(close_gate_endstop).state);

  - platform: template
    id: gate_opening
    name: "Gate Opening Current"
    lambda: |-
      float current = id(gate_power_sensor_current).state;
      // Positive current indicates opening
      return current > 0.01;  // Small threshold to avoid noise
    filters:
      - delayed_off: 100ms # Only consider "off" if the condition is false for at least 
    
    
    
  - platform: template
    id: gate_closing
    name: "Gate Closing Current"
    lambda: |-
      float current = id(gate_power_sensor_current).state;
      // Negative current indicates closing
      return current < -0.010;  // Small threshold to avoid noise
    filters:   
      - delayed_off: 100ms
         
  #######################################This works for a rollback but its super janky!!############################################  
  # - platform: template
  #   id: obstacle_detected
  #   name: "Obstacle Detected Current"
  #   publish_initial_state: True
  #   filters:
  #     - delayed_on: 50ms
  #     - delayed_off: 200ms
  #   lambda: |-
  #     // Only check for obstacles if gate is moving
  #     if (id(gate_cover).current_operation == COVER_OPERATION_IDLE) {
  #         return false;
  #     }

  #     float current_threshold = 0.20;  // Base threshold
  #     if (id(is_soft_starting)) {
  #         current_threshold = current_threshold + (1.0 - pow(id(pwm_level), 2.0f)) * 0.3;
  #     }
  #     id(gate_power_sensor).update();
  #     float current = abs(id(gate_power_sensor_current).state);
      
  #     ESP_LOGD("obstacle", "Current: %.3fA, Threshold: %.3fA%s", 
  #         current, 
  #         current_threshold,
  #         id(is_soft_starting) ? " (Soft Start)" : "");
          
  #     return current > current_threshold;
  #   on_state:
  #     - if:
  #         condition:
  #              lambda: 'return id(gate_cover).current_operation == COVER_OPERATION_OPENING;'  # Was opening
  #         then:
  #           - cover.stop: gate_cover
  #           - cover.close: gate_cover
  #           - delay: 4s
  #           - cover.stop: gate_cover
  #     - if:
  #         condition:
  #           lambda: 'return id(gate_cover).current_operation == COVER_OPERATION_CLOSING;'  # Was closing
  #         then:
  #           - cover.stop: gate_cover
  #           - cover.open: gate_cover
  #           - delay: 4s
  #           - cover.stop: gate_cover


  - platform: template
    id: current_threshold_exceeded
    internal: true
    lambda: |-
        bool is_opening = id(gate_cover).current_operation == COVER_OPERATION_OPENING;
        float position = id(gate_cover).position;
        
        float current_threshold = is_opening ? 0.17 : 0.17;
        
        if (id(is_soft_starting)) {
            current_threshold = current_threshold + (1.0 - pow(id(pwm_level), 2.0f)) * 0.4;
        } else if (id(is_soft_stoping)) {
            current_threshold = current_threshold + (1.0 - pow(id(pwm_level), 2.0f)) * 0.3;
        }
        
        if (position > 0.85 || position < 0.15) {
            current_threshold *= 1.2;
        }
        

        float current = abs(id(gate_power_sensor_current).state);
        
        ESP_LOGD("obstacle", "Current: %.3fA, Threshold: %.3fA, Position: %.2f%s%s", 
            current, 
            current_threshold,
            position,
            id(is_soft_starting) ? " (Soft Start)" : "",
            id(is_soft_stoping) ? " (Soft Stop)" : "");
            
        return current > current_threshold;

  - platform: template
    id: obstacle_detected
    name: "Obstacle Detected"
    publish_initial_state: true
    lambda: |-
        if (id(current_threshold_exceeded).state) {
          return true;  // Once true, stays true until reset
        }
        return id(obstacle_detected).state;  // Maintain previous state
    on_press:
      - logger.log: "Obstacle detected!"


# Sensors
sensor:
  
  # Current sensor
  - platform: ina260
    address: 0x40
    id: gate_power_sensor
    update_interval: 50ms  # Will be updated by the interval component when needed
    current:
      id: gate_power_sensor_current
      name: "Gate Motor Current"
      accuracy_decimals: 2
      filters:
        - sliding_window_moving_average:
            window_size: 30
            send_every: 1


  - platform: template
    name: "Gate Raw Position"
    unit_of_measurement: "RAW"
    accuracy_decimals: 2
    update_interval: 50ms
    lambda: |-
      return id(gate_cover).position;

  - platform: template
    name: "Gate Cover Operating State"
    id: gate_cover_operation_state
    lambda: |-
      return id(gate_cover).current_operation;  
    unit_of_measurement: "state"
    accuracy_decimals: 0
    icon: "mdi:gate"
    update_interval: 50ms
        
  - platform: template
    name: "Gate Closing Countdown"
    id: gate_closing_countdown
    unit_of_measurement: "Seconds"
    accuracy_decimals: 0
    icon: mdi:timer
    lambda: |-
      return id(gate_close_countdown);  
    # Display for the the global countdown value

  - platform: template
    name: "Last Open Rotation Count"
    id: last_open_rotation_count_sensor
    unit_of_measurement: "rotations"
    accuracy_decimals: 0
    lambda: |-
      return id(last_open_rotation_count);
    
  - platform: template
    name: "Last Close Rotation Count"
    id: last_close_rotation_count_sensor
    unit_of_measurement: "rotations"
    accuracy_decimals: 0
    lambda: |-
      return id(last_close_rotation_count);

  # Rotation counter
  - platform: pulse_meter
    pin: ${pulse_pin}
    id: gate_motor_rotations
    internal: true
    filters: 
      - debounce: 30ms
    total:
      name: "Motor Rotations"
      id: gate_motor_rotations_total
      on_value:
        then:
          - if:
              condition:
                binary_sensor.is_on: gate_opening
              then:
                - lambda: |-
                    id(current_rotation_count) = id(current_rotation_count) + 1;
          - if:
              condition:
                binary_sensor.is_on: gate_closing
              then:
                - lambda: |-
                    id(current_rotation_count) = id(current_rotation_count) - 1;

  - platform: homeassistant
    id: ui_gate_duration
    entity_id: input_number.${purpose}_gate_duration
    on_value:
      then:
        - sensor.template.publish:
            id: ${purpose}_gate_duration
            state: !lambda return id(ui_gate_duration).state;

  - platform: template
    name: ${purpose} duration - gate
    id: ${purpose}_gate_duration
    accuracy_decimals: 0
    unit_of_measurement: sec
    icon: mdi:camera-timer

# Cover component
cover:
  - platform: feedback
    name: "Main Gate"
    id: gate_cover
    device_class: gate
    update_interval: 1s
    direction_change_wait_time: 1s
    obstacle_rollback: 20%
    open_endstop: open_gate_endstop
    close_endstop: close_gate_endstop
    open_duration: 53s
    close_duration: 55s
    open_obstacle_sensor: obstacle_detected
    close_obstacle_sensor: obstacle_detected

    open_action:
      - if:
          condition:
            binary_sensor.is_on: open_gate_endstop
          then:
          - logger.log: "Cannot open - gate at open endstop"   #this is for a bug in feedback cover
          else:
            - globals.set:
                id: last_direction
                value: "1"  # Mark as opening
            - globals.set:
                id: is_soft_starting
                value: "true"
            - globals.set:
                id: is_soft_stoping
                value: "true"       
            - logger.log: "Starting soft start open sequence"

            
    close_action:
      - if:
          condition:
            binary_sensor.is_on: close_gate_endstop
          then:
            - logger.log: "Cannot close - gate at close endstop" #this is for a bug in feedback cover
          else:
            - globals.set:
                id: last_direction
                value: "2"  # Mark as closing
            - globals.set:
                id: is_soft_starting
                value: "true"
            - globals.set:
                id: is_soft_stoping
                value: "true"
            - globals.set:
                id: gate_close_countdown 
                value: "0"
            - component.update: gate_closing_countdown
            - logger.log: "Starting soft start for closing gate"
           

    on_open:  # When successfully reaches open position
      - globals.set:
          id: last_open_rotation_count
          value: id(current_rotation_count)
      - logger.log: 
          format: "Gate successfully opened. Final rotation count: %d"
          args: ['id(current_rotation_count)']
      - pulse_meter.set_total_pulses:
          id: gate_motor_rotations
          value: 0
      - globals.set:
          id: current_rotation_count
          value: '0'
      
      - component.update: gate_state_sensor
           
    on_closed:  # When successfully reaches closed position
      - globals.set:
          id: last_close_rotation_count
          value: id(current_rotation_count)
      - logger.log: 
          format: "Gate successfully closed. Final rotation count: %d"
          args: ['id(current_rotation_count)']
      - pulse_meter.set_total_pulses:
          id: gate_motor_rotations
          value: 0
      - globals.set:
          id: current_rotation_count
          value: '0'
      - globals.set:
          id: auto_close_active
          value: 'false'
      # - delay: 1s

      - component.update: gate_state_sensor


    stop_action:  #stop everything!!
      - globals.set: #just in case stop was called before ramp up was complete
          id: is_soft_starting
          value: "false"
      - globals.set: #just in case stop was called before ramp down was complete
          id: is_soft_stoping
          value: "false"
      - globals.set: #OFF
          id: pwm_level
          value: "0.0"
      - globals.set:
          id: gate_close_countdown  #if something was counting down, stop it
          value: "0"
      # - globals.set:
      #     id: auto_close_active  # Cancel any active auto-close sequence
      #     value: "false"
      - output.turn_off: gate_control_gate_open     #Stop both outputs
      - output.turn_off: gate_control_gate_close
      - delay: 1s
      
      - component.update: gate_state_sensor 
      
# Update interval
interval:
  ##########################################DEBUG##############################################################
  - interval: 10s
    then:
      - lambda: |-
          ESP_LOGD("state_monitor", "State Check - Operation: %d, Soft Start: %d, Soft Stop: %d, Auto Close: %d, Last Direction: %d, PWM: %.2f, Position: %.2f",
            id(gate_cover).current_operation,
            id(is_soft_starting),
            id(is_soft_stoping),
            id(auto_close_active),
            id(last_direction),
            id(pwm_level),
            id(gate_cover).position);

  #######################################END###DEBUG##############################################################

############################################100ms SOFT START INTERVAL###################################
  - interval: 100ms
    then:
      # First check endstop safety
      - if:
          condition:
            or:
              - and:
                  - binary_sensor.is_on: open_gate_endstop
                  - lambda: 'return id(gate_cover).current_operation == COVER_OPERATION_OPENING;'
              - and:
                  - binary_sensor.is_on: close_gate_endstop
                  - lambda: 'return id(gate_cover).current_operation == COVER_OPERATION_CLOSING;'
          then:
          - logger.log: "Safety stop: Cover operating against endstop"
          - cover.stop: gate_cover
          - if:
              condition:
                binary_sensor.is_on: open_gate_endstop
              then:
                - cover.close: gate_cover
              else:
                - if:
                    condition:
                      binary_sensor.is_on: close_gate_endstop
                    then:
                      - cover.open: gate_cover
                    
                      
      # Only perform this logic if soft start is active
      - if:
          condition:
            lambda: 'return id(is_soft_starting);'
          then:
           # Increment soft start level until we reach full power
            - lambda: |-
                if (id(pwm_level) < 1.0) {
                    id(pwm_level) = std::min(1.0f, id(pwm_level) + 0.02f);
                }
            # Determine gate direction and apply corresponding PWM
            - if:
                condition:
                  lambda: 'return id(gate_cover).current_operation == COVER_OPERATION_OPENING;' # Opening
                then:
                  - output.set_level:
                      id: gate_control_gate_open
                      level: !lambda 'return pow(id(pwm_level), 2.0f);'
                  # - logger.log:
                  #     format: "Applying PWM to OPEN direction. Level: %.2f"
                  #     args: ['pow(id(pwm_level), 2.0f)']
            - if:
                condition:
                  lambda: 'return id(gate_cover).current_operation == COVER_OPERATION_CLOSING;' 
                then:
                  - output.set_level:
                      id: gate_control_gate_close
                      level: !lambda 'return pow(id(pwm_level), 2.0f);'
                  # - logger.log:
                  #     format: "Applying PWM to CLOSE direction. Level: %.2f"
                  #     args: ['pow(id(pwm_level), 2.0f)']
            
            # When soft start is complete, deactivate the soft start mode
            - if:
                condition:
                  lambda: 'return id(pwm_level) == 1.0;'
                then:
                  - globals.set:
                      id: is_soft_starting
                      value: "false"
                  - logger.log: "Ramp complete - Motor at full power - Deactivating soft start"
############################################50ms SOFT STOP INTERVAL###################################
  - interval: 50ms
    then:
      - if:
          condition:
            and:
              #Check if is_soft_starting is false becasue soft start has been completed
              - lambda: 'return !id(is_soft_starting);'
              - lambda: 'return id(is_soft_stoping);'
              # Condition: Gate position and direction checks
              - or:
                  - and:
                    # Check if the gate is opening and the position is >= 99%
                    - lambda: 'return id(gate_cover).current_operation == COVER_OPERATION_OPENING;'
                    - lambda: 'return id(gate_cover).position >= .99;'
                  - and:
                  # Check if the gate is closing and the position is <= 1%
                    - lambda: 'return id(gate_cover).current_operation == COVER_OPERATION_CLOSING;'
                    - lambda: 'return id(gate_cover).position <= .01;'
          then:
            # - logger.log: "Ramp down starting - soft stop"
            # Decrement soft stop level until we reach minimum power
            - lambda: |-
                if (id(pwm_level) > 0.35) {
                id(pwm_level) = std::max(0.1f, id(pwm_level) - 0.01f);
                }
            # - logger.log:
            #     format: "Ramp down progress: %.0f%%, Level: %.2f, Smoothed: %.2f"
            #     args: [
            #       "id(pwm_level) * 100", 
            #       'id(pwm_level)', 
            #       'pow(id(pwm_level), 2.0f)'
            #           ]
                # Apply PWM to active output
            - if:
                condition:
                  binary_sensor.is_on: gate_opening
                then:
                  - output.set_level:
                      id: gate_control_gate_open
                      level: !lambda 'return std::max(0.25f, pow(id(pwm_level), 2.0f));'
            - if:
                condition:
                  binary_sensor.is_on: gate_closing
                then:
                  - output.set_level:
                      id: gate_control_gate_close
                      level: !lambda 'return std::max(0.25f, pow(id(pwm_level), 2.0f));'
#####################################ONE SECOND COUNTDOWN######################################
  - interval: 1s
    then:
      - if:
          condition:
            lambda: 'return id(gate_close_countdown) > 0;'
          then:
            - lambda: |-
                id(gate_close_countdown)--;
                ESP_LOGD("countdown", "Countdown: %d seconds remaining", id(gate_close_countdown));
            - component.update: gate_closing_countdown
button:
##########################GATE CYCLE LOGIC BUTTONS#################################
  - platform: template
    name: "Gate Cycle" 
    id: gate_cycle_button
    on_press:
      - if:
          condition:
            lambda: 'return id(gate_cover).current_operation != COVER_OPERATION_IDLE;'
          then:
            - cover.stop: gate_cover  #Just STOP
            - logger.log: "STOP!!!"
          else:
            - logger.log: "Condition: Gate is idle, proceeding with checks."
            - if:
                condition:
                  lambda: 'return id(gate_cover).position == COVER_OPEN;'
                then:
                  - logger.log: "Condition: Gate is at OPEN position, starting close."
                  - cover.close: gate_cover  #Just CLOSE
                else:
                  - if:
                      condition:
                        # Modified condition to be more explicit about valid states for opening
                        lambda: 'return (id(gate_cover).position == COVER_CLOSED);'
                      then:
                        - logger.log: "Starting open cycle from CLOSED position"
                        - cover.open: gate_cover  #Open the cover
                        - globals.set:
                            id: auto_close_active #set auto close bit
                            value: "true"
                        - wait_until:
                            condition:
                              lambda: 'return id(gate_cover).position == COVER_OPEN;' 
                        - lambda: |-
                            id(gate_close_countdown) = int(id(ui_gate_duration).state);
                        - wait_until:
                            condition:
                              lambda: 'return id(gate_close_countdown) <= 0 && id(auto_close_active);'
                        - cover.close: gate_cover
                        - globals.set:
                            id: auto_close_active #set auto close bit
                            value: "false"

                      else:
                        - logger.log: "Position uncertain or was opening, defaulting to close"
                        - cover.close: gate_cover

# ####################################################TESTING BUTTONS
  - platform: template
    name: "Test Open Output"
    id: Test_OPEN
    on_press:
      - if:
          condition:
            binary_sensor.is_on: open_gate_endstop
          then:
            - logger.log: "Cannot activate open output - Gate already at open endstop!"
          else:
            - output.set_level:
                id: gate_control_gate_open
                level: 1.0
            - logger.log: "Setting open output to full"

      
  - platform: template
    name: "Test Close Output"
    id: Test_CLOSE

    on_press:
      - if:
          condition:
            binary_sensor.is_on: close_gate_endstop
          then:
            - logger.log: "Cannot activate close output - Gate already at close endstop!"
          else:
            - output.set_level:
                id: gate_control_gate_close
                level: 1.0
            - logger.log: "Setting close output to full"
            # Optional: Add auto-shutoff after brief period
# ####################################################TESTING BUTTONS

And your log doesn’t give any hint?

Oh no, it absolutely does. Full object detection and an internal STOP is issued, However that’s where it ends. No Rollback action takes place. I am wondering if the internal STOP its issuing is killing the rollback routine
``
[12:17:36][D][esp32.preferences:114]: Saving 3 preferences to flash…
[12:17:36][D][esp32.preferences:143]: Saving 3 preferences to flash: 0 cached, 3 written, 0 failed
[12:17:36][D][cover:170]: ‘Main Gate’ - Publishing:
[12:17:36][D][cover:173]: Position: 13%
[12:17:36][D][cover:186]: Current Operation: OPENING
[12:17:37][D][cover:170]: ‘Main Gate’ - Publishing:
[12:17:37][D][cover:173]: Position: 15%
[12:17:37][D][cover:186]: Current Operation: OPENING
[12:17:38][D][binary_sensor:036]: ‘current_threshold_exceeded’: Sending state ON
[12:17:38][D][binary_sensor:036]: ‘Obstacle Detected’: Sending state ON
[12:17:38][D][main:385]: Obstacle detected!
[12:17:38][D][feedback.cover:208]: ‘Main Gate’ - Open obstacle detected.
[12:17:38][D][cover:170]: ‘Main Gate’ - Publishing:
[12:17:38][D][cover:173]: Position: 15%
[12:17:38][D][cover:186]: Current Operation: IDLE
[12:17:38][D][feedback.cover:385]: ‘Main Gate’ - Firing ‘STOP’ trigger.
[12:17:38][D][feedback.cover:364]: ‘Main Gate’ - Close obstacle detected. Action not started.
[12:17:38][D][binary_sensor:036]: ‘current_threshold_exceeded’: Sending state OFF
[12:17:39][D][binary_sensor:036]: ‘Gate Opening Current’: Sending state OFF
[12:17:39][D][binary_sensor:036]: ‘Gate Closing Current’: Sending state ON
[12:17:39][D][binary_sensor:036]: ‘Gate Closing Current’: Sending state OFF
[12:17:45][D][state_monitor:626]: State Check - Operation: 0, Soft Start: 0, Soft Stop: 0, Auto Close: 1, Last Direction: 1, PWM: 0.00, Position: 0.15
[12:17:55][D][state_monitor:626]: State Check - Operation: 0, Soft Start: 0, Soft Stop: 0, Auto Close: 1, Last Direction: 1, PWM: 0.00, Position: 0.15 ```

At least briefly something happens?

That’s detected flyback current from the motor stopping, causing the ina260 to briefly go negative, even through the snubber circuit. It should not have any bearing but maybe it is causing an odd condition, I will try to filter it. However there should be a feedback.cover function and at 20% rollback would be very obvious. I am not seeing it.
Obviously these parts of the built in cover function are working
12:17:38][D][feedback.cover:385]: ‘Main Gate’ - Firing ‘STOP’ trigger.
[12:17:38][D][feedback.cover:364]: ‘Main Gate’ - Close obstacle detected. Action not started.

Yep, I agree… But you have yaml long like a bible and board that can have weird implementations, so while I expect it’s something simple, there are odds.

My apologies.

Try that rollback with some simplified code for test purposes.