Skip to content

Instantly share code, notes, and snippets.

@lumascet
Last active May 17, 2024 03:29
Show Gist options
  • Save lumascet/d5a12a8ba942864726f4c34d10feba12 to your computer and use it in GitHub Desktop.
Save lumascet/d5a12a8ba942864726f4c34d10feba12 to your computer and use it in GitHub Desktop.
FYSETC-E4 esphome roller blinds
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));
}
@lumascet
Copy link
Author

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.

@dimatx
Copy link

dimatx commented May 23, 2023 via email

@lumascet
Copy link
Author

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 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment