From e1a99c644d05fd6b2085b900bab86698aafbb21c Mon Sep 17 00:00:00 2001 From: "JOSHS-PC\\JOSH" Date: Sun, 17 Nov 2024 21:32:54 +1300 Subject: [PATCH] Updated ESPHome Examples --- .../ESPHome/PD-Stepper-Blinds-Advanced.yaml | 283 ++++++++++++++++++ ...per.yaml => PD-Stepper-Blinds-Simple.yaml} | 61 +--- .../ESPHome/PD-Stepper-Position-Control.yaml | 218 ++++++++++++++ 3 files changed, 514 insertions(+), 48 deletions(-) create mode 100644 Software/ESPHome/PD-Stepper-Blinds-Advanced.yaml rename Software/ESPHome/{PD-Stepper.yaml => PD-Stepper-Blinds-Simple.yaml} (77%) create mode 100644 Software/ESPHome/PD-Stepper-Position-Control.yaml diff --git a/Software/ESPHome/PD-Stepper-Blinds-Advanced.yaml b/Software/ESPHome/PD-Stepper-Blinds-Advanced.yaml new file mode 100644 index 0000000..63ccd68 --- /dev/null +++ b/Software/ESPHome/PD-Stepper-Blinds-Advanced.yaml @@ -0,0 +1,283 @@ +# This example uses a custom TMC2209 component to control the PD Stepper +# It uses the encoder to get the current blind position so it will not lose home if blind is manually moved + +external_components: + - source: github://slimcdk/esphome-custom-components + components: [tmc2209, stepper] + +substitutions: + encoder_closed_pos: "30000" # full blinds length (in encoder counts) !! CHANGE TO SUIT YOUR SETUP !! + stepper_encoder_ratio: "0.195" # ratio between stepper microstepping (4) and encoder. 4 x 200 / 4096 = 0.195 + +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" + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + +api: + +ota: + - platform: esphome + +logger: + +esp32: + board: esp32-s3-devkitc-1 + framework: + type: esp-idf + +esphome: + name: pd-stepper-blinds-2 + platformio_options: + board_build.flash_mode: dio + upload_speed: 921600 + on_boot: + - tmc2209.configure: + microsteps: 4 + interpolation: true + tcool_threshold: 400 + - tmc2209.stallguard: + threshold: 45 #set lower if stall gaurd triggering too often + - tmc2209.currents: + irun: 4 + ihold: 0 + tpowerdown: 0 + iholddelay: 0 + standstill_mode: freewheeling + + #set PD voltage # 5V 9V 12V 15V 20V + - output.turn_off: # 1 0 0 0 0 + id: CFG1_pin + - output.turn_on: # - 0 0 1 1 + id: CFG2_pin + - output.turn_off: # - 0 1 1 0 + id: CFG3_pin + + - delay: 0.5s + - lambda: id(sensored_home_pos) = id(encoder)->get_state(); # Set the home position to power on position + # - button.press: home + + +web_server: + include_internal: true + ota: false + version: 3 + log: false + + +i2c: + sda: 8 + scl: 9 + scan: true + +uart: + tx_pin: 17 + rx_pin: 18 + baud_rate: 712000 + +output: + - platform: ledc + pin: 10 + id: led1_output + + - platform: ledc + pin: 12 + 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 + +stepper: + - platform: tmc2209 + id: motor + max_speed: 800 steps/s + acceleration: 1500 steps/s^2 + deceleration: 1500 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: "Motor stalled!" + # - 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: Home + id: home + on_press: + - stepper.set_target: + id: motor + target: -${encoder_closed_pos} + + - 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.open: 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.close: 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 + update_interval: 0s # beware of the polling rate + 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; //current encoder value 0-4095 + const uint16_t prev = id(encoder_tracking_)[0]; //previous encoder value 0-4095 + if (curr > 3000 && prev < 1000) { + id(encoder_tracking_)[1] -= (4095 - curr + prev); // crossed zero clockwise (went under 0) + } else if (curr < 1000 && prev > 3000) { + id(encoder_tracking_)[1] += (4095 - prev + curr); // crossed zero counterclockwise (went over 4095) + } else { + id(encoder_tracking_)[1] += (curr - prev); + } + id(encoder_tracking_)[0] = curr; + return id(encoder_tracking_)[1]; + - multiply: -1.0 + 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: "return 1.0 - ((id(encoder)->get_state()-id(sensored_home_pos)) / ${encoder_closed_pos});" + stop_action: + - tmc2209.disable: motor + open_action: + - stepper.report_position: + id: motor + position: !lambda return (1.0-id(pd_blinds)->position) * ${encoder_closed_pos} * ${stepper_encoder_ratio}; + - stepper.set_target: + id: motor + target: 0 + close_action: + - stepper.report_position: + id: motor + position: !lambda return (1.0-id(pd_blinds)->position) * ${encoder_closed_pos} * ${stepper_encoder_ratio}; + - stepper.set_target: + id: motor + target: !lambda return ${encoder_closed_pos} * ${stepper_encoder_ratio} * 1.01; + position_action: + - stepper.report_position: + id: motor + position: !lambda return (1.0-id(pd_blinds)->position) * ${encoder_closed_pos} * ${stepper_encoder_ratio}; + - stepper.set_target: + id: motor + target: !lambda return (1.0-pos) * ${encoder_closed_pos} * ${stepper_encoder_ratio}; \ No newline at end of file diff --git a/Software/ESPHome/PD-Stepper.yaml b/Software/ESPHome/PD-Stepper-Blinds-Simple.yaml similarity index 77% rename from Software/ESPHome/PD-Stepper.yaml rename to Software/ESPHome/PD-Stepper-Blinds-Simple.yaml index 2f4dfe1..fb5c832 100644 --- a/Software/ESPHome/PD-Stepper.yaml +++ b/Software/ESPHome/PD-Stepper-Blinds-Simple.yaml @@ -1,34 +1,17 @@ # PD Stepper ESPHome Config -# https://github.com/joshr120/PD-Stepper - -# Todo: -# - add sensorless homing/serial comms to TMC2209 -# - VBUS_SENSE adc read -# - Motor NTC read - - -# Enable Home Assistant API -api: - encryption: - key: "c1uNv/dyYPAkygiSdfpmM2UlQzi1B9xElFm3sKEeEFc=" #EXAMPLE KEY GENERATE YOUR OWN - -ota: - password: "PASSWORD" +# Simple example using step/dir control with the A4988 Component wifi: ssid: !secret wifi_ssid password: !secret wifi_password - # Enable fallback hotspot (captive portal) in case wifi connection fails - ap: - ssid: "PD-Stepper Fallback Hotspot" - password: "password" +api: -captive_portal: - +ota: + - platform: esphome esphome: - name: stepper-motor + name: pd-stepper-blinds # Set microstepping and PD voltage pins on boot on_boot: priority: 600 @@ -69,13 +52,6 @@ output: - platform: gpio pin: GPIO47 id: CFG3_pin - - - platform: ledc - pin: GPIO10 - id: LED1_PIN - - platform: ledc - pin: GPIO12 - id: LED2_PIN # Define binary input sensor for power_good and push button @@ -121,8 +97,8 @@ stepper: step_pin: GPIO5 dir_pin: number: GPIO6 - inverted: false #invert to change direction - max_speed: 16000 steps/s #will depend on which microstep mode is set + inverted: false #to change direction (depending on what side blind is on?) + max_speed: 16000 steps/s #depends on microstep set sleep_pin: number: GPIO21 @@ -191,23 +167,12 @@ sensor: name: Magnitude status: name: Status - - #Read VBUS voltage (could be used to debug PD voltage etc) + + #Read VBUS voltage - platform: adc - pin: GPIO4 - name: "VBUS Voltage" + pin: 4 + name: VBUS Voltage update_interval: 10s - attenuation: 11dB + attenuation: 12dB filters: - - multiply: 8.47742 - -light: - - platform: monochromatic - output: LED1_PIN - id: LED1 - name: "LED 1" - - platform: monochromatic - output: LED2_PIN - id: LED2 - name: "LED 2" - \ No newline at end of file + - multiply: 8.47742 \ No newline at end of file diff --git a/Software/ESPHome/PD-Stepper-Position-Control.yaml b/Software/ESPHome/PD-Stepper-Position-Control.yaml new file mode 100644 index 0000000..7b9b088 --- /dev/null +++ b/Software/ESPHome/PD-Stepper-Position-Control.yaml @@ -0,0 +1,218 @@ +# This example uses a custom TMC2209 component to control the PD Stepper +# Motor can be moved using a slider within ESPHome + +external_components: + - source: github://slimcdk/esphome-custom-components + components: [tmc2209, stepper] + +globals: + - id: encoder_tracking_ + type: int32_t[2] + restore_value: no + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + +api: + +ota: + - platform: esphome + +logger: + +esp32: + board: esp32-s3-devkitc-1 + framework: + type: esp-idf + +esphome: + name: pd-stepper + platformio_options: + board_build.flash_mode: dio + upload_speed: 921600 + on_boot: + - tmc2209.configure: + microsteps: 4 + direction: clockwise + interpolation: true + tcool_threshold: 400 + - tmc2209.stallguard: + threshold: 60 + - tmc2209.currents: + irun: 16 + ihold: 0 + tpowerdown: 0 + iholddelay: 0 + standstill_mode: freewheeling + + #set PD voltage # 5V 9V 12V 15V 20V + - output.turn_off: # 1 0 0 0 0 + id: CFG1_pin + - output.turn_on: # - 0 0 1 1 + id: CFG2_pin + - output.turn_off: # - 0 1 1 0 + id: CFG3_pin + +i2c: + sda: 8 + scl: 9 + scan: true + +uart: + tx_pin: 17 + rx_pin: 18 + baud_rate: 712000 + +output: + - platform: ledc + pin: 10 + id: led1_output + + - platform: ledc + pin: 12 + 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 + +stepper: + - platform: tmc2209 + id: driver + max_speed: 800 steps/s + acceleration: 1500 steps/s^2 + deceleration: 1500 steps/s^2 + rsense: 100 mOhm + vsense: False + enn_pin: 21 + diag_pin: 16 + index_pin: 11 + on_status: + - logger.log: + format: "Driver is reporting an update! (code %d)" + args: ["code"] + on_stall: + - logger.log: "Motor stalled!" + - stepper.stop: driver + - 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: driver + +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 + + - platform: gpio + name: Button 2 + id: btn2 + pin: + number: 36 + mode: INPUT + inverted: true + filters: + - delayed_on: 10ms + + - platform: gpio + name: Button 3 + id: btn3 + pin: + number: 37 + mode: INPUT + inverted: true + filters: + - delayed_on: 10ms + +as5600: + slow_filter: 16x + +sensor: + - platform: as5600 + name: Encoder + id: encoder + update_interval: 0s # beware of the polling rate + filters: + - delta: 2 + # filter which computes absolute position from angle value + - lambda: | + const uint16_t curr = x; //current encoder value 0-4095 + const uint16_t prev = id(encoder_tracking_)[0]; //previous encoder value 0-4095 + if (curr > 3000 && prev < 1000) { + id(encoder_tracking_)[1] -= (4095 - curr + prev); // crossed zero clockwise (went under 0) + } else if (curr < 1000 && prev > 3000) { + id(encoder_tracking_)[1] += (4095 - prev + curr); // crossed zero counterclockwise (went over 4095) + } else { + id(encoder_tracking_)[1] += (curr - prev); + } + id(encoder_tracking_)[0] = curr; + 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 + +number: + - platform: template + name: Target position + min_value: -10000 + max_value: 10000 + step: 100 + lambda: return id(driver)->current_position; + update_interval: 1s + set_action: + - stepper.set_target: + id: driver + target: !lambda "return x;" \ No newline at end of file