diff --git a/config/example-extras.cfg b/config/example-extras.cfg index 806b5f7d..d22311a3 100644 --- a/config/example-extras.cfg +++ b/config/example-extras.cfg @@ -107,8 +107,8 @@ # is above the bed at the given nozzle coordinates. The default is # to not enable the command. #speed: 50 -# The speed (in mm/s) of non-probing moves during the -# calibration. The default is 50. +# The speed (in mm/s) of non-probing moves during the calibration. +# The default is 50. #horizontal_move_z: 5 # The height (in mm) that the head should be commanded to move to # just prior to starting a probe operation. The default is 5. @@ -226,6 +226,43 @@ # results in more curvature in the mesh. Default is .2. +# Tool to help adjust bed leveling screws. One may define a +# [bed_screws] config section to enable a BED_SCREWS_ADJUST g-code +# command. +#[bed_screws] +#screw1: 100,100 +# The X,Y coordinate of the first bed leveling screw. This is a +# position to command the nozzle to that is directly above the bed +# screw (or as close as possible while still being above the bed). +# This parameter must be provided. +#screw1_name: front screw +# An arbitrary name for the given screw. This name is displayed when +# the helper script runs. The default is to use a name based upon +# the screw XY location. +#screw1_fine_adjust: +# An X,Y coordinate to command the nozzle to so that one can fine +# tune the bed leveling screw. The default is to not perform fine +# adjustments on the bed screw. +#screw2: +#screw2_name: +#screw2_fine_adjust: +#... +# Additional bed leveling screws. At least three screws must be +# defined. +#horizontal_move_z: 5 +# The height (in mm) that the head should be commanded to move to +# when moving from one screw location to the next. The default is 5. +#probe_height: 0 +# The height of the probe (in mm) after adjusting for the thermal +# expansion of bed and nozzle. The default is zero. +#speed: 50 +# The speed (in mm/s) of non-probing moves during the calibration. +# The default is 50. +#probe_speed: 5 +# The speed (in mm/s) when moving from a horizontal_move_z position +# to a probe_height position. The default is 5. + + # Multiple Z stepper tilt adjustment. This feature enables independent # adjustment of multiple z steppers (see stepper_z1 section below) to # adjust for tilt. If this section is present then a Z_TILT_ADJUST diff --git a/docs/G-Codes.md b/docs/G-Codes.md index a39f2c30..8cbd34ba 100644 --- a/docs/G-Codes.md +++ b/docs/G-Codes.md @@ -261,6 +261,16 @@ section is enabled: REMOVE operations have been run the SAVE_CONFIG gcode must be run to make the changes to peristent memory permanent. +## Bed Screws Helper + +The following commands are available when the "bed_screws" config +section is enabled: +- `BED_SCREWS_ADJUST`: This command will invoke the bed screws + adjustment tool. It will command the nozzle to different locations + (as defined in the config file) and allow one to make adjustments to + the bed screws so that the bed is a constant distance from the + nozzle. + ## Z Tilt The following commands are available when the "z_tilt" config section diff --git a/klippy/extras/bed_screws.py b/klippy/extras/bed_screws.py new file mode 100644 index 00000000..ce6754da --- /dev/null +++ b/klippy/extras/bed_screws.py @@ -0,0 +1,119 @@ +# Helper script to adjust bed screws +# +# Copyright (C) 2019 Kevin O'Connor +# +# This file may be distributed under the terms of the GNU GPLv3 license. + +def parse_coord(config, param): + pair = config.get(param).strip().split(',', 1) + try: + return (float(pair[0]), float(pair[1])) + except: + raise config.error("%s:%s needs to be an x,y coordinate" % ( + config.get_name(), param)) + +class BedScrews: + def __init__(self, config): + self.printer = config.get_printer() + self.state = None + self.current_screw = 0 + self.adjust_again = False + # Read config + screws = [] + fine_adjust = [] + for i in range(99): + prefix = "screw%d" % (i + 1,) + if config.get(prefix, None) is None: + break + screw_coord = parse_coord(config, prefix) + screw_name = "screw at %.3f,%.3f" % screw_coord + screw_name = config.get(prefix + "_name", screw_name) + screws.append((screw_coord, screw_name)) + if config.get(prefix + "_fine_adjust", None) is not None: + fine_coord = parse_coord(config, prefix + "_fine_adjust") + fine_adjust.append((fine_coord, screw_name)) + if len(screws) < 3: + raise config.error("bed_screws: Must have at least three screws") + self.states = {'adjust': screws, 'fine': fine_adjust} + self.speed = config.getfloat('speed', 50., above=0.) + self.lift_speed = config.getfloat('probe_speed', 5., above=0.) + self.horizontal_move_z = config.getfloat('horizontal_move_z', 5.) + self.probe_z = config.getfloat('probe_height', 0.) + # Register command + self.gcode = self.printer.lookup_object('gcode') + self.gcode.register_command("BED_SCREWS_ADJUST", + self.cmd_BED_SCREWS_ADJUST, + desc=self.cmd_BED_SCREWS_ADJUST_help) + def move(self, coord, speed): + toolhead = self.printer.lookup_object('toolhead') + curpos = toolhead.get_position() + for i in range(len(coord)): + if coord[i] is not None: + curpos[i] = coord[i] + try: + toolhead.move(curpos, speed) + except homing.EndstopError as e: + raise self.gcode.error(str(e)) + def move_to_screw(self, state, screw): + # Move up, over, and then down + self.move((None, None, self.horizontal_move_z), self.lift_speed) + coord, name = self.states[state][screw] + self.move((coord[0], coord[1], self.horizontal_move_z), self.speed) + self.move((coord[0], coord[1], self.probe_z), self.lift_speed) + # Update state + self.state = state + self.current_screw = screw + # Register commands + self.gcode.respond_info( + "Adjust %s. Then run ACCEPT, ADJUSTED, or ABORT\n" + "Use ADJUSTED if a significant screw adjustment is made" % (name,)) + self.gcode.register_command('ACCEPT', self.cmd_ACCEPT, + desc=self.cmd_ACCEPT_help) + self.gcode.register_command('ADJUSTED', self.cmd_ADJUSTED, + desc=self.cmd_ADJUSTED_help) + self.gcode.register_command('ABORT', self.cmd_ABORT, + desc=self.cmd_ABORT_help) + def unregister_commands(self): + self.gcode.register_command('ACCEPT', None) + self.gcode.register_command('ADJUSTED', None) + self.gcode.register_command('ABORT', None) + cmd_BED_SCREWS_ADJUST_help = "Tool to help adjust bed leveling screws" + def cmd_BED_SCREWS_ADJUST(self, params): + if self.state is not None: + raise self.gcode.error( + "Already in bed_screws helper; use ABORT to exit") + self.adjust_again = False + self.move((None, None, self.horizontal_move_z), self.speed) + self.move_to_screw('adjust', 0) + cmd_ACCEPT_help = "Accept bed screw position" + def cmd_ACCEPT(self, params): + self.unregister_commands() + if self.current_screw + 1 < len(self.states[self.state]): + # Continue with next screw + self.move_to_screw(self.state, self.current_screw + 1) + return + if self.adjust_again: + # Retry coarse adjustments + self.adjust_again = False + self.move_to_screw('adjust', 0) + return + if self.state == 'adjust' and self.states['fine']: + # Perform fine screw adjustments + self.move_to_screw('fine', 0) + return + # Done + self.state = None + self.move((None, None, self.horizontal_move_z), self.lift_speed) + self.gcode.respond_info("Bed screws tool completed successfully") + cmd_ADJUSTED_help = "Accept bed screw position after notable adjustment" + def cmd_ADJUSTED(self, params): + self.unregister_commands() + self.adjust_again = True + self.cmd_ACCEPT(params) + cmd_ABORT_help = "Abort bed screws tool" + def cmd_ABORT(self, params): + self.unregister_commands() + self.state = None + +def load_config(config): + return BedScrews(config) diff --git a/test/klippy/bed_screws.cfg b/test/klippy/bed_screws.cfg new file mode 100644 index 00000000..5033e317 --- /dev/null +++ b/test/klippy/bed_screws.cfg @@ -0,0 +1,50 @@ +# Test config for bed screws tool +[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: ^ar18 +position_endstop: 0.5 +position_max: 200 + +[bed_screws] +screw1: 100,50 +screw1_name: Front right +screw1_fine_adjust: 200,50 +screw2: 75,75 +screw2_fine_adjust: 200,75 +screw3: 75,75 +screw3_name: Last +screw3_fine_adjust: 75,90 + +[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/bed_screws.test b/test/klippy/bed_screws.test new file mode 100644 index 00000000..53fa2cb1 --- /dev/null +++ b/test/klippy/bed_screws.test @@ -0,0 +1,49 @@ +# Test case for bed screws helper tool +CONFIG bed_screws.cfg +DICTIONARY atmega2560-16mhz.dict + +# Start helper script and then abort it +G28 +BED_SCREWS_ADJUST + +ACCEPT +ACCEPT +ABORT + +# Start helper script and run until success +BED_SCREWS_ADJUST + +ACCEPT +ACCEPT +ACCEPT + +ACCEPT +ACCEPT +ACCEPT + +# Start helper script and run with two readjusts +BED_SCREWS_ADJUST + +ACCEPT +ADJUSTED +ACCEPT + +ACCEPT +ACCEPT +ACCEPT + +ADJUSTED +ACCEPT +ACCEPT + +ACCEPT +ACCEPT +ACCEPT + +ACCEPT +ACCEPT +ACCEPT + +# Start helper script and run with two readjusts +BED_SCREWS_ADJUST +ABORT