Witam.
Znalazłem na innym forum kod sterowania silnikiem krokowym na A4988. Generalnie kod jest ok ale fizyczny endstop jest w nim umieszczony przy całkowitym otwarciu. Podczas restartu kod wykonuje test pozycji w związku z tym bez względu na aktualną pozycję wykonuje całkowite otwarcie i powrót. Autor zaprojektował go do sterowania roletami więc u niego nie stanowiło to problemu. U mnie sterownik ma służyć do automatycznego uchylania okna w szklarni w związku z tym takie rozwiązanie nie wchodzi w grę bo jeśli okno będzie fizycznie zaryglowane przy próbie otwarcia nastąpi zablokowanie silnika w najlepszym wypadku.
W związku z tym potrzebuję przenieść endstop do pozycji zamknięte. Próbowałem po prostu zamienić słowo “open” z “close”, o dziwo zadziałało ale tylko podczas pełnego otwierania/zamykania. Przy próbie ustawienia w pozycji np 10% działa jakby odwrotnie, później nie wraca do właściwej pozycji. Proszę o pomoc. Oto kod:
esphome:
name: nemav2
friendly_name: NemaV2
on_boot:
priority: 250
then:
- delay: 10s
- if:
condition:
# shade thinks it's at 0 but endstop is not triggered
lambda: "if ((id(stepper_position) == 0) && (id(endstop).state == 0)) { return 1; } else { return 0; }"
then:
# open to blind to calibrate the endstop, remember the steps to do so, put the blind back to where it was
- globals.set:
id: stepper_state
value: '1'
# set the assumed stepper position to stepper_steps + 4000 and have it travel to 0
- stepper.report_position:
id: my_stepper
position: !lambda "return id(stepper_steps) + 4000;"
- stepper.set_target:
id: my_stepper
target: 0
# wait until the stepper is no longer moving
- wait_until:
- lambda: "if (id(my_stepper).current_position == id(my_stepper).target_position) { return 1; } else { return 0; }"
# now move the blind back to however many steps it took to reach the endstop
- stepper.set_target:
id: my_stepper
target: !lambda "return id(stepper_steps) + 4000 - id(stepper_prevpos);"
- globals.set:
id: stepper_state
value: '1'
- delay: !lambda "return ((id(my_stepper).target_position - 834) * 2) + 3334;"
- globals.set:
id: stepper_position
value: !lambda "return id(my_stepper).target_position;"
- globals.set:
id: stepper_state
value: '0'
esp32:
board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
key: "4SHnfj/B2NW0aPI+IRu67+Cqd9dF2Q4LyHSzgabqjz8="
ota:
password: "84fa3c54bed2661a99656cac430ac015"
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Nemav2 Fallback Hotspot"
password: "FOR6F0xwBjBp"
captive_portal:
web_server:
port: 80
globals:
- id: stepper_steps
type: int
initial_value: '0'
restore_value: true
- id: stepper_prevpos
type: float
initial_value: '0'
- id: stepper_position
type: float
initial_value: '0'
- id: stepper_state
type: int
initial_value: '0'
- id: calib_state
type: int
initial_value: '0'
sensor:
- platform: uptime
name: "Node uptime"
switch:
- platform: restart
name: "Restart"
binary_sensor:
- platform: gpio
pin:
number: 14
mode: INPUT_PULLUP
name: "Open"
filters:
- invert:
- delayed_on: 10ms
on_click:
- min_length: 50ms
max_length: 1000ms
then:
- lambda: |
if ((id(stepper_state) == 0) && (id(endstop).state == 0)) {
//shade is stopped and not already open at endstop
id(blind).open();
} else {
//shade is moving
id(blind).stop();
}
- platform: gpio
pin:
number: 32
mode: INPUT_PULLUP
name: "Close"
filters:
- invert:
- delayed_on: 10ms
on_click:
- min_length: 50ms
max_length: 1000ms
then:
- lambda: |
if ((id(stepper_state) == 0) && (id(stepper_position) < id(stepper_steps))) {
//shade is stopped and not already closed
id(blind).close();
} else {
//shade is moving
id(blind).stop();
}
# a 10s press on the down button will enter calibration mode
# shutter goes all the way up and then travels down until a button is pressed
# where shutter is stopped is the new stepper_steps value
- min_length: 5000ms
max_length: 15000ms
then:
- lambda: |
id(calib_state) = 1;
if ((id(stepper_state) == 0) && (id(endstop).state == 0)) {
//shade is stopped and not already open at endstop
id(blind).open();
} else if ((id(stepper_state) == 0) && (id(endstop).state == 1)) {
//shade is stopped and already open at endstop
id(blind).close();
}
- platform: gpio
pin:
number: 33
mode: INPUT_PULLUP
name: "Endstop"
id: endstop
filters:
- delayed_on_off: 300ms
on_press:
then:
# hit the endstop, store the current steps value and reset stepper position to 0
- globals.set:
id: stepper_prevpos
value: !lambda "return id(my_stepper).current_position;"
- stepper.report_position:
id: my_stepper
position: 0
# just in case, also set the target to 0
- stepper.set_target:
id: my_stepper
target: 0
- lambda: |
if (id(stepper_state) == 1) {
//shade is moving
id(blind).stop();
}
cover:
- platform: template
name: "Blind"
id: blind
open_action:
- globals.set:
id: stepper_state
value: '1'
# overshoot past the endstop to make sure it's hit (endstop will stop blind)
- stepper.set_target:
id: my_stepper
target: -4000
# wait until the stepper is no longer moving
- wait_until:
- lambda: "if (id(my_stepper).current_position == id(my_stepper).target_position) { return 1; } else { return 0; }"
- globals.set:
id: stepper_position
value: !lambda "return id(my_stepper).target_position;"
- globals.set:
id: stepper_state
value: '0'
- if:
condition:
# reached past the 'top' but still haven't triggered the endstop yet
lambda: "if(id(stepper_position) == -4000 && id(endstop).state == 0) { return 1; } else { return 0; }"
then:
# reset stepper position to 0
- stepper.report_position:
id: my_stepper
position: 0
# just in case, also set the target to 0
- stepper.set_target:
id: my_stepper
target: 0
close_action:
- globals.set:
id: stepper_state
value: '1'
- stepper.set_target:
id: my_stepper
# for calibration the number of steps is doubled
target: !lambda "if(id(calib_state) == 0) { return id(stepper_steps); } else { return id(stepper_steps) * 2; }"
# wait until the stepper is no longer moving
- wait_until:
- lambda: "if (id(my_stepper).current_position == id(my_stepper).target_position) { return 1; } else { return 0; }"
- globals.set:
id: stepper_position
value: !lambda "return id(my_stepper).target_position;"
- globals.set:
id: stepper_state
value: '0'
- lambda: |
if (id(calib_state) == 1) {
//reached double the current stepper distance
id(stepper_steps) = id(stepper_position);
//continue with calibration
id(blind).close();
}
stop_action:
- stepper.set_target:
id: my_stepper
target: !lambda "return id(my_stepper).current_position;"
- globals.set:
id: stepper_position
value: !lambda "return id(my_stepper).current_position;"
- globals.set:
id: stepper_state
value: '0'
- lambda: |
if (id(calib_state) == 1 && id(endstop).state == 0) {
//stopping at something other than the endstop
id(calib_state) = 0;
id(stepper_steps) = id(stepper_position);
}
- cover.template.publish:
id: blind
position: !lambda "return 1 - (id(stepper_position) / id(stepper_steps));"
position_action:
- stepper.set_target:
id: my_stepper
target: !lambda "return id(stepper_steps) * (1 - pos);"
optimistic: true
assumed_state: true
has_position: true
stepper:
- platform: a4988
id: my_stepper
dir_pin:
number: 26
step_pin: 25
max_speed: 2000
# Optional:
sleep_pin: 27
acceleration: 1500
deceleration: 3000