Rotary Encoder to control cover position

Hi all,

I am trying to use a rotary encoder to control a cover position. I am able to achieve this using several automation’s but I’m sure there must be a shorter way to do using lambas which I have no experience with.

Looking around this forum I have came up with the below code which does not work.

esphome:
  name: rotary_test
  platform: ESP8266
  board: esp01_1m

wifi:
  ssid: "xxxxxxx"
  password: "xxxxxxx"

  ap:
    ssid: "Rotary Test Fallback Hotspot"
    password: "xxxxxxxx"

captive_portal:

logger:

api:
  password: "xxxxxxxxx"

ota:
  password: "xxxxxxxx"

sensor:
  - platform: rotary_encoder
    name: "Rotary Encoder"
    pin_a: 0
    pin_b: 2

    filters:
     - or:
        - debounce: 0.1s
        - delta: 3
    resolution: 1
    min_value: 0
    max_value: 10
    on_value:
      then:
        - homeassistant.service:   
            service: cover.set_cover_position    
            data_template:
              entity_id: cover.front_blinds
              position: "{{ position_1 | int }}"
            variables:
              position_1: 'return id(Rotary Encoder).state * 4;'

I’m sure there is something I am missing that someone could help me with.

Thanks in advance

I’m doing exactly the same thing but using an encoder with PWM output. At the moment I solved it like this:

switch:
  - platform: gpio
    pin: GPIO12
    name: "Cover Open Switch"
    id: open_switch
  - platform: gpio
    pin: GPIO13
    name: "Cover Close Switch"
    id: close_switch
sensor:
  - platform: duty_cycle
    pin: GPIO15
    name: Duty Cycle Sensor
    update_interval: 2s
    unit_of_measurement: "%"
    accuracy_decimals: 0
    filters:
      - calibrate_linear:
        - 2.9 -> 0.0
        - 97.1 -> 100.0
      - or:
        - throttle: 600s
        - delta: 5      
    on_value: 
      - cover.template.publish:
          id: mycover
          position: !lambda "return x/100;"
cover:
  - platform: template
    id: mycover
    name: "My Cover"
    open_action:
      # Cancel any previous action
      - switch.turn_off: close_switch
      # Turn the OPEN switch on briefly
      - switch.turn_on: open_switch
      - delay: 5s
      - switch.turn_off: open_switch
    close_action:
      - switch.turn_off: open_switch
      - switch.turn_on: close_switch
      - delay: 5s
      - switch.turn_off: close_switch
    stop_action:
      - switch.turn_off: close_switch
      - switch.turn_off: open_switch
    optimistic: false
    assumed_state: false
    has_position: true

However I have not figured out yet how to give a position setpoint (or how to control to a position which is not 0% or 100% that is)

1 Like

Ok, I’m having a rethink. I am trying to complete the whole project in esphome but I am struggling
still with the rotary encoder.

I what to call a certain action when the encoder value increases and a different action when the value decreases.

the code I have which does work is as follows.

esphome:
  name: passage_blind
  platform: ESP8266
  board: d1_mini

wifi:
  ssid: ""
  password: ""

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Passage Blind Fallback Hotspot"
    password: ""

captive_portal:

# Enable logging
logger:

# Enable Home Assistant API
api:
  password: ""
  services:
    - service: control_stepper
      variables:
        target: int
      then:
        - stepper.set_target:
            id: my_stepper
            target: !lambda 'return target;'

ota:
  password: ""


web_server:
  port: 80 

# physical connection
stepper: #https://community.home-assistant.io/t/motor-on-a-roller-blind-esphome-version/116179/11
  - platform: uln2003
    id: my_stepper
    pin_a: D0
    pin_b: D5
    pin_c: D6
    pin_d: D7
    max_speed: 250 steps/s
    sleep_when_done: true    
    acceleration: inf
    deceleration: inf


# items for Home Assistant 
cover:
  - platform: template
    name: "Venetian blinds"
    id: window1
    device_class: shutter

    open_action:
      - stepper.report_position:
          id: my_stepper
          position: 0
      - stepper.set_target:
          id: my_stepper
          target: -1000

    close_action:
      - stepper.report_position:
          id: my_stepper
          position: 0
      - stepper.set_target:
          id: my_stepper
          target: 1000

    stop_action:
      - stepper.set_target:
          id: my_stepper
          target: !lambda return id(my_stepper).current_position;      
    optimistic: true  

# for manual adjustment of the initial setting position
switch:
  - platform: template
    name: "Step minus"
    id: step_minus
    turn_on_action:
      - stepper.report_position:
          id: my_stepper
          position: 0
      - stepper.set_target:
          id: my_stepper
          target: -200
  - platform: template
    name: "Step plus"
    id: step_plus
    turn_on_action:
      - stepper.report_position:
          id: my_stepper
          position: 0
      - stepper.set_target:
          id: my_stepper
          target: 200
          

          
          
sensor:
  - platform: rotary_encoder
    name: "Blind Encoder "
    id: blind_encoder
    pin_a: D2
    pin_b: D3    

          
    filters:
     - or:
        - debounce: 0.1s
    resolution: 1
    min_value: 0
    max_value: 10  
    on_value:   
      then:
        - if: 
            condition:
              lambda: return id(blind_encoder).state =+ 1 ; 
            then: 
              switch.turn_on: step_plus
        - if:
            condition:
              lambda: return id(blind_encoder).state =- 1 ; 
            then: 
              switch.turn_on: step_minus

the motor turns the same way regardless of encoder direction.

you people might learn something from here https://github.com/esphome/feature-requests/issues/566