Using Rotary Encoder to control HA Thermostat temp from ESPHome

I’m trying to control my thermostat in HA from ESPHome using rotary encoder. I want to set the temp with it but for some reason it does not work. I would appreciate some help.

Thermostat is stepping values from 16 to 26 every half degree as needed but it does not pass the value to HA.

 - platform: rotary_encoder
   name: "Rotary Encoder Thermostat from ESPhome"
   id: rotary
   pin_a: 32
   pin_b: 33
   min_value: 32
   max_value: 52
   resolution: 2
   internal: true
   filters:
   - lambda: return x * 0.5;
   on_value:
     then:
     - homeassistant.service:
        service: climate.set_temperature
        data_template:
          entity_id: climate.home_thermostat
          temperature: "{{id(rotary).state}}"
1 Like

Logs? both HA and ESPhome

Ok got it working by using the following:

 - platform: rotary_encoder
   name: "Rotary Encoder Thermostat from ESPhome"
   id: rotary
   pin_a: 32
   pin_b: 33
   min_value: 32
   max_value: 52
   resolution: 2
   internal: true
   filters:
   - lambda: return x * 0.5;
   on_value:
     then:
     - homeassistant.service:
        service: climate.set_temperature
        data_template:
          entity_id: climate.home_thermostat
          temperature: !lambda "return id(rotary).state;"

Now question how to sync it so when the temp value in HA changes (by adjusting in another device) this updates new starting point for rotary encoder?

1 Like

I think start here https://esphome.io/components/sensor/homeassistant.html

Then you can use this (I think) to set the state of rotary.

Thanks! Ok managed to make it work by reading temp from HA

 - platform: homeassistant
   name: "Set Temperature from Home Asisstant"
   entity_id: sensor.home_thermostat_temperature 
   id: home_set_temp 
   internal: true
   on_value:
    - sensor.rotary_encoder.set_value:
       id: rotary
       value: !lambda "return id(home_set_temp).state * 2;"

err this probably should not be done this way. Weird stuff happens and number jumps up and down when I rotate encoder quickly through a few steps.

1 Like

I’ve been working on a similar project, here’s my code in case it helps anyone trying to do the same.

 ##################################
 ####   ESPHOME THERMO CODE    ####
 ####    BY STEVEN LOVEJOY     ####
 ##################################
 ## NODE-MCU V3 PINOUTS          ##
 ##################################
 ## D2 = DHT11 output            ##
 ## D3 = Output_A rotary encoder ##
 ## D4 = Output_B rotary encoder ##
 ## D6 = scl 128x64 ssd1306 oled ##
 ## D7 = sda 128x64 ssd1306 oled ##
 ## 3v3 oled & DHT11 positive    ##
 ##################################
 ## download font files to       ##
 ## /config/esphome/             ##
 ##################################
 
 esphome:
  name: Thermo
  platform: ESP8266
  board: nodemcuv2

wifi:
  ssid: '**********'
  password: '**************'

# Enable logging
logger:

# Enable Home Assistant API
api:
  password: '*************'

ota:
  password: '***************'
  
# TIME FROM HASSIO
time:
  - platform: homeassistant
    id: times

sensor:
# LOUNGE TEMP FROM HASSIO
  - platform: homeassistant
    id: lounge_temperature
    entity_id: sensor.lounge_temp
    internal: true

# HEATING TARGET TEMP FROM HASSIO
  - platform: homeassistant
    entity_id: sensor.target_temp_2
    name: "Target Temp State"
    id: target_temp_2
    internal: true
    on_value:
    - sensor.rotary_encoder.set_value:
       id: thermo_encoder
       value: !lambda "return id(target_temp_2).state * 2;"
       
# ONBOARD DHT11 TEMP & HUMIDITY SENSOR
  - platform: dht
    pin: D2
    temperature:
      id: thermo_temperature
      name: "Thermo Temperature"
    humidity:
      id: thermo_humidity
      name: "Thermo Humidity"
    update_interval: 60s
    model: DHT11

