fixed most of the bugs now as a Klipper plugin
This commit is contained in:
@@ -14,6 +14,14 @@ from scipy.signal import spectrogram
|
|||||||
|
|
||||||
from .console_output import ConsoleOutput
|
from .console_output import ConsoleOutput
|
||||||
|
|
||||||
|
# Constant used to define the standard axis direction and names
|
||||||
|
AXIS_CONFIG = [
|
||||||
|
{'axis': 'x', 'direction': (1, 0, 0), 'label': 'axis_X'},
|
||||||
|
{'axis': 'y', 'direction': (0, 1, 0), 'label': 'axis_Y'},
|
||||||
|
{'axis': 'a', 'direction': (1, -1, 0), 'label': 'belt_A'},
|
||||||
|
{'axis': 'b', 'direction': (1, 1, 0), 'label': 'belt_B'},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def parse_log(logname):
|
def parse_log(logname):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -5,20 +5,3 @@ from .axes_map import axes_map_calibration as axes_map_calibration
|
|||||||
from .belts_comparison import compare_belts_responses as compare_belts_responses
|
from .belts_comparison import compare_belts_responses as compare_belts_responses
|
||||||
from .static_freq import excitate_axis_at_freq as excitate_axis_at_freq
|
from .static_freq import excitate_axis_at_freq as excitate_axis_at_freq
|
||||||
from .vibrations_profile import create_vibrations_profile as create_vibrations_profile
|
from .vibrations_profile import create_vibrations_profile as create_vibrations_profile
|
||||||
|
|
||||||
AXIS_CONFIG = [
|
|
||||||
{'axis': 'x', 'direction': (1, 0, 0), 'label': 'axis_X'},
|
|
||||||
{'axis': 'y', 'direction': (0, 1, 0), 'label': 'axis_Y'},
|
|
||||||
{'axis': 'a', 'direction': (1, -1, 0), 'label': 'belt_A'},
|
|
||||||
{'axis': 'b', 'direction': (1, 1, 0), 'label': 'belt_B'},
|
|
||||||
]
|
|
||||||
|
|
||||||
# graph_creators = {
|
|
||||||
# 'axesmap': (AxesMapFinder, lambda gc: gc.configure(options.accel_used, options.chip_name)),
|
|
||||||
# 'belts': (BeltsGraphCreator, None),
|
|
||||||
# 'shaper': (ShaperGraphCreator, lambda gc: gc.configure(options.scv, options.max_smoothing)),
|
|
||||||
# 'vibrations': (
|
|
||||||
# VibrationsGraphCreator,
|
|
||||||
# lambda gc: gc.configure(options.kinematics, options.accel_used, options.chip_name, options.metadata),
|
|
||||||
# ),
|
|
||||||
# }
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
|
||||||
|
from ..helpers.common_func import AXIS_CONFIG
|
||||||
from ..helpers.console_output import ConsoleOutput
|
from ..helpers.console_output import ConsoleOutput
|
||||||
from ..shaketune_thread import ShakeTuneThread
|
from ..shaketune_thread import ShakeTuneThread
|
||||||
from . import AXIS_CONFIG
|
|
||||||
from .accelerometer import Accelerometer
|
from .accelerometer import Accelerometer
|
||||||
from .resonance_test import vibrate_axis
|
from .resonance_test import vibrate_axis
|
||||||
|
|
||||||
|
|
||||||
def axes_shaper_calibration(gcmd, gcode, printer, st_thread: ShakeTuneThread) -> None:
|
def axes_shaper_calibration(gcmd, config, st_thread: ShakeTuneThread) -> None:
|
||||||
min_freq = gcmd.get_float('FREQ_START', default=5, minval=1)
|
min_freq = gcmd.get_float('FREQ_START', default=5, minval=1)
|
||||||
max_freq = gcmd.get_float('FREQ_END', default=133.33, minval=1)
|
max_freq = gcmd.get_float('FREQ_END', default=133.33, minval=1)
|
||||||
hz_per_sec = gcmd.get_float('HZ_PER_SEC', default=1, minval=1)
|
hz_per_sec = gcmd.get_float('HZ_PER_SEC', default=1, minval=1)
|
||||||
@@ -21,9 +21,11 @@ def axes_shaper_calibration(gcmd, gcode, printer, st_thread: ShakeTuneThread) ->
|
|||||||
feedrate_travel = gcmd.get_float('TRAVEL_SPEED', default=120.0, minval=20.0)
|
feedrate_travel = gcmd.get_float('TRAVEL_SPEED', default=120.0, minval=20.0)
|
||||||
z_height = gcmd.get_float('Z_HEIGHT', default=None, minval=1)
|
z_height = gcmd.get_float('Z_HEIGHT', default=None, minval=1)
|
||||||
|
|
||||||
systime = printer.get_reactor().monotonic()
|
printer = config.get_printer()
|
||||||
|
gcode = printer.lookup_object('gcode')
|
||||||
toolhead = printer.lookup_object('toolhead')
|
toolhead = printer.lookup_object('toolhead')
|
||||||
res_tester = printer.lookup_object('resonance_tester')
|
res_tester = printer.lookup_object('resonance_tester')
|
||||||
|
systime = printer.get_reactor().monotonic()
|
||||||
|
|
||||||
if scv is None:
|
if scv is None:
|
||||||
toolhead_info = toolhead.get_status(systime)
|
toolhead_info = toolhead.get_status(systime)
|
||||||
@@ -92,7 +94,7 @@ def axes_shaper_calibration(gcmd, gcode, printer, st_thread: ShakeTuneThread) ->
|
|||||||
accelerometer.stop_measurement(config['label'], append_time=True)
|
accelerometer.stop_measurement(config['label'], append_time=True)
|
||||||
|
|
||||||
# And finally generate the graph for each measured axis
|
# And finally generate the graph for each measured axis
|
||||||
ConsoleOutput.print(f'{config['axis'].upper()} axis frequency profile generation...')
|
ConsoleOutput.print(f'{config["axis"].upper()} axis frequency profile generation...')
|
||||||
ConsoleOutput.print('This may take some time (1-3min)')
|
ConsoleOutput.print('This may take some time (1-3min)')
|
||||||
st_thread.run()
|
st_thread.run()
|
||||||
|
|
||||||
|
|||||||
@@ -6,13 +6,18 @@ from ..shaketune_thread import ShakeTuneThread
|
|||||||
from .accelerometer import Accelerometer
|
from .accelerometer import Accelerometer
|
||||||
|
|
||||||
|
|
||||||
def axes_map_calibration(gcmd, gcode, printer, st_thread: ShakeTuneThread) -> None:
|
def axes_map_calibration(gcmd, config, st_thread: ShakeTuneThread) -> None:
|
||||||
z_height = gcmd.get_float('Z_HEIGHT', default=20.0)
|
z_height = gcmd.get_float('Z_HEIGHT', default=20.0)
|
||||||
speed = gcmd.get_float('SPEED', default=80.0, minval=20.0)
|
speed = gcmd.get_float('SPEED', default=80.0, minval=20.0)
|
||||||
accel = gcmd.get_int('ACCEL', default=1500, minval=100)
|
accel = gcmd.get_int('ACCEL', default=1500, minval=100)
|
||||||
feedrate_travel = gcmd.get_float('TRAVEL_SPEED', default=120.0, minval=20.0)
|
feedrate_travel = gcmd.get_float('TRAVEL_SPEED', default=120.0, minval=20.0)
|
||||||
accel_chip = gcmd.get('ACCEL_CHIP', default=None)
|
accel_chip = gcmd.get('ACCEL_CHIP', default=None)
|
||||||
|
|
||||||
|
printer = config.get_printer()
|
||||||
|
gcode = printer.lookup_object('gcode')
|
||||||
|
toolhead = printer.lookup_object('toolhead')
|
||||||
|
systime = printer.get_reactor().monotonic()
|
||||||
|
|
||||||
if accel_chip is None:
|
if accel_chip is None:
|
||||||
accel_chip = Accelerometer.find_axis_accelerometer(printer, 'xy')
|
accel_chip = Accelerometer.find_axis_accelerometer(printer, 'xy')
|
||||||
if accel_chip is None:
|
if accel_chip is None:
|
||||||
@@ -21,8 +26,6 @@ def axes_map_calibration(gcmd, gcode, printer, st_thread: ShakeTuneThread) -> No
|
|||||||
)
|
)
|
||||||
accelerometer = Accelerometer(printer.lookup_object(accel_chip))
|
accelerometer = Accelerometer(printer.lookup_object(accel_chip))
|
||||||
|
|
||||||
systime = printer.get_reactor().monotonic()
|
|
||||||
toolhead = printer.lookup_object('toolhead')
|
|
||||||
toolhead_info = toolhead.get_status(systime)
|
toolhead_info = toolhead.get_status(systime)
|
||||||
old_accel = toolhead_info['max_accel']
|
old_accel = toolhead_info['max_accel']
|
||||||
old_mcr = toolhead_info['minimum_cruise_ratio']
|
old_mcr = toolhead_info['minimum_cruise_ratio']
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
|
||||||
|
from ..helpers.common_func import AXIS_CONFIG
|
||||||
from ..helpers.console_output import ConsoleOutput
|
from ..helpers.console_output import ConsoleOutput
|
||||||
from ..shaketune_thread import ShakeTuneThread
|
from ..shaketune_thread import ShakeTuneThread
|
||||||
from . import AXIS_CONFIG
|
|
||||||
from .accelerometer import Accelerometer
|
from .accelerometer import Accelerometer
|
||||||
from .resonance_test import vibrate_axis
|
from .resonance_test import vibrate_axis
|
||||||
|
|
||||||
|
|
||||||
def compare_belts_responses(gcmd, gcode, printer, st_thread: ShakeTuneThread) -> None:
|
def compare_belts_responses(gcmd, config, st_thread: ShakeTuneThread) -> None:
|
||||||
min_freq = gcmd.get_float('FREQ_START', default=5.0, minval=1)
|
min_freq = gcmd.get_float('FREQ_START', default=5.0, minval=1)
|
||||||
max_freq = gcmd.get_float('FREQ_END', default=133.33, minval=1)
|
max_freq = gcmd.get_float('FREQ_END', default=133.33, minval=1)
|
||||||
hz_per_sec = gcmd.get_float('HZ_PER_SEC', default=1.0, minval=1)
|
hz_per_sec = gcmd.get_float('HZ_PER_SEC', default=1.0, minval=1)
|
||||||
@@ -16,9 +16,11 @@ def compare_belts_responses(gcmd, gcode, printer, st_thread: ShakeTuneThread) ->
|
|||||||
feedrate_travel = gcmd.get_float('TRAVEL_SPEED', default=120.0, minval=20.0)
|
feedrate_travel = gcmd.get_float('TRAVEL_SPEED', default=120.0, minval=20.0)
|
||||||
z_height = gcmd.get_float('Z_HEIGHT', default=None, minval=1)
|
z_height = gcmd.get_float('Z_HEIGHT', default=None, minval=1)
|
||||||
|
|
||||||
systime = printer.get_reactor().monotonic()
|
printer = config.get_printer()
|
||||||
|
gcode = printer.lookup_object('gcode')
|
||||||
toolhead = printer.lookup_object('toolhead')
|
toolhead = printer.lookup_object('toolhead')
|
||||||
res_tester = printer.lookup_object('resonance_tester')
|
res_tester = printer.lookup_object('resonance_tester')
|
||||||
|
systime = printer.get_reactor().monotonic()
|
||||||
|
|
||||||
accel_chip = Accelerometer.find_axis_accelerometer(printer, 'xy')
|
accel_chip = Accelerometer.find_axis_accelerometer(printer, 'xy')
|
||||||
if accel_chip is None:
|
if accel_chip is None:
|
||||||
@@ -68,7 +70,7 @@ def compare_belts_responses(gcmd, gcode, printer, st_thread: ShakeTuneThread) ->
|
|||||||
input_shaper = None
|
input_shaper = None
|
||||||
|
|
||||||
# Filter axis configurations to get the A and B axis only
|
# Filter axis configurations to get the A and B axis only
|
||||||
filtered_config = [a for a in AXIS_CONFIG if a['axis'] in ('x', 'y')]
|
filtered_config = [a for a in AXIS_CONFIG if a['axis'] in ('a', 'b')]
|
||||||
for config in filtered_config:
|
for config in filtered_config:
|
||||||
accelerometer.start_measurement()
|
accelerometer.start_measurement()
|
||||||
vibrate_axis(toolhead, gcode, config['direction'], min_freq, max_freq, hz_per_sec, accel_per_hz)
|
vibrate_axis(toolhead, gcode, config['direction'], min_freq, max_freq, hz_per_sec, accel_per_hz)
|
||||||
|
|||||||
8
shaketune/measurement/macros.cfg
Normal file
8
shaketune/measurement/macros.cfg
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
# [gcode_macro AXES_MAP_CALIBRATION]
|
||||||
|
# gcode:
|
||||||
|
# {% set z_height = params.Z_HEIGHT|default(20)|int %} # z height to put the toolhead before starting the movements
|
||||||
|
# {% set speed = params.SPEED|default(80)|float * 60 %} # feedrate for the movements
|
||||||
|
# {% set accel = params.ACCEL|default(1500)|int %} # accel value used to move on the pattern
|
||||||
|
# {% set feedrate_travel = params.TRAVEL_SPEED|default(120)|int * 60 %} # travel feedrate between moves
|
||||||
|
# {% set accel_chip = params.ACCEL_CHIP|default("adxl345") %} # ADXL chip name in the config
|
||||||
@@ -4,8 +4,7 @@
|
|||||||
# from the Klipper configuration and the TMC registers
|
# from the Klipper configuration and the TMC registers
|
||||||
# Written by Frix_x#0161 #
|
# Written by Frix_x#0161 #
|
||||||
|
|
||||||
import re
|
from typing import Any, Dict, List, Optional
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
|
||||||
|
|
||||||
TRINAMIC_DRIVERS = ['tmc2130', 'tmc2208', 'tmc2209', 'tmc2240', 'tmc2660', 'tmc5160']
|
TRINAMIC_DRIVERS = ['tmc2130', 'tmc2208', 'tmc2209', 'tmc2240', 'tmc2660', 'tmc5160']
|
||||||
MOTORS = ['stepper_x', 'stepper_y', 'stepper_x1', 'stepper_y1', 'stepper_z', 'stepper_z1', 'stepper_z2', 'stepper_z3']
|
MOTORS = ['stepper_x', 'stepper_y', 'stepper_x1', 'stepper_y1', 'stepper_z', 'stepper_z1', 'stepper_z2', 'stepper_z3']
|
||||||
@@ -17,25 +16,20 @@ class Motor:
|
|||||||
self.name: str = name
|
self.name: str = name
|
||||||
self._registers: Dict[str, Dict[str, Any]] = {}
|
self._registers: Dict[str, Dict[str, Any]] = {}
|
||||||
self._config: Dict[str, Any] = {}
|
self._config: Dict[str, Any] = {}
|
||||||
self._driver: Tuple[str, Any] = ('', None)
|
|
||||||
|
|
||||||
def set_driver(self, driver_name: str, tmc_object: Any) -> None:
|
|
||||||
self._driver = (driver_name, tmc_object)
|
|
||||||
|
|
||||||
def get_driver(self) -> Tuple[str, Any]:
|
|
||||||
return self._driver
|
|
||||||
|
|
||||||
def set_register(self, register: str, value_dict: dict) -> None:
|
def set_register(self, register: str, value_dict: dict) -> None:
|
||||||
|
# First we filter out entries with a value of 0 to avoid having too much uneeded data
|
||||||
|
value_dict = {k: v for k, v in value_dict.items() if v != 0}
|
||||||
|
|
||||||
# Special parsing for CHOPCONF to extract meaningful values
|
# Special parsing for CHOPCONF to extract meaningful values
|
||||||
if register == 'CHOPCONF':
|
if register == 'CHOPCONF':
|
||||||
# Add intpol=0 if missing from the register dump
|
# Add intpol=0 if missing from the register dump to force printing it as it's important
|
||||||
if 'intpol=' not in value_dict:
|
if 'intpol' not in value_dict:
|
||||||
value_dict['intpol'] = '0'
|
value_dict['intpol'] = '0'
|
||||||
# Simplify the microstep resolution format
|
# Remove the microsteps entry as the format here is not easy to read and
|
||||||
|
# it's already read in the correct format directly from the Klipper config
|
||||||
if 'mres' in value_dict:
|
if 'mres' in value_dict:
|
||||||
mres_match = re.search(r'(\d+)usteps', value_dict['mres'])
|
del value_dict['mres']
|
||||||
if mres_match:
|
|
||||||
value_dict['mres'] = mres_match.group(1)
|
|
||||||
|
|
||||||
# Special parsing for CHOPCONF to avoid pwm_ before each values
|
# Special parsing for CHOPCONF to avoid pwm_ before each values
|
||||||
if register == 'PWMCONF':
|
if register == 'PWMCONF':
|
||||||
@@ -46,7 +40,7 @@ class Motor:
|
|||||||
new_value_dict[key] = val
|
new_value_dict[key] = val
|
||||||
value_dict = new_value_dict
|
value_dict = new_value_dict
|
||||||
|
|
||||||
# Then fill the registers while merging all the thresholds into the same THRS virtual register
|
# Then gets merged all the thresholds into the same THRS virtual register
|
||||||
if register in ['TPWMTHRS', 'TCOOLTHRS']:
|
if register in ['TPWMTHRS', 'TCOOLTHRS']:
|
||||||
existing_thrs = self._registers.get('THRS', {})
|
existing_thrs = self._registers.get('THRS', {})
|
||||||
merged_values = {**existing_thrs, **value_dict}
|
merged_values = {**existing_thrs, **value_dict}
|
||||||
@@ -110,35 +104,42 @@ class Motor:
|
|||||||
|
|
||||||
|
|
||||||
class MotorsConfigParser:
|
class MotorsConfigParser:
|
||||||
def __init__(self, printer, motors: List[str] = MOTORS, drivers: List[str] = TRINAMIC_DRIVERS):
|
def __init__(self, config, motors: List[str] = MOTORS, drivers: List[str] = TRINAMIC_DRIVERS):
|
||||||
|
self._printer = config.get_printer()
|
||||||
|
|
||||||
self._motors: List[Motor] = []
|
self._motors: List[Motor] = []
|
||||||
self._printer = printer
|
|
||||||
|
|
||||||
for motor_name in motors:
|
for motor_name in motors:
|
||||||
for driver in drivers:
|
for driver in drivers:
|
||||||
tmc_object = printer.lookup_object(f'{driver} {motor_name}', None)
|
tmc_object = self._printer.lookup_object(f'{driver} {motor_name}', None)
|
||||||
if tmc_object is None:
|
if tmc_object is None:
|
||||||
continue
|
continue
|
||||||
motor = self._create_motor(motor_name, driver, tmc_object)
|
motor = self._create_motor(motor_name, driver, tmc_object)
|
||||||
self._motors.append(motor)
|
self._motors.append(motor)
|
||||||
|
|
||||||
|
pconfig = self._printer.lookup_object('configfile')
|
||||||
|
self.kinematics = pconfig.status_raw_config['printer']['kinematics']
|
||||||
|
|
||||||
# Create a Motor object with the given name, driver and TMC object
|
# Create a Motor object with the given name, driver and TMC object
|
||||||
# and fill it with the relevant configuration and registers
|
# and fill it with the relevant configuration and registers
|
||||||
def _create_motor(self, motor_name: str, driver: str, tmc_object: Any) -> Motor:
|
def _create_motor(self, motor_name: str, driver: str, tmc_object: Any) -> Motor:
|
||||||
motor = Motor(motor_name)
|
motor = Motor(motor_name)
|
||||||
motor.set_driver(driver.upper(), tmc_object)
|
motor.set_config('tmc', driver)
|
||||||
self._parse_klipper_config(motor, tmc_object)
|
self._parse_klipper_config(motor, tmc_object)
|
||||||
self._parse_tmc_registers(motor, tmc_object)
|
self._parse_tmc_registers(motor, tmc_object)
|
||||||
return motor
|
return motor
|
||||||
|
|
||||||
def _parse_klipper_config(self, motor: Motor, tmc: Any) -> None:
|
def _parse_klipper_config(self, motor: Motor, tmc_object: Any) -> None:
|
||||||
# The TMCCommandHelper isn't a direct member of the TMC object... but we can still get it this way
|
# The TMCCommandHelper isn't a direct member of the TMC object... but we can still get it this way
|
||||||
tmc_cmdhelper = tmc.get_status.__self__
|
tmc_cmdhelper = tmc_object.get_status.__self__
|
||||||
|
|
||||||
motor_currents = tmc_cmdhelper.current_helper.get_current()
|
motor_currents = tmc_cmdhelper.current_helper.get_current()
|
||||||
motor.set_config('run_current', motor_currents[0])
|
motor.set_config('run_current', motor_currents[0])
|
||||||
motor.set_config('hold_current', motor_currents[1])
|
motor.set_config('hold_current', motor_currents[1])
|
||||||
|
|
||||||
|
pconfig = self._printer.lookup_object('configfile')
|
||||||
|
motor.set_config('microsteps', int(pconfig.status_raw_config[motor.name]['microsteps']))
|
||||||
|
|
||||||
autotune_object = self._printer.lookup_object(f'autotune_tmc {motor.name}', None)
|
autotune_object = self._printer.lookup_object(f'autotune_tmc {motor.name}', None)
|
||||||
if autotune_object is not None:
|
if autotune_object is not None:
|
||||||
motor.set_config('autotune_enabled', True)
|
motor.set_config('autotune_enabled', True)
|
||||||
@@ -147,24 +148,21 @@ class MotorsConfigParser:
|
|||||||
else:
|
else:
|
||||||
motor.set_config('autotune_enabled', False)
|
motor.set_config('autotune_enabled', False)
|
||||||
|
|
||||||
def _parse_tmc_registers(self, motor: Motor, tmc: Any) -> None:
|
def _parse_tmc_registers(self, motor: Motor, tmc_object: Any) -> None:
|
||||||
# The TMCCommandHelper isn't a direct member of the TMC object... but we can still get it this way
|
# The TMCCommandHelper isn't a direct member of the TMC object... but we can still get it this way
|
||||||
tmc_cmdhelper = tmc.get_status.__self__
|
tmc_cmdhelper = tmc_object.get_status.__self__
|
||||||
|
|
||||||
for register in RELEVANT_TMC_REGISTERS:
|
for register in RELEVANT_TMC_REGISTERS:
|
||||||
# value = tmc_cmdhelper.read_register(register)
|
|
||||||
# motor.set_register(register, value)
|
|
||||||
|
|
||||||
val = tmc_cmdhelper.fields.registers.get(register)
|
val = tmc_cmdhelper.fields.registers.get(register)
|
||||||
if (val is not None) and (register not in tmc_cmdhelper.read_registers):
|
if (val is not None) and (register not in tmc_cmdhelper.read_registers):
|
||||||
# write-only register
|
# write-only register
|
||||||
fields_string = self._extract_register_values(register, val)
|
fields_string = self._extract_register_values(tmc_cmdhelper, register, val)
|
||||||
elif register in tmc_cmdhelper.read_registers:
|
elif register in tmc_cmdhelper.read_registers:
|
||||||
# readable register
|
# readable register
|
||||||
val = tmc_cmdhelper.mcu_tmc.get_register(register)
|
val = tmc_cmdhelper.mcu_tmc.get_register(register)
|
||||||
if tmc_cmdhelper.read_translate is not None:
|
if tmc_cmdhelper.read_translate is not None:
|
||||||
register, val = tmc_cmdhelper.read_translate(register, val)
|
register, val = tmc_cmdhelper.read_translate(register, val)
|
||||||
fields_string = self._extract_register_values(register, val)
|
fields_string = self._extract_register_values(tmc_cmdhelper, register, val)
|
||||||
|
|
||||||
motor.set_register(register, fields_string)
|
motor.set_register(register, fields_string)
|
||||||
|
|
||||||
@@ -173,7 +171,7 @@ class MotorsConfigParser:
|
|||||||
reg_fields = tmc_cmdhelper.fields.all_fields.get(register, {})
|
reg_fields = tmc_cmdhelper.fields.all_fields.get(register, {})
|
||||||
reg_fields = sorted([(mask, name) for name, mask in reg_fields.items()])
|
reg_fields = sorted([(mask, name) for name, mask in reg_fields.items()])
|
||||||
fields = {}
|
fields = {}
|
||||||
for mask, field_name in reg_fields:
|
for _, field_name in reg_fields:
|
||||||
field_value = tmc_cmdhelper.fields.get_field(field_name, val, register)
|
field_value = tmc_cmdhelper.fields.get_field(field_name, val, register)
|
||||||
fields[field_name] = field_value
|
fields[field_name] = field_value
|
||||||
return fields
|
return fields
|
||||||
@@ -181,7 +179,7 @@ class MotorsConfigParser:
|
|||||||
# Find and return the motor by its name
|
# Find and return the motor by its name
|
||||||
def get_motor(self, motor_name: str) -> Optional[Motor]:
|
def get_motor(self, motor_name: str) -> Optional[Motor]:
|
||||||
for motor in self._motors:
|
for motor in self._motors:
|
||||||
if motor._name == motor_name:
|
if motor.name == motor_name:
|
||||||
return motor
|
return motor
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from ..helpers.common_func import AXIS_CONFIG
|
||||||
from ..helpers.console_output import ConsoleOutput
|
from ..helpers.console_output import ConsoleOutput
|
||||||
from . import AXIS_CONFIG
|
|
||||||
from .resonance_test import vibrate_axis
|
from .resonance_test import vibrate_axis
|
||||||
|
|
||||||
|
|
||||||
def excitate_axis_at_freq(gcmd, gcode, printer) -> None:
|
def excitate_axis_at_freq(gcmd, config) -> None:
|
||||||
freq = gcmd.get_int('FREQUENCY', default=25, minval=1)
|
freq = gcmd.get_int('FREQUENCY', default=25, minval=1)
|
||||||
duration = gcmd.get_int('DURATION', default=10, minval=1)
|
duration = gcmd.get_int('DURATION', default=10, minval=1)
|
||||||
accel_per_hz = gcmd.get_float('ACCEL_PER_HZ', default=None)
|
accel_per_hz = gcmd.get_float('ACCEL_PER_HZ', default=None)
|
||||||
@@ -19,9 +19,11 @@ def excitate_axis_at_freq(gcmd, gcode, printer) -> None:
|
|||||||
|
|
||||||
ConsoleOutput.print(f'Excitating {axis.upper()} axis at {freq}Hz for {duration} seconds')
|
ConsoleOutput.print(f'Excitating {axis.upper()} axis at {freq}Hz for {duration} seconds')
|
||||||
|
|
||||||
systime = printer.get_reactor().monotonic()
|
printer = config.get_printer()
|
||||||
|
gcode = printer.lookup_object('gcode')
|
||||||
toolhead = printer.lookup_object('toolhead')
|
toolhead = printer.lookup_object('toolhead')
|
||||||
res_tester = printer.lookup_object('resonance_tester')
|
res_tester = printer.lookup_object('resonance_tester')
|
||||||
|
systime = printer.get_reactor().monotonic()
|
||||||
|
|
||||||
if accel_per_hz is None:
|
if accel_per_hz is None:
|
||||||
accel_per_hz = res_tester.test.accel_per_hz
|
accel_per_hz = res_tester.test.accel_per_hz
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from .motorsconfigparser import MotorsConfigParser
|
|||||||
MIN_SPEED = 2 # mm/s
|
MIN_SPEED = 2 # mm/s
|
||||||
|
|
||||||
|
|
||||||
def create_vibrations_profile(gcmd, gcode, printer, st_thread: ShakeTuneThread) -> None:
|
def create_vibrations_profile(gcmd, config, st_thread: ShakeTuneThread) -> None:
|
||||||
size = gcmd.get_float('SIZE', default=100.0, minval=50.0)
|
size = gcmd.get_float('SIZE', default=100.0, minval=50.0)
|
||||||
z_height = gcmd.get_float('Z_HEIGHT', default=20.0)
|
z_height = gcmd.get_float('Z_HEIGHT', default=20.0)
|
||||||
max_speed = gcmd.get_float('MAX_SPEED', default=200.0, minval=10.0)
|
max_speed = gcmd.get_float('MAX_SPEED', default=200.0, minval=10.0)
|
||||||
@@ -23,29 +23,30 @@ def create_vibrations_profile(gcmd, gcode, printer, st_thread: ShakeTuneThread)
|
|||||||
if (size / (max_speed / 60)) < 0.25:
|
if (size / (max_speed / 60)) < 0.25:
|
||||||
gcmd.error('The size of the movement is too small for the given speed! Increase SIZE or decrease MAX_SPEED!')
|
gcmd.error('The size of the movement is too small for the given speed! Increase SIZE or decrease MAX_SPEED!')
|
||||||
|
|
||||||
# Check that input shaper is already configured
|
printer = config.get_printer()
|
||||||
|
gcode = printer.lookup_object('gcode')
|
||||||
|
toolhead = printer.lookup_object('toolhead')
|
||||||
input_shaper = printer.lookup_object('input_shaper', None)
|
input_shaper = printer.lookup_object('input_shaper', None)
|
||||||
|
systime = printer.get_reactor().monotonic()
|
||||||
|
|
||||||
|
# Check that input shaper is already configured
|
||||||
if input_shaper is None:
|
if input_shaper is None:
|
||||||
gcmd.error('Input shaper is not configured! Please run the shaper calibration macro first.')
|
gcmd.error('Input shaper is not configured! Please run the shaper calibration macro first.')
|
||||||
|
|
||||||
# TODO: Add the kinematics check to define the main_angles
|
motors_config_parser = MotorsConfigParser(config, motors=['stepper_x', 'stepper_y'])
|
||||||
# but this needs to retrieve it from the printer configuration
|
|
||||||
# {% if kinematics == "cartesian" %}
|
if motors_config_parser.kinematics == 'cartesian' or motors_config_parser.kinematics == 'corexz':
|
||||||
# # Cartesian motors are on X and Y axis directly
|
# Cartesian motors are on X and Y axis directly, same for CoreXZ
|
||||||
# RESPOND MSG="Cartesian kinematics mode"
|
|
||||||
# {% set main_angles = [0, 90] %}
|
|
||||||
# {% elif kinematics == "corexy" %}
|
|
||||||
# # CoreXY motors are on A and B axis (45 and 135 degrees)
|
|
||||||
# RESPOND MSG="CoreXY kinematics mode"
|
|
||||||
# {% set main_angles = [45, 135] %}
|
|
||||||
# {% else %}
|
|
||||||
# { action_raise_error("Only Cartesian and CoreXY kinematics are supported at the moment for the vibrations measurement tool!") }
|
|
||||||
# {% endif %}
|
|
||||||
kinematics = 'cartesian'
|
|
||||||
main_angles = [0, 90]
|
main_angles = [0, 90]
|
||||||
|
elif motors_config_parser.kinematics == 'corexy':
|
||||||
|
# CoreXY motors are on A and B axis (45 and 135 degrees)
|
||||||
|
main_angles = [45, 135]
|
||||||
|
else:
|
||||||
|
gcmd.error(
|
||||||
|
'Only Cartesian and CoreXY kinematics are supported at the moment for the vibrations measurement tool!'
|
||||||
|
)
|
||||||
|
ConsoleOutput.print(f'{motors_config_parser.kinematics.upper()} kinematics mode')
|
||||||
|
|
||||||
systime = printer.get_reactor().monotonic()
|
|
||||||
toolhead = printer.lookup_object('toolhead')
|
|
||||||
toolhead_info = toolhead.get_status(systime)
|
toolhead_info = toolhead.get_status(systime)
|
||||||
old_accel = toolhead_info['max_accel']
|
old_accel = toolhead_info['max_accel']
|
||||||
old_mcr = toolhead_info['minimum_cruise_ratio']
|
old_mcr = toolhead_info['minimum_cruise_ratio']
|
||||||
@@ -66,6 +67,7 @@ def create_vibrations_profile(gcmd, gcode, printer, st_thread: ShakeTuneThread)
|
|||||||
|
|
||||||
nb_speed_samples = int((max_speed - MIN_SPEED) / speed_increment + 1)
|
nb_speed_samples = int((max_speed - MIN_SPEED) / speed_increment + 1)
|
||||||
for curr_angle in main_angles:
|
for curr_angle in main_angles:
|
||||||
|
ConsoleOutput.print(f'-> Measuring angle: {curr_angle} degrees...')
|
||||||
radian_angle = math.radians(curr_angle)
|
radian_angle = math.radians(curr_angle)
|
||||||
|
|
||||||
# Find the best accelerometer chip for the current angle if not specified
|
# Find the best accelerometer chip for the current angle if not specified
|
||||||
@@ -86,6 +88,7 @@ def create_vibrations_profile(gcmd, gcode, printer, st_thread: ShakeTuneThread)
|
|||||||
# Sweep the speed range to record the vibrations at different speeds
|
# Sweep the speed range to record the vibrations at different speeds
|
||||||
for curr_speed_sample in range(nb_speed_samples):
|
for curr_speed_sample in range(nb_speed_samples):
|
||||||
curr_speed = MIN_SPEED + curr_speed_sample * speed_increment
|
curr_speed = MIN_SPEED + curr_speed_sample * speed_increment
|
||||||
|
ConsoleOutput.print(f'Current speed: {curr_speed} mm/s')
|
||||||
|
|
||||||
# Reduce the segments length for the lower speed range (0-100mm/s). The minimum length is 1/3 of the SIZE and is gradually increased
|
# Reduce the segments length for the lower speed range (0-100mm/s). The minimum length is 1/3 of the SIZE and is gradually increased
|
||||||
# to the nominal SIZE at 100mm/s. No further size changes are made above this speed. The goal is to ensure that the print head moves
|
# to the nominal SIZE at 100mm/s. No further size changes are made above this speed. The goal is to ensure that the print head moves
|
||||||
@@ -126,12 +129,9 @@ def create_vibrations_profile(gcmd, gcode, printer, st_thread: ShakeTuneThread)
|
|||||||
)
|
)
|
||||||
toolhead.wait_moves()
|
toolhead.wait_moves()
|
||||||
|
|
||||||
# Get the motors and TMC configurations from Klipper
|
|
||||||
motors_config_parser = MotorsConfigParser(printer, motors=['stepper_x', 'stepper_y'])
|
|
||||||
|
|
||||||
# Run post-processing
|
# Run post-processing
|
||||||
ConsoleOutput.print('Machine vibrations profile generation...')
|
ConsoleOutput.print('Machine vibrations profile generation...')
|
||||||
ConsoleOutput.print('This may take some time (5-8min)')
|
ConsoleOutput.print('This may take some time (5-8min)')
|
||||||
creator = st_thread.get_graph_creator()
|
creator = st_thread.get_graph_creator()
|
||||||
creator.configure(kinematics, accel, motors_config_parser)
|
creator.configure(motors_config_parser.kinematics, accel, motors_config_parser)
|
||||||
st_thread.run()
|
st_thread.run()
|
||||||
|
|||||||
@@ -109,7 +109,8 @@ def axesmap_calibration(lognames, accel=None):
|
|||||||
axes_map = ','.join([f'{spike[0][0]}{spike[1]}' for spike in spikes_sorted])
|
axes_map = ','.join([f'{spike[0][0]}{spike[1]}' for spike in spikes_sorted])
|
||||||
# alignment_error, sensitivity_error = compute_errors(filtered_data, spikes_sorted, accel, NUM_POINTS)
|
# alignment_error, sensitivity_error = compute_errors(filtered_data, spikes_sorted, accel, NUM_POINTS)
|
||||||
|
|
||||||
results = f'Detected axes_map:\n {axes_map}\n'
|
results = f'Be aware that this macro is experimental and has been known to sometimes produce incorrect results. Use it with caution and always check the results!\n'
|
||||||
|
results += f'Detected axes_map:\n {axes_map}\n'
|
||||||
|
|
||||||
# TODO: work on this function that is currently not giving good results...
|
# TODO: work on this function that is currently not giving good results...
|
||||||
# results += "Accelerometer angle deviation:\n"
|
# results += "Accelerometer angle deviation:\n"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import abc
|
import abc
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import tarfile
|
import tarfile
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -189,6 +190,7 @@ class VibrationsGraphCreator(GraphCreator):
|
|||||||
with tarfile.open(tar_path, 'w:gz') as tar:
|
with tarfile.open(tar_path, 'w:gz') as tar:
|
||||||
for csv_file in lognames:
|
for csv_file in lognames:
|
||||||
tar.add(csv_file, arcname=csv_file.name, recursive=False)
|
tar.add(csv_file, arcname=csv_file.name, recursive=False)
|
||||||
|
csv_file.unlink()
|
||||||
|
|
||||||
def create_graph(self) -> None:
|
def create_graph(self) -> None:
|
||||||
if not self._accel or not self._kinematics:
|
if not self._accel or not self._kinematics:
|
||||||
@@ -197,7 +199,7 @@ class VibrationsGraphCreator(GraphCreator):
|
|||||||
lognames = self._move_and_prepare_files(
|
lognames = self._move_and_prepare_files(
|
||||||
glob_pattern='shaketune-vib_*.csv',
|
glob_pattern='shaketune-vib_*.csv',
|
||||||
min_files_required=None,
|
min_files_required=None,
|
||||||
custom_name_func=lambda f: f.name,
|
custom_name_func=lambda f: re.search(r'shaketune-vib_(.*?)_\d{8}_\d{6}', f.name).group(1),
|
||||||
)
|
)
|
||||||
fig = vibrations_profile(
|
fig = vibrations_profile(
|
||||||
lognames=[str(path) for path in lognames],
|
lognames=[str(path) for path in lognames],
|
||||||
|
|||||||
@@ -564,23 +564,23 @@ def plot_motor_config_txt(fig, motors, differences):
|
|||||||
motor_details = [(motors[0], 'X motor'), (motors[1], 'Y motor')]
|
motor_details = [(motors[0], 'X motor'), (motors[1], 'Y motor')]
|
||||||
|
|
||||||
distance = 0.12
|
distance = 0.12
|
||||||
if motors[0].get_property('autotune_enabled'):
|
if motors[0].get_config('autotune_enabled'):
|
||||||
distance = 0.24
|
distance = 0.27
|
||||||
config_blocks = [
|
config_blocks = [
|
||||||
f"| {lbl}: {mot.get_property('motor').upper()} on {mot.get_property('tmc').upper()} @ {mot.get_property('voltage')}V {mot.get_property('run_current')}A"
|
f"| {lbl}: {mot.get_config('motor').upper()} on {mot.get_config('tmc').upper()} @ {mot.get_config('voltage'):0.1f}V {mot.get_config('run_current'):0.2f}A - {mot.get_config('microsteps')}usteps"
|
||||||
for mot, lbl in motor_details
|
for mot, lbl in motor_details
|
||||||
]
|
]
|
||||||
config_blocks.append('| TMC Autotune enabled')
|
config_blocks.append('| TMC Autotune enabled')
|
||||||
else:
|
else:
|
||||||
config_blocks = [
|
config_blocks = [
|
||||||
f"| {lbl}: {mot.get_property('tmc').upper()} @ {mot.get_property('run_current')}A"
|
f"| {lbl}: {mot.get_config('tmc').upper()} @ {mot.get_config('run_current'):0.2f}A - {mot.get_config('microsteps')}usteps"
|
||||||
for mot, lbl in motor_details
|
for mot, lbl in motor_details
|
||||||
]
|
]
|
||||||
config_blocks.append('| TMC Autotune not detected')
|
config_blocks.append('| TMC Autotune not detected')
|
||||||
|
|
||||||
for idx, block in enumerate(config_blocks):
|
for idx, block in enumerate(config_blocks):
|
||||||
fig.text(
|
fig.text(
|
||||||
0.40, 0.990 - 0.015 * idx, block, ha='left', va='top', fontsize=10, color=KLIPPAIN_COLORS['dark_purple']
|
0.41, 0.990 - 0.015 * idx, block, ha='left', va='top', fontsize=10, color=KLIPPAIN_COLORS['dark_purple']
|
||||||
)
|
)
|
||||||
|
|
||||||
tmc_registers = motors[0].get_registers()
|
tmc_registers = motors[0].get_registers()
|
||||||
@@ -589,7 +589,7 @@ def plot_motor_config_txt(fig, motors, differences):
|
|||||||
settings_str = ' '.join(f'{k}={v}' for k, v in settings.items())
|
settings_str = ' '.join(f'{k}={v}' for k, v in settings.items())
|
||||||
tmc_block = f'| {register.upper()}: {settings_str}'
|
tmc_block = f'| {register.upper()}: {settings_str}'
|
||||||
fig.text(
|
fig.text(
|
||||||
0.40 + distance,
|
0.41 + distance,
|
||||||
0.990 - 0.015 * idx,
|
0.990 - 0.015 * idx,
|
||||||
tmc_block,
|
tmc_block,
|
||||||
ha='left',
|
ha='left',
|
||||||
@@ -601,7 +601,7 @@ def plot_motor_config_txt(fig, motors, differences):
|
|||||||
if differences is not None:
|
if differences is not None:
|
||||||
differences_text = f'| Y motor diff: {differences}'
|
differences_text = f'| Y motor diff: {differences}'
|
||||||
fig.text(
|
fig.text(
|
||||||
0.40 + distance,
|
0.41 + distance,
|
||||||
0.990 - 0.015 * (idx + 1),
|
0.990 - 0.015 * (idx + 1),
|
||||||
differences_text,
|
differences_text,
|
||||||
ha='left',
|
ha='left',
|
||||||
|
|||||||
@@ -18,8 +18,9 @@ from .shaketune_thread import ShakeTuneThread
|
|||||||
|
|
||||||
class ShakeTune:
|
class ShakeTune:
|
||||||
def __init__(self, config) -> None:
|
def __init__(self, config) -> None:
|
||||||
|
self._pconfig = config
|
||||||
self._printer = config.get_printer()
|
self._printer = config.get_printer()
|
||||||
self._gcode = self._printer.lookup_object('gcode')
|
gcode = self._printer.lookup_object('gcode')
|
||||||
|
|
||||||
res_tester = self._printer.lookup_object('resonance_tester')
|
res_tester = self._printer.lookup_object('resonance_tester')
|
||||||
if res_tester is None:
|
if res_tester is None:
|
||||||
@@ -34,29 +35,29 @@ class ShakeTune:
|
|||||||
dpi = config.getint('dpi', default=150, minval=100, maxval=500)
|
dpi = config.getint('dpi', default=150, minval=100, maxval=500)
|
||||||
|
|
||||||
self._config = ShakeTuneConfig(result_folder_path, keep_n_results, keep_csv, dpi)
|
self._config = ShakeTuneConfig(result_folder_path, keep_n_results, keep_csv, dpi)
|
||||||
ConsoleOutput.register_output_callback(self._gcode.respond_info)
|
ConsoleOutput.register_output_callback(gcode.respond_info)
|
||||||
|
|
||||||
self._gcode.register_command(
|
gcode.register_command(
|
||||||
'EXCITATE_AXIS_AT_FREQ',
|
'EXCITATE_AXIS_AT_FREQ',
|
||||||
self.cmd_EXCITATE_AXIS_AT_FREQ,
|
self.cmd_EXCITATE_AXIS_AT_FREQ,
|
||||||
desc=self.cmd_EXCITATE_AXIS_AT_FREQ_help,
|
desc=self.cmd_EXCITATE_AXIS_AT_FREQ_help,
|
||||||
)
|
)
|
||||||
self._gcode.register_command(
|
gcode.register_command(
|
||||||
'AXES_MAP_CALIBRATION',
|
'AXES_MAP_CALIBRATION',
|
||||||
self.cmd_AXES_MAP_CALIBRATION,
|
self.cmd_AXES_MAP_CALIBRATION,
|
||||||
desc=self.cmd_AXES_MAP_CALIBRATION_help,
|
desc=self.cmd_AXES_MAP_CALIBRATION_help,
|
||||||
)
|
)
|
||||||
self._gcode.register_command(
|
gcode.register_command(
|
||||||
'COMPARE_BELTS_RESPONSES',
|
'COMPARE_BELTS_RESPONSES',
|
||||||
self.cmd_COMPARE_BELTS_RESPONSES,
|
self.cmd_COMPARE_BELTS_RESPONSES,
|
||||||
desc=self.cmd_COMPARE_BELTS_RESPONSES_help,
|
desc=self.cmd_COMPARE_BELTS_RESPONSES_help,
|
||||||
)
|
)
|
||||||
self._gcode.register_command(
|
gcode.register_command(
|
||||||
'AXES_SHAPER_CALIBRATION',
|
'AXES_SHAPER_CALIBRATION',
|
||||||
self.cmd_AXES_SHAPER_CALIBRATION,
|
self.cmd_AXES_SHAPER_CALIBRATION,
|
||||||
desc=self.cmd_AXES_SHAPER_CALIBRATION_help,
|
desc=self.cmd_AXES_SHAPER_CALIBRATION_help,
|
||||||
)
|
)
|
||||||
self._gcode.register_command(
|
gcode.register_command(
|
||||||
'CREATE_VIBRATIONS_PROFILE',
|
'CREATE_VIBRATIONS_PROFILE',
|
||||||
self.cmd_CREATE_VIBRATIONS_PROFILE,
|
self.cmd_CREATE_VIBRATIONS_PROFILE,
|
||||||
desc=self.cmd_CREATE_VIBRATIONS_PROFILE_help,
|
desc=self.cmd_CREATE_VIBRATIONS_PROFILE_help,
|
||||||
@@ -68,7 +69,7 @@ class ShakeTune:
|
|||||||
|
|
||||||
def cmd_EXCITATE_AXIS_AT_FREQ(self, gcmd) -> None:
|
def cmd_EXCITATE_AXIS_AT_FREQ(self, gcmd) -> None:
|
||||||
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
||||||
excitate_axis_at_freq(gcmd, self._gcode, self._printer)
|
excitate_axis_at_freq(gcmd, self._pconfig)
|
||||||
|
|
||||||
cmd_AXES_MAP_CALIBRATION_help = 'Perform a set of movements to measure the orientation of the accelerometer and help you set the best axes_map configuration for your printer'
|
cmd_AXES_MAP_CALIBRATION_help = 'Perform a set of movements to measure the orientation of the accelerometer and help you set the best axes_map configuration for your printer'
|
||||||
|
|
||||||
@@ -76,7 +77,7 @@ class ShakeTune:
|
|||||||
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
||||||
axes_map_finder = AxesMapFinder(self._config)
|
axes_map_finder = AxesMapFinder(self._config)
|
||||||
st_thread = ShakeTuneThread(self._config, axes_map_finder, self._printer.get_reactor(), self.timeout)
|
st_thread = ShakeTuneThread(self._config, axes_map_finder, self._printer.get_reactor(), self.timeout)
|
||||||
axes_map_calibration(gcmd, self._gcode, self._printer, st_thread)
|
axes_map_calibration(gcmd, self._pconfig, st_thread)
|
||||||
|
|
||||||
cmd_COMPARE_BELTS_RESPONSES_help = 'Perform a custom half-axis test to analyze and compare the frequency profiles of individual belts on CoreXY printers'
|
cmd_COMPARE_BELTS_RESPONSES_help = 'Perform a custom half-axis test to analyze and compare the frequency profiles of individual belts on CoreXY printers'
|
||||||
|
|
||||||
@@ -84,7 +85,7 @@ class ShakeTune:
|
|||||||
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
||||||
belt_graph_creator = BeltsGraphCreator(self._config)
|
belt_graph_creator = BeltsGraphCreator(self._config)
|
||||||
st_thread = ShakeTuneThread(self._config, belt_graph_creator, self._printer.get_reactor(), self.timeout)
|
st_thread = ShakeTuneThread(self._config, belt_graph_creator, self._printer.get_reactor(), self.timeout)
|
||||||
compare_belts_responses(gcmd, self._gcode, self._printer, st_thread)
|
compare_belts_responses(gcmd, self._pconfig, st_thread)
|
||||||
|
|
||||||
cmd_AXES_SHAPER_CALIBRATION_help = (
|
cmd_AXES_SHAPER_CALIBRATION_help = (
|
||||||
'Perform standard axis input shaper tests on one or both XY axes to select the best input shaper filter'
|
'Perform standard axis input shaper tests on one or both XY axes to select the best input shaper filter'
|
||||||
@@ -94,7 +95,7 @@ class ShakeTune:
|
|||||||
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
||||||
shaper_graph_creator = ShaperGraphCreator(self._config)
|
shaper_graph_creator = ShaperGraphCreator(self._config)
|
||||||
st_thread = ShakeTuneThread(self._config, shaper_graph_creator, self._printer.get_reactor(), self.timeout)
|
st_thread = ShakeTuneThread(self._config, shaper_graph_creator, self._printer.get_reactor(), self.timeout)
|
||||||
axes_shaper_calibration(gcmd, self._gcode, self._printer, st_thread)
|
axes_shaper_calibration(gcmd, self._pconfig, st_thread)
|
||||||
|
|
||||||
cmd_CREATE_VIBRATIONS_PROFILE_help = 'Perform a set of movements to measure the orientation of the accelerometer and help you set the best axes_map configuration for your printer'
|
cmd_CREATE_VIBRATIONS_PROFILE_help = 'Perform a set of movements to measure the orientation of the accelerometer and help you set the best axes_map configuration for your printer'
|
||||||
|
|
||||||
@@ -102,4 +103,4 @@ class ShakeTune:
|
|||||||
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
ConsoleOutput.print(f'Shake&Tune version: {ShakeTuneConfig.get_git_version()}')
|
||||||
vibration_profile_creator = VibrationsGraphCreator(self._config)
|
vibration_profile_creator = VibrationsGraphCreator(self._config)
|
||||||
st_thread = ShakeTuneThread(self._config, vibration_profile_creator, self._printer.get_reactor(), self.timeout)
|
st_thread = ShakeTuneThread(self._config, vibration_profile_creator, self._printer.get_reactor(), self.timeout)
|
||||||
create_vibrations_profile(gcmd, self._gcode, self._printer, st_thread)
|
create_vibrations_profile(gcmd, self._pconfig, st_thread)
|
||||||
|
|||||||
Reference in New Issue
Block a user