Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optionally handle clone deploy needed when 'stow_on_each_sample: False' #2678

Closed
wants to merge 8 commits into from
9 changes: 7 additions & 2 deletions config/example-extras.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -632,11 +632,16 @@
#pin_up_touch_mode_reports_triggered: True
# Set if the BLTouch consistently reports a "triggered" state after
# the commands "pin_up" followed by "touch_mode". This should be
# True for a genuine BLTouch v2 and earlier; the BLTouch v3 and some
# BLTouch clones require False. The default is True.
# True for a genuine BLTouch; Some BLTouch clones may require False.
# The default is True.
#stow_on_each_sample: True
# If set to False, intermediate STOW/DEPLOY sequences on certain
# operations that use the probe multiple times will be omitted.
#probe_clone_needs_deploy: False
# Set if the probe is not an original BLTouch and the probe needs
# a deploy in order to trigger multiple times. Only use this if
# you intend to use 'stow_on_each_sample: False' and the probe
# fails to trigger after the first.
#set_ouput_mode: [Possible values: 5V, OD, or do not specify this
# parameter at all if you don't want a mode setting to be performed]
# A BLTouch Smart V3.0 or V3.1(+) supports selection of an output
Expand Down
78 changes: 46 additions & 32 deletions klippy/extras/bltouch.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(self, config):
self.mcu_pwm = ppins.setup_pin('pwm', config.get('control_pin'))
self.mcu_pwm.setup_max_duration(0.)
self.mcu_pwm.setup_cycle_time(SIGNAL_PERIOD)
self.next_cmd_time = 0.
self.next_cmd_time = self.action_end_time = 0.
# Create an "endstop" object to handle the sensor pin
pin = config.get('sensor_pin')
pin_params = ppins.lookup_pin(pin, can_invert=True, can_pullup=True)
Expand All @@ -53,6 +53,8 @@ def __init__(self, config):
'pin_up_reports_not_triggered', True)
self.pin_up_touch_triggered = config.getboolean(
'pin_up_touch_mode_reports_triggered', True)
self.clone_needs_deploy = config.getboolean(
'probe_clone_needs_deploy', False)
self.start_mcu_pos = []
# Calculate pin move time
pmt = max(config.getfloat('pin_move_time', 0.675), MIN_CMD_TIME)
Expand Down Expand Up @@ -89,46 +91,48 @@ def sync_mcu_print_time(self):
def sync_print_time(self):
toolhead = self.printer.lookup_object('toolhead')
print_time = toolhead.get_last_move_time()
if self.next_cmd_time > print_time:
toolhead.dwell(self.next_cmd_time - print_time)
else:
if print_time > self.next_cmd_time:
self.next_cmd_time = print_time
elif self.action_end_time > print_time:
toolhead.dwell(self.action_end_time - print_time)
def send_cmd(self, cmd, duration=MIN_CMD_TIME):
self.mcu_pwm.set_pwm(self.next_cmd_time, Commands[cmd] / SIGNAL_PERIOD)
# Translate duration to ticks to avoid any secondary mcu clock skew
mcu = self.mcu_pwm.get_mcu()
cmd_clock = mcu.print_time_to_clock(self.next_cmd_time)
cmd_clock += mcu.seconds_to_clock(max(duration, MIN_CMD_TIME))
self.next_cmd_time = mcu.clock_to_print_time(cmd_clock)
if cmd is not None:
self.action_end_time = self.next_cmd_time
return self.next_cmd_time
def verify_state(self, check_start_time, check_end_time, triggered, msg):
def verify_state(self, check_start_time, check_end_time, triggered):
# Perform endstop check to verify bltouch reports desired state
self.mcu_endstop.home_start(check_start_time, ENDSTOP_SAMPLE_TIME,
ENDSTOP_SAMPLE_COUNT, ENDSTOP_REST_TIME,
triggered=triggered)
did_trigger = self.mcu_endstop.home_wait(check_end_time)
if not did_trigger:
raise homing.EndstopError("BLTouch failed to %s" % (msg,))
return self.mcu_endstop.home_wait(check_end_time)
def raise_probe(self):
self.sync_mcu_print_time()
if not self.pin_up_not_triggered:
# No way to verify raise attempt - just issue commands
self.send_cmd('reset')
self.send_cmd('pin_up', duration=self.pin_move_time)
self.send_cmd(None)
return
for retry in range(3):
self.sync_mcu_print_time()
if retry or not self.pin_up_not_triggered:
self.send_cmd('reset')
check_start_time = self.send_cmd('pin_up',
duration=self.pin_move_time)
check_end_time = self.send_cmd(None)
if self.pin_up_not_triggered:
try:
self.verify_state(check_start_time, check_end_time,
False, "raise probe")
except homing.CommandError as e:
if retry >= 2:
raise
msg = "Failed to verify BLTouch probe is raised; retrying."
self.gcode.respond_info(msg)
self.next_cmd_time += RETRY_RESET_TIME
continue
break
success = self.verify_state(check_start_time, check_end_time, False)
if success:
# The "probe raised" test completed successfully
break
if retry >= 2:
raise homing.EndstopError("BLTouch failed to raise probe")
msg = "Failed to verify BLTouch probe is raised; retrying."
self.gcode.respond_info(msg)
self.sync_mcu_print_time()
self.send_cmd('reset', duration=RETRY_RESET_TIME)
def lower_probe(self):
self.test_sensor()
self.sync_print_time()
Expand All @@ -146,14 +150,22 @@ def test_sensor(self):
return
# Raise the bltouch probe and test if probe is raised
self.sync_print_time()
check_start_time = self.send_cmd('reset', duration=self.pin_move_time)
check_end_time = self.send_cmd('touch_mode')
self.send_cmd(None)
self.verify_state(check_start_time, check_end_time, True,
"verify sensor state")
# Test was successful
self.next_test_time = check_end_time + TEST_TIME
self.sync_print_time()
for retry in range(3):
check_start_time = self.send_cmd('pin_up',
duration=self.pin_move_time)
self.send_cmd('touch_mode')
check_end_time = self.send_cmd(None)
success = self.verify_state(check_start_time, check_end_time, True)
self.sync_print_time()
if success:
# The "bltouch connection" test completed successfully
self.next_test_time = check_end_time + TEST_TIME
return
msg = "BLTouch failed to verify sensor state"
if retry >= 2:
raise homing.EndstopError(msg)
self.gcode.respond_info(msg + '; retrying.')
self.send_cmd('reset', duration=RETRY_RESET_TIME)
def multi_probe_begin(self):
if self.stow_on_each_sample:
return
Expand All @@ -162,9 +174,11 @@ def multi_probe_end(self):
if self.stow_on_each_sample:
return
self.raise_probe()
self.sync_print_time()
self.multi = 'OFF'
def probe_prepare(self):
if self.multi == 'OFF' or self.multi == 'FIRST':
if (self.multi == 'OFF' or self.multi == 'FIRST'
or self.clone_needs_deploy):
self.lower_probe()
if self.multi == 'FIRST':
self.multi = 'ON'
Expand Down