diff --git a/config/example-extras.cfg b/config/example-extras.cfg index 20fb9476..318669d2 100644 --- a/config/example-extras.cfg +++ b/config/example-extras.cfg @@ -43,6 +43,24 @@ # not run any special G-Code commands on deactivation. +# BLTouch probe. One may define this section (instead of a probe +# section) to enable a BLTouch probe. A virtual +# "probe:z_virtual_endstop" pin is also created (see the "probe" +# section above for the details). +#[bltouch] +#sensor_pin: +# Pin connected to the BLTouch sensor pin. This parameter must be +# provided. +#control_pin: +# Pin connected to the BLTouch control pin. This parameter must be +# provided. +#x_offset: +#y_offset: +#z_offset: +#speed: +# See the "probe" section for information on these parameters. + + # Bed tilt compensation. One may define a [bed_tilt] config section to # enable move transformations that account for a tilted bed. #[bed_tilt] diff --git a/klippy/extras/bltouch.py b/klippy/extras/bltouch.py new file mode 100644 index 00000000..c3ce14db --- /dev/null +++ b/klippy/extras/bltouch.py @@ -0,0 +1,93 @@ +# BLTouch support +# +# Copyright (C) 2018 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. +import homing, probe + +SIGNAL_PERIOD = 0.025600 +PIN_MOVE_TIME = 8 * SIGNAL_PERIOD +MIN_CMD_TIME = 4 * SIGNAL_PERIOD + +TEST_TIME = 5 * 60. +ENDSTOP_SAMPLE_TIME = .000015 +ENDSTOP_SAMPLE_COUNT = 4 + +CMD_PIN_DOWN = 0.000700 +CMD_PIN_UP = 0.001500 +CMD_SELF_TEST = 0.001800 +CMD_RESET = 0.002200 +CMD_TOUCH_MODE = 0.001200 + +# BLTouch "endstop" wrapper +class BLTouchEndstopWrapper: + def __init__(self, config): + self.printer = config.get_printer() + self.next_test_time = 0. + self.position_endstop = config.getfloat('z_offset') + # Create a pwm object to handle the control pin + ppins = self.printer.lookup_object('pins') + 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) + # 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) + mcu = pin_params['chip'] + mcu.register_config_callback(self._build_config) + self.mcu_endstop = mcu.setup_pin('endstop', pin_params) + # Wrappers + self.get_mcu = self.mcu_endstop.get_mcu + self.add_stepper = self.mcu_endstop.add_stepper + self.get_steppers = self.mcu_endstop.get_steppers + self.home_start = self.mcu_endstop.home_start + self.home_wait = self.mcu_endstop.home_wait + self.query_endstop = self.mcu_endstop.query_endstop + self.query_endstop_wait = self.mcu_endstop.query_endstop_wait + self.TimeoutError = self.mcu_endstop.TimeoutError + def _build_config(self): + kin = self.printer.lookup_object('toolhead').get_kinematics() + for stepper in kin.get_steppers('Z'): + stepper.add_to_endstop(self) + def send_cmd(self, print_time, cmd): + self.mcu_pwm.set_pwm(print_time, cmd / SIGNAL_PERIOD) + def test_sensor(self): + toolhead = self.printer.lookup_object('toolhead') + print_time = toolhead.get_last_move_time() + if print_time < self.next_test_time: + self.next_test_time = print_time + TEST_TIME + return + self.send_cmd(print_time, CMD_RESET) + home_time = print_time + PIN_MOVE_TIME + self.send_cmd(home_time, CMD_TOUCH_MODE) + self.send_cmd(home_time + MIN_CMD_TIME, 0.) + self.mcu_endstop.home_start( + home_time, ENDSTOP_SAMPLE_TIME, ENDSTOP_SAMPLE_COUNT, .001) + try: + self.mcu_endstop.home_wait(home_time + MIN_CMD_TIME) + except self.mcu_endstop.TimeoutError as e: + raise homing.EndstopError("BLTouch sensor test failed") + self.next_test_time = home_time + TEST_TIME + toolhead.reset_print_time(home_time + 2. * MIN_CMD_TIME) + def home_prepare(self): + self.test_sensor() + toolhead = self.printer.lookup_object('toolhead') + print_time = toolhead.get_last_move_time() + self.send_cmd(print_time, CMD_PIN_DOWN) + self.send_cmd(print_time + PIN_MOVE_TIME, CMD_TOUCH_MODE) + toolhead.dwell(PIN_MOVE_TIME + MIN_CMD_TIME) + self.mcu_endstop.home_prepare() + def home_finalize(self): + toolhead = self.printer.lookup_object('toolhead') + print_time = toolhead.get_last_move_time() + self.send_cmd(print_time, CMD_RESET) + self.send_cmd(print_time + PIN_MOVE_TIME, 0.) + toolhead.dwell(PIN_MOVE_TIME + MIN_CMD_TIME) + self.mcu_endstop.home_finalize() + def get_position_endstop(self): + return self.position_endstop + +def load_config(config): + blt = BLTouchEndstopWrapper(config) + config.get_printer().add_object('probe', probe.PrinterProbe(config, blt)) + return blt diff --git a/klippy/extras/probe.py b/klippy/extras/probe.py index 5a5096cf..24223cfb 100644 --- a/klippy/extras/probe.py +++ b/klippy/extras/probe.py @@ -13,8 +13,9 @@ the Z axis minimum position so the probe can travel further """ class PrinterProbe: - def __init__(self, config): + def __init__(self, config, mcu_probe): self.printer = config.get_printer() + self.mcu_probe = mcu_probe self.speed = config.getfloat('speed', 5.0) self.x_offset = config.getfloat('x_offset', 0.) self.y_offset = config.getfloat('y_offset', 0.) @@ -26,10 +27,8 @@ class PrinterProbe: else: pconfig = config.getsection('printer') self.z_position = pconfig.getfloat('minimum_z_position', 0.) - # Create mcu_probe object and register z_virtual_endstop pin - self.mcu_probe = ProbeEndstopWrapper(config) - ppins = self.printer.lookup_object('pins') - ppins.register_chip('probe', self) + # Register z_virtual_endstop pin + self.printer.lookup_object('pins').register_chip('probe', self) # Register PROBE/QUERY_PROBE commands self.gcode = self.printer.lookup_object('gcode') self.gcode.register_command( @@ -239,4 +238,4 @@ class ProbePointsHelper: self.finalize_callback(self.probe_offsets, self.results) def load_config(config): - return PrinterProbe(config) + return PrinterProbe(config, ProbeEndstopWrapper(config)) diff --git a/test/klippy/bltouch.cfg b/test/klippy/bltouch.cfg new file mode 100644 index 00000000..4c295f50 --- /dev/null +++ b/test/klippy/bltouch.cfg @@ -0,0 +1,73 @@ +# Test config for probe:z_virtual_endstop +[stepper_x] +step_pin: ar54 +dir_pin: ar55 +enable_pin: !ar38 +step_distance: .0125 +endstop_pin: ^ar3 +position_endstop: 0 +position_max: 200 +homing_speed: 50 + +[stepper_y] +step_pin: ar60 +dir_pin: !ar61 +enable_pin: !ar56 +step_distance: .0125 +endstop_pin: ^ar14 +position_endstop: 0 +position_max: 200 +homing_speed: 50 + +[stepper_z] +step_pin: ar46 +dir_pin: ar48 +enable_pin: !ar62 +step_distance: .0025 +endstop_pin: probe:z_virtual_endstop +position_max: 200 + +[extruder] +step_pin: ar26 +dir_pin: ar28 +enable_pin: !ar24 +step_distance: .002 +nozzle_diameter: 0.400 +filament_diameter: 1.750 +heater_pin: ar10 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: analog13 +control: pid +pid_Kp: 22.2 +pid_Ki: 1.08 +pid_Kd: 114 +min_temp: 0 +max_temp: 250 + +[heater_bed] +heater_pin: ar8 +sensor_type: EPCOS 100K B57560G104F +sensor_pin: analog14 +control: watermark +min_temp: 0 +max_temp: 130 + +[bltouch] +sensor_pin: ar30 +control_pin: ar32 +z_offset: 1.15 + +[bed_mesh] +min_point: 10,10 +max_point: 180,180 + +[mcu] +serial: /dev/ttyACM0 +pin_map: arduino + +[printer] +kinematics: cartesian +max_velocity: 300 +max_accel: 3000 +max_z_velocity: 5 +max_z_accel: 100 diff --git a/test/klippy/bltouch.test b/test/klippy/bltouch.test new file mode 100644 index 00000000..914695df --- /dev/null +++ b/test/klippy/bltouch.test @@ -0,0 +1,25 @@ +# Test case for probe:z_virtual_endstop support +CONFIG bltouch.cfg +DICTIONARY atmega2560-16mhz.dict + +# Start by homing the printer. +G28 +G1 F6000 + +# Z / X / Y moves +G1 Z1 +G1 X1 +G1 Y1 + +# Run bed_mesh_calibrate +BED_MESH_CALIBRATE + +# Move again +G1 Z5 X0 Y0 + +# Do regular probe +PROBE +QUERY_PROBE + +# Move again +G1 Z9