| 
									
										
										
										
											2018-07-26 11:15:51 -04:00
										 |  |  | # Utility for manually moving a stepper for diagnostic purposes | 
					
						
							| 
									
										
										
										
											2018-06-14 12:01:22 -04:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											2019-10-29 11:49:13 -04:00
										 |  |  | # Copyright (C) 2018-2019  Kevin O'Connor <kevin@koconnor.net> | 
					
						
							| 
									
										
										
										
											2018-06-14 12:01:22 -04:00
										 |  |  | # | 
					
						
							|  |  |  | # This file may be distributed under the terms of the GNU GPLv3 license. | 
					
						
							| 
									
										
										
										
											2019-03-03 13:23:45 -05:00
										 |  |  | import math, logging | 
					
						
							| 
									
										
										
										
											2018-06-14 13:44:01 -04:00
										 |  |  | import chelper | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-04 18:42:59 -05:00
										 |  |  | BUZZ_DISTANCE = 1. | 
					
						
							|  |  |  | BUZZ_VELOCITY = BUZZ_DISTANCE / .250 | 
					
						
							|  |  |  | BUZZ_RADIANS_DISTANCE = math.radians(1.) | 
					
						
							|  |  |  | BUZZ_RADIANS_VELOCITY = BUZZ_RADIANS_DISTANCE / .250 | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  | STALL_TIME = 0.100 | 
					
						
							| 
									
										
										
										
											2018-06-14 12:01:22 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-03 13:23:45 -05:00
										 |  |  | # Calculate a move's accel_t, cruise_t, and cruise_v | 
					
						
							|  |  |  | def calc_move_time(dist, speed, accel): | 
					
						
							| 
									
										
										
										
											2019-11-06 08:41:50 -05:00
										 |  |  |     axis_r = 1. | 
					
						
							|  |  |  |     if dist < 0.: | 
					
						
							|  |  |  |         axis_r = -1. | 
					
						
							|  |  |  |         dist = -dist | 
					
						
							| 
									
										
										
										
											2019-03-31 09:00:23 -04:00
										 |  |  |     if not accel or not dist: | 
					
						
							| 
									
										
										
										
											2019-11-06 08:41:50 -05:00
										 |  |  |         return axis_r, 0., dist / speed, speed | 
					
						
							| 
									
										
										
										
											2019-03-03 13:23:45 -05:00
										 |  |  |     max_cruise_v2 = dist * accel | 
					
						
							|  |  |  |     if max_cruise_v2 < speed**2: | 
					
						
							|  |  |  |         speed = math.sqrt(max_cruise_v2) | 
					
						
							|  |  |  |     accel_t = speed / accel | 
					
						
							|  |  |  |     accel_decel_d = accel_t * speed | 
					
						
							|  |  |  |     cruise_t = (dist - accel_decel_d) / speed | 
					
						
							| 
									
										
										
										
											2019-11-06 08:41:50 -05:00
										 |  |  |     return axis_r, accel_t, cruise_t, speed | 
					
						
							| 
									
										
										
										
											2019-03-03 13:23:45 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-26 11:15:51 -04:00
										 |  |  | class ForceMove: | 
					
						
							| 
									
										
										
										
											2018-06-14 12:01:22 -04:00
										 |  |  |     def __init__(self, config): | 
					
						
							|  |  |  |         self.printer = config.get_printer() | 
					
						
							|  |  |  |         self.steppers = {} | 
					
						
							| 
									
										
										
										
											2018-06-14 13:44:01 -04:00
										 |  |  |         # Setup iterative solver | 
					
						
							|  |  |  |         ffi_main, ffi_lib = chelper.get_ffi() | 
					
						
							| 
									
										
										
										
											2019-10-29 11:49:13 -04:00
										 |  |  |         self.trapq = ffi_main.gc(ffi_lib.trapq_alloc(), ffi_lib.trapq_free) | 
					
						
							| 
									
										
										
										
											2019-10-29 12:44:39 -04:00
										 |  |  |         self.trapq_append = ffi_lib.trapq_append | 
					
						
							| 
									
										
										
										
											2019-10-29 11:49:13 -04:00
										 |  |  |         self.trapq_free_moves = ffi_lib.trapq_free_moves | 
					
						
							| 
									
										
										
										
											2018-06-14 13:44:01 -04:00
										 |  |  |         self.stepper_kinematics = ffi_main.gc( | 
					
						
							|  |  |  |             ffi_lib.cartesian_stepper_alloc('x'), ffi_lib.free) | 
					
						
							| 
									
										
										
										
											2018-07-26 12:12:07 -04:00
										 |  |  |         # Register commands | 
					
						
							| 
									
										
										
										
											2020-04-24 22:06:26 -04:00
										 |  |  |         gcode = self.printer.lookup_object('gcode') | 
					
						
							|  |  |  |         gcode.register_command('STEPPER_BUZZ', self.cmd_STEPPER_BUZZ, | 
					
						
							|  |  |  |                                desc=self.cmd_STEPPER_BUZZ_help) | 
					
						
							| 
									
										
										
										
											2018-07-26 12:12:07 -04:00
										 |  |  |         if config.getboolean("enable_force_move", False): | 
					
						
							| 
									
										
										
										
											2020-04-24 22:06:26 -04:00
										 |  |  |             gcode.register_command('FORCE_MOVE', self.cmd_FORCE_MOVE, | 
					
						
							|  |  |  |                                    desc=self.cmd_FORCE_MOVE_help) | 
					
						
							|  |  |  |             gcode.register_command('SET_KINEMATIC_POSITION', | 
					
						
							|  |  |  |                                    self.cmd_SET_KINEMATIC_POSITION, | 
					
						
							|  |  |  |                                    desc=self.cmd_SET_KINEMATIC_POSITION_help) | 
					
						
							| 
									
										
										
										
											2018-07-26 11:15:51 -04:00
										 |  |  |     def register_stepper(self, stepper): | 
					
						
							|  |  |  |         name = stepper.get_name() | 
					
						
							|  |  |  |         self.steppers[name] = stepper | 
					
						
							| 
									
										
										
										
											2020-01-05 18:07:51 -05:00
										 |  |  |     def lookup_stepper(self, name): | 
					
						
							|  |  |  |         if name not in self.steppers: | 
					
						
							|  |  |  |             raise self.printer.config_error("Unknown stepper %s" % (name,)) | 
					
						
							|  |  |  |         return self.steppers[name] | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |     def force_enable(self, stepper): | 
					
						
							|  |  |  |         toolhead = self.printer.lookup_object('toolhead') | 
					
						
							|  |  |  |         print_time = toolhead.get_last_move_time() | 
					
						
							| 
									
										
										
										
											2019-11-12 12:49:21 -05:00
										 |  |  |         stepper_enable = self.printer.lookup_object('stepper_enable') | 
					
						
							| 
									
										
										
										
											2019-11-12 13:55:50 -05:00
										 |  |  |         enable = stepper_enable.lookup_enable(stepper.get_name()) | 
					
						
							|  |  |  |         was_enable = enable.is_motor_enabled() | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |         if not was_enable: | 
					
						
							| 
									
										
										
										
											2019-11-12 13:55:50 -05:00
										 |  |  |             enable.motor_enable(print_time) | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |             toolhead.dwell(STALL_TIME) | 
					
						
							| 
									
										
										
										
											2019-10-29 12:06:46 -04:00
										 |  |  |         return was_enable | 
					
						
							|  |  |  |     def restore_enable(self, stepper, was_enable): | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |         if not was_enable: | 
					
						
							|  |  |  |             toolhead = self.printer.lookup_object('toolhead') | 
					
						
							|  |  |  |             toolhead.dwell(STALL_TIME) | 
					
						
							|  |  |  |             print_time = toolhead.get_last_move_time() | 
					
						
							| 
									
										
										
										
											2019-11-12 12:49:21 -05:00
										 |  |  |             stepper_enable = self.printer.lookup_object('stepper_enable') | 
					
						
							| 
									
										
										
										
											2019-11-12 13:55:50 -05:00
										 |  |  |             enable = stepper_enable.lookup_enable(stepper.get_name()) | 
					
						
							|  |  |  |             enable.motor_disable(print_time) | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |             toolhead.dwell(STALL_TIME) | 
					
						
							| 
									
										
										
										
											2019-03-03 13:23:45 -05:00
										 |  |  |     def manual_move(self, stepper, dist, speed, accel=0.): | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |         toolhead = self.printer.lookup_object('toolhead') | 
					
						
							| 
									
										
										
										
											2019-11-13 23:34:21 -05:00
										 |  |  |         toolhead.flush_step_generation() | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |         prev_sk = stepper.set_stepper_kinematics(self.stepper_kinematics) | 
					
						
							| 
									
										
										
										
											2020-06-30 20:20:16 -04:00
										 |  |  |         prev_trapq = stepper.set_trapq(self.trapq) | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |         stepper.set_position((0., 0., 0.)) | 
					
						
							| 
									
										
										
										
											2019-11-06 08:41:50 -05:00
										 |  |  |         axis_r, accel_t, cruise_t, cruise_v = calc_move_time(dist, speed, accel) | 
					
						
							| 
									
										
										
										
											2019-11-13 23:34:21 -05:00
										 |  |  |         print_time = toolhead.get_last_move_time() | 
					
						
							| 
									
										
										
										
											2019-10-29 12:44:39 -04:00
										 |  |  |         self.trapq_append(self.trapq, print_time, accel_t, cruise_t, accel_t, | 
					
						
							| 
									
										
										
										
											2019-11-06 08:41:50 -05:00
										 |  |  |                           0., 0., 0., axis_r, 0., 0., 0., cruise_v, accel) | 
					
						
							| 
									
										
										
										
											2019-11-24 10:59:13 -05:00
										 |  |  |         print_time = print_time + accel_t + cruise_t + accel_t | 
					
						
							| 
									
										
										
										
											2019-10-29 11:49:13 -04:00
										 |  |  |         stepper.generate_steps(print_time) | 
					
						
							| 
									
										
										
										
											2019-11-24 10:59:13 -05:00
										 |  |  |         self.trapq_free_moves(self.trapq, print_time + 99999.9) | 
					
						
							| 
									
										
										
										
											2020-06-30 20:20:16 -04:00
										 |  |  |         stepper.set_trapq(prev_trapq) | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |         stepper.set_stepper_kinematics(prev_sk) | 
					
						
							| 
									
										
										
										
											2019-11-24 10:59:13 -05:00
										 |  |  |         toolhead.note_kinematic_activity(print_time) | 
					
						
							| 
									
										
										
										
											2019-03-03 13:23:45 -05:00
										 |  |  |         toolhead.dwell(accel_t + cruise_t + accel_t) | 
					
						
							| 
									
										
										
										
											2020-04-24 22:06:26 -04:00
										 |  |  |     def _lookup_stepper(self, gcmd): | 
					
						
							|  |  |  |         name = gcmd.get('STEPPER') | 
					
						
							| 
									
										
										
										
											2018-07-26 11:15:51 -04:00
										 |  |  |         if name not in self.steppers: | 
					
						
							| 
									
										
										
										
											2020-04-24 22:06:26 -04:00
										 |  |  |             raise gcmd.error("Unknown stepper %s" % (name,)) | 
					
						
							| 
									
										
										
										
											2018-07-26 12:12:07 -04:00
										 |  |  |         return self.steppers[name] | 
					
						
							|  |  |  |     cmd_STEPPER_BUZZ_help = "Oscillate a given stepper to help id it" | 
					
						
							| 
									
										
										
										
											2020-04-24 22:06:26 -04:00
										 |  |  |     def cmd_STEPPER_BUZZ(self, gcmd): | 
					
						
							|  |  |  |         stepper = self._lookup_stepper(gcmd) | 
					
						
							| 
									
										
										
										
											2018-07-26 12:12:07 -04:00
										 |  |  |         logging.info("Stepper buzz %s", stepper.get_name()) | 
					
						
							| 
									
										
										
										
											2019-10-29 12:06:46 -04:00
										 |  |  |         was_enable = self.force_enable(stepper) | 
					
						
							| 
									
										
										
										
											2018-06-14 12:01:22 -04:00
										 |  |  |         toolhead = self.printer.lookup_object('toolhead') | 
					
						
							| 
									
										
										
										
											2019-12-04 18:42:59 -05:00
										 |  |  |         dist, speed = BUZZ_DISTANCE, BUZZ_VELOCITY | 
					
						
							|  |  |  |         if stepper.units_in_radians(): | 
					
						
							|  |  |  |             dist, speed = BUZZ_RADIANS_DISTANCE, BUZZ_RADIANS_VELOCITY | 
					
						
							| 
									
										
										
										
											2018-06-14 12:01:22 -04:00
										 |  |  |         for i in range(10): | 
					
						
							| 
									
										
										
										
											2019-12-04 18:42:59 -05:00
										 |  |  |             self.manual_move(stepper, dist, speed) | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |             toolhead.dwell(.050) | 
					
						
							| 
									
										
										
										
											2019-12-04 18:42:59 -05:00
										 |  |  |             self.manual_move(stepper, -dist, speed) | 
					
						
							| 
									
										
										
										
											2018-07-26 11:39:57 -04:00
										 |  |  |             toolhead.dwell(.450) | 
					
						
							| 
									
										
										
										
											2019-10-29 12:06:46 -04:00
										 |  |  |         self.restore_enable(stepper, was_enable) | 
					
						
							| 
									
										
										
										
											2018-07-26 12:12:07 -04:00
										 |  |  |     cmd_FORCE_MOVE_help = "Manually move a stepper; invalidates kinematics" | 
					
						
							| 
									
										
										
										
											2020-04-24 22:06:26 -04:00
										 |  |  |     def cmd_FORCE_MOVE(self, gcmd): | 
					
						
							|  |  |  |         stepper = self._lookup_stepper(gcmd) | 
					
						
							|  |  |  |         distance = gcmd.get_float('DISTANCE') | 
					
						
							|  |  |  |         speed = gcmd.get_float('VELOCITY', above=0.) | 
					
						
							|  |  |  |         accel = gcmd.get_float('ACCEL', 0., minval=0.) | 
					
						
							| 
									
										
										
										
											2019-03-03 13:23:45 -05:00
										 |  |  |         logging.info("FORCE_MOVE %s distance=%.3f velocity=%.3f accel=%.3f", | 
					
						
							|  |  |  |                      stepper.get_name(), distance, speed, accel) | 
					
						
							| 
									
										
										
										
											2019-10-29 12:06:46 -04:00
										 |  |  |         self.force_enable(stepper) | 
					
						
							| 
									
										
										
										
											2019-03-03 13:23:45 -05:00
										 |  |  |         self.manual_move(stepper, distance, speed, accel) | 
					
						
							| 
									
										
										
										
											2018-07-26 12:12:07 -04:00
										 |  |  |     cmd_SET_KINEMATIC_POSITION_help = "Force a low-level kinematic position" | 
					
						
							| 
									
										
										
										
											2020-04-24 22:06:26 -04:00
										 |  |  |     def cmd_SET_KINEMATIC_POSITION(self, gcmd): | 
					
						
							| 
									
										
										
										
											2018-07-26 12:12:07 -04:00
										 |  |  |         toolhead = self.printer.lookup_object('toolhead') | 
					
						
							|  |  |  |         toolhead.get_last_move_time() | 
					
						
							|  |  |  |         curpos = toolhead.get_position() | 
					
						
							| 
									
										
										
										
											2020-04-24 22:06:26 -04:00
										 |  |  |         x = gcmd.get_float('X', curpos[0]) | 
					
						
							|  |  |  |         y = gcmd.get_float('Y', curpos[1]) | 
					
						
							|  |  |  |         z = gcmd.get_float('Z', curpos[2]) | 
					
						
							| 
									
										
										
										
											2018-08-01 15:40:35 -04:00
										 |  |  |         logging.info("SET_KINEMATIC_POSITION pos=%.3f,%.3f,%.3f", x, y, z) | 
					
						
							| 
									
										
										
										
											2018-07-26 12:12:07 -04:00
										 |  |  |         toolhead.set_position([x, y, z, curpos[3]], homing_axes=(0, 1, 2)) | 
					
						
							| 
									
										
										
										
											2018-06-14 12:01:22 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | def load_config(config): | 
					
						
							| 
									
										
										
										
											2018-07-26 11:15:51 -04:00
										 |  |  |     return ForceMove(config) |