# ONBOARD ROTARY ENCODER
  - platform: rotary_encoder
    name: "Thermo Encoder"
    id: thermo_encoder
    pin_a: D3
    pin_b: D4
    min_value: 20
    max_value: 70
    resolution: 2
    filters:
    - lambda: return x * 0.5;
    on_value:
      then:
      - delay: 0.2s
      - homeassistant.service:
          service: climate.set_temperature
          data_template:
            entity_id: climate.lounge
            temperature: !lambda "return id(thermo_encoder).state;"

# SET FONTS
font:
  - file: 'slkscr.ttf'
    id: font1
    size: 8

  - file: 'arial.ttf'
    id: font2
    size: 16
    
  - file: 'BebasNeue-Regular.ttf'
    id: font3
    size: 36
    
  - file: 'BebasNeue-Regular.ttf'
    id: font4
    size: 50

# ICON SIZE 20
  - file: 'materialdesignicons-webfont.ttf'
    id: icon_font_20
    size: 20
    glyphs: [
      "\U000F0238"
      ]
# ICON SIZE 30  
  - file: 'materialdesignicons-webfont.ttf'
    id: icon_font_30
    size: 30
    glyphs: [
      "\U000F0238"
      ]

# HEATING STATE BINARY FROM HASSIO
binary_sensor:
  - platform: homeassistant
    entity_id: binary_sensor.heating_state
    name: "Heating State Binary"
    id: heating_state_binary
    internal: true

# HEATING STATE TEXT FROM HASSIO
text_sensor:
  - platform: homeassistant
    entity_id: binary_sensor.heating_state
    name: "Heating State"
    id: heating_state
    internal: true

# ONBOARD OLED DISPLAY
i2c:
  scl: D6
  sda: D7
  scan: false
    
display:
  - platform: ssd1306_i2c
    model: "SSD1306 128x64"
    reset_pin: D0
    address: 0x3C
    lambda: |-
    
      // Print time in HH:MM format (from hassio)
      it.strftime(64, 5, id(font2), TextAlign::TOP_CENTER, "%H:%M", id(times).now());
      
      // Print font icon if heating is on
      if (id(heating_state_binary).state) {
        it.print(10, 0, id(icon_font_30), TextAlign::TOP_LEFT, "\U000F0238");
      }
      
      // Print climate target temperature (from hassio)
      if (id(thermo_encoder).has_state()) {
        it.printf(10, 30, id(font3), TextAlign::TOP_LEFT , "%.0f°", id(target_temp_2).state);
      }

      // Print lounge temperature (from hassio)
      if (id(lounge_temperature).has_state()) {
        it.printf(70, 20, id(font4), TextAlign::TOP_LEFT, "%.0f°", id(lounge_temperature).state);
      }

Notice I added a delay to stop the same jumping around as wasyl00 experienced.

Note: in the above code I’m using the temperature from another sensor i have already setup in my lounge, I will change it to use the onboard sensor once I get it in a case and installed.

4 Likes

Good stuff lovejoy777 I just updated my code and it seem to be working without jumps!

Here is my desk gizmo: thermostat control/ble sensors tracker/air quality sensor display thing:D

1 Like

looking good, I’ll post mine once i get it finished :grin:

the small temp is the target temp and the big temp is the actual temp, the flame icon only when the heating is on.

finally finished :blush:

1 Like

Looks nice! Dont forget to make use of click button on the rotary encoder. I use mine to cycle thermostat on/off. Pretty useful.

1 Like

I was thinking of making the button change to a different climate entity.

1 Like

i set this up too for scheduling my heating.

i will use the encoder button for my hot water.

1 Like

hi lovjoy.

thank you for sharing. i am trying to read temperature setpoint for the generic thermostat at homeassistant from esphome. i follow your code but it did not work. can you help me please?.
many thanks

alberto

Can you post your code with the flame option?