-
-
Save lumascet/d5a12a8ba942864726f4c34d10feba12 to your computer and use it in GitHub Desktop.
substitutions: | |
device_name: "lush-cover-controller" | |
pulley_diameter_mm: "21.963" | |
gear_ratio: "1880/2000" | |
distance_mm: "2050" | |
acceleration: 500 steps/s^2 | |
velocity: 2500 steps/s # 200 (motor steps) * ${microsteps} | |
back_off_steps: "200" # back off some steps to reduce stepper energize noise | |
open_current_x: 1000ma | |
open_stall_threshold_x: "28" | |
close_current_x: 300ma | |
close_stall_threshold_x: "30" | |
tcool_threshold_x: "1000" | |
change_direction_x: "True" | |
tmc_address_x: "0x01" | |
sense_resistor: "0.15" | |
external_components: | |
source: github://lumascet/esphome@stepper-tmc2209-new_uart | |
components: [uart, tmc2209] | |
esphome: | |
name: ${device_name} | |
platform: ESP32 | |
board: nodemcu-32s | |
platformio_options: | |
upload_speed: 921600 | |
on_boot: | |
- tmc2209.setup: | |
id: stepper_x | |
microsteps: 16 | |
tcool_threshold: ${tcool_threshold_x} | |
current: ${close_current_x} | |
stall_threshold: ${open_stall_threshold_x} | |
sense_resistor: ${sense_resistor} | |
uart_address: ${tmc_address_x} | |
- script.execute: | |
id: script_set_cover_open | |
stepper_id: stepper_x | |
wifi: | |
ssid: !secret wifi_ssid | |
password: !secret wifi_password | |
# Enable logging | |
logger: | |
level: INFO | |
# verbose logger over uart causes motor artifacts as pulses are generated in main loop | |
#logger: | |
# level: VERBOSE | |
# logs: | |
# api: DEBUG | |
# api.service: DEBUG | |
# scheduler: DEBUG | |
# stepper: DEBUG | |
# uart: DEBUG | |
ota: | |
password: "xxx" | |
uart: | |
id: uart_stepper | |
tx_pin: GPIO22 | |
rx_pin: GPIO21 | |
baud_rate: 9600 | |
status_led: | |
pin: GPIO26 | |
api: | |
encryption: | |
key: "xxx" | |
services: | |
- service: control_stepper | |
variables: | |
stepper_id: string | |
target: int | |
speed: int | |
microsteps: int | |
tcool_threshold: int | |
stall_threshold: int | |
rms_current_amps: float | |
then: | |
- if: | |
condition: | |
lambda: 'return stepper_id == "stepper_x";' | |
then: | |
- tmc2209.setup: | |
id: stepper_x | |
microsteps: !lambda "return microsteps;" | |
tcool_threshold: !lambda "return tcool_threshold;" | |
stall_threshold: !lambda "return stall_threshold;" | |
current: !lambda "return rms_current_amps;" | |
sense_resistor: ${sense_resistor} | |
uart_address: ${tmc_address_x} | |
- logger.log: | |
format: moving to %d | |
args: [target] | |
- stepper.set_speed: | |
id: stepper_x | |
speed: !lambda "return speed;" | |
- stepper.set_target: | |
id: stepper_x | |
target: !lambda "return target;" | |
- service: set_cover_closed | |
variables: | |
stepper_id: string | |
then: | |
- script.execute: | |
id: script_set_cover_closed | |
stepper_id: !lambda "return stepper_id;" | |
- service: set_cover_open | |
variables: | |
stepper_id: string | |
then: | |
- script.execute: | |
id: script_set_cover_open | |
stepper_id: !lambda "return stepper_id;" | |
- service: close_variable_speed | |
variables: | |
stepper_id: string | |
speed: int | |
stall_threshold: int | |
then: | |
- if: | |
condition: | |
lambda: 'return stepper_id == "stepper_x";' | |
then: | |
- if: | |
condition: | |
and: | |
- binary_sensor.is_off: window_sensor | |
- binary_sensor.is_off: lower_limit_sensor | |
then: | |
- tmc2209.setup: | |
id: stepper_x | |
microsteps: 16 | |
current: ${close_current_x} | |
stall_threshold: !lambda "return stall_threshold;" | |
sense_resistor: ${sense_resistor} | |
uart_address: ${tmc_address_x} | |
- stepper.set_speed: | |
id: stepper_x | |
speed: !lambda "return speed;" | |
- stepper.set_target: | |
id: stepper_x | |
target: 0 | |
- wait_until: | |
condition: | |
lambda: |- | |
return id(stepper_x).current_position < 10; | |
- stepper.set_target: | |
id: stepper_x | |
target: ${back_off_steps} | |
- service: open_variable_speed | |
variables: | |
stepper_id: string | |
speed: int | |
stall_threshold: int | |
then: | |
- if: | |
condition: | |
and: | |
- binary_sensor.is_off: window_sensor | |
then: | |
- if: | |
condition: | |
lambda: 'return stepper_id == "stepper_x";' | |
then: | |
- tmc2209.setup: | |
id: stepper_x | |
microsteps: 16 | |
current: ${open_current_x} | |
stall_threshold: !lambda "return stall_threshold;" | |
sense_resistor: ${sense_resistor} | |
uart_address: ${tmc_address_x} | |
- stepper.set_speed: | |
id: stepper_x | |
speed: !lambda "return speed;" | |
- stepper.set_target: | |
id: stepper_x | |
target: !lambda "return id(open_position);" | |
- wait_until: | |
condition: | |
lambda: |- | |
return id(stepper_x).current_position > (id(open_position)-10); | |
- stepper.set_target: | |
id: stepper_x | |
target: !lambda "return id(open_position)-int(${back_off_steps});" | |
stepper: | |
- platform: tmc2209 | |
steppers: | |
- id: stepper_x | |
step_pin: GPIO27 | |
dir_pin: | |
number: GPIO26 | |
inverted: ${change_direction_x} | |
sleep_pin: | |
number: GPIO25 | |
inverted: true | |
acceleration: ${acceleration} | |
deceleration: ${acceleration} | |
max_speed: ${velocity} | |
sense_resistor: ${sense_resistor} | |
uart_address: ${tmc_address_x} | |
binary_sensor: | |
# - platform: gpio | |
# name: Button1 | |
# pin: | |
# number: GPIO23 | |
# inverted: true | |
# mode: INPUT | |
# on_press: | |
# then: | |
# - cover.open: | |
# id: cover_x | |
# - platform: gpio | |
# name: Button2 | |
# pin: | |
# number: GPIO34 | |
# inverted: true | |
# mode: INPUT | |
# on_press: | |
# then: | |
# - cover.close: | |
# id: cover_x | |
# - platform: gpio | |
# name: Sensor1 | |
# pin: | |
# number: GPIO22 | |
# inverted: true | |
# - platform: gpio | |
# name: SensorGPIO0 | |
# pin: | |
# number: GPIO0 | |
# inverted: true | |
# - platform: gpio | |
# name: Sensor2 | |
# pin: | |
# number: GPIO32 | |
# inverted: true | |
- platform: homeassistant | |
name: "Window sensor homeassistant" | |
entity_id: binary_sensor.lumi_lumi_sensor_magnet_aq2_2ad04f04_on_off | |
id: window_sensor | |
on_press: | |
script.execute: | |
id: stop_at_current_position | |
stepper_id: stepper_x | |
- platform: gpio | |
id: stall_guard_sensor | |
name: StallGuard | |
pin: GPIO34 | |
on_press: | |
script.execute: | |
id: stop_at_current_position | |
stepper_id: stepper_x | |
- platform: gpio # or use this pin as stall guard for y-axis | |
id: lower_limit_sensor | |
name: Lower Limit | |
pin: | |
number: GPIO35 | |
inverted: True | |
on_press: | |
if: | |
condition: | |
lambda: "return id(cover_x).current_operation == COVER_OPERATION_CLOSING;" | |
then: | |
- script.execute: | |
id: stop_at_current_position | |
stepper_id: stepper_x | |
- script.execute: | |
id: script_set_cover_closed | |
stepper_id: stepper_x | |
script: | |
- id: stop_at_current_position | |
parameters: | |
stepper_id: string | |
then: | |
- if: | |
condition: | |
lambda: 'return stepper_id == "stepper_x";' | |
then: | |
stepper.set_target: | |
id: stepper_x | |
target: !lambda "return id(stepper_x).current_position;" | |
- id: script_set_cover_closed | |
parameters: | |
stepper_id: string | |
then: | |
- if: | |
condition: | |
lambda: 'return stepper_id == "stepper_x";' | |
then: | |
- stepper.report_position: | |
id: stepper_x | |
position: 0 | |
- stepper.set_target: | |
id: stepper_x | |
target: 0 | |
- id: script_set_cover_open | |
parameters: | |
stepper_id: string | |
then: | |
- if: | |
condition: | |
lambda: 'return stepper_id == "stepper_x";' | |
then: | |
- stepper.report_position: | |
id: stepper_x | |
position: !lambda "return id(open_position);" | |
- stepper.set_target: | |
id: stepper_x | |
target: !lambda "return id(open_position);" | |
globals: | |
- id: open_position | |
type: float | |
initial_value: "${distance_mm} / (${pulley_diameter_mm} * ${gear_ratio} * PI) * 200 * 16" | |
cover: | |
# X-COVER | |
- platform: template | |
id: cover_x | |
name: "${device_name} cover X" | |
has_position: True | |
open_action: | |
- if: | |
condition: | |
and: | |
- binary_sensor.is_off: window_sensor | |
then: | |
- tmc2209.setup: | |
id: stepper_x | |
current: ${open_current_x} | |
stall_threshold: ${open_stall_threshold_x} | |
sense_resistor: ${sense_resistor} | |
uart_address: ${tmc_address_x} | |
microsteps: 16 | |
- stepper.set_speed: | |
id: stepper_x | |
speed: ${velocity} | |
- stepper.set_target: | |
id: stepper_x | |
target: !lambda "return id(open_position);" | |
- wait_until: | |
condition: | |
lambda: |- | |
return id(stepper_x).current_position > (id(open_position)-10); | |
- stepper.set_target: | |
id: stepper_x | |
target: !lambda "return id(open_position)-int(${back_off_steps});" | |
close_action: | |
- if: | |
condition: | |
and: | |
- binary_sensor.is_off: window_sensor | |
- binary_sensor.is_off: lower_limit_sensor | |
then: | |
- tmc2209.setup: | |
id: stepper_x | |
current: ${close_current_x} | |
stall_threshold: ${close_stall_threshold_x} | |
sense_resistor: ${sense_resistor} | |
uart_address: ${tmc_address_x} | |
microsteps: 16 | |
- stepper.set_speed: | |
id: stepper_x | |
speed: ${velocity} | |
- stepper.set_target: | |
id: stepper_x | |
# 0 Means closed | |
target: 0 | |
- wait_until: | |
condition: | |
lambda: |- | |
return id(stepper_x).current_position < 10; | |
- stepper.set_target: | |
id: stepper_x | |
target: ${back_off_steps} | |
position_action: | |
- if: | |
condition: | |
binary_sensor.is_off: window_sensor | |
then: | |
- tmc2209.setup: | |
id: stepper_x | |
current: ${open_current_x} | |
stall_threshold: ${open_stall_threshold_x} | |
sense_resistor: ${sense_resistor} | |
uart_address: ${tmc_address_x} | |
microsteps: 16 | |
- stepper.set_speed: | |
id: stepper_x | |
speed: ${velocity} | |
- stepper.set_target: | |
id: stepper_x | |
target: !lambda "return id(open_position) * pos;" | |
stop_action: | |
- script.execute: | |
id: stop_at_current_position | |
stepper_id: stepper_x | |
interval: | |
- interval: 2s | |
then: | |
lambda: |- | |
static auto operation = COVER_OPERATION_IDLE; | |
static auto position = id(stepper_x).current_position; | |
if (operation != id(cover_x).current_operation || | |
position != id(stepper_x).current_position) | |
{ | |
if (id(stepper_x).current_position > id(stepper_x).target_position) | |
operation = COVER_OPERATION_CLOSING; | |
else if (id(stepper_x).current_position < id(stepper_x).target_position) | |
operation = COVER_OPERATION_OPENING; | |
else | |
operation = COVER_OPERATION_IDLE; | |
id(cover_x).current_operation = operation; | |
position = id(stepper_x).current_position; | |
id(cover_x).position = position / id(open_position); | |
id(cover_x).publish_state(); | |
ESP_LOGD("main", "Stepper X Position is: %d/%d", id(stepper_x).current_position, (int)id(open_position)); | |
// ESP_LOGD("main", "Stepper X Position is: %d/%d", id(stepper_x).current_position, (int)id(open_position)); | |
// ESP_LOGD("main", "Stepper X Position is: %d/%d", id(stepper_x).current_position, (int)id(open_position)); | |
} |
Could you suggest how to make modifications to control two blinds with a single board. I tried duplicating everything, but it seems to break the first one.
I tried step by step, first adding the following, but it breaks the first previously working stepper:
stepper: - platform: tmc2209b01 id: left_blind_stepper step_pin: GPIO27 dir_pin: number: GPIO26 inverted: ${change_direction} sleep_pin: number: GPIO25 inverted: true acceleration: ${acceleration} max_speed: ${velocity} # adding code following this comment breaks the above left blind - platform: tmc2209b01 id: right_blind_stepper step_pin: GPIO33 dir_pin: number: GPIO32 inverted: ${change_direction} sleep_pin: number: GPIO25 inverted: true acceleration: ${acceleration} max_speed: ${velocity}
Thanks!
Unfortunately there seems to be a bug hidden somewhere in the tmc2209 component if multiple components attach to the same uart... I have sadly not figured out how to fix it. Feel free to have a look at the code! It needs quite some improvement as it is only a fork made to work with the basic features for esphome.
have a look at the adapted config: Gist
Thanks! If I understand correctly, the adapted config isn't quite working yet for two steppers, or it's working but needs improvement? I'm looking to use it for basic features: open, close, stop. What's the stuff that's not working yet?
Thanks! If I understand correctly, the adapted config isn't quite working yet for two steppers, or it's working but needs improvement? I'm looking to use it for basic features: open, close, stop. What's the stuff that's not working yet?
Yes indeed, the uart communication specifically is not working correctly when using 2 or more steppers. You can probably make the bare minimum work without the uart configuration, but keep in mind you cant configure the current and microsteps of the tmc. Meaning defaults will be used, where current is maxed out and the microsteps are all over the place (because of how the pins are configured) x-Axis has 32 microsteps, y-axis 16, z-axis 8, and E-axis 64. Have a look at the a4988-component. Exchange the tmc2209 component with this one.
Ah I see. Thanks for elaborating. Unfortunately I don't have the experience to fix this. My blinds do require changing from the defaults, so I think I'll have to wait for now.
I have searched around on Aliexpress looking for alternatives and I think I found another ESP32 based 3d printer board which should work without messing around on TMC uart: Makerbase MKS TinyBee 3D. With this board you can set the microsteps and current via switches and potentiometer. The pinout diagram can be found here .
Could you suggest how to make modifications to control two blinds with a single board. I tried duplicating everything, but it seems to break the first one.
I tried step by step, first adding the following, but it breaks the first previously working stepper:
Thanks!