Skip to content

Commit

Permalink
Merge branch 'main' into show_macros_in_webui
Browse files Browse the repository at this point in the history
  • Loading branch information
Anonoei authored Dec 5, 2024
2 parents b3fb0fc + 9ad85f0 commit 8d28347
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 12 deletions.
196 changes: 184 additions & 12 deletions autospeed/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def __init__(self, config):
self.accel_min = config.getfloat('accel_min', default=1000.0, above=1.0)
self.accel_max = config.getfloat('accel_max', default=100000.0, above=self.accel_min)
self.accel_accu = config.getfloat('accel_accu', default=0.05, above=0.0, below=1.0)
self.scv = config.getfloat('scv', default=5, above=1.0, below=50)

self.veloc_min = config.getfloat('velocity_min', default=50.0, above=1.0)
self.veloc_max = config.getfloat('velocity_max', default=5000.0, above=self.veloc_min)
Expand All @@ -58,7 +59,7 @@ def __init__(self, config):
):
if os.path.exists(path):
results_default = path
self.results_dir = config.get('results_dir',default=results_default)
self.results_dir = os.path.expanduser(config.get('results_dir',default=results_default))

self.toolhead = None
self.printer.register_event_handler("klippy:connect", self.handle_connect)
Expand All @@ -70,6 +71,9 @@ def __init__(self, config):
('AUTO_SPEED_ACCEL', self.cmd_AUTO_SPEED_ACCEL, self.cmd_AUTO_SPEED_ACCEL_help),
('AUTO_SPEED_VALIDATE', self.cmd_AUTO_SPEED_VALIDATE, self.cmd_AUTO_SPEED_VALIDATE_help),
('AUTO_SPEED_GRAPH', self.cmd_AUTO_SPEED_GRAPH, self.cmd_AUTO_SPEED_GRAPH_help),
('X_ENDSTOP_ACCURACY', self.cmd_X_ENDSTOP_ACCURACY, self.cmd_AUTO_SPEED_GRAPH_help),
('Y_ENDSTOP_ACCURACY', self.cmd_Y_ENDSTOP_ACCURACY, self.cmd_AUTO_SPEED_GRAPH_help),
('Z_ENDSTOP_ACCURACY', self.cmd_Z_ENDSTOP_ACCURACY, self.cmd_AUTO_SPEED_GRAPH_help)
]
command_descriptions = {name: desc for name, _, desc in measurement_commands}
gcode = self.printer.lookup_object('gcode')
Expand Down Expand Up @@ -117,6 +121,7 @@ def handle_connect(self):
# Reduce speed/acceleration for positioning movement
self.th_accel = self.toolhead.max_accel/2
self.th_veloc = self.toolhead.max_velocity/2
self.th_scv = self.toolhead.square_corner_velocity

# Find and define leveling method
if self.printer.lookup_object("screw_tilt_adjust", None) is not None:
Expand All @@ -140,8 +145,9 @@ def handle_home_rails_end(self, homing_state, rails):
if name in ["stepper_x", "stepper_y", "stepper_z"]:
config = self.printer.lookup_object('configfile').status_raw_config[name]
microsteps = int(config["microsteps"])
self.steppers[name[-1]] = [pos_min, pos_max, microsteps]

homing_retract_dist = float (config["homing_retract_dist"])
second_homing_speed = float(config["second_homing_speed"])
self.steppers[name[-1]] = [pos_min, pos_max, microsteps, homing_retract_dist, second_homing_speed]

