# Based on https://github.com/joshr120/PD-Stepper/blob/main/Software/ESPHome/PD-Stepper-Blinds-Advanced.yaml
# (GPLv3)
+# Tuning...
+#
+# Total motor speed (steps/s / microsteps) should be fast enough to be useful,
+# but slow enough not to be too noisy. Too fast may also make the cord skip on
+# the gear when it should be stalling.
+#
+# If steps/s is too high (regardless of microsteps), the Power Good light randomly
+# cuts out and the board resets (with three different power supplies). Decreasing
+# run_current doesn't seem to make any difference to that.
+#
+# StallGuard should be sensitive (high) enough to stop quickly when it reaches
+# the end stop (although that's less important with the reed switch hooked up),
+# but low enough not to trigger if starting up in the high-torque region when
+# the blind is almost, but not quite fully up.
+#
+# Making the re-homing run at half speed helps with the latter, as does lower
+# acceleration.
+#
+# Increasing microsteps decreases torque, as does decreasing the current. This
+# affects the StallGuard settings.
+#
+# Microsteps (between 1 and 4 at least) don't seem to make any noticeable difference
+# to the smoothness of operation.
+#
+# Setting standstill_mode to coil_short_ls prevents high back EMF if someone
+# manually turns the blinds.
esp32:
board: esp32-s3-devkitc-1
framework:
type: esp-idf
+ version: latest
+# platform_version: 6.10.0
esphome:
name: ${name}
id(CFG2_pin).set_state(cfg2);
id(CFG3_pin).set_state(cfg3);
-
- delay: 0.5s
- lambda: id(sensored_home_pos) = id(encoder)->get_state(); # Set the home position to power on position
# - button.press: home
packages:
base: !include base.yaml
+# Log too much, and the encoder can miss revolutions.
logger:
level: INFO
+# Close the blind at sunset. Open it at 07:30 or sunrise, whichever is later.
time:
- platform: sntp
on_time:
mqtt:
on_connect:
then:
- - light.turn_on: led2
+ - light.turn_on: blue_led
on_disconnect:
then:
- - light.turn_off: led2
+ - light.turn_off: blue_led
+ idf_send_async: true
+# log_topic: null
i2c:
sda: 8
output:
- platform: ledc
pin: 12
- id: led1_output
+ id: red_led_output
- platform: ledc
pin: 10
- id: led2_output
+ id: blue_led_output
- platform: gpio
pin: GPIO38
light:
- platform: monochromatic
- output: led1_output
- id: led1
+ internal: true
+ output: red_led_output
+ id: red_led
name: LED 1
- platform: status_led
- output: led2_output
- id: led2
+ internal: true
+ output: blue_led_output
+ id: blue_led
name: Status LED
globals:
}
- stepper.stop: motor
- light.turn_on:
- id: led1
+ id: red_led
transition_length: 0s
- delay: 250ms
- light.turn_off:
- id: led1
+ id: red_led
transition_length: 1s
button:
- platform: gpio
name: Button 1
+ internal: true
pin:
number: 35
mode: INPUT
- platform: gpio
name: Button 3
+ internal: true
id: btn3
pin:
number: 37
state_class: measurement
- platform: adc
+ internal: true
pin: 4
name: VBUS Voltage
update_interval: 10s
- multiply: 8.47742
- platform: tmc2209
+ internal: true
type: motor_load
name: Motor load
update_interval: 250ms
delta: 1
- platform: tmc2209
+ internal: true
type: stallguard_result
name: StallGuard result
update_interval: 250ms
delta: 1
- platform: tmc2209
+ internal: true
type: actual_current
name: Actual current
update_interval: 250ms
- lambda: |-
int32_t wantpos = id(sensored_home_pos);
int32_t posdelta = wantpos - id(encoder)->get_state();
- int32_t stepdelta = ((posdelta * 200 * ${microsteps}) + 2048) / 4096;
+ int32_t stepdelta = ((posdelta * 200 * ${microsteps} * ${encoder_direction}) + 2048) / 4096;
ESP_LOGI("cover", "From %f to open (%f to %d) is delta %d, %d steps. Step %d -> %d",
id(pd_blinds)->position, id(encoder)->get_state(), wantpos, posdelta, stepdelta,
id(motor)->current_position, id(motor)->current_position + stepdelta);
- lambda: |-
int32_t wantpos = id(sensored_home_pos) + ${encoder_closed_pos};
int32_t posdelta = wantpos - id(encoder)->get_state();
- int32_t stepdelta = ((posdelta * 200 * ${microsteps}) + 2048) / 4096;
+ int32_t stepdelta = ((posdelta * 200 * ${microsteps} * ${encoder_direction}) + 2048) / 4096;
ESP_LOGI("cover", "From %f to closed (%f to %d) is delta %d, %d steps. Step %d -> %d",
id(pd_blinds)->position, id(encoder)->get_state(), wantpos, posdelta, stepdelta,
id(motor)->current_position, id(motor)->current_position + stepdelta);
- lambda: |-
int32_t wantpos = id(sensored_home_pos) + (1.0 - pos) * ${encoder_closed_pos};
int32_t posdelta = wantpos - id(encoder)->get_state();
- int32_t stepdelta = ((posdelta * 200 * ${microsteps}) + 2048) / 4096;
+ int32_t stepdelta = ((posdelta * 200 * ${microsteps} * ${encoder_direction}) + 2048) / 4096;
ESP_LOGI("cover", "From %f to %f (%f to %d) is delta %d, %d steps. Step %d -> %d",
id(pd_blinds)->position, pos, id(encoder)->get_state(), wantpos, posdelta, stepdelta,
id(motor)->current_position, id(motor)->current_position + stepdelta);