I recommend you watching this:
Motorize and Automate your Blinds for $10! (WiFi) - YouTube specially at 2:30
I recommend you watching this:
Motorize and Automate your Blinds for $10! (WiFi) - YouTube specially at 2:30
Ok this one tested my whole knowledge of electrical engineering
I was under the impression that a 12V 28BYJ-48 will have more torque than the 5V version but seems like I may be better off using a 12V supply on a 5V version with A4988 driver in short burst. And this is actually true as the motor shaft literally need move just about 90 degrees (1/4th rotation) to get blinds to either open or close.
I will give this one a try and report updates!!
Another question, is it fair to assume that barring any manufacturing quality variances all 5V 28BYJ-48 should have same torque?
Just trying to eliminate OEM specific factor since I searched for the the cheapest deal on Amazon/eBay/Ali and ordered.
From all information that I have read/watch on the 28BYJ-48, I would say that all behave the same. I have used different brands on different projects and they are the same. Of course, that’s a generalization.
If you don’t have this fixed by now I would suggest limiting the stepper speed to 300 steps and setting your accel and decell to arounld 150.
Hiya,
I’m trying to do exactly the same thing. Here’s where I ended up:
esphome:
name: blinds-tilt3
platform: ESP8266
board: d1_mini
esp8266_restore_from_flash: true
on_boot:
priority: -100
then:
- stepper.report_position:
id: blind_stepper
position: !lambda "return id(saved_position);"
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(saved_position);"
- stepper.set_speed:
id: blind_stepper
speed: 200 steps/s
- script.execute: update_cover_position
logger:
ota:
password: "foo" # set by ESPHome - use that value!
wifi:
ssid: "foo"
password: "foo"
reboot_timeout: 2min
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Blinds-Tilt3 Fallback Hotspot"
password: "foo"
captive_portal:
# Enable Home Assistant API
api:
services:
- service: set_stepper_target
variables:
target: int
then:
- stepper.set_target:
id: blind_stepper
target: !lambda 'return target;'
- script.execute: record_stepper_position
- service: set_stepper_speed
variables:
speed: int
then:
- stepper.set_speed:
id: blind_stepper
speed: !lambda 'return speed;'
- service: set_stepper_position
variables:
stepper_position: int
then:
- stepper.report_position:
id: blind_stepper
position: !lambda "return stepper_position;"
- stepper.set_target:
id: blind_stepper
target: !lambda "return stepper_position;"
globals:
- id: open_position
type: int
initial_value: '8000'
- id: closed_position
type: int
initial_value: '1000'
- id: saved_position
type: int
initial_value: '1000'
restore_value: true
stepper:
- platform: a4988
id: blind_stepper
dir_pin: D4
step_pin: D3
sleep_pin: D2
max_speed: 250 steps/s
acceleration: 200
deceleration: 200
cover:
- platform: template
id: "blind_cover"
device_class: blind
name: "Blinds"
has_position: true
optimistic: false
open_action:
- logger.log: "Opening"
- cover.template.publish:
id: blind_cover
current_operation: OPENING
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(open_position);"
- while:
condition:
lambda: 'return id(blind_stepper).current_position < id(open_position);'
then:
- script.execute: update_cover_position
- delay: 1000 ms
- script.execute: update_cover_position
- script.execute: record_stepper_position
- cover.template.publish:
id: blind_cover
current_operation: IDLE
close_action:
- logger.log: "Closing"
- cover.template.publish:
id: blind_cover
current_operation: CLOSING
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(closed_position);"
- while:
condition:
lambda: 'return id(blind_stepper).current_position > id(closed_position);'
then:
- script.execute: update_cover_position
- delay: 1000 ms
- script.execute: update_cover_position
- script.execute: record_stepper_position
- cover.template.publish:
id: blind_cover
current_operation: IDLE
position_action:
- logger.log: "Setting position"
- stepper.set_target:
id: blind_stepper
target: !lambda 'return (float(pos) * float( float(id(open_position)) - float(id(closed_position)) )) + float(id(closed_position));'
- while:
condition:
lambda: 'return id(blind_stepper).current_position != ((float(pos) * float( float(id(open_position)) - float(id(closed_position)) )) + float(id(closed_position)));'
then:
- script.execute: update_cover_position
- delay: 1000 ms
- script.execute: update_cover_position
- script.execute: record_stepper_position
- cover.template.publish:
id: blind_cover
current_operation: IDLE
stop_action:
- logger.log: "Stopping"
- cover.template.publish:
id: blind_cover
current_operation: IDLE
- stepper.set_target:
id: blind_stepper
target: !lambda 'return id(blind_stepper).current_position;'
- script.execute: update_cover_position
- script.execute: record_stepper_position
sensor:
- platform: template
name: "Current stepper position"
lambda: return id(blind_stepper).current_position;
update_interval: 5s
script:
- id: update_cover_position
then:
- cover.template.publish:
id: blind_cover
position: !lambda 'return float( float(id(blind_stepper).current_position) - float(id(closed_position))) / float( float(id(open_position)) - float(id(closed_position)) );'
- id: record_stepper_position
then:
- globals.set:
id: saved_position
value: !lambda 'return id(blind_stepper).current_position;'
Key learnings:
Hi, how do I get it to turn the other way? And also how do I control the home assistant? Can you help me?
@triblondon Thanks Andrew, your step by step instructions worked out of the box!
@fourtrax011 applying your tweak ( 300 stepper speed and 150 for acceleration/decceleration) did boost the torque and blinds moved
HI Triblondon,
thnx for sharing your code,
i still got problems, current position value randomly “freaks”. been banging my head for days…
first some questions:
by globals: restore value is set to TRUE, makes it look at the stored value in “saved_position”"
now i do some movements, wait some seconds, make another movement that brings the blind back to 0.
now i wait again some seconds and do a restart…
instead of getting the position zero i get a totally different readout…
here’s “my” code…
esphome:
name: blind2
on_boot:
priority: -500.0
then:
- stepper.report_position:
id: blind_stepper
position: !lambda "return id(saved_position);"
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(saved_position);"
- stepper.set_speed:
id: blind_stepper
speed: 450 steps/s
- script.execute: update_cover_position
on_shutdown:
then:
- delay: 10ms
- script.execute: record_stepper_position
- delay: 10 ms
esp8266:
board: esp01_1m
restore_from_flash: true
globals:
- id: open_position # verschil tussen open en dicht = 28.800
type: int
initial_value: '0'
- id: closed_position
type: int
initial_value: '28800'
- id: saved_position
type: int
initial_value: '28800'
restore_value: true
ota:
wifi:
ssid: blablabla
password: zegikniet
power_save_mode: none
fast_connect: true
reboot_timeout: 5s
#enable_mdns: true
domain: .local
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Blind2"
password: "zegiknogsteedsniet"
captive_portal:
# Enable logging
logger:
level: very_verbose
# Enable Web server
web_server:
port: 80
time:
- platform: homeassistant
id: homeassistant_time
# Enable Home Assistant API
#######
api:
services:
- service: control_stepper # set_stepper_target
variables:
target: int
then:
- stepper.set_target:
id: blind_stepper
target: !lambda 'return target;'
- script.execute: record_stepper_position
- service: set_stepper_speed
variables:
speed: int
then:
- stepper.set_speed:
id: blind_stepper
speed: !lambda 'return speed;'
- service: set_stepper_position
variables:
stepper_position: int
then:
- stepper.report_position:
id: blind_stepper
position: !lambda "return stepper_position;"
- stepper.set_target:
id: blind_stepper
target: !lambda "return stepper_position;"
- service: control_servo2
variables:
level: float
then:
- servo.write:
id: servo2
level: !lambda 'return level / 1.0;'
cover:
- platform: template
id: "blind_cover"
device_class: blind
name: "Blinder2"
has_position: true
optimistic: false
open_action:
- logger.log: "Opening"
- cover.template.publish:
id: blind_cover
current_operation: OPENING
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(open_position);"
- while:
condition:
lambda: 'return id(blind_stepper).current_position < id(open_position);'
then:
- script.execute: update_cover_position
- delay: 1000 ms
- script.execute: update_cover_position
- script.execute: record_stepper_position
- cover.template.publish:
id: blind_cover
current_operation: IDLE
close_action:
- logger.log: "Closing"
- cover.template.publish:
id: blind_cover
current_operation: CLOSING
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(closed_position);"
- while:
condition:
lambda: 'return id(blind_stepper).current_position > id(closed_position);'
then:
- script.execute: update_cover_position
- delay: 1000 ms
- script.execute: update_cover_position
- script.execute: record_stepper_position
- cover.template.publish:
id: blind_cover
current_operation: IDLE
position_action:
- logger.log: "Setting position"
- stepper.set_target:
id: blind_stepper
target: !lambda 'return (float(pos) * float( float(id(open_position)) - float(id(closed_position)) )) + float(id(closed_position));'
- while:
condition:
lambda: 'return id(blind_stepper).current_position != ((float(pos) * float( float(id(open_position)) - float(id(closed_position)) )) + float(id(closed_position)));'
then:
- script.execute: update_cover_position
- delay: 1000 ms
- script.execute: update_cover_position
- script.execute: record_stepper_position
- cover.template.publish:
id: blind_cover
current_operation: IDLE
stop_action:
- logger.log: "Stopping"
- cover.template.publish:
id: blind_cover
current_operation: IDLE
- stepper.set_target:
id: blind_stepper
target: !lambda 'return id(blind_stepper).current_position;'
- script.execute: update_cover_position
- script.execute: record_stepper_position
script:
- id: update_cover_position
then:
- cover.template.publish:
id: blind_cover
position: !lambda 'return float( float(id(blind_stepper).current_position) - float(id(closed_position))) / float( float(id(open_position)) - float(id(closed_position)) );'
- id: record_stepper_position
then:
- globals.set:
id: saved_position
value: !lambda 'return id(blind_stepper).current_position;'
# Example configuration entry
# Example output platform
output:
- platform: esp8266_pwm
id: pwm_output
pin: GPIO2
frequency: 50 Hz
- platform: esp8266_pwm
pin: GPIO3
frequency: 19000 Hz
id: light_pwm_output
servo:
- id: servo2
output: pwm_output
#restore: true
auto_detach_time: 400ms
restore: true
stepper:
- platform: uln2003
id: blind_stepper
sleep_when_done: true
pin_a: GPIO4
pin_b: GPIO16
pin_c: GPIO14
pin_d: GPIO12
max_speed: 450 steps/s
step_mode: FULL_STEP
# Optional:
acceleration: inf
deceleration: inf
sensor:
- platform: template
name: "Current stepper2 position"
lambda: return id(blind_stepper).current_position;
update_interval: 5s
- platform: wifi_signal
name: "blinder2 WiFi Signal"
update_interval: 60s
# Extra sensor to keep track of plug uptime
- platform: uptime
name: blinder2_Uptime Sensor
light:
- platform: monochromatic
output: light_pwm_output
name: "light blind2"
switch:
- platform: restart
name: "blind2 Restart"
id: restart_switch
Hello,
I see in the solution, you use a 5V version of the 28BYJ-48 steooer motor with a 12V VMOT through the A4988, is there a risk to burn the motor?
Initially I had only 5V motor which worked fine as the load was in short bursts, but I replaced it with 12V motor eventually.
Did you ever figure this out? I’m experiencing the same thing where the stepper only turns one direction.
I’ve got mine working today, same hardware. But it doesn’t quite pull hard enough at the end to fully close the tilt. How do you suggest setting up the acceleration for extra torque I require?
I was able to increase torque using two things:
#The substitution block has all the configurable details
substitutions:
name_of_board: blinds01
ota_password: !secret blinds01_ota
ap_point: !secret blinds01_ssid
ap_point_password: !secret blinds01_ssid_password
#api_password: !secret blinds01_api_password
api_encryption_key: !secret blinds01_api_encryption
stepper_speed: "300 steps/s"
stepper_max_speed: "250 steps/s"
acceleration_value: "150"
deceleration_value: "150"
initial_open_position: "8000" # sets this as the open position or the farthest motor will move for open
initial_closed_position: "1000" # sets this as the close position or the farthest motor will move for close
initial_saved_position: "1000" # sets the default value if there is no saved position saved to flash
############################################
#YOU SHOULD NOT NEED TO EDIT BELOW THIS LINE
############################################
esphome:
name: $name_of_board
platform: ESP8266
board: d1_mini
esp8266_restore_from_flash: true
on_boot:
priority: -100
then:
- stepper.report_position:
id: blind_stepper
position: !lambda "return id(saved_position);"
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(saved_position);"
- stepper.set_speed:
id: blind_stepper
speed: $stepper_speed
- script.execute: update_cover_position
# Enable logging
logger:
ota:
password: $ota_password
wifi:
ssid: !secret ssid
password: !secret ssid_password
fast_connect: True
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: $ap_point
password: $ap_point_password
captive_portal:
# Enable Home Assistant API
api:
password: $api_password
encryption:
key: $api_encryption_key
services:
- service: set_stepper_target
variables:
target: int
then:
- stepper.set_target:
id: blind_stepper
target: !lambda 'return target;'
- script.execute: record_stepper_position
- service: set_stepper_speed
variables:
speed: int
then:
- stepper.set_speed:
id: blind_stepper
speed: !lambda 'return speed;'
- service: set_stepper_position
variables:
stepper_position: int
then:
- stepper.report_position:
id: blind_stepper
position: !lambda "return stepper_position;"
- stepper.set_target:
id: blind_stepper
target: !lambda "return stepper_position;"
globals:
- id: open_position
type: int
initial_value: $initial_open_position
- id: closed_position
type: int
initial_value: $initial_closed_position
- id: saved_position
type: int
initial_value: $initial_saved_position
restore_value: true
stepper:
- platform: a4988
id: blind_stepper
dir_pin: D4
step_pin: D3
sleep_pin: D2
max_speed: $stepper_max_speed
acceleration: $acceleration_value
deceleration: $deceleration_value
cover:
- platform: template
id: blind_cover
device_class: blind
name: ${name_of_board} Blinds
has_position: true
optimistic: false
open_action:
- logger.log: "Opening"
- cover.template.publish:
id: blind_cover
current_operation: OPENING
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(open_position);"
- while:
condition:
lambda: 'return id(blind_stepper).current_position < id(open_position);'
then:
- script.execute: update_cover_position
- delay: 1000 ms
- script.execute: update_cover_position
- script.execute: record_stepper_position
- cover.template.publish:
id: blind_cover
current_operation: IDLE
close_action:
- logger.log: "Closing"
- cover.template.publish:
id: blind_cover
current_operation: CLOSING
- stepper.set_target:
id: blind_stepper
target: !lambda "return id(closed_position);"
- while:
condition:
lambda: 'return id(blind_stepper).current_position > id(closed_position);'
then:
- script.execute: update_cover_position
- delay: 1000 ms
- script.execute: update_cover_position
- script.execute: record_stepper_position
- cover.template.publish:
id: blind_cover
current_operation: IDLE
position_action:
- logger.log: "Setting position"
- stepper.set_target:
id: blind_stepper
target: !lambda 'return (float(pos) * float( float(id(open_position)) - float(id(closed_position)) )) + float(id(closed_position));'
- while:
condition:
lambda: 'return id(blind_stepper).current_position != ((float(pos) * float( float(id(open_position)) - float(id(closed_position)) )) + float(id(closed_position)));'
then:
- script.execute: update_cover_position
- delay: 1000 ms
- script.execute: update_cover_position
- script.execute: record_stepper_position
- cover.template.publish:
id: blind_cover
current_operation: IDLE
stop_action:
- logger.log: "Stopping"
- cover.template.publish:
id: blind_cover
current_operation: IDLE
- stepper.set_target:
id: blind_stepper
target: !lambda 'return id(blind_stepper).current_position;'
- script.execute: update_cover_position
- script.execute: record_stepper_position
sensor:
- platform: template
name: ${name_of_board} Current position
lambda: return id(blind_stepper).current_position;
update_interval: 5s
- platform: wifi_signal
name: ${name_of_board} Wifi
update_interval: 60s
binary_sensor:
- platform: status
name: ${name_of_board} Status
script:
- id: update_cover_position
then:
- cover.template.publish:
id: blind_cover
position: !lambda 'return float( float(id(blind_stepper).current_position) - float(id(closed_position))) / float( float(id(open_position)) - float(id(closed_position)) );'
- id: record_stepper_position
then:
- globals.set:
id: saved_position
value: !lambda 'return id(blind_stepper).current_position;'
HTH.
PS: If your blinds are large then you may want to look at more expensive motors like Nema which have better performance characterstics.
So I am trying your code to control a damper project I am working on.
My concern is if the stepper positioning gets out of sync with my damper - it could strip gears or snap the panel.
I see that this appears to save the last position to overcome this but in a recent test, it did not work.
I also see that you had another thread trying to get more information on this feature. Flash memory
Have you had any problems with losing positioning? How do you reset/correct if so?
Add 2 limit switches, one fully open and fully closed. If either switch is turned on then stop the stepper and update the position to open/closed based on which limit switch is turned on… You can buy micro switches from Amazon and they work great…
Thanks, seems logical enough. I’ve tested for a couple of day and I think I will be okay without them but still interested for future versions. I’ll have to play with the code to understand more.
I know it’s been a while since this thread has moved, but was wondering about using the limit switch or a reed switch. Do you have any example code of what you had to change to make this work?
Look at the documentation. This is called “human readable” code because its pretty self explanatory what it does and how you use it, they also give you lots of examples.