Hi
I’ve been at this for a couple of days. I’m trying to control my mini-blinds (venetian blinds) with a servo using Esphome. I’ve done this a few times over the years with arduino but now I’d like to do it with a Wemos D1 mini and add some functionality. I’ve used MySensors and Domoticz but now I’m considering moving to Home Assistant and Esphome.
My goal:
To have a rotary encoder that gradually moves the servo to open/close the slats while the state is reported back to HA and if the state (including position, not just OPEN/CLOSED) is changed in HA, move the servo accordingly.
Where I’m now:
I have a ton of YAML (which is NOT growing on me…) which does pretty much everyhing I just described except for the position adjustment when called from Home Assistant. Open/close works even from there.
esphome:
name: test
platform: ESP8266
board: d1_mini
wifi:
ssid: xxx
password: xxx
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Test Fallback Hotspot"
password: ...
captive_portal:
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
globals:
- id: my_pos
type: float
script:
- id: move_servo
then:
- servo.write:
id: my_servo
level: !lambda "return id(my_pos);"
- delay: 1s
- servo.detach: my_servo
- cover.template.publish:
id: pub_pos
position: !lambda "return id(my_pos) / 2 + 0.5;"
- logger.log:
format: "position: %.2f"
args: ['id(my_pos)']
sensor:
- platform: rotary_encoder
name: "Rotary Encoder"
id: knob
pin_a: D8
pin_b: D6
min_value: -1
max_value: 1
on_value:
then:
- lambda: !lambda |-
if (id(my_pos) > -0.9 && id(my_pos) < 0.9) {
id(my_pos) += id(knob).state * 0.1;
}
else if (id(my_pos) <= -0.9 && id(knob).state == -1 && id(my_pos) > -1) {
id(my_pos) = -1;
}
else if (id(my_pos) >= 0.9 && id(knob).state == 1 && id(my_pos) < 1) {
id(my_pos) = 1;
}
else if (id(my_pos) == 1 && id(knob).state == -1) {
id(my_pos) += id(knob).state * 0.1;
}
else if (id(my_pos) == -1 && id(knob).state == 1) {
id(my_pos) += id(knob).state * 0.1;
}
- script.execute: move_servo
- sensor.rotary_encoder.set_value:
id: knob
value: 0
binary_sensor:
- platform: gpio
pin:
number: D7
mode: INPUT_PULLUP
id: knob_button
servo:
- id: my_servo
output: pwm_output
output:
- platform: esp8266_pwm
id: pwm_output
pin: D5
frequency: 50 Hz
cover:
- platform: template
name: "Blinds"
id: pub_pos
open_action:
- lambda: |-
id(my_pos) = 1;
- script.execute: move_servo
close_action:
- lambda: |-
id(my_pos) = -1;
- script.execute: move_servo
stop_action:
- servo.detach: my_servo
position_action:
- logger.log:
format: "position_action_position: %.2f"
args: ['id(pub_pos).position']
- lambda: |-
id(my_pos) = 2 * (id(pub_pos).position) - 1.0;
- script.execute: move_servo
The log tells me that when a position command comes in from HA id(pub_pos) is not a float but something very large and it’s not mapped to the variable (my_pos) which would drive the servo script.
This is probably some sort of a bug in Esphome but as this is a little convoluted to write in YAML, I was wondering if anyone has made a custom cover component that writes values directly to a servo? Without going through the change global variable -> script - servo component - output component hoops?