配置信息
[probe]
pin: ! PD4
x_offset: 0
y_offset: 0
z_offset: - 0. 20
speed: 10
samples: 2
samples_result: average
sample_retract_dist: 5
samples_tolerance: 0. 05
samples_tolerance_retries: 5
入口
def load_config ( config) : return PrinterProbe( config, ProbeEndstopWrapper( config) )
初始化
class PrinterProbe : def __init__ ( self, config, mcu_probe) : self. printer = config. get_printer( ) self. name = config. get_name( ) self. mcu_probe = mcu_probeself. speed = config. getfloat( 'speed' , 5.0 , above= 0. ) self. lift_speed = config. getfloat( 'lift_speed' , self. speed, above= 0. ) self. x_offset = config. getfloat( 'x_offset' , 0. ) self. y_offset = config. getfloat( 'y_offset' , 0. ) self. z_offset = config. getfloat( 'z_offset' ) self. probe_calibrate_z = 0. self. multi_probe_pending = False self. last_state = False self. last_z_result = 0. self. gcode_move = self. printer. load_object( config, "gcode_move" ) if config. has_section( 'stepper_z' ) : zconfig = config. getsection( 'stepper_z' ) self. z_position = zconfig. getfloat( 'position_min' , 0. , note_valid= False ) else : pconfig = config. getsection( 'printer' ) self. z_position = pconfig. getfloat( 'minimum_z_position' , 0. , note_valid= False ) self. sample_count = config. getint( 'samples' , 1 , minval= 1 ) self. sample_retract_dist = config. getfloat( 'sample_retract_dist' , 2. , above= 0. ) atypes = { 'median' : 'median' , 'average' : 'average' } self. samples_result = config. getchoice( 'samples_result' , atypes, 'average' ) self. samples_tolerance = config. getfloat( 'samples_tolerance' , 0.100 , minval= 0. ) self. samples_retries = config. getint( 'samples_tolerance_retries' , 0 , minval= 0 ) self. printer. lookup_object( 'pins' ) . register_chip( 'probe' , self) self. printer. register_event_handler( "homing:homing_move_begin" , self. _handle_homing_move_begin) self. printer. register_event_handler( "homing:homing_move_end" , self. _handle_homing_move_end) self. printer. register_event_handler( "homing:home_rails_begin" , self. _handle_home_rails_begin) self. printer. register_event_handler( "homing:home_rails_end" , self. _handle_home_rails_end) self. printer. register_event_handler( "gcode:command_error" , self. _handle_command_error) self. gcode = self. printer. lookup_object( 'gcode' ) self. gcode. register_command( 'PROBE' , self. cmd_PROBE, desc= self. cmd_PROBE_help) self. gcode. register_command( 'QUERY_PROBE' , self. cmd_QUERY_PROBE, desc= self. cmd_QUERY_PROBE_help) self. gcode. register_command( 'PROBE_CALIBRATE' , self. cmd_PROBE_CALIBRATE, desc= self. cmd_PROBE_CALIBRATE_help) self. gcode. register_command( 'PROBE_ACCURACY' , self. cmd_PROBE_ACCURACY, desc= self. cmd_PROBE_ACCURACY_help) self. gcode. register_command( 'Z_OFFSET_APPLY_PROBE' , self. cmd_Z_OFFSET_APPLY_PROBE, desc= self. cmd_Z_OFFSET_APPLY_PROBE_help)
初始化打印机对象和探针参数 :
self.printer
:通过 config.get_printer()
获取打印机对象。self.name
:通过 config.get_name()
获取探针名称。self.mcu_probe
:保存传入的 MCU 探针对象。速度设置:speed
、lift_speed
、x_offset
、y_offset
、z_offset
和 probe_calibrate_z
等控制探针的移动速度和偏移。
推断探针的 Z 轴位置 :
根据配置文件,确定探针在探测过程中的 Z 轴移动位置。 如果配置中有 stepper_z
段,使用其中 position_min
定义的 Z 轴最小位置。 否则,从 printer
配置的 minimum_z_position
获取 Z 轴最小位置。配置里minimum_z_position: -5
多重采样设置(提高测量精度) :
sample_count
:设定采样次数,以便进行多次测量来提高精度。sample_retract_dist
:设定每次采样后探针提升的距离。samples_result
:采样结果的处理方式,可以选择 ‘median’(中位数)或 ‘average’(平均值)。samples_tolerance
和 samples_retries
:设定采样的误差容忍度和重试次数,用于提高多重采样的稳定性。
注册探针的 Z 虚拟端点 :
使用 self.printer.lookup_object('pins').register_chip('probe', self)
将探针注册为 Z 虚拟端点,使其在打印机控制系统中可以作为端点来使用。
注册归位事件处理器 :
homing
相关事件处理器会在归位过程的不同阶段触发,分别在归位移动开始和结束时执行 _handle_homing_move_begin
和 _handle_homing_move_end
,在归位轨道的开始和结束时执行 _handle_home_rails_begin
和 _handle_home_rails_end
。如果在 GCode 命令中遇到错误,则会触发 _handle_command_error
。
注册 GCode 命令 :
PROBE
:触发一次探针操作。QUERY_PROBE
:查询探针状态。PROBE_CALIBRATE
:校准探针的 Z 轴偏移。PROBE_ACCURACY
:测量探针的精度。Z_OFFSET_APPLY_PROBE
:将当前 Z 轴偏移应用到探针。
class ProbeEndstopWrapper : def __init__ ( self, config) : self. printer = config. get_printer( ) self. position_endstop = config. getfloat( 'z_offset' ) self. stow_on_each_sample = config. getboolean( 'deactivate_on_each_sample' , True ) gcode_macro = self. printer. load_object( config, 'gcode_macro' ) self. activate_gcode = gcode_macro. load_template( config, 'activate_gcode' , '' ) self. deactivate_gcode = gcode_macro. load_template( config, 'deactivate_gcode' , '' ) ppins = self. printer. lookup_object( 'pins' ) pin = config. get( 'pin' ) pin_params = ppins. lookup_pin( pin, can_invert= True , can_pullup= True ) mcu = pin_params[ 'chip' ] self. mcu_endstop = mcu. setup_pin( 'endstop' , pin_params) self. printer. register_event_handler( 'klippy:mcu_identify' , self. _handle_mcu_identify) self. get_mcu = self. mcu_endstop. get_mcuself. add_stepper = self. mcu_endstop. add_stepperself. get_steppers = self. mcu_endstop. get_steppersself. home_start = self. mcu_endstop. home_startself. home_wait = self. mcu_endstop. home_waitself. query_endstop = self. mcu_endstop. query_endstopself. multi = 'OFF'
初始化打印机对象和配置参数 :
self.printer
使用 config.get_printer()
获取打印机对象。self.position_endstop
设定了 z_offset
(Z 轴端点偏移量),用于定义探针的初始位置或偏移。self.stow_on_each_sample
用于配置探针是否在每次采样后停放,默认为 True
。
加载 GCode 宏 :
使用 gcode_macro
对象从配置中加载探针激活和停用的 GCode 模板:
activate_gcode
:在探针激活时执行的 GCode。deactivate_gcode
:在探针停用时执行的 GCode。
创建端点对象 :
使用 pins
对象(通过 self.printer.lookup_object('pins')
获得)查找探针的 pin
(引脚)配置。 通过 lookup_pin()
配置引脚参数,包括是否可以反转或上拉电阻,随后得到引脚参数 pin_params
。 使用引脚所在的 mcu
芯片设置一个 endstop
引脚对象 mcu_endstop
,负责处理探针状态。
注册事件处理程序 :
注册事件 klippy:mcu_identify
,当触发该事件时调用 _handle_mcu_identify
方法。这个方法通常用于在初始化或连接时对探针或端点进行识别和确认。
简化调用的包装函数 :
定义一些包装函数用于直接调用 mcu_endstop
对象的相关方法,包括:
get_mcu
:获取探针所在的 MCU 对象。add_stepper
:将步进电机添加到探针控制中。get_steppers
:获取当前与探针关联的步进电机。home_start
和 home_wait
:用于控制探针的归位和等待状态。query_endstop
:查询端点的当前状态(是否被触发)。
多重探针状态 :
定义 self.multi
,表示多重探针采样状态,默认为 'OFF'
。
class ProbePointsHelper : def __init__ ( self, config, finalize_callback, default_points= None ) : self. printer = config. get_printer( ) self. finalize_callback = finalize_callbackself. probe_points = default_pointsself. name = config. get_name( ) self. gcode = self. printer. lookup_object( 'gcode' ) if default_points is None or config. get( 'points' , None ) is not None : self. probe_points = config. getlists( 'points' , seps= ( ',' , '\n' ) , parser= float , count= 2 ) self. horizontal_move_z = config. getfloat( 'horizontal_move_z' , 5. ) self. speed = config. getfloat( 'speed' , 50. , above= 0. ) self. use_offsets = False self. lift_speed = self. speedself. probe_offsets = ( 0. , 0. , 0. ) self. results = [ ]
该对象会在 bed_mesh 和 delta_calibrate 模块加载时进行初始化,并传入回调函数和探测点points等信息。
探测判断
ProbePointsHelper. start_probe ( probe. py) - > ProbePointsHelper. _move_next ( probe. py) - >
DeltaCalibrate. probe_finalize ( delta_calibrate. py)
ProbePointsHelper. start_probe ( probe. py) - > ProbePointsHelper. _move_next ( probe. py) - >
BedMeshCalibrate. probe_finalize ( bed_mesh. py)
探测是否结束代码逻辑
def _move_next ( self) : toolhead = self. printer. lookup_object( 'toolhead' ) speed = self. lift_speedif not self. results: speed = self. speedtoolhead. manual_move( [ None , None , self. horizontal_move_z] , speed) if len ( self. results) >= len ( self. probe_points) : toolhead. get_last_move_time( ) res = self. finalize_callback( self. probe_offsets, self. results) if res != "retry" : return True self. results = [ ] nextpos = list ( self. probe_points[ len ( self. results) ] ) if self. use_offsets: nextpos[ 0 ] -= self. probe_offsets[ 0 ] nextpos[ 1 ] -= self. probe_offsets[ 1 ] toolhead. manual_move( nextpos, self. speed) return False
提升探针或工具头
通过调用 toolhead.manual_move
,将探针或工具头移动到指定的高度 self.horizontal_move_z
。 如果这是第一次探测(self.results
为空),会使用较快的初始速度(self.speed
)。否则使用探针提升速度(self.lift_speed
)。
检查探测是否完成
检查已完成探测点的数量是否达到预定的探测点总数(len(self.probe_points)
)。 如果所有点都探测完成:
调用 toolhead.get_last_move_time()
记录最后的移动时间。 执行 self.finalize_callback
,处理探测结果(如计算网格调整数据等)。
处理探测结果
finalize_callback
返回值决定后续操作:如果返回值不是 "retry"
,探测结束,方法返回 True
。 如果返回值为 "retry"
,表示需要重新探测,清空结果 self.results
并从头开始。
移动到下一个探测点
确定下一个探测点的坐标:
从 self.probe_points
列表中取出对应位置的点。 如果启用了偏移(self.use_offsets
),会调整 X、Y 坐标以考虑探针的实际偏移量。
将探针移动到下一个点,准备进行探测。
返回继续探测
方法返回 False
,表示探测未完成,需要继续执行探测流程。