So everything works almost perfectly, here is my code if anybody wants it. It also keeps track of the current position, so when the power is out or anything unexpected happens, the stepper position will be reset to the saved one. I also have different speeds for closing/opening, since I can close the blinds faster that opening due to them being quite heavy. I also have a relay connected to my heating, but that is another point.
esphome:
name: kitchen_blind
platform: ESP8266
board: nodemcuv2
on_boot:
priority: -100
then:
- stepper.report_position:
id: blind_stepper
position: !lambda "return id(current_position);"
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(current_position);"
- stepper.set_speed:
id: blind_stepper
speed: 500 steps/s
- cover.template.publish:
id: kitchen_blind
current_operation: IDLE
position: !lambda 'return (float(float(id(blind_stepper).current_position) / float(id(open_position))));'
- output.turn_on: builtin_led
esp8266_restore_from_flash: true
wifi:
ssid: ""
password: ""
manual_ip:
static_ip: 192.168.1.3
gateway: 192.168.1.1
subnet: 192.168.1.0
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Kitchen Blind Fallback Hotspot"
password: !secret esphome_password
ap_timeout: 1min
reboot_timeout: 2min
use_address: 192.168.1.3
captive_portal:
# web_server:
# port: 80
# Enable logging
logger:
ota:
password: !secret esphome_password
# Enable Home Assistant API
api:
services:
- service: control_stepper
variables:
target: int
then:
- stepper.set_target:
id: blind_stepper
target: !lambda 'return target;'
- globals.set:
id: current_position
value: !lambda 'return target;'
- output.turn_on: builtin_led
- service: set_speed
variables:
speed: int
then:
- stepper.set_speed:
id: blind_stepper
speed: !lambda 'return speed;'
- service: middle
then:
- stepper.set_speed:
id: blind_stepper
speed: !lambda |-
if (id(middle_position) >= id(blind_stepper).current_position) {
return 500;
} else {
return 800;
}
- stepper.set_target:
id: blind_stepper
target: !lambda 'return id(middle_position);'
- while:
condition:
lambda: |-
return id(blind_stepper).current_position != id(middle_position);
then:
- cover.template.publish:
id: kitchen_blind
current_operation: !lambda |-
if(id(middle_position) >= id(blind_stepper).current_position) {
return COVER_OPERATION_OPENING;
} else {
return COVER_OPERATION_CLOSING;
}
position: !lambda 'return (float(float(id(blind_stepper).current_position) / float(id(open_position))));'
- delay: 1000 ms
- cover.template.publish:
id: kitchen_blind
current_operation: IDLE
position: !lambda 'return (float(float(id(blind_stepper).current_position) / float(id(open_position))));'
- globals.set:
id: current_position
value: !lambda 'return id(middle_position);'
- output.turn_on: builtin_led
globals:
- id: open_position
type: int
initial_value: '9400'
- id: middle_position
type: int
initial_value: '3760'
- id: current_position
type: int
initial_value: '9400'
restore_value: true
output:
- platform: gpio
pin: GPIO2
id: builtin_led
switch:
- platform: gpio
name: "Heating Relay"
pin:
number: D6
inverted: yes
restore_mode: ALWAYS_OFF
stepper:
- platform: a4988
id: blind_stepper
step_pin: D3
dir_pin: D4
max_speed: 800 steps/s
sleep_pin:
number: D2
inverted: yes
acceleration: inf
deceleration: inf
status_led:
pin: D1
cover:
- platform: template
device_class: shade
name: Kitchen Blind
id: kitchen_blind
open_action:
- stepper.set_speed:
id: blind_stepper
speed: 500 steps/s
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(open_position);"
- while:
condition:
lambda: |-
return id(kitchen_blind).position != 1;
then:
- cover.template.publish:
id: kitchen_blind
current_operation: !lambda |-
return COVER_OPERATION_OPENING;
position: !lambda 'return (float(float(id(blind_stepper).current_position) / float(id(open_position))));'
- delay: 1000 ms
- cover.template.publish:
id: kitchen_blind
current_operation: IDLE
position: !lambda 'return 1;'
- globals.set:
id: current_position
value: !lambda 'return id(open_position);'
- output.turn_on: builtin_led
close_action:
- stepper.set_speed:
id: blind_stepper
speed: 800 steps/s
- stepper.set_target:
id: blind_stepper
target: 0
- while:
condition:
lambda: |-
return id(kitchen_blind).position != 0;
then:
- cover.template.publish:
id: kitchen_blind
current_operation: !lambda |-
return COVER_OPERATION_CLOSING;
position: !lambda 'return (float(float(id(blind_stepper).current_position) / float(id(open_position))));'
- delay: 1000 ms
- cover.template.publish:
id: kitchen_blind
current_operation: IDLE
position: !lambda 'return 0;'
- globals.set:
id: current_position
value: !lambda 'return 0;'
- output.turn_on: builtin_led
stop_action:
- stepper.set_target:
id: blind_stepper
target: !lambda return id(blind_stepper).current_position;
- cover.template.publish:
id: kitchen_blind
current_operation: IDLE
position: !lambda 'return (float(float(id(blind_stepper).current_position) / float(id(open_position))));'
- globals.set:
id: current_position
value: !lambda 'return id(blind_stepper).current_position;'
- output.turn_on: builtin_led
has_position: true
I have a problem though. I don’t know why, but it seems like the stepper goes a full rotation, and then pauses for a fraction of a second, and this cycle repeats until the stepper gets to the desired position. Not sure what stepper library it is used, but I am guessing that my loop function takes to long to execute maybe?Or it might be because I use the a4988 driver with the sleep function in ESPHome, but the sleep pin is actually connected to the enable pin of the driver. But this worked well with my custom code, I woke the driver before I need to change position, and after the stepper was in the desired position, the driver was disabled, not sure how ESPHome does it.