From b0cc7348d18139ef9404380b998f46dc748cbc9d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 11 Feb 2025 18:31:13 +0000 Subject: [PATCH] First mostly working version of blind control --- blind.yaml | 316 +++++++++++++++++++++++++++++++++++++++++++ landing-blind-3.yaml | 7 + 2 files changed, 323 insertions(+) create mode 100644 blind.yaml create mode 100644 landing-blind-3.yaml diff --git a/blind.yaml b/blind.yaml new file mode 100644 index 0000000..3d22b14 --- /dev/null +++ b/blind.yaml @@ -0,0 +1,316 @@ +# Based on https://github.com/joshr120/PD-Stepper/blob/main/Software/ESPHome/PD-Stepper-Blinds-Advanced.yaml +# (GPLv3) + + +esp32: + board: esp32-s3-devkitc-1 + framework: + type: esp-idf + +esphome: + name: ${name} + platformio_options: + board_build.flash_mode: dio + upload_speed: 921600 + on_boot: + - tmc2209.configure: + microsteps: 2 # ${microsteps} + interpolation: true + tcool_threshold: 400 + - tmc2209.stallguard: + threshold: 45 #set lower if stall gaurd triggering too often + - tmc2209.currents: + ihold: 0 + tpowerdown: 0 + iholddelay: 0 + # irun: 16 + run_current: 800m #Set your desired current here (800m = 800mA, 1 = 1A etc.) + standstill_mode: freewheeling + + # set PD voltage # 5V 9V 12V 15V 20V + # CFG1 # 1 0 0 0 0 + # CFG2 # - 0 0 1 1 + # CFG3 # - 0 1 1 0 + - lambda: |- + int voltage = 15; // 5, 9, 12, 15 or 20. + bool cfg1 = false, cfg2 = false, cfg3 = false; + if (voltage == 5) { + cfg1 = true; + } else if (voltage == 9) { + // all off; + } else if (voltage == 12) { + cfg3 = true; + } else if (voltage == 15) { + cfg2 = cfg3 = true; + } else if (voltage == 20) { + cfg2 = true; + } else ESP_LOGE("USB-PD", "Invalid voltage %dV selected", voltage); + id(CFG1_pin).set_state(cfg1); + 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 + +wifi: + power_save_mode: none + networks: + - ssid: !secret wifi_ssid + password: !secret wifi_pw + bssid: !secret lantiq_bssid + priority: 1 + +logger: + level: INFO + +sun: + latitude: !secret latitude + longitude: !secret longitude + + on_sunrise: + - then: + - cover.open: pd_blinds + on_sunset: + - then: + - cover.close: pd_blinds + +external_components: + - source: github://slimcdk/esphome-custom-components + components: [tmc2209_hub, tmc2209, stepper] + +mqtt: + on_connect: + then: + - light.turn_on: led2 + on_disconnect: + then: + - light.turn_off: led2 + +i2c: + sda: 8 + scl: 9 + scan: true + +uart: + tx_pin: 17 + rx_pin: 18 + baud_rate: 712000 + +output: + - platform: ledc + pin: 12 + id: led1_output + + - platform: ledc + pin: 10 + id: led2_output + + - platform: gpio + pin: GPIO38 + id: CFG1_pin + - platform: gpio + pin: GPIO48 + id: CFG2_pin + - platform: gpio + pin: GPIO47 + id: CFG3_pin + +light: + - platform: monochromatic + output: led1_output + id: led1 + name: LED 1 + - platform: status_led + output: led2_output + id: led2 + name: Status LED + +globals: + - id: encoder_tracking_ + type: int32_t[2] + restore_value: no + + - id: encoder_offset_ + type: int32_t + restore_value: no + + - id: sensored_home_pos + type: int32_t + restore_value: no + initial_value: "0" + +stepper: + - platform: tmc2209 + id: motor + max_speed: 600 steps/s + acceleration: 400 steps/s^2 + deceleration: 400 steps/s^2 + rsense: 100 mOhm + vsense: False + enn_pin: 21 + diag_pin: 16 + index_pin: 11 + # step_pin: 5 + # dir_pin: 6 + on_stall: + - logger.log: + format: "Motor stalled!" + level: INFO + - stepper.stop: motor #un-comment this to disable on stall + - lambda: id(sensored_home_pos) = id(encoder)->get_state(); #un-comment this to not reset home on stall + - cover.template.publish: + id: pd_blinds + state: OPEN + - light.turn_on: + id: led1 + transition_length: 0s + - delay: 250ms + - light.turn_off: + id: led1 + transition_length: 1s + +button: + - platform: restart + name: Restart + + - platform: template + name: Stop + on_press: + - stepper.stop: motor + +binary_sensor: + - platform: gpio + name: Power Good + pin: + number: 15 + mode: INPUT + inverted: true + device_class: power + filters: + - delayed_on: 10ms + + - platform: gpio + name: Button 1 + pin: + number: 35 + mode: INPUT + inverted: true + id: btn1 + filters: + - delayed_on: 10ms + on_press: + - cover.close: pd_blinds + + - platform: gpio + name: Button 2 + id: btn2 + pin: + number: 36 + mode: INPUT + inverted: true + filters: + - delayed_on: 10ms + on_press: + - tmc2209.disable: motor + + - platform: gpio + name: Button 3 + id: btn3 + pin: + number: 37 + mode: INPUT + inverted: true + filters: + - delayed_on: 10ms + on_press: + - cover.open: pd_blinds + +as5600: + slow_filter: 16x + +sensor: + - platform: as5600 + id: encoder_status + update_interval: 60s + status: + name: Encoder status + + - platform: as5600 + name: Encoder + id: encoder + internal: true + update_interval: 0ms + filters: + - delta: 2 # throttle the high polling rate to only act on value changes + # compute absolute position from angle value + - lambda: | + const uint16_t curr = x; + int16_t delta = curr - id(encoder_tracking_)[0]; + if (delta > 2048) + delta -= 4096; + else if (delta < -2047) + delta += 4096; + ESP_LOGD("angle", "Old %d new %d delta %d now %d home %d", id(encoder_tracking_)[0], curr, delta, + id(encoder_tracking_)[1] + delta, id(sensored_home_pos) ); + id(encoder_tracking_)[0] = curr; + id(encoder_tracking_)[1] -= delta; + if (id(encoder_tracking_)[1] < id(sensored_home_pos)) { + ESP_LOGI("home", "Adjusted to %d", id(encoder_tracking_)[1]); + id(sensored_home_pos) = id(encoder_tracking_)[1]; + } + return id(encoder_tracking_)[1]; + accuracy_decimals: 0 + state_class: measurement + + - platform: adc + pin: 4 + name: VBUS Voltage + update_interval: 10s + attenuation: 12dB + filters: + - multiply: 8.47742 + +cover: + - platform: template + id: pd_blinds + name: PD Stepper Blinds + has_position: true + assumed_state: false + # internal: true + lambda: |- + int percent = 100.0 * (id(encoder)->get_state()-id(sensored_home_pos)) / ${encoder_closed_pos}; + return (100.0 - percent) / 100.0; + stop_action: + - tmc2209.disable: motor + open_action: + - lambda: |- + int32_t wantpos = id(sensored_home_pos); + int32_t posdelta = wantpos - id(encoder)->get_state(); + int32_t stepdelta = ((posdelta * 200 * ${microsteps}) + 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); + id(motor).set_target(id(motor)->current_position + stepdelta); + close_action: + - 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; + 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); + id(motor).set_target(id(motor)->current_position + stepdelta); + position_action: + - 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; + 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); + id(motor).set_target(id(motor)->current_position + stepdelta); diff --git a/landing-blind-3.yaml b/landing-blind-3.yaml new file mode 100644 index 0000000..ce7ebfc --- /dev/null +++ b/landing-blind-3.yaml @@ -0,0 +1,7 @@ +substitutions: + name: "landing-blind-3" + encoder_closed_pos: "230000" # full blinds length (in encoder counts) !! CHANGE TO SUIT YOUR SETUP !! + microsteps: "2" + +packages: + blind: !include blind.yaml -- 2.50.1