Last active
March 31, 2025 14:50
-
-
Save rubin110/c078a82283a22ee05974e276ca332b8e to your computer and use it in GitHub Desktop.
ESPHome blinds with a stepper motor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ESPHome config to control veneitan style blinds where a stepper motor has been attached to the spinning rod that lits the blinds one direction or other. | |
# 3D printed model by sidoh: | |
# https://www.printables.com/model/22186-retrofitted-motor-mount-for-blinds-automation | |
# Cobble a bunch of code from the designer's config: | |
# https://github.com/sidoh/esphome/tree/master | |
# This is setup to use a ULN2003 driver. Also a bit of modification because saving the end_posotion | |
# value didn't make sense. | |
# | |
# If it's not clear, this device is setup with 2 steppers for 2 different sets of blinds, left and right | |
# Please pay attention to which direction your stepper motor is turning during the intial config | |
# so you don't accidentally snap any wires. | |
# | |
# To configure start and stop position first begin by setting the blinds to the close posotion. | |
# You can do this by calling the HA servce control_stepper. You can use negative values. For my | |
# steppers 2048 steps is a full turn. Once at the closed position | |
# call the service set_closed_position to set the current step value to zero/origin. | |
# Use control_stepper again to get the blinds to what you would like to be as an option position. | |
# You can again use nagtive values if needed. | |
# Now use set_open_position to save to memory the numbers of steps from 0 to be decalred as fully open. | |
# And that should be it. Values will get saved to flash and should be restored on restart. | |
substitutions: | |
device_name: "sunroom-blinds" | |
friendly_name: "Sunroom Blinds" | |
project_name: "blinds" | |
device_description: "blinds" | |
project_version: "1.0" | |
relay_restore_mode: RESTORE_DEFAULT_OFF | |
platform_name: esp8285 | |
board_name: esp01_1m | |
left_end_position: '0' | |
right_end_position: '0' | |
esp8266: | |
early_pin_init: false | |
restore_from_flash: true | |
packages: | |
device_base: !include common/device_base.yaml | |
i2c: | |
sda: 3 | |
scl: 1 | |
scan: True | |
sensor: | |
- platform: tsl2561 | |
name: "${friendly_name} Ambient Light raw" | |
id: ambient_raw | |
address: 0x39 | |
update_interval: 2s | |
accuracy_decimals: 0 | |
- platform: template | |
name: "${friendly_name} Ambient Light" | |
id: ambient_light | |
lambda: !lambda |- | |
if (isnan(id(ambient_raw).state)) { | |
return {}; | |
} | |
else { | |
return id(ambient_raw).state; | |
} | |
# lambda: !lambda |- | |
# if (((isnan(id(ambient_raw).state))) and (id(ambient_light).state > 10000)) { | |
# return 18500; | |
# } | |
# else if (((isnan(id(ambient_raw).state))) and (id(ambient_light).state < 10000)) { | |
# return 0; | |
# } | |
# else | |
# { | |
# return id(ambient_raw).state; | |
# } | |
accuracy_decimals: 1 | |
unit_of_measurement: lx | |
device_class: ILLUMINANCE | |
update_interval: 2s | |
filters: | |
- sliding_window_moving_average: | |
window_size: 5 | |
send_every: 2 | |
interval: | |
- interval: 5s | |
then: | |
- logger.log: | |
format: "Left stepper_position: %d" | |
args: [ 'id(left_stepper_position)' ] | |
- logger.log: | |
format: "Left current_position : %d" | |
args: [ 'id(left_blinds_stepper).current_position' ] | |
- logger.log: | |
format: "Left end_position: %d" | |
args: [ 'id(left_end_position)' ] | |
- logger.log: | |
format: "Right stepper_position: %d" | |
args: [ 'id(right_stepper_position)' ] | |
- logger.log: | |
format: "Right current_position : %d" | |
args: [ 'id(right_blinds_stepper).current_position' ] | |
- logger.log: | |
format: "Right end_position: %d" | |
args: [ 'id(right_end_position)' ] | |
esphome: | |
name: $device_name | |
on_boot: | |
then: | |
- stepper.report_position: | |
id: left_blinds_stepper | |
position: !lambda return id(left_stepper_position); | |
- stepper.set_target: | |
id: left_blinds_stepper | |
target: !lambda return id(left_stepper_position); | |
- if: | |
condition: | |
- lambda: 'return id(left_stepper_position) == 0;' | |
then: | |
- cover.template.publish: | |
id: left_blinds | |
state: Closed | |
current_operation: IDLE | |
else: | |
- cover.template.publish: | |
id: left_blinds | |
state: Open | |
current_operation: IDLE | |
- stepper.report_position: | |
id: right_blinds_stepper | |
position: !lambda return id(right_stepper_position); | |
- stepper.set_target: | |
id: right_blinds_stepper | |
target: !lambda return id(right_stepper_position); | |
- if: | |
condition: | |
- lambda: 'return id(right_stepper_position) == 0;' | |
then: | |
- cover.template.publish: | |
id: right_blinds | |
state: Closed | |
current_operation: IDLE | |
else: | |
- cover.template.publish: | |
id: right_blinds | |
state: Open | |
current_operation: IDLE | |
preferences: | |
flash_write_interval: 0s | |
globals: | |
- id: left_stepper_position | |
type: int | |
restore_value: true | |
initial_value: '0' | |
- id: left_end_position | |
type: int | |
restore_value: true | |
initial_value: '${left_end_position}' | |
- id: right_stepper_position | |
type: int | |
restore_value: true | |
initial_value: '0' | |
- id: right_end_position | |
type: int | |
restore_value: true | |
initial_value: '${right_end_position}' | |
stepper: | |
- platform: uln2003 | |
id: left_blinds_stepper | |
pin_a: 5 | |
pin_b: 4 | |
pin_c: 0 | |
pin_d: 2 | |
max_speed: 512 steps/s | |
# Optional: | |
acceleration: inf | |
deceleration: inf | |
sleep_when_done: true | |
- platform: uln2003 | |
id: right_blinds_stepper | |
pin_a: 14 | |
pin_b: 12 | |
pin_c: 13 | |
pin_d: 15 | |
max_speed: 512 steps/s | |
# Optional: | |
acceleration: inf | |
deceleration: inf | |
sleep_when_done: true | |
cover: | |
- platform: template | |
id: left_blinds | |
device_class: blind | |
name: "${friendly_name} Left" | |
open_action: | |
- logger.log: | |
format: "Left OPEN called. Stepper position is set to: %d" | |
args: [ 'id(left_stepper_position)' ] | |
- stepper.set_target: | |
id: left_blinds_stepper | |
target: !lambda return id(left_end_position); | |
- globals.set: | |
id: left_stepper_position | |
value: !lambda return id(left_end_position); | |
close_action: | |
- logger.log: | |
format: "Left CLOSE called. Stepper position is set to: %d" | |
args: [ 'id(left_stepper_position)' ] | |
- stepper.set_target: | |
id: left_blinds_stepper | |
target: 0 | |
- globals.set: | |
id: left_stepper_position | |
value: '0' | |
stop_action: | |
- stepper.set_target: | |
id: left_blinds_stepper | |
target: !lambda return id(left_blinds_stepper).current_position; | |
- globals.set: | |
id: left_stepper_position | |
value: !lambda return id(left_blinds_stepper).current_position; | |
optimistic: true | |
- platform: template | |
id: right_blinds | |
device_class: blind | |
name: "${friendly_name} Right" | |
open_action: | |
- logger.log: | |
format: "Right OPEN called. Stepper position is set to: %d" | |
args: [ 'id(right_stepper_position)' ] | |
- stepper.set_target: | |
id: right_blinds_stepper | |
target: !lambda return id(right_end_position); | |
- globals.set: | |
id: right_stepper_position | |
value: !lambda return id(right_end_position); | |
close_action: | |
- logger.log: | |
format: "Right CLOSE called. Stepper position is set to: %d" | |
args: [ 'id(right_stepper_position)' ] | |
- stepper.set_target: | |
id: right_blinds_stepper | |
target: 0 | |
- globals.set: | |
id: right_stepper_position | |
value: '0' | |
stop_action: | |
- stepper.set_target: | |
id: right_blinds_stepper | |
target: !lambda return id(right_blinds_stepper).current_position; | |
- globals.set: | |
id: right_stepper_position | |
value: !lambda return id(right_blinds_stepper).current_position; | |
optimistic: true | |
api: | |
services: | |
- service: left_set_closed_position | |
then: | |
- stepper.report_position: | |
id: left_blinds_stepper | |
position: 0 | |
- stepper.set_target: | |
id: left_blinds_stepper | |
target: 0 | |
- globals.set: | |
id: left_stepper_position | |
value: '0' | |
- service: left_set_open_position | |
then: | |
- stepper.report_position: | |
id: left_blinds_stepper | |
position: !lambda return id(left_stepper_position); | |
- stepper.set_target: | |
id: left_blinds_stepper | |
target: !lambda return id(left_stepper_position); | |
- globals.set: | |
id: left_end_position | |
value: !lambda return id(left_stepper_position); | |
- service: left_control_stepper | |
variables: | |
target: int | |
then: | |
- stepper.set_target: | |
id: left_blinds_stepper | |
target: !lambda 'return target;' | |
- globals.set: | |
id: left_stepper_position | |
value: !lambda return target; | |
- service: right_set_closed_position | |
then: | |
- stepper.report_position: | |
id: right_blinds_stepper | |
position: 0 | |
- stepper.set_target: | |
id: right_blinds_stepper | |
target: 0 | |
- globals.set: | |
id: right_stepper_position | |
value: '0' | |
- service: right_set_open_position | |
then: | |
- stepper.report_position: | |
id: right_blinds_stepper | |
position: !lambda return id(right_stepper_position); | |
- stepper.set_target: | |
id: right_blinds_stepper | |
target: !lambda return id(right_stepper_position); | |
- globals.set: | |
id: right_end_position | |
value: !lambda return id(right_stepper_position); | |
- service: right_control_stepper | |
variables: | |
target: int | |
then: | |
- stepper.set_target: | |
id: right_blinds_stepper | |
target: !lambda 'return target;' | |
- globals.set: | |
id: right_stepper_position | |
value: !lambda return target; | |
button: | |
# - platform: template | |
# name: "${friendly_name} Rotate Right 0.25 turn" | |
# id: rotate_right_025 | |
# on_press: | |
# # Move 150 steps forward | |
# - stepper.report_position: | |
# id: stepper_motor_left | |
# position: 0 | |
# - stepper.set_target: | |
# id: stepper_motor_left | |
# target: -512 | |
# - platform: template | |
# name: "${friendly_name} Rotate Right 0.5 turn" | |
# id: rotate_right_050 | |
# on_press: | |
# # Move 150 steps forward | |
# - stepper.report_position: | |
# id: stepper_motor_left | |
# position: 0 | |
# - stepper.set_target: | |
# id: stepper_motor_left | |
# target: -1024 | |
# - platform: template | |
# name: "${friendly_name} Left 1 Turn Close" | |
# id: rotate_left_1_turn_right | |
# on_press: | |
# # Move 150 steps forward | |
# - stepper.report_position: | |
# id: stepper_motor_left | |
# position: 0 | |
# - stepper.set_target: | |
# id: stepper_motor_left | |
# target: -2048 | |
# - platform: template | |
# name: "${friendly_name} Rotate Left 0.25 turn" | |
# id: rotate_left_025 | |
# on_press: | |
# # Move 150 steps forward | |
# - stepper.report_position: | |
# id: stepper_motor_left | |
# position: 0 | |
# - stepper.set_target: | |
# id: stepper_motor_left | |
# target: 512 | |
# - platform: template | |
# name: "${friendly_name} Rotate Left 0.5 turn" | |
# id: rotate_left_050 | |
# on_press: | |
# # Move 150 steps forward | |
# - stepper.report_position: | |
# id: stepper_motor_left | |
# position: 0 | |
# - stepper.set_target: | |
# id: stepper_motor_left | |
# target: 1024 | |
# - platform: template | |
# name: "${friendly_name} Left 1 Turn Open" | |
# id: rotate_left_1_turn_left | |
# on_press: | |
# # Move 150 steps forward | |
# - stepper.report_position: | |
# id: stepper_motor_left | |
# position: 0 | |
# - stepper.set_target: | |
# id: stepper_motor_left | |
# target: 2048 | |
# - platform: template | |
# name: "${friendly_name} Right 1 Turn Close" | |
# id: other_rotate_right_1_turn_right | |
# on_press: | |
# # Move 150 steps forward | |
# - stepper.report_position: | |
# id: stepper_motor_right | |
# position: 0 | |
# - stepper.set_target: | |
# id: stepper_motor_right | |
# target: -2048 | |
# - platform: template | |
# name: "${friendly_name} Right 1 Turn Open" | |
# id: other_rotate_right_1_turn_left | |
# on_press: | |
# # Move 150 steps forward | |
# - stepper.report_position: | |
# id: stepper_motor_right | |
# position: 0 | |
# - stepper.set_target: | |
# id: stepper_motor_right | |
# target: 2048 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment