mirror of
				https://github.com/Klipper3d/klipper.git
				synced 2025-10-31 10:25:57 +01:00 
			
		
		
		
	homing: Calculate homing position based on trigger time
Calculate the "homing position" using the endstop trigger time instead of the position of the steppers. This is in preparation for multi-mcu homing. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
		| @@ -8,6 +8,12 @@ All dates in this document are approximate. | |||||||
|  |  | ||||||
| ## Changes | ## Changes | ||||||
|  |  | ||||||
|  | 20210819: In some cases, a `G28` homing move may end in a position | ||||||
|  | that is nominally outside the valid movement range.  In rare | ||||||
|  | situations this may result in confusing "Move out of range" errors | ||||||
|  | after homing.  If this occurs, change your start scripts to move the | ||||||
|  | toolhead to a valid position immediately after homing. | ||||||
|  |  | ||||||
| 20210814: The analog only pseudo-pins on the atmega168 and atmega328 | 20210814: The analog only pseudo-pins on the atmega168 and atmega328 | ||||||
| have been renamed from PE0/PE1 to PE2/PE3. | have been renamed from PE0/PE1 to PE2/PE3. | ||||||
|  |  | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| # Copyright (C) 2016-2021  Kevin O'Connor <kevin@koconnor.net> | # Copyright (C) 2016-2021  Kevin O'Connor <kevin@koconnor.net> | ||||||
| # | # | ||||||
| # This file may be distributed under the terms of the GNU GPLv3 license. | # This file may be distributed under the terms of the GNU GPLv3 license. | ||||||
| import logging, math, collections | import logging, math | ||||||
|  |  | ||||||
| HOMING_START_DELAY = 0.001 | HOMING_START_DELAY = 0.001 | ||||||
| ENDSTOP_SAMPLE_TIME = .000015 | ENDSTOP_SAMPLE_TIME = .000015 | ||||||
| @@ -21,6 +21,18 @@ def multi_complete(printer, completions): | |||||||
|         reactor.register_callback(lambda e: cp.complete(1) if c.wait() else 0) |         reactor.register_callback(lambda e: cp.complete(1) if c.wait() else 0) | ||||||
|     return cp |     return cp | ||||||
|  |  | ||||||
|  | # Tracking of stepper positions during a homing/probing move | ||||||
|  | class StepperPosition: | ||||||
|  |     def __init__(self, stepper, endstop_name): | ||||||
|  |         self.stepper = stepper | ||||||
|  |         self.endstop_name = endstop_name | ||||||
|  |         self.stepper_name = stepper.get_name() | ||||||
|  |         self.start_pos = stepper.get_mcu_position() | ||||||
|  |         self.halt_pos = self.trig_pos = None | ||||||
|  |     def note_home_end(self, trigger_time): | ||||||
|  |         self.halt_pos = self.stepper.get_mcu_position() | ||||||
|  |         self.trig_pos = self.stepper.get_past_mcu_position(trigger_time) | ||||||
|  |  | ||||||
| # Implementation of homing/probing moves | # Implementation of homing/probing moves | ||||||
| class HomingMove: | class HomingMove: | ||||||
|     def __init__(self, printer, endstops, toolhead=None): |     def __init__(self, printer, endstops, toolhead=None): | ||||||
| @@ -29,7 +41,7 @@ class HomingMove: | |||||||
|         if toolhead is None: |         if toolhead is None: | ||||||
|             toolhead = printer.lookup_object('toolhead') |             toolhead = printer.lookup_object('toolhead') | ||||||
|         self.toolhead = toolhead |         self.toolhead = toolhead | ||||||
|         self.end_mcu_pos = [] |         self.stepper_positions = [] | ||||||
|     def get_mcu_endstops(self): |     def get_mcu_endstops(self): | ||||||
|         return [es for es, name in self.endstops] |         return [es for es, name in self.endstops] | ||||||
|     def _calc_endstop_rate(self, mcu_endstop, movepos, speed): |     def _calc_endstop_rate(self, mcu_endstop, movepos, speed): | ||||||
| @@ -44,6 +56,14 @@ class HomingMove: | |||||||
|         if max_steps <= 0.: |         if max_steps <= 0.: | ||||||
|             return .001 |             return .001 | ||||||
|         return move_t / max_steps |         return move_t / max_steps | ||||||
|  |     def calc_toolhead_pos(self, kin_spos, offsets): | ||||||
|  |         kin_spos = dict(kin_spos) | ||||||
|  |         kin = self.toolhead.get_kinematics() | ||||||
|  |         for stepper in kin.get_steppers(): | ||||||
|  |             sname = stepper.get_name() | ||||||
|  |             kin_spos[sname] += offsets.get(sname, 0) * stepper.get_step_dist() | ||||||
|  |         thpos = self.toolhead.get_position() | ||||||
|  |         return list(kin.calc_position(kin_spos))[:3] + thpos[3:] | ||||||
|     def homing_move(self, movepos, speed, probe_pos=False, |     def homing_move(self, movepos, speed, probe_pos=False, | ||||||
|                     triggered=True, check_triggered=True): |                     triggered=True, check_triggered=True): | ||||||
|         # Notify start of homing/probing move |         # Notify start of homing/probing move | ||||||
| @@ -53,7 +73,7 @@ class HomingMove: | |||||||
|         kin = self.toolhead.get_kinematics() |         kin = self.toolhead.get_kinematics() | ||||||
|         kin_spos = {s.get_name(): s.get_commanded_position() |         kin_spos = {s.get_name(): s.get_commanded_position() | ||||||
|                     for s in kin.get_steppers()} |                     for s in kin.get_steppers()} | ||||||
|         start_mcu_pos = [(s, name, s.get_mcu_position()) |         self.stepper_positions = [ StepperPosition(s, name) | ||||||
|                                    for es, name in self.endstops |                                    for es, name in self.endstops | ||||||
|                                    for s in es.get_steppers() ] |                                    for s in es.get_steppers() ] | ||||||
|         # Start endstop checking |         # Start endstop checking | ||||||
| @@ -74,24 +94,39 @@ class HomingMove: | |||||||
|         except self.printer.command_error as e: |         except self.printer.command_error as e: | ||||||
|             error = "Error during homing move: %s" % (str(e),) |             error = "Error during homing move: %s" % (str(e),) | ||||||
|         # Wait for endstops to trigger |         # Wait for endstops to trigger | ||||||
|  |         trigger_times = {} | ||||||
|         move_end_print_time = self.toolhead.get_last_move_time() |         move_end_print_time = self.toolhead.get_last_move_time() | ||||||
|         for mcu_endstop, name in self.endstops: |         for mcu_endstop, name in self.endstops: | ||||||
|             trigger_time = mcu_endstop.home_wait(move_end_print_time) |             trigger_time = mcu_endstop.home_wait(move_end_print_time) | ||||||
|             if trigger_time < 0. and error is None: |             if trigger_time > 0.: | ||||||
|  |                 trigger_times[name] = trigger_time | ||||||
|  |             elif trigger_time < 0. and error is None: | ||||||
|                 error = "Communication timeout during homing %s" % (name,) |                 error = "Communication timeout during homing %s" % (name,) | ||||||
|             elif not trigger_time and check_triggered and error is None: |             elif check_triggered and error is None: | ||||||
|                 error = "No trigger on %s after full movement" % (name,) |                 error = "No trigger on %s after full movement" % (name,) | ||||||
|         # Determine stepper halt positions |         # Determine stepper halt positions | ||||||
|         self.toolhead.flush_step_generation() |         self.toolhead.flush_step_generation() | ||||||
|         self.end_mcu_pos = [(s, name, spos, s.get_mcu_position()) |         for sp in self.stepper_positions: | ||||||
|                             for s, name, spos in start_mcu_pos] |             tt = trigger_times.get(sp.endstop_name, move_end_print_time) | ||||||
|  |             sp.note_home_end(tt) | ||||||
|         if probe_pos: |         if probe_pos: | ||||||
|             for s, name, spos, epos in self.end_mcu_pos: |             halt_steps = {sp.stepper_name: sp.halt_pos - sp.start_pos | ||||||
|                 sname = s.get_name() |                           for sp in self.stepper_positions} | ||||||
|                 if sname in kin_spos: |             trig_steps = {sp.stepper_name: sp.trig_pos - sp.start_pos | ||||||
|                     kin_spos[sname] += (epos - spos) * s.get_step_dist() |                           for sp in self.stepper_positions} | ||||||
|             movepos = list(kin.calc_position(kin_spos))[:3] + movepos[3:] |             haltpos = trigpos = self.calc_toolhead_pos(kin_spos, trig_steps) | ||||||
|  |             if trig_steps != halt_steps: | ||||||
|  |                 haltpos = self.calc_toolhead_pos(kin_spos, halt_steps) | ||||||
|  |         else: | ||||||
|  |             haltpos = trigpos = movepos | ||||||
|  |             over_steps = {sp.stepper_name: sp.halt_pos - sp.trig_pos | ||||||
|  |                           for sp in self.stepper_positions} | ||||||
|  |             if any(over_steps.values()): | ||||||
|                 self.toolhead.set_position(movepos) |                 self.toolhead.set_position(movepos) | ||||||
|  |                 halt_kin_spos = {s.get_name(): s.get_commanded_position() | ||||||
|  |                                  for s in kin.get_steppers()} | ||||||
|  |                 haltpos = self.calc_toolhead_pos(halt_kin_spos, over_steps) | ||||||
|  |         self.toolhead.set_position(haltpos) | ||||||
|         # Signal homing/probing move complete |         # Signal homing/probing move complete | ||||||
|         try: |         try: | ||||||
|             self.printer.send_event("homing:homing_move_end", self) |             self.printer.send_event("homing:homing_move_end", self) | ||||||
| @@ -100,13 +135,13 @@ class HomingMove: | |||||||
|                 error = str(e) |                 error = str(e) | ||||||
|         if error is not None: |         if error is not None: | ||||||
|             raise self.printer.command_error(error) |             raise self.printer.command_error(error) | ||||||
|         return movepos |         return trigpos | ||||||
|     def check_no_movement(self): |     def check_no_movement(self): | ||||||
|         if self.printer.get_start_args().get('debuginput') is not None: |         if self.printer.get_start_args().get('debuginput') is not None: | ||||||
|             return None |             return None | ||||||
|         for s, name, spos, epos in self.end_mcu_pos: |         for sp in self.stepper_positions: | ||||||
|             if spos == epos: |             if sp.start_pos == sp.trig_pos: | ||||||
|                 return name |                 return sp.endstop_name | ||||||
|         return None |         return None | ||||||
|  |  | ||||||
| # State tracking of homing requests | # State tracking of homing requests | ||||||
|   | |||||||
| @@ -117,7 +117,8 @@ class MCU_stepper: | |||||||
|     def get_past_mcu_position(self, print_time): |     def get_past_mcu_position(self, print_time): | ||||||
|         clock = self._mcu.print_time_to_clock(print_time) |         clock = self._mcu.print_time_to_clock(print_time) | ||||||
|         ffi_main, ffi_lib = chelper.get_ffi() |         ffi_main, ffi_lib = chelper.get_ffi() | ||||||
|         return ffi_lib.stepcompress_find_past_position(self._stepqueue, clock) |         pos = ffi_lib.stepcompress_find_past_position(self._stepqueue, clock) | ||||||
|  |         return int(pos) | ||||||
|     def get_past_commanded_position(self, print_time): |     def get_past_commanded_position(self, print_time): | ||||||
|         mcu_pos = self.get_past_mcu_position(print_time) |         mcu_pos = self.get_past_mcu_position(print_time) | ||||||
|         return mcu_pos * self._step_dist - self._mcu_position_offset |         return mcu_pos * self._step_dist - self._mcu_position_offset | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user