if self.steppers.get("x", None) is not None:
self.axis_limits["x"] = {
Expand Down Expand Up @@ -221,6 +227,7 @@ def cmd_AUTO_SPEED_ACCEL(self, gcmd):
accel_accu = gcmd.get_float('ACCEL_ACCU', self.accel_accu, above=0.0, below=1.0)

veloc = gcmd.get_float('VELOCITY', 1.0, above=1.0)
scv = gcmd.get_float('SCV', self.scv, above=1.0)

respond = "AUTO SPEED finding maximum acceleration on"
for axis in axes:
Expand All @@ -239,6 +246,7 @@ def cmd_AUTO_SPEED_ACCEL(self, gcmd):
aw.min = accel_min
aw.max = accel_max
aw.veloc = veloc
aw.scv = scv
self.init_axis(aw, axis)
rw.vals[aw.axis] = self.binary_search(aw)
rw.duration = perf_counter() - start
Expand Down Expand Up @@ -275,6 +283,7 @@ def cmd_AUTO_SPEED_VELOCITY(self, gcmd):
veloc_accu = gcmd.get_float('VELOCITY_ACCU', self.veloc_accu, above=0.0, below=1.0)

accel = gcmd.get_float('ACCEL', 1.0, above=1.0)
scv = gcmd.get_float('SCV', self.scv, above=1.0)

respond = "AUTO SPEED finding maximum velocity on"
for axis in axes:
Expand All @@ -293,6 +302,7 @@ def cmd_AUTO_SPEED_VELOCITY(self, gcmd):
aw.min = veloc_min
aw.max = veloc_max
aw.accel = accel
aw.scv = scv
self.init_axis(aw, axis)
rw.vals[aw.axis] = self.binary_search(aw)
rw.duration = perf_counter() - start
Expand Down Expand Up @@ -326,12 +336,14 @@ def cmd_AUTO_SPEED_VALIDATE(self, gcmd):

accel = gcmd.get_float('ACCEL', default=self.toolhead.max_accel, above=0.0)
veloc = gcmd.get_float('VELOCITY', default=self.toolhead.max_velocity, above=0.0)

scv = gcmd.get_float('SCV', default=self.toolhead.square_corner_velocity, above=1.0)

respond = f"AUTO SPEED validating over {iterations} iterations\n"
respond += f"Acceleration: {accel:.0f}\n"
respond += f"Velocity: {veloc:.0f}"
respond += f"Velocity: {veloc:.0f}\n"
respond += f"SCV: {scv:.0f}"
self.gcode.respond_info(respond)
self._set_velocity(veloc, accel)
self._set_velocity(veloc, accel, scv)
valid, duration, missed_x, missed_y = self._validate(veloc, iterations, margin, small_margin, max_missed)

respond = f"AUTO SPEED validated results after {duration:.2f}s\n"
Expand Down Expand Up @@ -598,10 +610,10 @@ def binary_search(self, aw: AttemptWrapper):
def _attempt(self, aw: AttemptWrapper):
timeAttempt = perf_counter()

self._set_velocity(self.th_veloc, self.th_accel)
self._set_velocity(self.th_veloc, self.th_accel, self.th_scv)
self._move([aw.move.pos["x"][0], aw.move.pos["y"][0], aw.move.pos["z"][0]], self.th_veloc)
self.toolhead.wait_moves()
self._set_velocity(aw.veloc, aw.accel)
self._set_velocity(aw.veloc, aw.accel, aw.scv)
timeMove = perf_counter()

self._move([aw.move.pos["x"][1], aw.move.pos["y"][1], aw.move.pos["z"][1]], aw.veloc)
Expand Down Expand Up @@ -715,7 +727,8 @@ def _move(self, coord, speed):
def _home(self, x=True, y=True, z=True):
prevAccel = self.toolhead.max_accel
prevVeloc = self.toolhead.max_velocity
self._set_velocity(self.th_veloc, self.th_accel)
prevScv = self.toolhead.square_corner_velocity
self._set_velocity(self.th_veloc, self.th_accel, self.th_scv)
command = ["G28"]
if x:
command[-1] += " X0"
Expand All @@ -725,7 +738,7 @@ def _home(self, x=True, y=True, z=True):
command[-1] += " Z0"
self.gcode._process_commands(command, False)
self.toolhead.wait_moves()
self._set_velocity(prevVeloc, prevAccel)
self._set_velocity(prevVeloc, prevAccel, prevScv)

def _get_steps(self):
kin = self.toolhead.get_kinematics()
Expand Down Expand Up @@ -776,9 +789,168 @@ def _posttest(self, start_steps, max_missed, home: list):

return valid, stop_steps, missed, dur

def _set_velocity(self, velocity: float, accel: float):
def _set_velocity(self, velocity: float, accel: float, scv: float):
#self.gcode.respond_info(f"AUTO SPEED setting limits to VELOCITY={velocity} ACCEL={accel}")
self.toolhead.max_velocity = velocity
self.toolhead.max_accel = accel
self.toolhead.requested_accel_to_decel = accel/2

self.toolhead.requested_accel_to_decel = accel
self.toolhead.square_corner_velocity = scv
self.toolhead._calc_junction_deviation()

def cmd_X_ENDSTOP_ACCURACY(self, gcmd):

if not len(self.steppers.keys()) == 3:
raise gcmd.error(f"Printer must be homed first! Found {len(self.steppers.keys())} homed axes.")

# Number of samples for accuracy check
sample_count = gcmd.get_int("SAMPLES", 10, minval=1)

# Retrieve homing parameters for the X axis from the previously stored values
second_homing_speed = self.steppers['x'][4]
homing_retract_dist = self.steppers['x'][3]

# Toolhead object to control the movement
toolhead = self.printer.lookup_object('toolhead')
pos = toolhead.get_position()

# Log the starting position for X
gcmd.respond_info("X_ENDSTOP_ACCURACY at X:%.3f (samples=%d)\n" % (pos[0], sample_count))
gcmd.respond_info("Second Homing Speed: %.2f mm/s" % second_homing_speed)
gcmd.respond_info("Homing Retract Distance: %.2f mm" % homing_retract_dist)


# Create a dummy gcode command for a single sample
fo_params = dict(gcmd.get_command_parameters())
fo_params['SAMPLES'] = '1'
gcode = self.printer.lookup_object('gcode')
fo_gcmd = gcode.create_gcode_command("", "", fo_params)

# List to store the X positions hit during each sample
positions = []

# Move to the X endstop sample_count times and collect the X positions
for _ in range(sample_count):
self._home(True, False, False)
pos = toolhead.get_position() # Get the current X position after homing
positions.append(pos[0])
toolhead.manual_move([pos[0] - homing_retract_dist, None, None], speed=second_homing_speed) # Move away from the endstop

# Calculate the maximum, minimum, average, and standard deviation for X positions
max_value = max(positions)
min_value = min(positions)
avg_value = sum(positions) / len(positions)
range_value = max_value - min_value

deviation_sum = sum([(x - avg_value) ** 2 for x in positions])
sigma = (deviation_sum / len(positions)) ** 0.5

# Display results
gcmd.respond_info(
"X endstop accuracy results: maximum %.6f, minimum %.6f, range %.6f, "
"average %.6f, standard deviation %.6f" % (max_value, min_value, range_value, avg_value, sigma))


def cmd_Y_ENDSTOP_ACCURACY(self, gcmd):

if not len(self.steppers.keys()) == 3:
raise gcmd.error(f"Printer must be homed first! Found {len(self.steppers.keys())} homed axes.")

# Number of samples for accuracy check
sample_count = gcmd.get_int("SAMPLES", 10, minval=1)

# Retrieve homing parameters for the Y axis from the previously stored values
second_homing_speed = self.steppers['y'][4]
homing_retract_dist = self.steppers['y'][3]

# Toolhead object to control the movement
toolhead = self.printer.lookup_object('toolhead')
pos = toolhead.get_position()

# Log the starting position for Y
gcmd.respond_info("Y_ENDSTOP_ACCURACY at Y:%.3f (samples=%d)\n" % (pos[1], sample_count))
gcmd.respond_info("Second Homing Speed: %.2f mm/s" % second_homing_speed)
gcmd.respond_info("Homing Retract Distance: %.2f mm" % homing_retract_dist)


# Create a dummy gcode command for a single sample
fo_params = dict(gcmd.get_command_parameters())
fo_params['SAMPLES'] = '1'
gcode = self.printer.lookup_object('gcode')
fo_gcmd = gcode.create_gcode_command("", "", fo_params)

# List to store the Y positions hit during each sample
positions = []

# Move to the Y endstop sample_count times and collect the Y positions
for _ in range(sample_count):
self._home(False, True, False)
pos = toolhead.get_position() # Get the current Y position after homing
positions.append(pos[1])
toolhead.manual_move([None, pos[1] - homing_retract_dist, None], speed=second_homing_speed) # Move away from the endstop

# Calculate the maximum, minimum, average, and standard deviation for Y positions
max_value = max(positions)
min_value = min(positions)
avg_value = sum(positions) / len(positions)
range_value = max_value - min_value

deviation_sum = sum([(y - avg_value) ** 2 for y in positions])
sigma = (deviation_sum / len(positions)) ** 0.5

# Display results
gcmd.respond_info(
"Y endstop accuracy results: maximum %.6f, minimum %.6f, range %.6f, "
"average %.6f, standard deviation %.6f" % (max_value, min_value, range_value, avg_value, sigma))

def cmd_Z_ENDSTOP_ACCURACY(self, gcmd):

if not len(self.steppers.keys()) == 3:
raise gcmd.error(f"Printer must be homed first! Found {len(self.steppers.keys())} homed axes.")

# Number of samples for accuracy check
sample_count = gcmd.get_int("SAMPLES", 10, minval=1)

# Retrieve homing parameters for the Z axis from the previously stored values
second_homing_speed = self.steppers['z'][4]
homing_retract_dist = self.steppers['z'][3]

# Toolhead object to control the movement
toolhead = self.printer.lookup_object('toolhead')
pos = toolhead.get_position()

# Log the starting position for Z
gcmd.respond_info("Z_ENDSTOP_ACCURACY at Z:%.3f (samples=%d)\n" % (pos[2], sample_count))
gcmd.respond_info("Second Homing Speed: %.2f mm/s" % second_homing_speed)
gcmd.respond_info("Homing Retract Distance: %.2f mm" % homing_retract_dist)


# Create a dummy gcode command for a single sample
fo_params = dict(gcmd.get_command_parameters())
fo_params['SAMPLES'] = '1'
gcode = self.printer.lookup_object('gcode')
fo_gcmd = gcode.create_gcode_command("", "", fo_params)

# List to store the Z positions hit during each sample
positions = []

# Move to the Z endstop sample_count times and collect the Z positions
for _ in range(sample_count):
self._home(False, False, True)
pos = toolhead.get_position() # Get the current Z position after homing
positions.append(pos[2])
toolhead.manual_move([None, None, pos[2] + homing_retract_dist], speed=second_homing_speed) # Move away from the endstop

# Calculate the maximum, minimum, average, and standard deviation for Z positions
max_value = max(positions)
min_value = min(positions)
avg_value = sum(positions) / len(positions)
range_value = max_value - min_value

deviation_sum = sum([(z - avg_value) ** 2 for z in positions])
sigma = (deviation_sum / len(positions)) ** 0.5

# Display results
gcmd.respond_info(
"Z endstop accuracy results: maximum %.6f, minimum %.6f, range %.6f, "
"average %.6f, standard deviation %.6f" % (max_value, min_value, range_value, avg_value, sigma))
3 changes: 3 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ else
exit -1
fi

# Check for old python
~/klippy-env/bin/python -c 'import sys; assert sys.version_info[0] == 3, "Python 3 is required."'

# Link auto speed to klipper
echo "Linking auto speed to Klipper..."
ln -sf "${SRCDIR}/auto_speed.py" "${KLIPPER_PATH}/klippy/extras/auto_speed.py"
Expand Down

0 comments on commit 8d28347

Please sign in to comment.