diff --git a/README.md b/README.md index d47f07793..af48b2738 100644 --- a/README.md +++ b/README.md @@ -125,6 +125,8 @@ See the [Danger Features document](https://dangerklipper.io/Danger_Features.html - [core: non-critical-mcus](https://github.com/DangerKlippers/danger-klipper/pull/339) +- [gcode_macros: !python templates](https://github.com/DangerKlippers/danger-klipper/pull/360) + - [core: action_log](https://github.com/DangerKlippers/danger-klipper/pull/367) - [danger_options: configurable homing constants](https://github.com/DangerKlippers/danger-klipper/pull/378) diff --git a/docs/Command_Templates.md b/docs/Command_Templates.md index 5fa95700c..6cb0737bb 100644 --- a/docs/Command_Templates.md +++ b/docs/Command_Templates.md @@ -78,14 +78,17 @@ speed (via the `F` parameter) on the first `G1` command. ## Template expansion -The gcode_macro `gcode:` config section is evaluated using the Jinja2 -template language. One can evaluate expressions at run-time by -wrapping them in `{ }` characters or use conditional statements -wrapped in `{% %}`. See the +The gcode_macro `gcode:` config section is evaluated using either the Jinja2 +template language or Python. + +### Jinja2 + +One can evaluate expressions at run-time by wrapping them in `{ }` characters +or use conditional statements wrapped in `{% %}`. See the [Jinja2 documentation](http://jinja.pocoo.org/docs/2.10/templates/) for further information on the syntax. -An example of a complex macro: +An example of a complex Jinja2 macro: ``` [gcode_macro clean_nozzle] gcode: @@ -101,7 +104,7 @@ gcode: RESTORE_GCODE_STATE NAME=clean_nozzle_state ``` -### Macro parameters +#### Jinja2: Macro parameters It is often useful to inspect parameters passed to the macro when it is called. These parameters are available via the `params` @@ -128,7 +131,7 @@ gcode: M140 S{bed_temp} ``` -### The "rawparams" variable +#### Jinja2: The "rawparams" variable The full unparsed parameters for the running macro can be access via the `rawparams` pseudo-variable. @@ -138,7 +141,7 @@ Note that this will include any comments that were part of the original command. See the [sample-macros.cfg](../config/sample-macros.cfg) file for an example showing how to override the `M117` command using `rawparams`. -### The "printer" Variable +#### Jinja2 The "printer" variable It is possible to inspect (and alter) the current state of the printer via the `printer` pseudo-variable. For example: @@ -178,6 +181,77 @@ gcode: M117 Temp:{sensor.temperature} Humidity:{sensor.humidity} ``` +### Python + +Templates can also be written in Python code. The template will automatically +be interpreted as Python if lines are prefixed with `!`. +Note: You can't mix Python and Jinja2. + +An example of a complex Python macro: +``` +[gcode_macro clean_nozzle] +gcode: + !wipe_count = 8 + !emit("G90") + !emit("G0 Z15 F300") + !for wipe in range(wipe_count): + ! for coordinate in [(275, 4), (235, 4)]: + ! emit(f"G0 X{coordinate[0]} Y{coordinate[1] + 0.25 * wipe} Z9.7 F12000") +``` + +#### Python: Rawparams + +``` +[gcode_macro G4] +rename_existing: G4.1 +gcode: + !if rawparams and "S" in rawparams: + ! s = int(rawparams.split("S")[1]) + ! respond_info(f"Sleeping for {s} seconds") + ! emit(f"G4.1 P{s * 1000}") + !else: + ! p = int(rawparams.split("P")[1]) + ! respond_info(f"Sleeping for {p/1000} seconds") + ! emit(f"G4.1 {rawparams}") +``` + +#### Python: Variables + +``` +[gcode_macro POKELOOP] +variable_count: 10 +variable_speed: 3 +gcode: + !for i in range(own_vars.count): + ! emit(f"BEACON_POKE SPEED={own_vars.speed} TOP=5 BOTTOM=-0.3") +``` + +#### Python: Printer objects + +``` +[gcode_macro EXTRUDER_TEMP] +gcode: + !ACTUAL_TEMP = printer["extruder"]["temperature"] + !TARGET_TEMP = printer["extruder"]["target"] + ! + !respond_info("Extruder Target: %.1fC, Actual: %.1fC" % (TARGET_TEMP, ACTUAL_TEMP)) +``` + +#### Python: Helpers + +- emit +- wait_while +- wait_until +- wait_moves +- blocking +- sleep +- set_gcode_variable +- emergency_stop / action_emergency_stop +- respond_info / action_respond_info +- raise_error / action_raise_error +- call_remote_method / action_call_remote_method +- math + ## Actions There are some commands available that can alter the state of the diff --git a/docs/Config_Changes.md b/docs/Config_Changes.md index a98563aee..385df8abb 100644 --- a/docs/Config_Changes.md +++ b/docs/Config_Changes.md @@ -8,6 +8,12 @@ All dates in this document are approximate. ## Changes +20241125: The `off_below` parameter in fans config section is +deprecated. It will be removed in the near future. Use +[`min_power`](./Config_Reference.md#fans) +instead. The `printer[fan object].speed` status will be replaced by +`printer[fan object].value` and `printer[fan object].power`. + 20240430: The `adc_ignore_limits` parameter in the `[danger_options]` config section has been renamed to `temp_ignore_limits` and it now covers all possible temperature sensors. diff --git a/docs/Config_Reference.md b/docs/Config_Reference.md index a9df987b7..41e8791ec 100644 --- a/docs/Config_Reference.md +++ b/docs/Config_Reference.md @@ -3326,6 +3326,9 @@ pin: # input. In such a case, the PWM pin can be used normally, and e.g. a # ground-switched FET(standard fan pin) can be used to control power to # the fan. +#off_below: +# These option is deprecated and should no longer be specified. +# Use `min_power` instead. ``` ### [heated_fan] diff --git a/docs/Danger_Features.md b/docs/Danger_Features.md index 5773083ca..818739465 100644 --- a/docs/Danger_Features.md +++ b/docs/Danger_Features.md @@ -58,6 +58,7 @@ - The jinja `do` extension has been enabled. You can now call functions in your macros without resorting to dirty hacks: `{% do array.append(5) %}` - The python [`math`](https://docs.python.org/3/library/math.html) library is available to macros. `{math.sin(math.pi * variable)}` and more! - New [`RELOAD_GCODE_MACROS`](./G-Codes.md#reload_gcode_macros) G-Code command to reload `[gcode_macro]` templates without requiring a restart. +- G-Code Macros can be written in Python. Read more [here](./Command_Templates.md) ## [Plugins](./Plugins.md) diff --git a/docs/Status_Reference.md b/docs/Status_Reference.md index 32661ec5c..fe8c5e504 100644 --- a/docs/Status_Reference.md +++ b/docs/Status_Reference.md @@ -156,9 +156,12 @@ The following information is available in [heater_fan some_name](Config_Reference.md#heater_fan) and [controller_fan some_name](Config_Reference.md#controller_fan) objects: -- `speed`: The fan speed as a float between 0.0 and 1.0. +- `value`: The fan speed value as a float between 0.0 and 1.0. +- `power`: The fan power as a float between 0|`min_power` and 1.0|`max_power`. - `rpm`: The measured fan speed in rotations per minute if the fan has a tachometer_pin defined. +deprecated objects (for UI compatibility only): +- `speed`: The fan speed as a float between 0.0 and `max_power`. ## filament_switch_sensor diff --git a/klippy/clocksync.py b/klippy/clocksync.py index 1bd6ee00b..080b4e7ae 100644 --- a/klippy/clocksync.py +++ b/klippy/clocksync.py @@ -93,15 +93,21 @@ def _handle_clock(self, params): self.clock_est[2], ) # Filter out samples that are extreme outliers - exp_clock = (sent_time - self.time_avg) * self.clock_est[2] + self.clock_avg + exp_clock = (sent_time - self.time_avg) * self.clock_est[ + 2 + ] + self.clock_avg clock_diff2 = (clock - exp_clock) ** 2 if ( clock_diff2 > 25.0 * self.prediction_variance and clock_diff2 > (0.000500 * self.mcu_freq) ** 2 ): - if clock > exp_clock and sent_time < self.last_prediction_time + 10.0: + if ( + clock > exp_clock + and sent_time < self.last_prediction_time + 10.0 + ): logging.debug( - "Ignoring clock sample %.3f:" " freq=%d diff=%d stddev=%.3f", + "Ignoring clock sample %.3f:" + " freq=%d diff=%d stddev=%.3f", sent_time, self.clock_est[2], clock - exp_clock, @@ -109,7 +115,8 @@ def _handle_clock(self, params): ) return logging.info( - "Resetting prediction variance %.3f:" " freq=%d diff=%d stddev=%.3f", + "Resetting prediction variance %.3f:" + " freq=%d diff=%d stddev=%.3f", sent_time, self.clock_est[2], clock - exp_clock, @@ -234,7 +241,9 @@ def connect_file(self, serial, pace=False): # clock frequency conversions def print_time_to_clock(self, print_time): if self.clock_adj[1] == 1.0: - logging.warning("Clock not yet synchronized, clock is untrustworthy") + logging.warning( + "Clock not yet synchronized, clock is untrustworthy" + ) for line in traceback.format_stack(): logging.warning(line.strip()) adjusted_offset, adjusted_freq = self.clock_adj @@ -242,7 +251,9 @@ def print_time_to_clock(self, print_time): def clock_to_print_time(self, clock): if self.clock_adj[1] == 1.0: - logging.warning("Clock not yet synchronized, print time is untrustworthy") + logging.warning( + "Clock not yet synchronized, print time is untrustworthy" + ) for line in traceback.format_stack(): logging.warning(line.strip()) adjusted_offset, adjusted_freq = self.clock_adj diff --git a/klippy/configfile.py b/klippy/configfile.py index b2c95a5eb..b094ad8bc 100644 --- a/klippy/configfile.py +++ b/klippy/configfile.py @@ -46,7 +46,8 @@ def _get_wrapper( self.access_tracking[acc_id] = default return default raise error( - "Option '%s' in section '%s' must be specified" % (option, self.section) + "Option '%s' in section '%s' must be specified" + % (option, self.section) ) try: v = parser(self.section, option) @@ -54,7 +55,8 @@ def _get_wrapper( raise except: raise error( - "Unable to parse option '%s' in section '%s'" % (option, self.section) + "Unable to parse option '%s' in section '%s'" + % (option, self.section) ) if note_valid: self.access_tracking[(self.section.lower(), option.lower())] = v @@ -171,9 +173,13 @@ def lparser(value, pos): def fcparser(section, option): return lparser(self.fileconfig.get(section, option), len(seps) - 1) - return self._get_wrapper(fcparser, option, default, note_valid=note_valid) + return self._get_wrapper( + fcparser, option, default, note_valid=note_valid + ) - def getlist(self, option, default=sentinel, sep=",", count=None, note_valid=True): + def getlist( + self, option, default=sentinel, sep=",", count=None, note_valid=True + ): return self.getlists( option, default, @@ -224,7 +230,9 @@ def get_prefix_sections(self, prefix): def get_prefix_options(self, prefix): return [ - o for o in self.fileconfig.options(self.section) if o.startswith(prefix) + o + for o in self.fileconfig.options(self.section) + if o.startswith(prefix) ] def deprecate(self, option, value=None): @@ -298,7 +306,8 @@ def _find_autosave_data(self, data): # Check for errors and strip line prefixes if "\n#*# " in regular_data: logging.warning( - "Can't read autosave from config file" " - autosave state corrupted" + "Can't read autosave from config file" + " - autosave state corrupted" ) return data, "" out = [""] @@ -353,7 +362,9 @@ def _parse_config_buffer(self, buffer, filename, fileconfig): else: fileconfig.readfp(sbuffer, filename) - def _resolve_include(self, source_filename, include_spec, fileconfig, visited): + def _resolve_include( + self, source_filename, include_spec, fileconfig, visited + ): dirname = os.path.dirname(source_filename) include_spec = include_spec.strip() include_glob = os.path.join(dirname, include_spec) @@ -367,7 +378,9 @@ def _resolve_include(self, source_filename, include_spec, fileconfig, visited): include_filenames.sort() for include_filename in include_filenames: include_data = self._read_config_file(include_filename) - self._parse_config(include_data, include_filename, fileconfig, visited) + self._parse_config( + include_data, include_filename, fileconfig, visited + ) return include_filenames def _parse_config(self, data, filename, fileconfig, visited): @@ -390,7 +403,9 @@ def _parse_config(self, data, filename, fileconfig, visited): if header and header.startswith("include "): self._parse_config_buffer(buffer, filename, fileconfig) include_spec = header[8:].strip() - self._resolve_include(filename, include_spec, fileconfig, visited) + self._resolve_include( + filename, include_spec, fileconfig, visited + ) else: buffer.append(line) self._parse_config_buffer(buffer, filename, fileconfig) @@ -412,7 +427,9 @@ def _build_config_string(self, config): return sfile.getvalue().strip() def read_config(self, filename): - return self._build_config_wrapper(self._read_config_file(filename), filename) + return self._build_config_wrapper( + self._read_config_file(filename), filename + ) def read_main_config(self): filename = self.printer.get_start_args()["config_file"] @@ -439,7 +456,8 @@ def check_unused_options(self, config, error_on_unused): if section not in valid_sections and section not in objects: if error_on_unused: raise error( - "Section '%s' is not a valid config section" % (section,) + "Section '%s' is not a valid config section" + % (section,) ) else: self.unused_sections.append(section) @@ -557,7 +575,9 @@ def _disallow_include_conflicts(self, regular_data, cfgname, gcode): if config.fileconfig.has_option(section, option): # They conflict only if they are not the same value included_value = config.fileconfig.get(section, option) - autosave_value = self.autosave.fileconfig.get(section, option) + autosave_value = self.autosave.fileconfig.get( + section, option + ) if included_value != autosave_value: msg = ( "SAVE_CONFIG section '%s' option '%s' value '%s' conflicts " @@ -586,7 +606,9 @@ def _write_backup(self, cfgpath, cfgdata, gcode, write_backups): backup_path = backupdir + "/" + cfgname + datestr if cfgpath.endswith(".cfg"): backup_path = backupdir + "/" + cfgname[:-4] + datestr + ".cfg" - logging.info("SAVE_CONFIG to '%s' (backup in '%s')", cfgpath, backup_path) + logging.info( + "SAVE_CONFIG to '%s' (backup in '%s')", cfgpath, backup_path + ) try: if write_backups: # Read the current config into the backup before making changes to @@ -632,7 +654,9 @@ def _save_includes(self, cfgpath, data, visitedpaths, gcode, write_backups): if not include_filenames and not glob.has_magic(include_glob): # Empty set is OK if wildcard but not for direct file # reference - raise error("Include file '%s' does not exist" % (include_glob,)) + raise error( + "Include file '%s' does not exist" % (include_glob,) + ) include_filenames.sort() # Read the include files and check them against autosave data. # If autosave data overwites anything we'll update the file diff --git a/klippy/console.py b/klippy/console.py index 47586df1e..b7b6e34f2 100644 --- a/klippy/console.py +++ b/klippy/console.py @@ -82,7 +82,10 @@ def connect(self, eventtime): "MCU config: %s" % ( " ".join( - ["%s=%s" % (k, v) for k, v in msgparser.get_constants().items()] + [ + "%s=%s" % (k, v) + for k, v in msgparser.get_constants().items() + ] ) ) ) @@ -194,7 +197,8 @@ def command_FLOOD(self, parts): msg = " ".join(parts[3:]) delay_clock = int(delay * self.mcu_freq) msg_clock = int( - self.clocksync.get_clock(self.reactor.monotonic()) + self.mcu_freq * 0.200 + self.clocksync.get_clock(self.reactor.monotonic()) + + self.mcu_freq * 0.200 ) try: for i in range(count): @@ -218,7 +222,9 @@ def command_SUPPRESS(self, parts): def command_STATS(self, parts): curtime = self.reactor.monotonic() - self.output(" ".join([self.ser.stats(curtime), self.clocksync.stats(curtime)])) + self.output( + " ".join([self.ser.stats(curtime), self.clocksync.stats(curtime)]) + ) def command_LIST(self, parts): self.update_evals(self.reactor.monotonic()) diff --git a/klippy/extras/adc_temperature.py b/klippy/extras/adc_temperature.py index ac1e8588c..f26fa08db 100644 --- a/klippy/extras/adc_temperature.py +++ b/klippy/extras/adc_temperature.py @@ -93,7 +93,8 @@ def interpolate(self, key): def reverse_interpolate(self, value): values = [ - key * gain + offset for key, (gain, offset) in zip(self.keys, self.slopes) + key * gain + offset + for key, (gain, offset) in zip(self.keys, self.slopes) ] if values[0] < values[-2]: valid = [i for i in range(len(values)) if values[i] >= value] @@ -592,7 +593,9 @@ def create(self, config): def calc_pt100(base=100.0): # Calc PT100/PT1000 resistances using Callendar-Van Dusen formula A, B = (3.9083e-3, -5.775e-7) - return [(float(t), base * (1.0 + A * t + B * t * t)) for t in range(0, 500, 10)] + return [ + (float(t), base * (1.0 + A * t + B * t * t)) for t in range(0, 500, 10) + ] def calc_ina826_pt100(): @@ -619,13 +622,17 @@ def load_config(config): for sensor_type, params in DefaultVoltageSensors: def func(config, params=params): - return PrinterADCtoTemperature(config, LinearVoltage(config, params)) + return PrinterADCtoTemperature( + config, LinearVoltage(config, params) + ) pheaters.add_sensor_factory(sensor_type, func) for sensor_type, params in DefaultResistanceSensors: def func(config, params=params): - return PrinterADCtoTemperature(config, LinearResistance(config, params)) + return PrinterADCtoTemperature( + config, LinearResistance(config, params) + ) pheaters.add_sensor_factory(sensor_type, func) diff --git a/klippy/extras/ads1220.py b/klippy/extras/ads1220.py index 8c01dd949..87f142ebc 100644 --- a/klippy/extras/ads1220.py +++ b/klippy/extras/ads1220.py @@ -65,7 +65,9 @@ def __init__(self, config): } self.sps_options = self.sps_normal.copy() self.sps_options.update(self.sps_turbo) - self.sps = config.getchoice("sample_rate", self.sps_options, default="660") + self.sps = config.getchoice( + "sample_rate", self.sps_options, default="660" + ) self.is_turbo = str(self.sps) in self.sps_turbo # Input multiplexer: AINP and AINN mux_options = { @@ -82,7 +84,9 @@ def __init__(self, config): "AIN2_AVSS": 0b1010, "AIN3_AVSS": 0b1011, } - self.mux = config.getchoice("input_mux", mux_options, default="AIN0_AIN1") + self.mux = config.getchoice( + "input_mux", mux_options, default="AIN0_AIN1" + ) # PGA Bypass self.pga_bypass = config.getboolean("pga_bypass", default=False) # bypass PGA when AVSS is the negative input @@ -95,7 +99,9 @@ def __init__(self, config): "REF1": 0b10, "analog_supply": 0b11, } - self.vref = config.getchoice("vref", self.vref_options, default="internal") + self.vref = config.getchoice( + "vref", self.vref_options, default="internal" + ) # check for conflict between REF1 and AIN0/AIN3 mux_conflict = [ 0b0000, diff --git a/klippy/extras/adxl345.py b/klippy/extras/adxl345.py index 33f330f9a..4ed8244ac 100644 --- a/klippy/extras/adxl345.py +++ b/klippy/extras/adxl345.py @@ -111,7 +111,9 @@ def write_impl(): f.write("#time,accel_x,accel_y,accel_z\n") samples = self.samples or self.get_samples() for t, accel_x, accel_y, accel_z in samples: - f.write("%.6f,%.6f,%.6f,%.6f\n" % (t, accel_x, accel_y, accel_z)) + f.write( + "%.6f,%.6f,%.6f,%.6f\n" % (t, accel_x, accel_y, accel_z) + ) f.close() write_proc = multiprocessing.Process(target=write_impl) @@ -123,53 +125,15 @@ def write_impl(): class AccelCommandHelper: def __init__(self, config, chip): self.printer = config.get_printer() - self.reactor = self.printer.get_reactor() self.chip = chip self.bg_client = None name_parts = config.get_name().split() self.base_name = name_parts[0] self.name = name_parts[-1] self.register_commands(self.name) - self.disabled_heaters = [] - if hasattr(config, "getlist"): - self.disabled_heaters = config.getlist( - "disable_heaters", self.disabled_heaters - ) if len(name_parts) == 1: if self.name == "adxl345" or not config.has_section("adxl345"): self.register_commands(None) - self.printer.register_event_handler("klippy:ready", self._handle_ready) - - def read_accelerometer(self): - toolhead = self.printer.lookup_object("toolhead") - aclient = self.chip.start_internal_client() - toolhead.dwell(1.0) - aclient.finish_measurements() - values = aclient.get_samples() - if not values: - raise Exception("No accelerometer measurements found") - - def _handle_ready(self): - self.reactor.register_callback(self._init_accel, self.reactor.NOW) - - def _init_accel(self, eventtime=None): - try: - self.read_accelerometer() - connected = True - except Exception as e: - connected = False - for heater_name in self.disabled_heaters: - heater_object = self.printer.lookup_object(heater_name) - if not hasattr(heater_object, "heater"): - raise self.printer.config_error( - "'%s' is not a valid heater." % (heater_name,) - ) - heater = heater_object.heater - if not hasattr(heater, "set_enabled"): - raise self.printer.config_error( - "'%s' is not a valid heater." % (heater_name,) - ) - heater.set_enabled(not connected) def register_commands(self, name): # Register commands @@ -224,7 +188,9 @@ def cmd_ACCELEROMETER_MEASURE(self, gcmd): else: filename = "/tmp/%s-%s-%s.csv" % (self.base_name, self.name, name) bg_client.write_to_file(filename) - gcmd.respond_info("Writing raw accelerometer data to %s file" % (filename,)) + gcmd.respond_info( + "Writing raw accelerometer data to %s file" % (filename,) + ) cmd_ACCELEROMETER_QUERY_help = "Query accelerometer for the current values" diff --git a/klippy/extras/aht10.py b/klippy/extras/aht10.py index ca83b8609..f892b7b06 100644 --- a/klippy/extras/aht10.py +++ b/klippy/extras/aht10.py @@ -4,13 +4,10 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import logging -import threading -import time from . import bus from extras.danger_options import get_danger_options -from extras.danger_options import get_danger_options ###################################################################### # Compatible Sensors: @@ -46,7 +43,9 @@ def __init__(self, config): ) self.ignore = self.name in get_danger_options().temp_ignore_limits self.printer.add_object("aht10 " + self.name, self) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.is_calibrated = False self.init_sent = False @@ -95,7 +94,9 @@ def _make_measurement(self): # Read data read = self.i2c.i2c_read([], 6) if read is None: - logging.warning("aht10: received data from" + " i2c_read is None") + logging.warning( + "aht10: received data from" + " i2c_read is None" + ) continue data = bytearray(read["response"]) if len(data) < 6: diff --git a/klippy/extras/angle.py b/klippy/extras/angle.py index bfc85f388..cc4d212ae 100644 --- a/klippy/extras/angle.py +++ b/klippy/extras/angle.py @@ -48,7 +48,9 @@ def __init__(self, config): self.printer.register_event_handler( "stepper:sync_mcu_position", self.handle_sync_mcu_pos ) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) cname = self.name.split()[-1] gcode = self.printer.lookup_object("gcode") gcode.register_mux_command( @@ -236,7 +238,9 @@ def handle_batch(msg): "Failed calibration - incomplete sensor data" ) fcal = {i: cal[i] for i in range(full_steps)} - rcal = {full_steps - i - 1: cal[i + full_steps] for i in range(full_steps)} + rcal = { + full_steps - i - 1: cal[i + full_steps] for i in range(full_steps) + } return fcal, rcal def calc_angles(self, meas): @@ -459,7 +463,9 @@ def start(self): mcu_clock, chip_clock = self._query_clock() self.last_chip_clock = chip_clock self.last_chip_mcu_clock = mcu_clock - self.chip_freq = float(1 << 5) / self.mcu.seconds_to_clock(1.0 / 750000.0) + self.chip_freq = float(1 << 5) / self.mcu.seconds_to_clock( + 1.0 / 750000.0 + ) self.update_clock() cmd_ANGLE_DEBUG_READ_help = "Query low-level angle sensor register" @@ -473,7 +479,9 @@ def cmd_ANGLE_DEBUG_READ(self, gcmd): def cmd_ANGLE_DEBUG_WRITE(self, gcmd): reg = gcmd.get("REG", minval=0, maxval=0x30, parser=lambda x: int(x, 0)) - val = gcmd.get("VAL", minval=0, maxval=0xFFFF, parser=lambda x: int(x, 0)) + val = gcmd.get( + "VAL", minval=0, maxval=0xFFFF, parser=lambda x: int(x, 0) + ) self._write_reg(reg, val) @@ -487,7 +495,9 @@ def cmd_ANGLE_DEBUG_WRITE(self, gcmd): class Angle: def __init__(self, config): self.printer = config.get_printer() - self.sample_period = config.getfloat("sample_period", SAMPLE_PERIOD, above=0.0) + self.sample_period = config.getfloat( + "sample_period", SAMPLE_PERIOD, above=0.0 + ) self.calibration = AngleCalibration(config) # Measurement conversion self.start_clock = self.time_shift = self.sample_ticks = 0 diff --git a/klippy/extras/axis_twist_compensation.py b/klippy/extras/axis_twist_compensation.py index 952c929b1..38286631b 100644 --- a/klippy/extras/axis_twist_compensation.py +++ b/klippy/extras/axis_twist_compensation.py @@ -44,7 +44,9 @@ def __init__(self, config): self.compensation_start_x = config.getfloat( "compensation_start_x", default=None ) - self.compensation_end_x = config.getfloat("compensation_start_y", default=None) + self.compensation_end_x = config.getfloat( + "compensation_start_y", default=None + ) self.m = None self.b = None @@ -62,7 +64,9 @@ def get_z_compensation_value(self, pos): x_coord = pos[0] z_compensations = self.z_compensations sample_count = len(z_compensations) - spacing = (self.calibrate_end_x - self.calibrate_start_x) / (sample_count - 1) + spacing = (self.calibrate_end_x - self.calibrate_start_x) / ( + sample_count - 1 + ) interpolate_t = (x_coord - self.calibrate_start_x) / spacing interpolate_i = int(math.floor(interpolate_t)) interpolate_i = BedMesh.constrain(interpolate_i, 0, sample_count - 2) @@ -94,7 +98,9 @@ def __init__(self, compensation, config): None, None, ) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.speed = compensation.speed self.horizontal_move_z = compensation.horizontal_move_z self.start_gcode = compensation.start_gcode @@ -126,7 +132,9 @@ def _handle_connect(self): self.probe = self.printer.lookup_object("probe", None) if self.probe is None: config = self.printer.lookup_object("configfile") - raise config.error("AXIS_TWIST_COMPENSATION requires [probe] to be defined") + raise config.error( + "AXIS_TWIST_COMPENSATION requires [probe] to be defined" + ) self.lift_speed = self.probe.get_lift_speed() self.probe_x_offset, self.probe_y_offset, _ = self.probe.get_offsets() @@ -156,9 +164,13 @@ def cmd_AXIS_TWIST_COMPENSATION_CALIBRATE(self, gcmd): ) manual_probe = self.printer.lookup_object("manual_probe") if manual_probe.status["is_active"]: - raise gcmd.error("Already in a manual Z probe. Use ABORT to abort it.") + raise gcmd.error( + "Already in a manual Z probe. Use ABORT to abort it." + ) self.is_active = True - self.gcode.register_command("ABORT", self.cmd_ABORT, desc=self.cmd_ABORT_help) + self.gcode.register_command( + "ABORT", self.cmd_ABORT, desc=self.cmd_ABORT_help + ) self.gcode.register_command( "QUERY_TWIST_COMPENSATION_RUNNING", self.cmd_QUERY_TWIST_COMPENSATION_RUNNING, @@ -189,7 +201,9 @@ def cmd_AXIS_TWIST_COMPENSATION_CALIBRATE(self, gcmd): # begin calibration self.current_point_index = 0 self.results = [] - self._calibration(self.probe_points, self.nozzle_points, self.interval_dist) + self._calibration( + self.probe_points, self.nozzle_points, self.interval_dist + ) def _calculate_nozzle_points(self, sample_count, interval_dist): # calculate the points to put the probe at, returned as a list of tuples @@ -200,7 +214,9 @@ def _calculate_nozzle_points(self, sample_count, interval_dist): nozzle_points.append((x, y)) return nozzle_points - def _calculate_probe_points(self, nozzle_points, probe_x_offset, probe_y_offset): + def _calculate_probe_points( + self, nozzle_points, probe_x_offset, probe_y_offset + ): # calculate the points to put the nozzle at # returned as a list of tuples probe_points = [] @@ -226,7 +242,8 @@ def _calibration(self, probe_points, nozzle_points, interval): # begin the calibration process self.gcmd.respond_info( "AXIS_TWIST_COMPENSATION_CALIBRATE: " - "Probing point %d of %d" % (self.current_point_index + 1, len(probe_points)) + "Probing point %d of %d" + % (self.current_point_index + 1, len(probe_points)) ) # horizontal_move_z (to prevent probe trigger or hitting bed) @@ -256,7 +273,9 @@ def _calibration(self, probe_points, nozzle_points, interval): ManualProbe.ManualProbeHelper( self.printer, self.gcmd, - self._manual_probe_callback_factory(probe_points, nozzle_points, interval), + self._manual_probe_callback_factory( + probe_points, nozzle_points, interval + ), ) def _manual_probe_callback_factory( @@ -312,7 +331,9 @@ def callback(kin_pos): def cmd_CONTINUE(self, gcmd): self.gcode.register_command("CONTINUE", None) - self._calibration(self.probe_points, self.nozzle_points, self.interval_dist) + self._calibration( + self.probe_points, self.nozzle_points, self.interval_dist + ) cmd_QUERY_TWIST_COMPENSATION_RUNNING_help = """Query if we are running a twist compensation""" @@ -325,7 +346,8 @@ def cmd_QUERY_TWIST_COMPENSATION_RUNNING(self, gcmd): def cmd_ABORT(self, gcmd=None): self.gcmd.respond_info( - "AXIS_TWIST_COMPENSATION_CALIBRATE: Probe cancelled, " "calibration aborted" + "AXIS_TWIST_COMPENSATION_CALIBRATE: Probe cancelled, " + "calibration aborted" ) self.abort_gcode.run_gcode_from_command() self.is_active = False @@ -344,7 +366,9 @@ def _finalize_calibration(self): configfile = self.printer.lookup_object("configfile") values_as_str = ", ".join(["{:.6f}".format(x) for x in self.results]) configfile.set(self.configname, "z_compensations", values_as_str) - configfile.set(self.configname, "compensation_start_x", self.start_point[0]) + configfile.set( + self.configname, "compensation_start_x", self.start_point[0] + ) configfile.set(self.configname, "compensation_end_x", self.end_point[0]) self.compensation.z_compensations = self.results self.compensation.compensation_start_x = self.start_point[0] diff --git a/klippy/extras/bed_mesh.py b/klippy/extras/bed_mesh.py index 007d056d1..9755df9e3 100644 --- a/klippy/extras/bed_mesh.py +++ b/klippy/extras/bed_mesh.py @@ -51,7 +51,13 @@ def lerp(t, v0, v1): # retreive commma separated pair from config def parse_config_pair( - config, option, default, minval=None, maxval=None, default_x=None, default_y=None + config, + option, + default, + minval=None, + maxval=None, + default_x=None, + default_y=None, ): default_x = default if default_x is None else default_x default_y = default if default_y is None else default_y @@ -59,7 +65,8 @@ def parse_config_pair( if len(pair) != 2: if len(pair) != 1: raise config.error( - "bed_mesh: malformed '%s' value: %s" % (option, config.get(option)) + "bed_mesh: malformed '%s' value: %s" + % (option, config.get(option)) ) pair = (pair[0], pair[0]) if minval is not None: @@ -114,7 +121,9 @@ class BedMesh: def __init__(self, config): self.printer = config.get_printer() - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) config_file = self.printer.lookup_object("configfile") self.last_position = [0.0, 0.0, 0.0, 0.0] self.bmc = BedMeshCalibrate(config, self) @@ -185,7 +194,10 @@ def set_mesh(self, mesh): else: self.fade_target = self.base_fade_target min_z, max_z = mesh.get_z_range() - if not min_z <= self.fade_target <= max_z and self.fade_target != 0.0: + if ( + not min_z <= self.fade_target <= max_z + and self.fade_target != 0.0 + ): # fade target is non-zero, out of mesh range err_target = self.fade_target self.z_mesh = None @@ -271,7 +283,9 @@ def move(self, newpos, speed): if split_move: self.toolhead.move(split_move, speed) else: - raise self.gcode.error("Mesh Leveling: Error splitting move ") + raise self.gcode.error( + "Mesh Leveling: Error splitting move " + ) self.last_position[:] = newpos def get_status(self, eventtime=None): @@ -376,7 +390,10 @@ def __init__(self, config, bedmesh): self._generate_points(config.error) self._profile_name = "default" self.probe_helper = probe.ProbePointsHelper( - config, self.probe_finalize, self._get_adjusted_points() + config, + self.probe_finalize, + self._get_adjusted_points(), + use_probe_offsets=True, ) self.scan_speed = None if self.radius is None: @@ -384,7 +401,7 @@ def __init__(self, config, bedmesh): "scan_speed", self.probe_helper.speed, above=0.0 ) self.probe_helper.minimum_points(3) - self.probe_helper.use_xy_offsets(True) + # self.probe_helper.use_xy_offsets(True) self.gcode = self.printer.lookup_object("gcode") self.gcode.register_command( "BED_MESH_CALIBRATE", @@ -431,7 +448,9 @@ def _generate_points(self, error, probe_method="automatic"): # round bed, check distance from origin dist_from_origin = math.sqrt(pos_x * pos_x + pos_y * pos_y) if dist_from_origin <= self.radius: - points.append((self.origin[0] + pos_x, self.origin[1] + pos_y)) + points.append( + (self.origin[0] + pos_x, self.origin[1] + pos_y) + ) pos_y += y_dist self.points = points if self.zero_ref_pos is None or probe_method == "manual": @@ -511,7 +530,9 @@ def print_generated_points(self, print_func): probe = self.printer.lookup_object("probe", None) if probe is not None: x_offset, y_offset = probe.get_offsets()[:2] - print_func("bed_mesh: generated points\nIndex" " | Tool Adjusted | Probe") + print_func( + "bed_mesh: generated points\nIndex" " | Tool Adjusted | Probe" + ) for i, (x, y) in enumerate(self.points): adj_pt = "(%.1f, %.1f)" % (x - x_offset, y - y_offset) mesh_pt = "(%.1f, %.1f)" % (x, y) @@ -535,11 +556,15 @@ def _init_mesh_config(self, config): orig_cfg = self.orig_config self.radius = config.getfloat("mesh_radius", None, above=0.0) if self.radius is not None: - self.origin = config.getfloatlist("mesh_origin", (0.0, 0.0), count=2) + self.origin = config.getfloatlist( + "mesh_origin", (0.0, 0.0), count=2 + ) x_cnt = y_cnt = config.getint("round_probe_count", 5, minval=3) # round beds must have an odd number of points along each axis if not x_cnt & 1: - raise config.error("bed_mesh: probe_count must be odd for round beds") + raise config.error( + "bed_mesh: probe_count must be odd for round beds" + ) # radius may have precision to .1mm self.radius = math.floor(self.radius * 10) / 10 orig_cfg["radius"] = self.radius @@ -575,6 +600,9 @@ def _init_mesh_config(self, config): self.scan_algo = None self.scan_tension = None if self.radius is None: + # config.get("contact_mesh_min", None) + # config.get("contact_mesh_max", None) + self.scan_probe_count = parse_config_pair( config, "scan_probe_count", @@ -598,14 +626,16 @@ def _init_mesh_config(self, config): ) self.scan_tension = config.getfloat( - "scan_bicubic_tension", orig_cfg["tension"], minval=0.0, maxval=2.0 + "scan_bicubic_tension", + orig_cfg["tension"], + minval=0.0, + maxval=2.0, ) - config.get("contact_mesh_min", None) - config.get("contact_mesh_max", None) - for i in list(range(1, 100, 1)): - start = config.getfloatlist("faulty_region_%d_min" % (i,), None, count=2) + start = config.getfloatlist( + "faulty_region_%d_min" % (i,), None, count=2 + ) if start is None: break end = config.getfloatlist("faulty_region_%d_max" % (i,), count=2) @@ -656,7 +686,9 @@ def _verify_algorithm(self, error): x_pps = params["mesh_x_pps"] y_pps = params["mesh_y_pps"] if params["algo"] not in self.ALGOS: - raise error("bed_mesh: Unknown algorithm <%s>" % (self.mesh_config["algo"])) + raise error( + "bed_mesh: Unknown algorithm <%s>" % (self.mesh_config["algo"]) + ) # Check the algorithm against the current configuration max_probe_cnt = max(params["x_count"], params["y_count"]) min_probe_cnt = min(params["x_count"], params["y_count"]) @@ -739,9 +771,15 @@ def set_adaptive_mesh(self, gcmd): # Compute a ratio between the adapted and original sizes ratio = ( adjusted_mesh_size[0] - / (self.orig_config["mesh_max"][0] - self.orig_config["mesh_min"][0]), + / ( + self.orig_config["mesh_max"][0] + - self.orig_config["mesh_min"][0] + ), adjusted_mesh_size[1] - / (self.orig_config["mesh_max"][1] - self.orig_config["mesh_min"][1]), + / ( + self.orig_config["mesh_max"][1] + - self.orig_config["mesh_min"][1] + ), ) gcmd.respond_info( @@ -753,12 +791,17 @@ def set_adaptive_mesh(self, gcmd): % (self.mesh_config["x_count"], self.mesh_config["y_count"]) ) gcmd.respond_info( - "Adapted mesh bounds: (%s,%s)" % (adjusted_mesh_min, adjusted_mesh_max) + "Adapted mesh bounds: (%s,%s)" + % (adjusted_mesh_min, adjusted_mesh_max) ) gcmd.respond_info("Ratio: (%s, %s)" % ratio) - new_x_probe_count = int(math.ceil(self.mesh_config["x_count"] * ratio[0])) - new_y_probe_count = int(math.ceil(self.mesh_config["y_count"] * ratio[1])) + new_x_probe_count = int( + math.ceil(self.mesh_config["x_count"] * ratio[0]) + ) + new_y_probe_count = int( + math.ceil(self.mesh_config["y_count"] * ratio[1]) + ) # There is one case, where we may have to adjust the probe counts: # axis0 < 4 and axis1 > 6 (see _verify_algorithm). @@ -773,7 +816,8 @@ def set_adaptive_mesh(self, gcmd): new_y_probe_count = max(min_num_of_probes, new_y_probe_count) gcmd.respond_info( - "Adapted probe count: (%s,%s)" % (new_x_probe_count, new_y_probe_count) + "Adapted probe count: (%s,%s)" + % (new_x_probe_count, new_y_probe_count) ) # If the adapted mesh size is too small, adjust it to something @@ -785,7 +829,9 @@ def set_adaptive_mesh(self, gcmd): if self.radius is not None: adapted_radius = ( - math.sqrt((adjusted_mesh_size[0] ** 2) + (adjusted_mesh_size[1] ** 2)) + math.sqrt( + (adjusted_mesh_size[0] ** 2) + (adjusted_mesh_size[1] ** 2) + ) / 2 ) adapted_origin = ( @@ -923,7 +969,8 @@ def cmd_BED_MESH_CALIBRATE(self, gcmd): ) if beacon is not None: if ( - gcmd.get("PROBE_METHOD", beacon.default_mesh_method).lower() == "scan" + gcmd.get("PROBE_METHOD", beacon.default_mesh_method).lower() + == "scan" and horizontal_move_z <= beacon.trigger_dive_threshold ): beacon_scan = True @@ -938,7 +985,8 @@ def probe_finalize(self, offsets, positions): ref_pos = positions.pop() logging.info( "bed_mesh: z-offset replaced with probed z value at " - "position (%.2f, %.2f, %.6f)" % (ref_pos[0], ref_pos[1], ref_pos[2]) + "position (%.2f, %.2f, %.6f)" + % (ref_pos[0], ref_pos[1], ref_pos[2]) ) z_offset = ref_pos[2] params = dict(self.mesh_config) @@ -962,7 +1010,9 @@ def probe_finalize(self, offsets, positions): idx = i + idx_offset # Add "normal" points corrected_pts.extend(positions[start_idx:idx]) - avg_z = sum([p[2] for p in positions[idx : idx + len(pts)]]) / len(pts) + avg_z = sum( + [p[2] for p in positions[idx : idx + len(pts)]] + ) / len(pts) idx_offset += len(pts) - 1 start_idx = idx + len(pts) fpt.append(avg_z) @@ -983,9 +1033,9 @@ def probe_finalize(self, offsets, positions): ) for gen_pt, probed in zip(self.points, corrected_pts): off_pt = [p - o for p, o in zip(gen_pt, offsets[:2])] - if not isclose(off_pt[0], probed[0], abs_tol=0.1) or not isclose( - off_pt[1], probed[1], abs_tol=0.1 - ): + if not isclose( + off_pt[0], probed[0], abs_tol=0.1 + ) or not isclose(off_pt[1], probed[1], abs_tol=0.1): self._dump_points(positions, corrected_pts, offsets) raise self.gcode.error( "bed_mesh: point mismatch, orig = (%.2f, %.2f)" @@ -1083,14 +1133,18 @@ def _dump_points(self, probed_pts, corrected_pts, offsets): probed_pt = "(%.2f, %.2f, %.4f)" % tuple(probed_pts[i]) if i < len(corrected_pts): corr_pt = "(%.2f, %.2f, %.4f)" % tuple(corrected_pts[i]) - logging.info(" %-4d| %-17s| %-25s| %s" % (i, gen_pt, probed_pt, corr_pt)) + logging.info( + " %-4d| %-17s| %-25s| %s" % (i, gen_pt, probed_pt, corr_pt) + ) class MoveSplitter: def __init__(self, config, gcode): - self.split_delta_z = config.getfloat("split_delta_z", 0.025, minval=0.01) + self.split_delta_z = config.getfloat( + "split_delta_z", 0.025, minval=0.01 + ) self.move_check_distance = config.getfloat( - "move_check_distance", 5.0, minval=3.0 + "move_check_distance", 5.0, minval=2.5 ) self.z_mesh = None self.fade_offset = 0.0 @@ -1126,7 +1180,9 @@ def _set_next_move(self, distance_from_prev): ) for i in range(4): if self.axis_move[i]: - self.current_pos[i] = lerp(t, self.prev_pos[i], self.next_pos[i]) + self.current_pos[i] = lerp( + t, self.prev_pos[i], self.next_pos[i] + ) def split(self): if not self.traverse_complete: @@ -1202,8 +1258,12 @@ def __init__(self, params, name): "bed_mesh: Mesh grid size - X:%d, Y:%d" % (self.mesh_x_count, self.mesh_y_count) ) - self.mesh_x_dist = (self.mesh_x_max - self.mesh_x_min) / (self.mesh_x_count - 1) - self.mesh_y_dist = (self.mesh_y_max - self.mesh_y_min) / (self.mesh_y_count - 1) + self.mesh_x_dist = (self.mesh_x_max - self.mesh_x_min) / ( + self.mesh_x_count - 1 + ) + self.mesh_y_dist = (self.mesh_y_max - self.mesh_y_min) / ( + self.mesh_y_count - 1 + ) def get_mesh_matrix(self): if self.mesh_matrix is not None: @@ -1529,7 +1589,9 @@ def __init__(self, config, bedmesh): self.profiles[name] = {} zvals = profile.getlists("points", seps=(",", "\n"), parser=float) self.profiles[name]["points"] = zvals - self.profiles[name]["mesh_params"] = params = collections.OrderedDict() + self.profiles[name]["mesh_params"] = params = ( + collections.OrderedDict() + ) for key, t in PROFILE_OPTIONS.items(): if t is int: params[key] = profile.getint(key) @@ -1594,7 +1656,8 @@ def save_profile(self, prof_name): self.gcode.respond_info( "Bed Mesh state has been saved to profile [%s]\n" "for the current session. The SAVE_CONFIG command will\n" - "update the printer config file and restart the printer." % (prof_name) + "update the printer config file and restart the printer." + % (prof_name) ) def load_profile(self, prof_name): @@ -1624,7 +1687,9 @@ def remove_profile(self, prof_name): "configuration and restart the printer" % (prof_name) ) else: - self.gcode.respond_info("No profile named [%s] to remove" % (prof_name)) + self.gcode.respond_info( + "No profile named [%s] to remove" % (prof_name) + ) cmd_BED_MESH_PROFILE_help = "Bed Mesh Persistent Storage management" diff --git a/klippy/extras/bed_screws.py b/klippy/extras/bed_screws.py index 28be0e163..f0530633d 100644 --- a/klippy/extras/bed_screws.py +++ b/klippy/extras/bed_screws.py @@ -74,7 +74,9 @@ def move_to_screw(self, state, screw): self.gcode.register_command( "ADJUSTED", self.cmd_ADJUSTED, desc=self.cmd_ADJUSTED_help ) - self.gcode.register_command("ABORT", self.cmd_ABORT, desc=self.cmd_ABORT_help) + self.gcode.register_command( + "ABORT", self.cmd_ABORT, desc=self.cmd_ABORT_help + ) def unregister_commands(self): self.gcode.register_command("ACCEPT", None) diff --git a/klippy/extras/bed_tilt.py b/klippy/extras/bed_tilt.py index 57dc6dd64..3705b0bc8 100644 --- a/klippy/extras/bed_tilt.py +++ b/klippy/extras/bed_tilt.py @@ -11,7 +11,9 @@ class BedTilt: def __init__(self, config): self.printer = config.get_printer() - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.x_adjust = config.getfloat("x_adjust", 0.0) self.y_adjust = config.getfloat("y_adjust", 0.0) self.z_adjust = config.getfloat("z_adjust", 0.0) @@ -93,7 +95,10 @@ def probe_finalize(self, offsets, positions): def adjusted_height(pos, params): x, y, z = pos return ( - z - x * params["x_adjust"] - y * params["y_adjust"] - params["z_adjust"] + z + - x * params["x_adjust"] + - y * params["y_adjust"] + - params["z_adjust"] ) def errorfunc(params): @@ -102,7 +107,9 @@ def errorfunc(params): total_error += adjusted_height(pos, params) ** 2 return total_error - new_params = mathutil.coordinate_descent(params.keys(), params, errorfunc) + new_params = mathutil.coordinate_descent( + params.keys(), params, errorfunc + ) # Update current bed_tilt calculations x_adjust = new_params["x_adjust"] y_adjust = new_params["y_adjust"] diff --git a/klippy/extras/belay.py b/klippy/extras/belay.py index 5c483bab3..57cf314ae 100644 --- a/klippy/extras/belay.py +++ b/klippy/extras/belay.py @@ -14,7 +14,9 @@ def __init__(self, config): # initial type-specific setup type_options = ["trad_rack", "extruder_stepper"] - self.type = config.getchoice("extruder_type", {t: t for t in type_options}) + self.type = config.getchoice( + "extruder_type", {t: t for t in type_options} + ) if self.type == "trad_rack": enable_events = ["trad_rack:synced_to_extruder"] disable_events = ["trad_rack:unsyncing_from_extruder"] @@ -26,7 +28,9 @@ def __init__(self, config): self.enable_initial = True # register event handlers - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.printer.register_event_handler("klippy:ready", self._handle_ready) for event in enable_events: self.printer.register_event_handler(event, self.handle_enable) @@ -59,7 +63,9 @@ def __init__(self, config): self.disable_conditions = [lambda: self.enabled] self.gcode = self.printer.lookup_object("gcode") self.toolhead = None - self.update_direction_timer = self.reactor.register_timer(self.update_direction) + self.update_direction_timer = self.reactor.register_timer( + self.update_direction + ) # register commands self.gcode.register_mux_command( @@ -126,7 +132,9 @@ def handle_disable(self): if not condition(): return self.reset_multiplier() - self.reactor.update_timer(self.update_direction_timer, self.reactor.NEVER) + self.reactor.update_timer( + self.update_direction_timer, self.reactor.NEVER + ) self.enabled = False def sensor_callback(self, eventtime, state): @@ -185,7 +193,9 @@ def cmd_QUERY_BELAY(self, gcmd): ) def cmd_BELAY_SET_MULTIPLIER(self, gcmd): - self.multiplier_high = gcmd.get_float("HIGH", self.multiplier_high, minval=1.0) + self.multiplier_high = gcmd.get_float( + "HIGH", self.multiplier_high, minval=1.0 + ) self.multiplier_low = gcmd.get_float( "LOW", self.multiplier_low, minval=0.0, maxval=1.0 ) diff --git a/klippy/extras/bltouch.py b/klippy/extras/bltouch.py index 8f5a262b6..3057c2b6d 100644 --- a/klippy/extras/bltouch.py +++ b/klippy/extras/bltouch.py @@ -37,13 +37,19 @@ class BLTouchEndstopWrapper: def __init__(self, config): self.printer = config.get_printer() - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.printer.register_event_handler( "klippy:mcu_identify", self.handle_mcu_identify ) self.position_endstop = config.getfloat("z_offset", minval=0.0) - self.stow_on_each_sample = config.getboolean("stow_on_each_sample", True) - self.probe_touch_mode = config.getboolean("probe_with_touch_mode", False) + self.stow_on_each_sample = config.getboolean( + "stow_on_each_sample", True + ) + self.probe_touch_mode = config.getboolean( + "probe_with_touch_mode", False + ) # Create a pwm object to handle the control pin ppins = self.printer.lookup_object("pins") self.mcu_pwm = ppins.setup_pin("pwm", config.get("control_pin")) @@ -144,7 +150,9 @@ def verify_state(self, triggered): triggered=triggered, ) try: - trigger_time = self.mcu_endstop.home_wait(self.action_end_time + 0.100) + trigger_time = self.mcu_endstop.home_wait( + self.action_end_time + 0.100 + ) except self.printer.command_error as e: return False return trigger_time > 0.0 @@ -165,7 +173,9 @@ def verify_raise_probe(self): # The "probe raised" test completed successfully break if retry >= 2: - raise self.printer.command_error("BLTouch failed to raise probe") + raise self.printer.command_error( + "BLTouch failed to raise probe" + ) msg = "Failed to verify BLTouch probe is raised; retrying." self.gcode.respond_info(msg) self.sync_mcu_print_time() diff --git a/klippy/extras/bme280.py b/klippy/extras/bme280.py index 26b20a8ba..3e1ca1e88 100644 --- a/klippy/extras/bme280.py +++ b/klippy/extras/bme280.py @@ -198,7 +198,9 @@ def __init__(self, config): return self.last_gas_time = 0 - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): self._init_bmxx80() @@ -326,7 +328,8 @@ def read_calibration_data_bmp180(calib_data_1): else: self.chip_type = BME_CHIPS[chip_id] logging.info( - "bme280: Found Chip %s at %#x" % (self.chip_type, self.i2c.i2c_address) + "bme280: Found Chip %s at %#x" + % (self.chip_type, self.i2c.i2c_address) ) # Reset chip @@ -481,7 +484,9 @@ def _sample_bme280(self, eventtime): if self.chip_type == "BME280": humid_raw = (data[6] << 8) | data[7] self.humidity = self._compensate_humidity_bme280(humid_raw) - if (self.temp < self.min_temp or self.temp > self.max_temp) and not self.ignore: + if ( + self.temp < self.min_temp or self.temp > self.max_temp + ) and not self.ignore: self.printer.invoke_shutdown( "BME280 temperature %0.1f outside range of %0.1f-%.01f" % (self.temp, self.min_temp, self.max_temp) @@ -602,7 +607,9 @@ def data_ready(stat, run_gas): # wait until results are ready status = self.read_register("EAS_STATUS_0", 1)[0] while not data_ready(status, run_gas): - self.reactor.pause(self.reactor.monotonic() + self.max_sample_time) + self.reactor.pause( + self.reactor.monotonic() + self.max_sample_time + ) status = self.read_register("EAS_STATUS_0", 1)[0] data = self.read_register("PRESSURE_MSB", 8) @@ -619,7 +626,9 @@ def data_ready(stat, run_gas): self.temp = self._compensate_temp(temp_raw) pressure_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4) if pressure_raw != 0x80000: - self.pressure = self._compensate_pressure_bme680(pressure_raw) / 100.0 + self.pressure = ( + self._compensate_pressure_bme680(pressure_raw) / 100.0 + ) humid_raw = (data[6] << 8) | data[7] self.humidity = self._compensate_humidity_bme680(humid_raw) @@ -701,7 +710,9 @@ def _compensate_pressure_bme280(self, raw_pressure): var2 = var1 * var1 * dig["P6"] / 32768.0 var2 = var2 + var1 * dig["P5"] * 2.0 var2 = var2 / 4.0 + (dig["P4"] * 65536.0) - var1 = (dig["P3"] * var1 * var1 / 524288.0 + dig["P2"] * var1) / 524288.0 + var1 = ( + dig["P3"] * var1 * var1 / 524288.0 + dig["P2"] * var1 + ) / 524288.0 var1 = (1.0 + var1 / 32768.0) * dig["P1"] if var1 == 0: return 0.0 @@ -760,7 +771,9 @@ def _compensate_humidity_bme680(self, raw_humidity): dig = self.dig temp_comp = self.temp - var1 = raw_humidity - ((dig["H1"] * 16.0) + ((dig["H3"] / 2.0) * temp_comp)) + var1 = raw_humidity - ( + (dig["H1"] * 16.0) + ((dig["H3"] / 2.0) * temp_comp) + ) var2 = var1 * ( (dig["H2"] / 262144.0) * ( @@ -776,8 +789,12 @@ def _compensate_humidity_bme680(self, raw_humidity): def _compensate_gas(self, gas_raw, gas_range): gas_switching_error = self.read_register("RANGE_SWITCHING_ERROR", 1)[0] - var1 = (1340.0 + 5.0 * gas_switching_error) * BME680_GAS_CONSTANTS[gas_range][0] - gas = var1 * BME680_GAS_CONSTANTS[gas_range][1] / (gas_raw - 512.0 + var1) + var1 = (1340.0 + 5.0 * gas_switching_error) * BME680_GAS_CONSTANTS[ + gas_range + ][0] + gas = ( + var1 * BME680_GAS_CONSTANTS[gas_range][1] / (gas_raw - 512.0 + var1) + ) return gas def _calc_gas_heater_resistance(self, target_temp): diff --git a/klippy/extras/bulk_sensor.py b/klippy/extras/bulk_sensor.py index 8eaf8c807..a29f6c7ad 100644 --- a/klippy/extras/bulk_sensor.py +++ b/klippy/extras/bulk_sensor.py @@ -203,13 +203,16 @@ def update(self, mcu_clock, chip_clock): diff_chip_clock = chip_clock - self.chip_clock_avg self.chip_clock_avg += decay * diff_chip_clock self.chip_clock_covariance = (1.0 - decay) * ( - self.chip_clock_covariance + diff_mcu_clock * diff_chip_clock * decay + self.chip_clock_covariance + + diff_mcu_clock * diff_chip_clock * decay ) def set_last_chip_clock(self, chip_clock): base_mcu, base_chip, inv_cfreq = self.get_clock_translation() self.last_chip_clock = chip_clock - self.last_exp_mcu_clock = base_mcu + (chip_clock - base_chip) * inv_cfreq + self.last_exp_mcu_clock = ( + base_mcu + (chip_clock - base_chip) * inv_cfreq + ) def get_clock_translation(self): inv_chip_freq = self.mcu_clock_variance / self.chip_clock_covariance diff --git a/klippy/extras/bus.py b/klippy/extras/bus.py index 4a9a22a52..f5d221ce5 100644 --- a/klippy/extras/bus.py +++ b/klippy/extras/bus.py @@ -41,7 +41,9 @@ def resolve_bus_name(mcu, param, bus): # Helper code for working with devices connected to an MCU via an SPI bus class MCU_SPI: - def __init__(self, mcu, bus, pin, mode, speed, sw_pins=None, cs_active_high=False): + def __init__( + self, mcu, bus, pin, mode, speed, sw_pins=None, cs_active_high=False + ): self.mcu = mcu self.bus = bus # Config SPI object (set all CS pins high before spi_set_bus commands) @@ -61,10 +63,13 @@ def __init__(self, mcu, bus, pin, mode, speed, sw_pins=None, cs_active_high=Fals % (self.oid, sw_pins[0], sw_pins[1], sw_pins[2], mode, speed) ) else: - self.config_fmt = "spi_set_bus oid=%d spi_bus=%%s mode=%d rate=%d" % ( - self.oid, - mode, - speed, + self.config_fmt = ( + "spi_set_bus oid=%d spi_bus=%%s mode=%d rate=%d" + % ( + self.oid, + mode, + speed, + ) ) self.cmd_queue = mcu.alloc_command_queue() mcu.register_config_callback(self.build_config) @@ -109,14 +114,18 @@ def spi_send(self, data, minclock=0, reqclock=0): "spi_send oid=%d data=%s" % (self.oid, data_msg), is_init=True ) return - self.spi_send_cmd.send([self.oid, data], minclock=minclock, reqclock=reqclock) + self.spi_send_cmd.send( + [self.oid, data], minclock=minclock, reqclock=reqclock + ) def spi_transfer(self, data, minclock=0, reqclock=0): return self.spi_transfer_cmd.send( [self.oid, data], minclock=minclock, reqclock=reqclock ) - def spi_transfer_with_preface(self, preface_data, data, minclock=0, reqclock=0): + def spi_transfer_with_preface( + self, preface_data, data, minclock=0, reqclock=0 + ): return self.spi_transfer_cmd.send_with_preface( self.spi_send_cmd, [self.oid, preface_data], @@ -151,7 +160,8 @@ def MCU_SPI_from_config( "spi_software_%s_pin" % (name,) for name in ["miso", "mosi", "sclk"] ] sw_pin_params = [ - ppins.lookup_pin(config.get(name), share_type=name) for name in sw_pin_names + ppins.lookup_pin(config.get(name), share_type=name) + for name in sw_pin_names ] for pin_params in sw_pin_params: if pin_params["chip"] != mcu: @@ -188,10 +198,13 @@ def __init__(self, mcu, bus, addr, speed, sw_pins=None): % (self.oid, sw_pins[0], sw_pins[1], speed, addr) ) else: - self.config_fmt = "i2c_set_bus oid=%d i2c_bus=%%s rate=%d address=%d" % ( - self.oid, - speed, - addr, + self.config_fmt = ( + "i2c_set_bus oid=%d i2c_bus=%%s rate=%d address=%d" + % ( + self.oid, + speed, + addr, + ) ) self.cmd_queue = self.mcu.alloc_command_queue() self.mcu.register_config_callback(self.build_config) @@ -232,7 +245,9 @@ def i2c_write(self, data, minclock=0, reqclock=0): "i2c_write oid=%d data=%s" % (self.oid, data_msg), is_init=True ) return - self.i2c_write_cmd.send([self.oid, data], minclock=minclock, reqclock=reqclock) + self.i2c_write_cmd.send( + [self.oid, data], minclock=minclock, reqclock=reqclock + ) def i2c_write_wait_ack(self, data, minclock=0, reqclock=0): self.i2c_write_cmd.send_wait_ack( @@ -242,7 +257,9 @@ def i2c_write_wait_ack(self, data, minclock=0, reqclock=0): def i2c_read(self, write, read_len): return self.i2c_read_cmd.send([self.oid, write, read_len]) - def i2c_modify_bits(self, reg, clear_bits, set_bits, minclock=0, reqclock=0): + def i2c_modify_bits( + self, reg, clear_bits, set_bits, minclock=0, reqclock=0 + ): clearset = clear_bits + set_bits if self.i2c_modify_bits_cmd is None: # Send setup message via mcu initialization @@ -271,9 +288,12 @@ def MCU_I2C_from_config(config, default_addr=None, default_speed=100000): # Determine pin from config ppins = config.get_printer().lookup_object("pins") if config.get("i2c_software_scl_pin", None) is not None: - sw_pin_names = ["i2c_software_%s_pin" % (name,) for name in ["scl", "sda"]] + sw_pin_names = [ + "i2c_software_%s_pin" % (name,) for name in ["scl", "sda"] + ] sw_pin_params = [ - ppins.lookup_pin(config.get(name), share_type=name) for name in sw_pin_names + ppins.lookup_pin(config.get(name), share_type=name) + for name in sw_pin_names ] sw_pins = tuple([pin_params["pin"] for pin_params in sw_pin_params]) bus = None @@ -297,7 +317,9 @@ def __init__(self, mcu, pin_desc, cmd_queue=None, value=0): ppins = mcu.get_printer().lookup_object("pins") pin_params = ppins.lookup_pin(pin_desc) if pin_params["chip"] is not mcu: - raise ppins.error("Pin %s must be on mcu %s" % (pin_desc, mcu.get_name())) + raise ppins.error( + "Pin %s must be on mcu %s" % (pin_desc, mcu.get_name()) + ) mcu.add_config_cmd( "config_digital_out oid=%d pin=%s value=%d" " default_value=%d max_duration=%d" diff --git a/klippy/extras/buttons.py b/klippy/extras/buttons.py index 0bf814b49..6b709dcc4 100644 --- a/klippy/extras/buttons.py +++ b/klippy/extras/buttons.py @@ -39,7 +39,8 @@ def build_config(self): return self.oid = self.mcu.create_oid() self.mcu.add_config_cmd( - "config_buttons oid=%d button_count=%d" % (self.oid, len(self.pin_list)) + "config_buttons oid=%d button_count=%d" + % (self.oid, len(self.pin_list)) ) for i, (pin, pull_up) in enumerate(self.pin_list): self.mcu.add_config_cmd( @@ -59,7 +60,9 @@ def build_config(self): % (self.oid, clock, rest_ticks, RETRANSMIT_COUNT, self.invert), is_init=True, ) - self.mcu.register_response(self.handle_buttons_state, "buttons_state", self.oid) + self.mcu.register_response( + self.handle_buttons_state, "buttons_state", self.oid + ) def handle_buttons_state(self, params): # Expand the message ack_count from 8-bit @@ -158,7 +161,9 @@ def adc_callback(self, read_time, read_value): def call_button(self, button, state): minval, maxval, callback = self.buttons[button] - self.reactor.register_async_callback((lambda e, cb=callback, s=state: cb(e, s))) + self.reactor.register_async_callback( + (lambda e, cb=callback, s=state: cb(e, s)) + ) ###################################################################### @@ -326,8 +331,13 @@ def register_buttons(self, pins, callback): pin_params_list.append(pin_params) # Register pins and callback with the appropriate MCU mcu_buttons = self.mcu_buttons.get(mcu_name) - if mcu_buttons is None or len(mcu_buttons.pin_list) + len(pin_params_list) > 8: - self.mcu_buttons[mcu_name] = mcu_buttons = MCU_buttons(self.printer, mcu) + if ( + mcu_buttons is None + or len(mcu_buttons.pin_list) + len(pin_params_list) > 8 + ): + self.mcu_buttons[mcu_name] = mcu_buttons = MCU_buttons( + self.printer, mcu + ) mcu_buttons.setup_buttons(pin_params_list, callback) def register_rotary_encoder( diff --git a/klippy/extras/canbus_ids.py b/klippy/extras/canbus_ids.py index f0c960167..78e2ee197 100644 --- a/klippy/extras/canbus_ids.py +++ b/klippy/extras/canbus_ids.py @@ -21,7 +21,9 @@ def add_uuid(self, config, canbus_uuid, canbus_iface): def get_nodeid(self, canbus_uuid): if canbus_uuid not in self.ids: - raise self.printer.config_error("Unknown canbus_uuid %s" % (canbus_uuid,)) + raise self.printer.config_error( + "Unknown canbus_uuid %s" % (canbus_uuid,) + ) return self.ids[canbus_uuid] diff --git a/klippy/extras/cold_extrude.py b/klippy/extras/cold_extrude.py index 1b58219dd..65e241a36 100644 --- a/klippy/extras/cold_extrude.py +++ b/klippy/extras/cold_extrude.py @@ -64,9 +64,12 @@ def set_cold_extrude( "printer config file and restart the " "printer." % (heater.min_extrude_temp, heater.name) ) - logging.info("COLD_EXTRUDE min_extrude_temp set to [%f]" % min_extrude_temp) + logging.info( + "COLD_EXTRUDE min_extrude_temp set to [%f]" % min_extrude_temp + ) heater.can_extrude = ( - heater.smoothed_temp >= heater.min_extrude_temp or heater.cold_extrude + heater.smoothed_temp >= heater.min_extrude_temp + or heater.cold_extrude ) diff --git a/klippy/extras/controller_fan.py b/klippy/extras/controller_fan.py index c70af4c48..23ebd339b 100644 --- a/klippy/extras/controller_fan.py +++ b/klippy/extras/controller_fan.py @@ -3,9 +3,6 @@ # Copyright (C) 2019 Nils Friedchen # # This file may be distributed under the terms of the GNU GPLv3 license. -import logging -import threading -import time from . import fan @@ -18,9 +15,13 @@ def __init__(self, config, defined_fan=None): self.name = self.full_name.split()[-1] self.printer = config.get_printer() self.klipper_threads = self.printer.get_klipper_threads() - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) if defined_fan is None: - self.printer.register_event_handler("klippy:ready", self._handle_ready) + self.printer.register_event_handler( + "klippy:ready", self._handle_ready + ) self.fan = fan.Fan(config) else: self.fan = defined_fan @@ -62,7 +63,9 @@ def _handle_connect(self): pheaters.lookup_heater(n) for n in pheaters.available_heaters ] else: - self.heaters = [pheaters.lookup_heater(n) for n in self.heater_names] + self.heaters = [ + pheaters.lookup_heater(n) for n in self.heater_names + ] # Stepper lookup all_steppers = self.stepper_enable.get_steppers() if self.stepper_names is None: diff --git a/klippy/extras/controller_temperature_fan.py b/klippy/extras/controller_temperature_fan.py index bf393fb42..b10c930a3 100644 --- a/klippy/extras/controller_temperature_fan.py +++ b/klippy/extras/controller_temperature_fan.py @@ -3,7 +3,6 @@ # Copyright (C) 2016-2020 Kevin O'Connor # # This file may be distributed under the terms of the GNU GPLv3 license. -import logging from . import fan, temperature_fan, controller_fan @@ -21,7 +20,9 @@ def __init__(self, config): self.name = self.full_name.split()[-1] self.printer = config.get_printer() self.fan = fan.Fan(config, default_shutdown_speed=1.0) - self.temperature_fan = temperature_fan.TemperatureFan(config, self.fan, self) + self.temperature_fan = temperature_fan.TemperatureFan( + config, self.fan, self + ) self.controller_fan = controller_fan.ControllerFan(config, self.fan) def get_mcu(self): diff --git a/klippy/extras/danger_options.py b/klippy/extras/danger_options.py index dadae82f1..3ee5a5d8d 100644 --- a/klippy/extras/danger_options.py +++ b/klippy/extras/danger_options.py @@ -23,7 +23,9 @@ def __init__(self, config): "jinja_boolean_filter", ["true", "1"] ) self.jinja_extensions = config.getlist("jinja_extensions", []) - self.allow_plugin_override = config.getboolean("allow_plugin_override", False) + self.allow_plugin_override = config.getboolean( + "allow_plugin_override", False + ) self.multi_mcu_trsync_timeout = config.getfloat( "multi_mcu_trsync_timeout", 0.025, minval=0.0 ) @@ -49,7 +51,9 @@ def __init__(self, config): self.disable_webhook_logging = True self.temp_ignore_limits = config.getlist("temp_ignore_limits", []) - self.echo_limits_to_console = config.getboolean("echo_limits_to_console", False) + self.echo_limits_to_console = config.getboolean( + "echo_limits_to_console", False + ) self.modify_check_runout_timeout = config.getboolean( "modify_check_runout_timeout", False ) @@ -66,7 +70,9 @@ def __init__(self, config): self.endstop_sample_time = config.getfloat( "endstop_sample_time", 0.000015, minval=0 ) - self.endstop_sample_count = config.getint("endstop_sample_count", 4, minval=1) + self.endstop_sample_count = config.getint( + "endstop_sample_count", 4, minval=1 + ) if self.minimal_logging: self.log_statistics = False diff --git a/klippy/extras/delta_calibrate.py b/klippy/extras/delta_calibrate.py index a1a08d89b..f5eb1cb93 100644 --- a/klippy/extras/delta_calibrate.py +++ b/klippy/extras/delta_calibrate.py @@ -42,18 +42,25 @@ def measurements_to_distances(measured_params, delta_params): scale = mp["SCALE"][0] cpw = mp["CENTER_PILLAR_WIDTHS"] center_widths = [cpw[0], cpw[2], cpw[1], cpw[0], cpw[2], cpw[1]] - center_dists = [od - cw for od, cw in zip(mp["CENTER_DISTS"], center_widths)] + center_dists = [ + od - cw for od, cw in zip(mp["CENTER_DISTS"], center_widths) + ] outer_dists = [ - od - opw for od, opw in zip(mp["OUTER_DISTS"], mp["OUTER_PILLAR_WIDTHS"]) + od - opw + for od, opw in zip(mp["OUTER_DISTS"], mp["OUTER_PILLAR_WIDTHS"]) ] # Convert angles in degrees to an XY multiplier obj_angles = list(map(math.radians, MeasureAngles)) xy_angles = list(zip(map(math.cos, obj_angles), map(math.sin, obj_angles))) # Calculate stable positions for center measurements inner_ridge = MeasureRidgeRadius * scale - inner_pos = [(ax * inner_ridge, ay * inner_ridge, 0.0) for ax, ay in xy_angles] + inner_pos = [ + (ax * inner_ridge, ay * inner_ridge, 0.0) for ax, ay in xy_angles + ] outer_ridge = (MeasureOuterRadius + MeasureRidgeRadius) * scale - outer_pos = [(ax * outer_ridge, ay * outer_ridge, 0.0) for ax, ay in xy_angles] + outer_pos = [ + (ax * outer_ridge, ay * outer_ridge, 0.0) for ax, ay in xy_angles + ] center_positions = [ (cd, dp.calc_stable_position(ip), dp.calc_stable_position(op)) for cd, ip, op in zip(center_dists, inner_pos, outer_pos) @@ -85,7 +92,9 @@ def measurements_to_distances(measured_params, delta_params): class DeltaCalibrate: def __init__(self, config): self.printer = config.get_printer() - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) # Calculate default probing points radius = config.getfloat("radius", above=0.0) points = [(0.0, 0.0)] @@ -112,7 +121,9 @@ def __init__(self, config): height = config.getfloat("manual_height%d" % (i,), None) if height is None: break - height_pos = load_config_stable(config, "manual_height%d_pos" % (i,)) + height_pos = load_config_stable( + config, "manual_height%d_pos" % (i,) + ) self.manual_heights.append((height, height_pos)) # Restore distance measurements self.delta_analyze_entry = {"SCALE": (1.0,)} @@ -222,7 +233,9 @@ def delta_errorfunc(params): for dist, stable_pos1, stable_pos2 in distances: x1, y1, z1 = getpos(stable_pos1) x2, y2, z2 = getpos(stable_pos2) - d = math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2) + d = math.sqrt( + (x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2 + ) total_error += (d - dist) ** 2 return total_error except ValueError: @@ -244,10 +257,14 @@ def delta_errorfunc(params): for dist, spos1, spos2 in distances: x1, y1, z1 = orig_delta_params.get_position_from_stable(spos1) x2, y2, z2 = orig_delta_params.get_position_from_stable(spos2) - orig_dist = math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2) + orig_dist = math.sqrt( + (x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2 + ) x1, y1, z1 = new_delta_params.get_position_from_stable(spos1) x2, y2, z2 = new_delta_params.get_position_from_stable(spos2) - new_dist = math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2) + new_dist = math.sqrt( + (x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2 + ) logging.info( "distance orig: %.6f new: %.6f goal: %.6f", orig_dist, @@ -329,7 +346,9 @@ def cmd_DELTA_ANALYZE(self, gcmd): except: raise gcmd.error("Unable to parse parameter '%s'" % (name,)) if len(parts) != count: - raise gcmd.error("Parameter '%s' must have %d values" % (name, count)) + raise gcmd.error( + "Parameter '%s' must have %d values" % (name, count) + ) self.delta_analyze_entry[name] = parts logging.info("DELTA_ANALYZE %s = %s", name, parts) # Perform analysis if requested diff --git a/klippy/extras/display/display.py b/klippy/extras/display/display.py index 30bf9346e..4343dda16 100644 --- a/klippy/extras/display/display.py +++ b/klippy/extras/display/display.py @@ -30,7 +30,9 @@ def __init__(self, config): self.printer = config.get_printer() name_parts = config.get_name().split() if len(name_parts) != 2: - raise config.error("Section name '%s' is not valid" % (config.get_name(),)) + raise config.error( + "Section name '%s' is not valid" % (config.get_name(),) + ) self.name = name_parts[1] self.params = {} for option in config.get_prefix_options("param_"): @@ -70,7 +72,8 @@ def __init__(self, config, name, data_configs): row, col = [int(v.strip()) for v in pos.split(",")] except: raise config.error( - "Unable to parse 'position' in section '%s'" % (c.get_name(),) + "Unable to parse 'position' in section '%s'" + % (c.get_name(),) ) items.append((row, col, c.get_name())) # Load all templates and store sorted by display position @@ -136,7 +139,9 @@ def load_config(self, config): try: dconfig = pconfig.read_config(filename) except Exception: - raise self.printer.config_error("Cannot load config '%s'" % (filename,)) + raise self.printer.config_error( + "Cannot load config '%s'" % (filename,) + ) # Load display_template sections dt_main = config.get_prefix_sections( ( @@ -182,7 +187,9 @@ def load_config(self, config): for c in dd_main + dd_def: name_parts = c.get_name().split() if len(name_parts) != 3: - raise config.error("Section name '%s' is not valid" % (c.get_name(),)) + raise config.error( + "Section name '%s' is not valid" % (c.get_name(),) + ) groups.setdefault(name_parts[1], []).append(c) for group_name, data_configs in groups.items(): dg = DisplayGroup(config, group_name, data_configs) @@ -252,7 +259,9 @@ def __init__(self, config): self.lcd_chip.mcu.get_non_critical_reconnect_event_name(), self.handle_reconnect, ) - self.screen_update_timer = self.reactor.register_timer(self.screen_update_event) + self.screen_update_timer = self.reactor.register_timer( + self.screen_update_event + ) self.redraw_request_pending = False self.redraw_time = 0.0 # Register g-code commands diff --git a/klippy/extras/display/hd44780.py b/klippy/extras/display/hd44780.py index d74fcb541..a57c1221b 100644 --- a/klippy/extras/display/hd44780.py +++ b/klippy/extras/display/hd44780.py @@ -23,7 +23,9 @@ def __init__(self, config): ppins.lookup_pin(config.get(name + "_pin")) for name in ["rs", "e", "d4", "d5", "d6", "d7"] ] - self.hd44780_protocol_init = config.getboolean("hd44780_protocol_init", True) + self.hd44780_protocol_init = config.getboolean( + "hd44780_protocol_init", True + ) self.line_length = config.getchoice( "line_length", LINE_LENGTH_OPTIONS, LINE_LENGTH_DEFAULT ) @@ -97,7 +99,9 @@ def flush(self): continue # Find the position of all changed bytes in this framebuffer diffs = [ - [i, 1] for i, (n, o) in enumerate(zip(new_data, old_data)) if n != o + [i, 1] + for i, (n, o) in enumerate(zip(new_data, old_data)) + if n != o ] # Batch together changes that are close to each other for i in range(len(diffs) - 2, -1, -1): diff --git a/klippy/extras/display/hd44780_spi.py b/klippy/extras/display/hd44780_spi.py index b005f3f6c..be5a68b97 100644 --- a/klippy/extras/display/hd44780_spi.py +++ b/klippy/extras/display/hd44780_spi.py @@ -18,7 +18,9 @@ class hd44780_spi: def __init__(self, config): self.printer = config.get_printer() - self.hd44780_protocol_init = config.getboolean("hd44780_protocol_init", True) + self.hd44780_protocol_init = config.getboolean( + "hd44780_protocol_init", True + ) # spi config self.spi = bus.MCU_SPI_from_config(config, 0x00, pin_option="latch_pin") self.mcu = self.spi.get_mcu() @@ -75,7 +77,9 @@ def flush(self): continue # Find the position of all changed bytes in this framebuffer diffs = [ - [i, 1] for i, (n, o) in enumerate(zip(new_data, old_data)) if n != o + [i, 1] + for i, (n, o) in enumerate(zip(new_data, old_data)) + if n != o ] # Batch together changes that are close to each other for i in range(len(diffs) - 2, -1, -1): diff --git a/klippy/extras/display/menu.py b/klippy/extras/display/menu.py index 3f8f7c51a..afb54dbec 100644 --- a/klippy/extras/display/menu.py +++ b/klippy/extras/display/menu.py @@ -54,7 +54,9 @@ def __init__(self, manager, config, **kwargs): try: self._enable = config.getboolean("enable", self._enable) except config.error: - self._enable_tpl = manager.gcode_macro.load_template(config, "enable") + self._enable_tpl = manager.gcode_macro.load_template( + config, "enable" + ) self._suffix_tpl = manager.gcode_macro.load_template( config, "suffix", self._suffix ) @@ -65,9 +67,9 @@ def __init__(self, manager, config, **kwargs): # ns - item namespace key, used in item relative paths # $__id - generated id text variable self._id = "__menu_" + hex(id(self)).lstrip("0x").rstrip("L") - self._ns = Template("menu " + kwargs.get("ns", self._id)).safe_substitute( - __id=self._id - ) + self._ns = Template( + "menu " + kwargs.get("ns", self._id) + ).safe_substitute(__id=self._id) self._last_heartbeat = None self.__scroll_pos = None self.__scroll_request_pending = False @@ -97,7 +99,8 @@ def _load_script(self, config, name, option=None): """Load script template from config or callback from dict""" if name in self._scripts: logging.info( - "Declaration of '%s' hides " "previous script declaration" % (name,) + "Declaration of '%s' hides " + "previous script declaration" % (name,) ) option = option or name if isinstance(config, dict): @@ -151,7 +154,9 @@ def _eval_tpl(self, tpl, context, coerce=identity): try: return coerce(val) except: - logging.exception(f"{self._ns} Failed to coerce {val!r} as {coerce}") + logging.exception( + f"{self._ns} Failed to coerce {val!r} as {coerce}" + ) raise def eval_enable(self, context): @@ -230,7 +235,9 @@ def get_ns(self, name="."): return name.strip() def send_event(self, event, *args): - return self.manager.send_event("%s:%s" % (self.get_ns(), str(event)), *args) + return self.manager.send_event( + "%s:%s" % (self.get_ns(), str(event)), *args + ) def get_script(self, name): if name in self._scripts: @@ -290,7 +297,9 @@ class MenuContainer(MenuElement): def __init__(self, manager, config, **kwargs): if type(self) is MenuContainer: - raise error("Abstract MenuContainer cannot be instantiated directly") + raise error( + "Abstract MenuContainer cannot be instantiated directly" + ) super(MenuContainer, self).__init__(manager, config, **kwargs) self._populate_cb = kwargs.get("populate", None) self._cursor = ">" @@ -360,9 +369,9 @@ def add_parents(self, parents): self._parents.append(parents) def assert_recursive_relation(self, parents=None): - assert self not in ( - parents or self._parents - ), "Recursive relation of '%s' container" % (self.get_ns(),) + assert self not in (parents or self._parents), ( + "Recursive relation of '%s' container" % (self.get_ns(),) + ) def insert_item(self, s, index=None): self._insert_item(s, index) @@ -403,7 +412,9 @@ def update_items(self, keep_pointer=False): if keep_pointer: selection = self.selected_item() - _a = [(item, name) for item, name in self._allitems if item.is_enabled()] + _a = [ + (item, name) for item, name in self._allitems if item.is_enabled() + ] self._items, self._names = zip(*_a) or ([], []) if keep_pointer and selection in self._items: @@ -559,7 +570,9 @@ def heartbeat(self, eventtime): def get_context(self, cxt=None): context = super().get_context(cxt) value = ( - self._get_value(context) if self._input_value is None else self._input_value + self._get_value(context) + if self._input_value is None + else self._input_value ) context["menu"].update({"input": value}) return context @@ -673,7 +686,9 @@ def _cb(el, context): el.manager.back() # create back item - self._itemBack = self.manager.menuitem_from("command", name="..", gcode=_cb) + self._itemBack = self.manager.menuitem_from( + "command", name="..", gcode=_cb + ) def _names_aslist(self): return self.manager.lookup_children(self.get_ns()) @@ -727,7 +742,11 @@ def draw_container(self, nrows, eventtime): # draw item name tpos = display.draw_text(y, ppos, text.ljust(width), eventtime) # check scroller - if selected and tpos > self.manager.cols and current.is_scrollable(): + if ( + selected + and tpos > self.manager.cols + and current.is_scrollable() + ): # scroll next current.need_scroller(True) else: @@ -735,7 +754,9 @@ def draw_container(self, nrows, eventtime): current.need_scroller(None) # draw item suffix if suffix: - display.draw_text(y, self.manager.cols - slen, suffix, eventtime) + display.draw_text( + y, self.manager.cols - slen, suffix, eventtime + ) # next display row y += 1 except Exception: @@ -761,7 +782,8 @@ def _cb(el: MenuElement, context): name=repr(fname), gcode=_cb, context={ - "gcode": "SDCARD_PRINT_FILE FILENAME='/%s'" % str(fname) + "gcode": "SDCARD_PRINT_FILE FILENAME='/%s'" + % str(fname) }, ) ) @@ -783,7 +805,9 @@ def __init__(self, manager, config, **kwargs): super().__init__(manager, config, **kwargs) self._sort_by = ( - (config or self._context or {}).get("sort_by", "last_modified").lower() + (config or self._context or {}) + .get("sort_by", "last_modified") + .lower() ) if not self.manager.virtual_sdcard: @@ -1019,10 +1043,14 @@ def __init__(self, config, display): self.timeout = config.getint("menu_timeout", 0) self.timer = 0 # reverse container navigation - self._reverse_navigation = config.getboolean("menu_reverse_navigation", False) + self._reverse_navigation = config.getboolean( + "menu_reverse_navigation", False + ) # load printer objects self.gcode_macro = self.printer.load_object(config, "gcode_macro") - self.virtual_sdcard = self.printer.load_object(config, "virtual_sdcard", None) + self.virtual_sdcard = self.printer.load_object( + config, "virtual_sdcard", None + ) # register itself for printer callbacks self.printer.add_object("menu", self) self.printer.register_event_handler("klippy:ready", self.handle_ready) @@ -1277,7 +1305,11 @@ def exit(self, force=False): if self.running and isinstance(container, MenuContainer): self.timer = 0 current = container.selected_item() - if not force and isinstance(current, MenuInput) and current.is_editing(): + if ( + not force + and isinstance(current, MenuInput) + and current.is_editing() + ): return if isinstance(container, MenuList): container.run_script("leave") @@ -1344,7 +1376,8 @@ def add_menuitem(self, name, item): if name in self.menuitems: existing_item = True logging.info( - "Declaration of '%s' hides " "previous menuitem declaration" % (name,) + "Declaration of '%s' hides " + "previous menuitem declaration" % (name,) ) self.menuitems[name] = item if isinstance(item, MenuElement): @@ -1377,7 +1410,9 @@ def load_config(self, *args): try: cfg = self.pconfig.read_config(filename) except Exception: - raise self.printer.config_error("Cannot load config '%s'" % (filename,)) + raise self.printer.config_error( + "Cannot load config '%s'" % (filename,) + ) if cfg: self.load_menuitems(cfg) return cfg diff --git a/klippy/extras/display/menu_keys.py b/klippy/extras/display/menu_keys.py index 5da9b05cc..7edf0bdf3 100644 --- a/klippy/extras/display/menu_keys.py +++ b/klippy/extras/display/menu_keys.py @@ -33,7 +33,9 @@ def __init__(self, config, callback): self.encoder_ccw_callback, encoder_steps_per_detent, ) - self.encoder_fast_rate = config.getfloat("encoder_fast_rate", 0.030, above=0.0) + self.encoder_fast_rate = config.getfloat( + "encoder_fast_rate", 0.030, above=0.0 + ) self.last_encoder_cw_eventtime = 0 self.last_encoder_ccw_eventtime = 0 # Register click button @@ -94,7 +96,9 @@ def long_click_event(self, eventtime): def click_callback(self, eventtime, state): if state: self.is_short_click = True - self.reactor.update_timer(self.click_timer, eventtime + LONG_PRESS_DURATION) + self.reactor.update_timer( + self.click_timer, eventtime + LONG_PRESS_DURATION + ) elif self.is_short_click: self.reactor.update_timer(self.click_timer, self.reactor.NEVER) self.callback("click", eventtime) diff --git a/klippy/extras/display/st7920.py b/klippy/extras/display/st7920.py index 318c1a5bd..687314ae3 100644 --- a/klippy/extras/display/st7920.py +++ b/klippy/extras/display/st7920.py @@ -29,7 +29,8 @@ def __init__(self): (self.glyph_framebuffer, bytearray(b"~" * 128), 0x40), # Graphics framebuffers ] + [ - (self.graphics_framebuffers[i], bytearray(b"~" * 32), i) for i in range(32) + (self.graphics_framebuffers[i], bytearray(b"~" * 32), i) + for i in range(32) ] self.cached_glyphs = {} self.icons = {} @@ -41,7 +42,9 @@ def flush(self): continue # Find the position of all changed bytes in this framebuffer diffs = [ - [i, 1] for i, (n, o) in enumerate(zip(new_data, old_data)) if n != o + [i, 1] + for i, (n, o) in enumerate(zip(new_data, old_data)) + if n != o ] # Batch together changes that are close to each other for i in range(len(diffs) - 2, -1, -1): @@ -244,7 +247,8 @@ def __init__(self, config): "spi_software_%s_pin" % (name,) for name in ["miso", "mosi", "sclk"] ] sw_pin_params = [ - ppins.lookup_pin(config.get(name), share_type=name) for name in sw_pin_names + ppins.lookup_pin(config.get(name), share_type=name) + for name in sw_pin_names ] mcu = None for pin_params in sw_pin_params: diff --git a/klippy/extras/display/uc1701.py b/klippy/extras/display/uc1701.py index 203391cab..05810921f 100644 --- a/klippy/extras/display/uc1701.py +++ b/klippy/extras/display/uc1701.py @@ -23,7 +23,9 @@ def __init__(self, io, columns=128, x_offset=0): (self.vram[i], bytearray(b"~" * self.columns), i) for i in range(8) ] # Cache fonts and icons in display byte order - self.font = [self._swizzle_bits(bytearray(c)) for c in font8x14.VGA_FONT] + self.font = [ + self._swizzle_bits(bytearray(c)) for c in font8x14.VGA_FONT + ] self.icons = {} def flush(self): @@ -33,7 +35,9 @@ def flush(self): continue # Find the position of all changed bytes in this framebuffer diffs = [ - [i, 1] for i, (n, o) in enumerate(zip(new_data, old_data)) if n != o + [i, 1] + for i, (n, o) in enumerate(zip(new_data, old_data)) + if n != o ] # Batch together changes that are close to each other for i in range(len(diffs) - 2, -1, -1): @@ -134,7 +138,9 @@ def __init__(self, config, data_pin_name): ) def send(self, cmds, is_data=False): - self.mcu_dc.update_digital_out(is_data, reqclock=BACKGROUND_PRIORITY_CLOCK) + self.mcu_dc.update_digital_out( + is_data, reqclock=BACKGROUND_PRIORITY_CLOCK + ) self.spi.spi_send(cmds, reqclock=BACKGROUND_PRIORITY_CLOCK) diff --git a/klippy/extras/dockable_probe.py b/klippy/extras/dockable_probe.py index 394b425fb..c8903d26f 100644 --- a/klippy/extras/dockable_probe.py +++ b/klippy/extras/dockable_probe.py @@ -61,11 +61,19 @@ def __init__(self, config, aProbe): self.printer = config.get_printer() if ( - not config.fileconfig.has_option(config.section, "check_open_attach") - and not config.fileconfig.has_option(config.section, "probe_sense_pin") - and not config.fileconfig.has_option(config.section, "dock_sense_pin") + not config.fileconfig.has_option( + config.section, "check_open_attach" + ) + and not config.fileconfig.has_option( + config.section, "probe_sense_pin" + ) + and not config.fileconfig.has_option( + config.section, "dock_sense_pin" + ) ): - raise self.printer.config_error(HINT_VERIFICATION_ERROR.format(aProbe.name)) + raise self.printer.config_error( + HINT_VERIFICATION_ERROR.format(aProbe.name) + ) self.printer.register_event_handler("klippy:ready", self._handle_ready) @@ -161,7 +169,9 @@ def __init__(self, config): self.dock_retries = config.getint("dock_retries", 0) self.auto_attach_detach = config.getboolean("auto_attach_detach", True) self.restore_toolhead = config.getboolean("restore_toolhead", True) - self.travel_speed = config.getfloat("travel_speed", self.speed, above=0.0) + self.travel_speed = config.getfloat( + "travel_speed", self.speed, above=0.0 + ) self.attach_speed = config.getfloat( "attach_speed", self.travel_speed, above=0.0 ) @@ -185,7 +195,8 @@ def __init__(self, config): self.z_hop = config.getfloat("z_hop", 0.0, above=0.0) self.dock_requires_z = ( - self.approach_position[2] is not None or self.dock_position[2] is not None + self.approach_position[2] is not None + or self.dock_position[2] is not None ) # Entry distance self.approach_distance = self._get_distance( @@ -214,7 +225,9 @@ def __init__(self, config): # Macros to run before attach and after detach gcode_macro = self.printer.load_object(config, "gcode_macro") - self.activate_gcode = gcode_macro.load_template(config, "activate_gcode", "") + self.activate_gcode = gcode_macro.load_template( + config, "activate_gcode", "" + ) self.deactivate_gcode = gcode_macro.load_template( config, "deactivate_gcode", "" ) @@ -304,9 +317,13 @@ def __init__(self, config): ) # Event Handlers - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) - self.printer.register_event_handler("klippy:mcu_identify", self._handle_config) + self.printer.register_event_handler( + "klippy:mcu_identify", self._handle_config + ) # Parse a string coordinate representation from the config # and return a list of numbers. @@ -327,7 +344,9 @@ def _parse_coord(self, config, name, default=None, expected_dims=3): supplied_dims = len(vals) if not 2 <= supplied_dims <= expected_dims: raise config.error( - error_msg.format(name, self.name, "Invalid number of coordinates") + error_msg.format( + name, self.name, "Invalid number of coordinates" + ) ) p = [None] * 3 p[:supplied_dims] = vals @@ -364,7 +383,9 @@ def get_status(self, curtime): "auto_attach_detach": self.auto_attach_detach, } - cmd_MOVE_TO_APPROACH_PROBE_help = "Move close to the probe dock" "before attaching" + cmd_MOVE_TO_APPROACH_PROBE_help = ( + "Move close to the probe dock" "before attaching" + ) def cmd_MOVE_TO_APPROACH_PROBE(self, gcmd): self._align_z() @@ -376,18 +397,24 @@ def cmd_MOVE_TO_APPROACH_PROBE(self, gcmd): [None, None, self.approach_position[2]], self.speed ) - cmd_MOVE_TO_DOCK_PROBE_help = "Move to connect the toolhead/dock" "to the probe" + cmd_MOVE_TO_DOCK_PROBE_help = ( + "Move to connect the toolhead/dock" "to the probe" + ) def cmd_MOVE_TO_DOCK_PROBE(self, gcmd): if len(self.dock_position) > 2: - self.toolhead.manual_move([None, None, self.dock_position[2]], self.speed) + self.toolhead.manual_move( + [None, None, self.dock_position[2]], self.speed + ) self.toolhead.manual_move( [self.dock_position[0], self.dock_position[1], None], self.attach_speed, ) - cmd_MOVE_TO_EXTRACT_PROBE_help = "Move away from the dock with the" "probe attached" + cmd_MOVE_TO_EXTRACT_PROBE_help = ( + "Move away from the dock with the" "probe attached" + ) def cmd_MOVE_TO_EXTRACT_PROBE(self, gcmd): if len(self.extract_position) > 2: @@ -408,9 +435,13 @@ def cmd_MOVE_TO_INSERT_PROBE(self, gcmd): self._move_avoiding_dock(self.insert_position, self.travel_speed) if len(self.insert_position) > 2: - self.toolhead.manual_move([None, None, self.insert_position[2]], self.speed) + self.toolhead.manual_move( + [None, None, self.insert_position[2]], self.speed + ) - cmd_MOVE_TO_DETACH_PROBE_help = "Move away from the dock to detach" "the probe" + cmd_MOVE_TO_DETACH_PROBE_help = ( + "Move away from the dock to detach" "the probe" + ) def cmd_MOVE_TO_DETACH_PROBE(self, gcmd): if len(self.detach_position) > 2: @@ -465,7 +496,8 @@ def attach_probe(self, return_pos=None, always_restore_toolhead=False): retry = 0 while ( - self.get_probe_state() != PROBE_ATTACHED and retry < self.dock_retries + 1 + self.get_probe_state() != PROBE_ATTACHED + and retry < self.dock_retries + 1 ): if self.get_probe_state() != PROBE_DOCKED: raise self.printer.command_error( @@ -497,7 +529,10 @@ def attach_probe(self, return_pos=None, always_restore_toolhead=False): def detach_probe(self, return_pos=None): retry = 0 - while self.get_probe_state() != PROBE_DOCKED and retry < self.dock_retries + 1: + while ( + self.get_probe_state() != PROBE_DOCKED + and retry < self.dock_retries + 1 + ): # Call these gcodes as a script because we don't have enough # structs/data to call the cmd_...() funcs and supply 'gcmd'. # This method also has the advantage of calling user-written gcodes @@ -521,7 +556,9 @@ def detach_probe(self, return_pos=None): self._move_avoiding_dock(return_pos[:2], self.travel_speed) # Return to original Z position after detach as # there's no chance of the probe crashing into the bed. - self.toolhead.manual_move([None, None, return_pos[2]], self.lift_speed) + self.toolhead.manual_move( + [None, None, return_pos[2]], self.lift_speed + ) self._raise_probe() def auto_detach_probe(self, return_pos=None): @@ -535,7 +572,8 @@ def auto_attach_probe(self, return_pos=None, always_restore_toolhead=False): return if not self.auto_attach_detach: raise self.printer.command_error( - "Cannot probe, probe is not " "attached and auto-attach is disabled" + "Cannot probe, probe is not " + "attached and auto-attach is disabled" ) self.attach_probe(return_pos, always_restore_toolhead) @@ -571,7 +609,9 @@ def _move_avoiding_dock(self, end_point, speed): elif intersect_points: # input_tangent point safe_point = self._get_closest_point(end_point, self.safe_points) - tangent_points = self._get_tangent_points(radius - 0.1, dock, start_point) + tangent_points = self._get_tangent_points( + radius - 0.1, dock, start_point + ) arc_input = self._get_closest_point(safe_point, tangent_points) clockwise = self._get_rotation_direction(start_point, arc_input) coords.append(arc_input) @@ -581,7 +621,9 @@ def _move_avoiding_dock(self, end_point, speed): tangent_points = self._get_tangent_points(radius, dock, end_point) arc_output = self._get_closest_point(safe_point, tangent_points) # determine arc travel - arc_points = self._arc_points(arc_input, arc_output, dock, clockwise) + arc_points = self._arc_points( + arc_input, arc_output, dock, clockwise + ) coords.extend(arc_points) coords.append(end_point) @@ -750,7 +792,9 @@ def _align_z(self): if "z" in self._last_homed: tpos = self.toolhead.get_position() if tpos[2] < self.z_hop: - self.toolhead.manual_move([None, None, self.z_hop], self.lift_speed) + self.toolhead.manual_move( + [None, None, self.z_hop], self.lift_speed + ) else: self._force_z_hop() @@ -771,7 +815,9 @@ def _force_z_hop(self): return tpos = self.toolhead.get_position() - self.toolhead.set_position([tpos[0], tpos[1], 0.0, tpos[3]], homing_axes=[2]) + self.toolhead.set_position( + [tpos[0], tpos[1], 0.0, tpos[3]], homing_axes=[2] + ) self.toolhead.manual_move([None, None, self.z_hop], self.lift_speed) kin = self.toolhead.get_kinematics() kin.note_z_not_homed() @@ -817,7 +863,9 @@ def multi_probe_end(self): return_pos = self.toolhead.get_position() # Move away from the bed to ensure the probe isn't triggered, # preventing detaching in the event there's no probe/dock sensor. - self.toolhead.manual_move([None, None, return_pos[2] + 2], self.lift_speed) + self.toolhead.manual_move( + [None, None, return_pos[2] + 2], self.lift_speed + ) self.auto_detach_probe(return_pos) def probe_prepare(self, hmove): @@ -833,7 +881,9 @@ def probe_finish(self, hmove): return_pos = self.toolhead.get_position() # Move away from the bed to ensure the probe isn't triggered, # preventing detaching in the event there's no probe/dock sensor. - self.toolhead.manual_move([None, None, return_pos[2] + 2], self.lift_speed) + self.toolhead.manual_move( + [None, None, return_pos[2] + 2], self.lift_speed + ) self.auto_detach_probe(return_pos) def home_start( diff --git a/klippy/extras/dotstar.py b/klippy/extras/dotstar.py index 96949fc67..533f118a9 100644 --- a/klippy/extras/dotstar.py +++ b/klippy/extras/dotstar.py @@ -26,7 +26,9 @@ def __init__(self, config): self.spi = bus.MCU_SPI(mcu, None, None, 0, 500000, sw_spi_pins) # Initialize color data self.chain_count = config.getint("chain_count", 1, minval=1) - self.led_helper = led.LEDHelper(config, self.update_leds, self.chain_count) + self.led_helper = led.LEDHelper( + config, self.update_leds, self.chain_count + ) self.prev_data = None # Register commands printer.register_event_handler("klippy:connect", self._handle_connect) @@ -52,7 +54,9 @@ def update_leds(self, led_state, print_time): if print_time is not None: minclock = self.spi.get_mcu().print_time_to_clock(print_time) for d in [data[i : i + 20] for i in range(0, len(data), 20)]: - self.spi.spi_send(d, minclock=minclock, reqclock=BACKGROUND_PRIORITY_CLOCK) + self.spi.spi_send( + d, minclock=minclock, reqclock=BACKGROUND_PRIORITY_CLOCK + ) def get_status(self, eventtime): return self.led_helper.get_status(eventtime) diff --git a/klippy/extras/ds18b20.py b/klippy/extras/ds18b20.py index a508c9949..7a3dd9d50 100644 --- a/klippy/extras/ds18b20.py +++ b/klippy/extras/ds18b20.py @@ -7,7 +7,6 @@ from extras.danger_options import get_danger_options -from extras.danger_options import get_danger_options DS18_REPORT_TIME = 3.0 # Temperature can be sampled at any time but conversion time is ~750ms, so @@ -64,7 +63,9 @@ def _handle_ds18b20_response(self, params): temp = params["value"] / 1000.0 if params["fault"]: - logging.info("ds18b20 reports fault %d (temp=%0.1f)", params["fault"], temp) + logging.info( + "ds18b20 reports fault %d (temp=%0.1f)", params["fault"], temp + ) return next_clock = self._mcu.clock32_to_clock64(params["next_clock"]) diff --git a/klippy/extras/endstop_phase.py b/klippy/extras/endstop_phase.py index 2bfabbc90..221b9b99e 100644 --- a/klippy/extras/endstop_phase.py +++ b/klippy/extras/endstop_phase.py @@ -85,10 +85,14 @@ def __init__(self, config): if trigger_phase is not None: p, ps = config.getintlist("trigger_phase", sep="/", count=2) if p >= ps: - raise config.error("Invalid trigger_phase '%s'" % (trigger_phase,)) + raise config.error( + "Invalid trigger_phase '%s'" % (trigger_phase,) + ) self.endstop_phase = self.phase_calc.convert_phase(p, ps) self.endstop_align_zero = config.getboolean("endstop_align_zero", False) - self.endstop_accuracy = config.getfloat("endstop_accuracy", None, above=0.0) + self.endstop_accuracy = config.getfloat( + "endstop_accuracy", None, above=0.0 + ) # Determine endstop accuracy if self.endstop_accuracy is None: self.endstop_phase_accuracy = self.phases // 2 - 1 @@ -115,7 +119,8 @@ def align_endstop(self, rail): microsteps = self.phases // 4 half_microsteps = microsteps // 2 phase_offset = ( - ((self.endstop_phase + half_microsteps) % microsteps) - half_microsteps + ((self.endstop_phase + half_microsteps) % microsteps) + - half_microsteps ) * self.step_dist full_step = microsteps * self.step_dist pe = rail.get_homing_info().position_endstop @@ -204,14 +209,18 @@ def cmd_ENDSTOP_PHASE_CALIBRATE(self, gcmd): return phase_calc = self.tracking.get(stepper_name) if phase_calc is None or phase_calc.phase_history is None: - raise gcmd.error("Stats not available for stepper %s" % (stepper_name,)) + raise gcmd.error( + "Stats not available for stepper %s" % (stepper_name,) + ) endstop_phase, phases = self.generate_stats(stepper_name, phase_calc) if not phase_calc.is_primary: return configfile = self.printer.lookup_object("configfile") section = "endstop_phase %s" % (stepper_name,) configfile.remove_section(section) - configfile.set(section, "trigger_phase", "%s/%s" % (endstop_phase, phases)) + configfile.set( + section, "trigger_phase", "%s/%s" % (endstop_phase, phases) + ) gcmd.respond_info( "The SAVE_CONFIG command will update the printer config\n" "file with these parameters and restart the printer." @@ -229,7 +238,9 @@ def generate_stats(self, stepper_name, phase_calc): res.append((cost, phase)) res.sort() best = res[0][1] - found = [j for j in range(best - half_phases, best + half_phases) if wph[j]] + found = [ + j for j in range(best - half_phases, best + half_phases) if wph[j] + ] best_phase = best % phases lo, hi = found[0] % phases, found[-1] % phases self.gcode.respond_info( diff --git a/klippy/extras/exclude_object.py b/klippy/extras/exclude_object.py index 8311e7364..86a35d85f 100644 --- a/klippy/extras/exclude_object.py +++ b/klippy/extras/exclude_object.py @@ -18,7 +18,9 @@ def __init__(self, config): if not config.getboolean("enable_exclude_object", True): return - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.printer.register_event_handler( "virtual_sdcard:reset_file", self._reset_file ) @@ -58,7 +60,9 @@ def _register_transform(self): ) return - self.next_transform = self.gcode_move.set_move_transform(self, force=True) + self.next_transform = self.gcode_move.set_move_transform( + self, force=True + ) self.extrusion_offsets = {} self.max_position_extruded = 0 self.max_position_excluded = 0 @@ -99,10 +103,14 @@ def _reset_file(self): self._unregister_transform() def _get_extrusion_offsets(self): - offset = self.extrusion_offsets.get(self.toolhead.get_extruder().get_name()) + offset = self.extrusion_offsets.get( + self.toolhead.get_extruder().get_name() + ) if offset is None: offset = [0.0, 0.0, 0.0, 0.0] - self.extrusion_offsets[self.toolhead.get_extruder().get_name()] = offset + self.extrusion_offsets[self.toolhead.get_extruder().get_name()] = ( + offset + ) return offset def get_position(self): @@ -115,7 +123,10 @@ def get_position(self): def _normal_move(self, newpos, speed): offset = self._get_extrusion_offsets() - if self.initial_extrusion_moves > 0 and self.last_position[3] != newpos[3]: + if ( + self.initial_extrusion_moves > 0 + and self.last_position[3] != newpos[3] + ): # Since the transform is not loaded until there is a request to # exclude an object, the transform needs to track a few extrusions # to get the state of the extruder @@ -145,7 +156,10 @@ def _normal_move(self, newpos, speed): if offset[2] != 0 and newpos[2] != self.last_position_excluded[2]: offset[2] = 0 - if self.extruder_adj != 0 and newpos[3] != self.last_position_excluded[3]: + if ( + self.extruder_adj != 0 + and newpos[3] != self.last_position_excluded[3] + ): offset[3] += self.extruder_adj self.extruder_adj = 0 @@ -225,7 +239,8 @@ def cmd_EXCLUDE_OBJECT_START(self, gcmd): def cmd_EXCLUDE_OBJECT_END(self, gcmd): if self.current_object is None and self.next_transform: gcmd.respond_info( - "EXCLUDE_OBJECT_END called, but no object is" " currently active" + "EXCLUDE_OBJECT_END called, but no object is" + " currently active" ) return name = gcmd.get("NAME", default=None) @@ -295,7 +310,9 @@ def cmd_EXCLUDE_OBJECT_DEFINE(self, gcmd): self._list_objects(gcmd) def _add_object_definition(self, definition): - self.objects = sorted(self.objects + [definition], key=lambda o: o["name"]) + self.objects = sorted( + self.objects + [definition], key=lambda o: o["name"] + ) def _exclude_object(self, name): self._register_transform() diff --git a/klippy/extras/extruder_smoother.py b/klippy/extras/extruder_smoother.py index d1cd2d021..b229f9e77 100644 --- a/klippy/extras/extruder_smoother.py +++ b/klippy/extras/extruder_smoother.py @@ -53,7 +53,9 @@ def _estimate_shaper(np, shaper, test_damping_ratio, test_freqs): ) response += A[i] * s_r response *= inv_D - velocity = (response[:, 1:] - response[:, :-1]) / (omega * dt)[:, np.newaxis] + velocity = (response[:, 1:] - response[:, :-1]) / (omega * dt)[ + :, np.newaxis + ] return time[:-1], velocity @@ -93,7 +95,9 @@ def get_windows(m, wl): s_r = shaper_calibrate.step_response(np, time, omega, test_damping_ratio) w_dt = w[w_ind] * ((1.0 / norms) * dt) response = np.einsum("ijk,k->ij", get_windows(s_r, wl), w_dt[::-1]) - velocity = (response[:, 1:] - response[:, :-1]) / (omega * dt)[:, np.newaxis] + velocity = (response[:, 1:] - response[:, :-1]) / (omega * dt)[ + :, np.newaxis + ] return time[w_ind], velocity @@ -150,13 +154,15 @@ def get_extruder_smoother( try: np = importlib.import_module("numpy") except ImportError: - raise self.error( + raise Exception( "Failed to import `numpy` module, make sure it was " "installed via `~/klippy-env/bin/pip install` (refer to " "docs/Measuring_Resonances.md for more details)." ) shaper_name = shaper_name.lower() - smoother_cfg = EXTURDER_SMOOTHERS.get(shaper_name, EXTURDER_SMOOTHERS["default"]) + smoother_cfg = EXTURDER_SMOOTHERS.get( + shaper_name, EXTURDER_SMOOTHERS["default"] + ) test_freqs = np.linspace(*smoother_cfg.freq_opt_range) n = smoother_cfg.order for s in shaper_defs.INPUT_SHAPERS: @@ -166,7 +172,9 @@ def get_extruder_smoother( n = 2 * len(A) + 1 t_sm = T[-1] - T[0] shaper = A, T - t, velocities = _estimate_shaper(np, shaper, damping_ratio, test_freqs) + t, velocities = _estimate_shaper( + np, shaper, damping_ratio, test_freqs + ) break for s in shaper_defs.INPUT_SMOOTHERS: if s.name == shaper_name: @@ -174,10 +182,14 @@ def get_extruder_smoother( if n < 0: n = len(C) smoother = C, t_sm - t, velocities = _estimate_smoother(np, smoother, damping_ratio, test_freqs) + t, velocities = _estimate_smoother( + np, smoother, damping_ratio, test_freqs + ) break C_e = _calc_extruder_smoother(np, shaper_name, t, velocities, n, t_sm) - smoother = shaper_defs.init_smoother(C_e[::-1], smooth_time, normalize_coeffs) + smoother = shaper_defs.init_smoother( + C_e[::-1], smooth_time, normalize_coeffs + ) if not return_velocities: return smoother return smoother, (t, velocities) diff --git a/klippy/extras/extruder_stepper.py b/klippy/extras/extruder_stepper.py index abcc5a1e0..f05f0ee4c 100644 --- a/klippy/extras/extruder_stepper.py +++ b/klippy/extras/extruder_stepper.py @@ -11,7 +11,9 @@ def __init__(self, config): self.printer = config.get_printer() self.extruder_stepper = extruder.ExtruderStepper(config) self.extruder_name = config.get("extruder") - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): self.extruder_stepper.sync_to_extruder(self.extruder_name) diff --git a/klippy/extras/fan.py b/klippy/extras/fan.py index 68e7533ab..59eb4bcf5 100644 --- a/klippy/extras/fan.py +++ b/klippy/extras/fan.py @@ -28,7 +28,9 @@ def __init__( self.last_pwm_value = self.last_req_pwm_value = 0.0 self.last_fan_value = self.last_req_value = 0.0 # Read config - self.kick_start_time = config.getfloat("kick_start_time", 0.1, minval=0.0) + self.kick_start_time = config.getfloat( + "kick_start_time", 0.1, minval=0.0 + ) self.kick_start_threshold = ( config.getfloat("kick_start_threshold", 0.5, minval=0.0, maxval=1.0) if self.kick_start_time @@ -46,12 +48,17 @@ def __init__( self.off_below = config.getfloat( "off_below", default=None, minval=0.0, maxval=1.0 ) + if self.off_below is not None: + config.deprecate("off_below") + # handles switchover of variable # if new var is not set, and old var is, set new var to old var # if new var is not set and neither is old var, set new var to default of 0.0 # if new var is set, use new var if self.min_power is not None and self.off_below is not None: - raise config.error("min_power and off_below are both set. Remove one!") + raise config.error( + "min_power and off_below are both set. Remove one!" + ) if self.min_power is None: if self.off_below is None: # both unset, set to 0.0 @@ -59,13 +66,17 @@ def __init__( else: self.min_power = self.off_below - self.max_power = config.getfloat("max_power", 1.0, above=0.0, maxval=1.0) + self.max_power = config.getfloat( + "max_power", 1.0, above=0.0, maxval=1.0 + ) if self.min_power > self.max_power: raise config.error( "min_power=%f can't be larger than max_power=%f" % (self.min_power, self.max_power) ) - self.full_speed_max_power = config.getboolean("full_speed_max_power", False) + self.full_speed_max_power = config.getboolean( + "full_speed_max_power", False + ) cycle_time = config.getfloat("cycle_time", 0.010, above=0.0) hardware_pwm = config.getboolean("hardware_pwm", False) @@ -106,7 +117,9 @@ def __init__( self.on_error_gcode = config.get("on_error_gcode", None) self.startup_check = config.getboolean("startup_check", None) self.startup_check_delay = config.getfloat("startup_check_delay", None) - self.startup_check_rpm = config.getfloat("startup_check_rpm", None, minval=0) + self.startup_check_rpm = config.getfloat( + "startup_check_rpm", None, minval=0 + ) if ( self.min_rpm is not None and self.min_rpm > 0 @@ -141,14 +154,18 @@ def __init__( self.max_err = 3 if self.max_err is None else self.max_err self.fan_check_thread = None - self.startup_check = False if self.startup_check is None else self.startup_check + self.startup_check = ( + False if self.startup_check is None else self.startup_check + ) self.startup_check_delay = ( SAFETY_CHECK_INIT_TIME if self.startup_check_delay is None else self.startup_check_delay ) self.startup_check_rpm = ( - self.min_rpm if self.startup_check_rpm is None else self.startup_check_rpm + self.min_rpm + if self.startup_check_rpm is None + else self.startup_check_rpm ) self.self_checking = False @@ -211,7 +228,9 @@ def _apply_speed(self, print_time, value, force=False): pwm_value = 1.0 else: # Scale value between min_power and max_power - pwm_value = value * (self.max_power - self.min_power) + self.min_power + pwm_value = ( + value * (self.max_power - self.min_power) + self.min_power + ) pwm_value = max(self.min_power, min(self.max_power, pwm_value)) else: pwm_value = 0 @@ -234,7 +253,8 @@ def _apply_speed(self, print_time, value, force=False): and self.kick_start_time and ( not self.last_pwm_value - or pwm_value - self.last_pwm_value > self.kick_start_threshold + or pwm_value - self.last_pwm_value + > self.kick_start_threshold ) ): # Run fan at full speed for specified kick_start_time @@ -323,7 +343,9 @@ def __init__(self, config): pin = config.get("tachometer_pin", None) if pin is not None: self.ppr = config.getint("tachometer_ppr", 2, minval=1) - poll_time = config.getfloat("tachometer_poll_interval", 0.0015, above=0.0) + poll_time = config.getfloat( + "tachometer_poll_interval", 0.0015, above=0.0 + ) sample_time = 1.0 self._freq_counter = pulse_counter.FrequencyCounter( printer, pin, sample_time, poll_time diff --git a/klippy/extras/filament_motion_sensor.py b/klippy/extras/filament_motion_sensor.py index a480eb8bb..18483327f 100644 --- a/klippy/extras/filament_motion_sensor.py +++ b/klippy/extras/filament_motion_sensor.py @@ -13,7 +13,9 @@ def __init__(self, config): self.gcode = self.printer.lookup_object("gcode") switch_pin = config.get("switch_pin") self.extruder_name = config.get("extruder") - self.detection_length = config.getfloat("detection_length", 7.0, above=0.0) + self.detection_length = config.getfloat( + "detection_length", 7.0, above=0.0 + ) self.keep_enabled = config.getboolean("keep_enabled", False) # Configure pins buttons = self.printer.load_object(config, "buttons") @@ -74,12 +76,16 @@ def _handle_ready(self): def _handle_printing(self, *args): if self.keep_enabled and not self.runout_helper.smart: self.reset() - self.reactor.update_timer(self._extruder_pos_update_timer, self.reactor.NOW) + self.reactor.update_timer( + self._extruder_pos_update_timer, self.reactor.NOW + ) def _handle_printing_smart(self, *args): if self.keep_enabled and self.runout_helper.smart: self.reset() - self.reactor.update_timer(self._extruder_pos_update_timer, self.reactor.NOW) + self.reactor.update_timer( + self._extruder_pos_update_timer, self.reactor.NOW + ) def _handle_not_printing(self, *args): if self.keep_enabled and not self.runout_helper.smart: diff --git a/klippy/extras/filament_switch_sensor.py b/klippy/extras/filament_switch_sensor.py index c3ad693fc..1c83206a9 100644 --- a/klippy/extras/filament_switch_sensor.py +++ b/klippy/extras/filament_switch_sensor.py @@ -26,9 +26,13 @@ def __init__(self, config, defined_sensor, runout_distance=0): self.insert_gcode = None gcode_macro = self.printer.load_object(config, "gcode_macro") if self.runout_pause or config.get("runout_gcode", None) is not None: - self.runout_gcode = gcode_macro.load_template(config, "runout_gcode", "") + self.runout_gcode = gcode_macro.load_template( + config, "runout_gcode", "" + ) if config.get("insert_gcode", None) is not None: - self.insert_gcode = gcode_macro.load_template(config, "insert_gcode") + self.insert_gcode = gcode_macro.load_template( + config, "insert_gcode" + ) self.pause_delay = config.getfloat("pause_delay", 0.5, minval=0.0) self.event_delay = config.getfloat("event_delay", 3.0, minval=0.0) self.check_runout_timeout = CHECK_RUNOUT_TIMEOUT @@ -82,7 +86,9 @@ def _runout_event_handler(self, eventtime): # of pause_resume execute immediately. if self.runout_distance > 0: if self.runout_distance_timer is None: - self.runout_position = self.defined_sensor.get_extruder_pos(eventtime) + self.runout_position = self.defined_sensor.get_extruder_pos( + eventtime + ) self.runout_distance_timer = self.reactor.register_timer( self._pause_after_distance, self.reactor.NOW ) @@ -108,7 +114,8 @@ def reset_runout_distance_info(self): def _pause_after_distance(self, eventtime): runout_elapsed = max( 0.0, - self.defined_sensor.get_extruder_pos(eventtime) - self.runout_position, + self.defined_sensor.get_extruder_pos(eventtime) + - self.runout_position, ) if runout_elapsed < self.runout_distance: self.runout_elapsed = runout_elapsed @@ -175,7 +182,9 @@ def note_filament_present( % (self.name, eventtime) ) self.reactor.register_callback( - self._execute_runout if immediate else self._runout_event_handler + self._execute_runout + if immediate + else self._runout_event_handler ) def get_status(self, eventtime): @@ -241,13 +250,15 @@ def __init__(self, config): switch_pin = config.get("switch_pin") runout_distance = config.getfloat("runout_distance", 0.0, minval=0.0) buttons.register_buttons([switch_pin], self._button_handler) - self.check_on_print_start = config.getboolean("check_on_print_start", False) + self.check_on_print_start = config.getboolean( + "check_on_print_start", False + ) self.reactor = self.printer.get_reactor() self.estimated_print_time = None self.runout_helper = RunoutHelper(config, self, runout_distance) if config.get("immediate_runout_gcode", None) is not None: - self.runout_helper.immediate_runout_gcode = gcode_macro.load_template( - config, "immediate_runout_gcode", "" + self.runout_helper.immediate_runout_gcode = ( + gcode_macro.load_template(config, "immediate_runout_gcode", "") ) self.get_status = self.runout_helper.get_status self.printer.register_event_handler("klippy:ready", self._handle_ready) diff --git a/klippy/extras/firmware_retraction.py b/klippy/extras/firmware_retraction.py index b4847f59b..425b0679a 100644 --- a/klippy/extras/firmware_retraction.py +++ b/klippy/extras/firmware_retraction.py @@ -19,7 +19,9 @@ def __init__(self, config): # Get retraction params from config, used also in clear retraction self._get_config_params() # Initialize variables - self.unretract_length = self.retract_length + self.unretract_extra_length + self.unretract_length = ( + self.retract_length + self.unretract_extra_length + ) self.currentPos = [] self.currentZ = 0.0 self.z_hop_Z = 0.0 # Z coordinate of zhop move @@ -62,7 +64,9 @@ def _get_config_params(self): self.retract_length = self.config_ref.getfloat( "retract_length", 0.0, minval=0.0 ) - self.retract_speed = self.config_ref.getfloat("retract_speed", 20.0, minval=1) + self.retract_speed = self.config_ref.getfloat( + "retract_speed", 20.0, minval=1 + ) self.unretract_extra_length = self.config_ref.getfloat( "unretract_extra_length", 0.0, minval=0.0 ) @@ -70,7 +74,9 @@ def _get_config_params(self): "unretract_speed", 10.0, minval=1 ) # Zero min. and stand. zhop valueto ensure compatibility with macros - self.z_hop_height = self.config_ref.getfloat("z_hop_height", 0.0, minval=0.0) + self.z_hop_height = self.config_ref.getfloat( + "z_hop_height", 0.0, minval=0.0 + ) # Helper method to register commands and instantiate required objects def _handle_ready(self): @@ -83,7 +89,9 @@ def _handle_ready(self): self.printer.register_event_handler( "homing:homing_move_begin", self._evaluate_retraction ) - self.printer.register_event_handler("homing:home", self._evaluate_retraction) + self.printer.register_event_handler( + "homing:home", self._evaluate_retraction + ) self.printer.register_event_handler( "stepper_enable:motor_off", self._evaluate_retraction ) @@ -174,7 +182,9 @@ def _execute_set_retraction(self, gcmd): self.z_hop_height = gcmd.get_float( "Z_HOP_HEIGHT", self.z_hop_height, minval=0.0 ) # z_hop_height with 0mm min. to prevent nozzle crash - self.unretract_length = self.retract_length + self.unretract_extra_length + self.unretract_length = ( + self.retract_length + self.unretract_extra_length + ) # Command to report the current firmware retraction parameters cmd_GET_RETRACTION_help = "Report firmware retraction paramters" @@ -250,7 +260,9 @@ def cmd_G10(self, gcmd): "G90\n" # Switch to absolute mode (just in case) "{}" "RESTORE_GCODE_STATE NAME=_retract_state" - ).format(self.retract_length, int(self.retract_speed * 60), zhop_gcode) + ).format( + self.retract_length, int(self.retract_speed * 60), zhop_gcode + ) self.gcode.run_script_from_command(retract_gcode) self.is_retracted = True @@ -259,7 +271,9 @@ def cmd_G10(self, gcmd): # Swap original G1 handlers if z_hop enabled to offset following # moves in eiter absolute or relative mode self._unregister_G1() - self.G1_toggle_state = True # Prevent repeat unregister with flag + self.G1_toggle_state = ( + True # Prevent repeat unregister with flag + ) else: gcmd.respond_info("Printer is already retracted. Command ignored!") diff --git a/klippy/extras/force_move.py b/klippy/extras/force_move.py index 44f14d1db..c8d0ca9b0 100644 --- a/klippy/extras/force_move.py +++ b/klippy/extras/force_move.py @@ -208,7 +208,11 @@ def cmd_MARK_AS_HOMED(self, gcmd): axes = axes_str.split(",") invalid_axis = [] for axis in axes: - if axis.lower() != "x" and axis.lower() != "y" and axis.lower() != "z": + if ( + axis.lower() != "x" + and axis.lower() != "y" + and axis.lower() != "z" + ): invalid_axis.append(axis) if invalid_axis: gcmd.respond_info("MARK_AS_HOMED: Invalid axis %s" % invalid_axis) diff --git a/klippy/extras/gcode_button.py b/klippy/extras/gcode_button.py index ac3501147..3c11b81f4 100644 --- a/klippy/extras/gcode_button.py +++ b/klippy/extras/gcode_button.py @@ -17,13 +17,17 @@ def __init__(self, config): buttons.register_buttons([self.pin], self.button_callback) else: amin, amax = config.getfloatlist("analog_range", count=2) - pullup = config.getfloat("analog_pullup_resistor", 4700.0, above=0.0) + pullup = config.getfloat( + "analog_pullup_resistor", 4700.0, above=0.0 + ) buttons.register_adc_button( self.pin, amin, amax, pullup, self.button_callback ) gcode_macro = self.printer.load_object(config, "gcode_macro") self.press_template = gcode_macro.load_template(config, "press_gcode") - self.release_template = gcode_macro.load_template(config, "release_gcode", "") + self.release_template = gcode_macro.load_template( + config, "release_gcode", "" + ) self.gcode = self.printer.lookup_object("gcode") self.gcode.register_mux_command( "QUERY_BUTTON", diff --git a/klippy/extras/gcode_macro.py b/klippy/extras/gcode_macro.py index 1f292330c..aad598da6 100644 --- a/klippy/extras/gcode_macro.py +++ b/klippy/extras/gcode_macro.py @@ -4,19 +4,22 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import pipes +import threading import traceback, logging, ast, copy, json import jinja2, math import configfile from extras.danger_options import get_danger_options +PYTHON_SCRIPT_PREFIX = "!" + ###################################################################### # Template handling ###################################################################### # Wrapper for access to printer object get_status() methods -class GetStatusWrapper: +class GetStatusWrapperJinja: def __init__(self, printer, eventtime=None): self.printer = printer self.eventtime = eventtime @@ -47,6 +50,35 @@ def __iter__(self): yield name +class GetStatusWrapperPython: + def __init__(self, printer): + self.printer = printer + self.cache = {} + + def __getitem__(self, val): + sval = str(val).strip() + po = self.printer.lookup_object(sval, None) + if po is None or not hasattr(po, "get_status"): + raise KeyError(val) + eventtime = self.printer.get_reactor().monotonic() + return po.get_status(eventtime) + + def __getattr__(self, val): + return self.__getitem__(val) + + def __contains__(self, val): + try: + self.__getitem__(val) + except KeyError as e: + return False + return True + + def __iter__(self): + for name, obj in self.printer.lookup_objects(): + if self.__contains__(name): + yield name + + # Wrapper around a Jinja2 template class TemplateWrapper: def __init__(self, printer, env, name, script): @@ -82,12 +114,162 @@ def run_gcode_from_command(self, context=None): self.gcode.run_script_from_command(self.render(context)) +class TemplateWrapperPython: + def __init__(self, printer, env, name, script): + self.printer = printer + self.name = name + self.toolhead = None + self.gcode = self.printer.lookup_object("gcode") + self.gcode_macro = self.printer.lookup_object("gcode_macro") + self.create_template_context = self.gcode_macro.create_template_context + self.checked_own_macro = False + self.vars = None + + try: + script = "\n".join( + map(lambda l: l.removeprefix("!"), script.split("\n")) + ) + self.func = compile(script, name, "exec") + except SyntaxError as e: + msg = "Error compiling expression '%s': %s at line %d column %d" % ( + self.name, + traceback.format_exception_only(type(e), e)[-1], + e.lineno, + e.offset, + ) + logging.exception(msg) + raise self.gcode.error(msg) + + def run_gcode_from_command(self, context=None): + helpers = { + "printer": GetStatusWrapperPython(self.printer), + "emit": self._action_emit, + "wait_while": self._action_wait_while, + "wait_until": self._action_wait_until, + "wait_moves": self._action_wait_moves, + "blocking": self._action_blocking, + "sleep": self._action_sleep, + "set_gcode_variable": self._action_set_gcode_variable, + "emergency_stop": self.gcode_macro._action_emergency_stop, + "respond_info": self.gcode_macro._action_respond_info, + "raise_error": self.gcode_macro._action_raise_error, + "call_remote_method": self.gcode_macro._action_call_remote_method, + "action_emergency_stop": self.gcode_macro._action_emergency_stop, + "action_respond_info": self.gcode_macro._action_respond_info, + "action_raise_error": self.gcode_macro._action_raise_error, + "action_call_remote_method": self.gcode_macro._action_call_remote_method, + "math": math, + } + + if not self.checked_own_macro: + self.checked_own_macro = True + own_macro = self.printer.lookup_object( + self.name.split(":")[0], None + ) + if own_macro is not None and isinstance(own_macro, GCodeMacro): + self.vars = TemplateVariableWrapperPython(own_macro) + if self.vars is not None: + helpers["own_vars"] = self.vars + + if context is None: + context = {} + exec_globals = dict(context | helpers) + try: + exec(self.func, exec_globals, {}) + except Exception as e: + msg = "Error evaluating '%s': %s" % ( + self.name, + traceback.format_exception_only(type(e), e)[-1], + ) + logging.exception(msg) + raise self.gcode.error(msg) + + def _action_emit(self, gcode): + self.gcode.run_script_from_command(gcode) + + def _action_wait_while(self, check): + def inner(eventtime): + return check() + + self.printer.wait_while(check) + + def _action_wait_until(self, check): + def inner(eventtime): + return not check() + + self.printer.wait_while(inner) + + def _action_wait_moves(self): + if self.toolhead is None: + self.toolhead = self.printer.lookup_object("toolhead") + self.toolhead.wait_moves() + + def _action_blocking(self, func): + completion = self.printer.get_reactor().completion() + + def run(): + try: + ret = func() + completion.complete((False, ret)) + except Exception as e: + completion.complete((True, e)) + + t = threading.Thread(target=run, daemon=True) + t.start() + [is_exception, ret] = completion.wait() + if is_exception: + raise ret + else: + return ret + + def _action_sleep(self, timeout): + reactor = self.printer.get_reactor() + deadline = reactor.monotonic() + timeout + + def check(event): + return deadline > reactor.monotonic() + + self.printer.wait_while(check) + + def _action_set_gcode_variable(self, macro, variable, value): + macro = self.printer.lookup_object(f"gcode_macro {macro}") + v = dict(macro.variables) + v[variable] = value + macro.variables = v + + +class TemplateVariableWrapperPython: + def __init__(self, macro): + self.__dict__["__macro"] = macro + + def __setattr__(self, name, value): + v = dict(self.__dict__["__macro"].variables) + v[name] = value + self.__dict__["__macro"].variables = v + + def __getattr__(self, name): + if name not in self.__dict__["__macro"].variables: + raise KeyError(name) + return self.__dict__["__macro"].variables[name] + + def __contains__(self, val): + try: + self.__getattr__(val) + except KeyError as e: + return False + return True + + def __iter__(self): + for name, obj in self.__dict__["__macro"].variables: + yield name + + class Template: def __init__(self, printer, env, name, script) -> None: self.name = name self.printer = printer self.env = env - self.function = TemplateWrapper(self.printer, self.env, name, script) + self.reload(script) def __call__(self, context=None): return self.function(context) @@ -96,7 +278,15 @@ def __getattr__(self, name): return getattr(self.function, name) def reload(self, script): - self.function = TemplateWrapper(self.printer, self.env, self.name, script) + if script.startswith(PYTHON_SCRIPT_PREFIX): + script = script[len(PYTHON_SCRIPT_PREFIX) :] + self.function = TemplateWrapperPython( + self.printer, self.env, self.name, script + ) + else: + self.function = TemplateWrapper( + self.printer, self.env, self.name, script + ) # Main gcode macro template tracking @@ -118,7 +308,9 @@ def __init__(self, config): self.env.filters["repr"] = repr self.env.filters["shell_quote"] = pipes.quote self.gcode = self.printer.lookup_object("gcode") - self.gcode.register_command("RELOAD_GCODE_MACROS", self.cmd_RELOAD_GCODE_MACROS) + self.gcode.register_command( + "RELOAD_GCODE_MACROS", self.cmd_RELOAD_GCODE_MACROS + ) def boolean(self, value): lowercase_value = str(value).lower() @@ -130,6 +322,7 @@ def load_template(self, config, option, default=None): script = config.get(option) else: script = config.get(option, default) + script = script.strip() return Template(self.printer, self.env, name, script) def _action_emergency_stop(self, msg="action_emergency_stop"): @@ -157,7 +350,7 @@ def _action_call_remote_method(self, method, **kwargs): def create_template_context(self, eventtime=None): return { - "printer": GetStatusWrapper(self.printer, eventtime), + "printer": GetStatusWrapperJinja(self.printer, eventtime), "action_emergency_stop": self._action_emergency_stop, "action_respond_info": self._action_respond_info, "action_log": self._action_log, @@ -176,7 +369,8 @@ def cmd_RELOAD_GCODE_MACROS(self, gcmd): continue if name in [ - s.get_name() for s in new_config.get_prefix_sections("gcode_macro") + s.get_name() + for s in new_config.get_prefix_sections("gcode_macro") ]: template = obj.template new_script = new_section.get("gcode").strip() @@ -196,7 +390,8 @@ class GCodeMacro: def __init__(self, config): if len(config.get_name().split()) > 2: raise config.error( - "Name of section '%s' contains illegal whitespace" % (config.get_name()) + "Name of section '%s' contains illegal whitespace" + % (config.get_name()) ) name = config.get_name().split()[1] self.alias = name.upper() @@ -214,9 +409,13 @@ def __init__(self, config): "G-Code macro rename of different types ('%s' vs '%s')" % (self.alias, self.rename_existing) ) - printer.register_event_handler("klippy:connect", self._handle_connect) + printer.register_event_handler( + "klippy:connect", self._handle_connect + ) else: - self.gcode.register_command(self.alias, self.cmd, desc=self.cmd_desc) + self.gcode.register_command( + self.alias, self.cmd, desc=self.cmd_desc + ) self.gcode.register_mux_command( "SET_GCODE_VARIABLE", "MACRO", @@ -249,7 +448,8 @@ def _handle_connect(self): prev_cmd = self.gcode.register_command(self.alias, None) if prev_cmd is None: raise self.printer.config_error( - "Existing command '%s' not found in gcode_macro rename" % (self.alias,) + "Existing command '%s' not found in gcode_macro rename" + % (self.alias,) ) pdesc = "Renamed builtin of '%s'" % (self.alias,) self.gcode.register_command(self.rename_existing, prev_cmd, desc=pdesc) @@ -269,7 +469,9 @@ def cmd_SET_GCODE_VARIABLE(self, gcmd): literal = ast.literal_eval(value) json.dumps(literal, separators=(",", ":")) except (SyntaxError, TypeError, ValueError) as e: - raise gcmd.error("Unable to parse '%s' as a literal: %s" % (value, e)) + raise gcmd.error( + "Unable to parse '%s' as a literal: %s" % (value, e) + ) v = dict(self.variables) v[variable] = literal self.variables = v diff --git a/klippy/extras/gcode_move.py b/klippy/extras/gcode_move.py index 3d61cab2e..1868d7a6f 100644 --- a/klippy/extras/gcode_move.py +++ b/klippy/extras/gcode_move.py @@ -14,8 +14,12 @@ def __init__(self, config): printer.register_event_handler( "toolhead:set_position", self.reset_last_position ) - printer.register_event_handler("toolhead:manual_move", self.reset_last_position) - printer.register_event_handler("gcode:command_error", self.reset_last_position) + printer.register_event_handler( + "toolhead:manual_move", self.reset_last_position + ) + printer.register_event_handler( + "gcode:command_error", self.reset_last_position + ) printer.register_event_handler( "extruder:activate_extruder", self._handle_activate_extruder ) @@ -104,7 +108,9 @@ def _handle_home_rails_end(self, homing_state, rails): def set_move_transform(self, transform, force=False): if self.move_transform is not None and not force: - raise self.printer.config_error("G-Code move transform already specified") + raise self.printer.config_error( + "G-Code move transform already specified" + ) old_transform = self.move_transform if old_transform is None: old_transform = self.printer.lookup_object("toolhead", None) @@ -171,7 +177,9 @@ def cmd_G1(self, gcmd): ) self.speed = gcode_speed * self.speed_factor except ValueError as e: - raise gcmd.error("Unable to parse move '%s'" % (gcmd.get_commandline(),)) + raise gcmd.error( + "Unable to parse move '%s'" % (gcmd.get_commandline(),) + ) self.move_with_transform(self.last_position, self.speed) # G-Code coordinate manipulation @@ -290,7 +298,9 @@ def cmd_RESTORE_GCODE_STATE(self, gcmd): self.last_position[:3] = state["last_position"][:3] self.move_with_transform(self.last_position, speed) - cmd_GET_POSITION_help = "Return information on the current location of the toolhead" + cmd_GET_POSITION_help = ( + "Return information on the current location of the toolhead" + ) def cmd_GET_POSITION(self, gcmd): toolhead = self.printer.lookup_object("toolhead", None) @@ -306,7 +316,10 @@ def cmd_GET_POSITION(self, gcmd): kinfo = zip("XYZ", kin.calc_position(dict(cinfo))) kin_pos = " ".join(["%s:%.6f" % (a, v) for a, v in kinfo]) toolhead_pos = " ".join( - ["%s:%.6f" % (a, v) for a, v in zip("XYZE", toolhead.get_position())] + [ + "%s:%.6f" % (a, v) + for a, v in zip("XYZE", toolhead.get_position()) + ] ) gcode_pos = " ".join( ["%s:%.6f" % (a, v) for a, v in zip("XYZE", self.last_position)] diff --git a/klippy/extras/gcode_shell_command.py b/klippy/extras/gcode_shell_command.py index ca195bc38..3b6e29697 100644 --- a/klippy/extras/gcode_shell_command.py +++ b/klippy/extras/gcode_shell_command.py @@ -24,9 +24,13 @@ def __init__(self, config): self.verbose = config.getboolean("verbose", False) self.on_success_template = self.on_failure_template = None if config.get("success", None) is not None: - self.on_success_template = gcode_macro.load_template(config, "success", "") + self.on_success_template = gcode_macro.load_template( + config, "success", "" + ) if config.get("failure", None) is not None: - self.on_failure_template = gcode_macro.load_template(config, "failure", "") + self.on_failure_template = gcode_macro.load_template( + config, "failure", "" + ) self.proc_fd = None self.partial_output = "" self.values = {} @@ -89,7 +93,9 @@ def cmd_RUN_SHELL_COMMAND(self, params): stderr=subprocess.STDOUT, ) except Exception: - logging.exception("shell_command: Command {%s} failed" % (self.name)) + logging.exception( + "shell_command: Command {%s} failed" % (self.name) + ) raise self.gcode.error("Error running command {%s}" % (self.name)) self.proc_fd = proc.stdout.fileno() hdl = reactor.register_fd(self.proc_fd, self._process_output) diff --git a/klippy/extras/hall_filament_width_sensor.py b/klippy/extras/hall_filament_width_sensor.py index 8ccce33eb..be8980396 100644 --- a/klippy/extras/hall_filament_width_sensor.py +++ b/klippy/extras/hall_filament_width_sensor.py @@ -28,8 +28,12 @@ def __init__(self, config): ) self.measurement_delay = config.getfloat("measurement_delay", above=0.0) self.measurement_max_difference = config.getfloat("max_difference", 0.2) - self.max_diameter = self.nominal_filament_dia + self.measurement_max_difference - self.min_diameter = self.nominal_filament_dia - self.measurement_max_difference + self.max_diameter = ( + self.nominal_filament_dia + self.measurement_max_difference + ) + self.min_diameter = ( + self.nominal_filament_dia - self.measurement_max_difference + ) self.diameter = self.nominal_filament_dia self.is_active = config.getboolean("enable", False) self.runout_dia_min = config.getfloat("min_diameter", 1.0) @@ -41,7 +45,9 @@ def __init__(self, config): "use_current_dia_while_delay", False ) runout_distance = config.getfloat("runout_distance", 0.0, minval=0.0) - self.check_on_print_start = config.getboolean("check_on_print_start", False) + self.check_on_print_start = config.getboolean( + "check_on_print_start", False + ) # filament array [position, filamentWidth] self.filament_array = [] self.lastFilamentWidthReading = 0 @@ -69,18 +75,28 @@ def __init__(self, config): self.gcode.register_command( "RESET_FILAMENT_WIDTH_SENSOR", self.cmd_ClearFilamentArray ) - self.gcode.register_command("DISABLE_FILAMENT_WIDTH_SENSOR", self.cmd_M406) - self.gcode.register_command("ENABLE_FILAMENT_WIDTH_SENSOR", self.cmd_M405) - self.gcode.register_command("QUERY_RAW_FILAMENT_WIDTH", self.cmd_Get_Raw_Values) - self.gcode.register_command("ENABLE_FILAMENT_WIDTH_LOG", self.cmd_log_enable) - self.gcode.register_command("DISABLE_FILAMENT_WIDTH_LOG", self.cmd_log_disable) + self.gcode.register_command( + "DISABLE_FILAMENT_WIDTH_SENSOR", self.cmd_M406 + ) + self.gcode.register_command( + "ENABLE_FILAMENT_WIDTH_SENSOR", self.cmd_M405 + ) + self.gcode.register_command( + "QUERY_RAW_FILAMENT_WIDTH", self.cmd_Get_Raw_Values + ) + self.gcode.register_command( + "ENABLE_FILAMENT_WIDTH_LOG", self.cmd_log_enable + ) + self.gcode.register_command( + "DISABLE_FILAMENT_WIDTH_LOG", self.cmd_log_disable + ) self.runout_helper = filament_switch_sensor.RunoutHelper( config, self, runout_distance ) if config.get("immediate_runout_gcode", None) is not None: - self.runout_helper.immediate_runout_gcode = gcode_macro.load_template( - config, "immediate_runout_gcode", "" + self.runout_helper.immediate_runout_gcode = ( + gcode_macro.load_template(config, "immediate_runout_gcode", "") ) self.printer.register_event_handler( @@ -91,8 +107,8 @@ def __init__(self, config): config, self, runout_distance ) if config.get("immediate_runout_gcode", None) is not None: - self.runout_helper.immediate_runout_gcode = gcode_macro.load_template( - config, "immediate_runout_gcode", "" + self.runout_helper.immediate_runout_gcode = ( + gcode_macro.load_template(config, "immediate_runout_gcode", "") ) self.printer.register_event_handler( @@ -113,34 +129,9 @@ def _handle_ready(self): ).estimated_print_time # Start extrude factor update timer - self.reactor.update_timer(self.extrude_factor_update_timer, self.reactor.NOW) - - def _handle_printing(self, *args): - if not self.runout_helper.smart: - if self.check_on_print_start: - self.reset() - self.runout_helper.note_filament_present( - self.runout_dia_min <= self.diameter <= self.runout_dia_max, - True, - True, - ) - - def _handle_printing_smart(self, *args): - if self.runout_helper.smart: - if self.check_on_print_start: - self.reset() - self.runout_helper.note_filament_present( - self.runout_dia_min <= self.diameter <= self.runout_dia_max, - True, - True, - ) - - def get_extruder_pos(self, eventtime=None): - if eventtime is None: - eventtime = self.reactor.monotonic() - print_time = self.estimated_print_time(eventtime) - extruder = self.printer.lookup_object("toolhead").get_extruder() - return extruder.find_past_position(print_time) + self.reactor.update_timer( + self.extrude_factor_update_timer, self.reactor.NOW + ) def _handle_printing(self, *args): if not self.runout_helper.smart: @@ -202,14 +193,18 @@ def update_filament_array(self, last_epos): [last_epos + self.measurement_delay, self.diameter] ) if self.is_log: - self.gcode.respond_info("Filament width:%.3f" % (self.diameter)) + self.gcode.respond_info( + "Filament width:%.3f" % (self.diameter) + ) else: # add first item to array self.filament_array.append( [self.measurement_delay + last_epos, self.diameter] ) - self.firstExtruderUpdatePosition = self.measurement_delay + last_epos + self.firstExtruderUpdatePosition = ( + self.measurement_delay + last_epos + ) def extrude_factor_update_event(self, eventtime): # Update extrude factor @@ -241,7 +236,9 @@ def extrude_factor_update_event(self, eventtime): self.filament_width >= self.min_diameter ): percentage = round( - self.nominal_filament_dia**2 / self.filament_width**2 * 100 + self.nominal_filament_dia**2 + / self.filament_width**2 + * 100 ) self.gcode.run_script("M221 S" + str(percentage)) else: @@ -359,7 +356,9 @@ def sensor_get_status(self, eventtime=None): def get_status(self, eventtime=None): return { "Diameter": self.diameter, - "Raw": (self.lastFilamentWidthReading + self.lastFilamentWidthReading2), + "Raw": ( + self.lastFilamentWidthReading + self.lastFilamentWidthReading2 + ), "is_active": self.is_active, "check_on_print_start": bool(self.check_on_print_start), } diff --git a/klippy/extras/heated_fan.py b/klippy/extras/heated_fan.py index 81935f418..ff94b96ec 100644 --- a/klippy/extras/heated_fan.py +++ b/klippy/extras/heated_fan.py @@ -21,7 +21,9 @@ def __init__(self, config): except: self.printer.add_object("fan", self) else: - raise self.printer.config_error("Can't setup fan and heated_fan together") + raise self.printer.config_error( + "Can't setup fan and heated_fan together" + ) # setup heater pheaters = self.printer.load_object(config, "heaters") @@ -31,7 +33,9 @@ def __init__(self, config): # setup fan self.fan = fan.Fan(config, default_shutdown_speed=1.0) - self.min_speed = config.getfloat("min_speed", 1.0, minval=0.0, maxval=1.0) + self.min_speed = config.getfloat( + "min_speed", 1.0, minval=0.0, maxval=1.0 + ) self.idle_timeout = config.getfloat("idle_timeout", 60.0, minval=0.0) self.speed = 0.0 diff --git a/klippy/extras/heater_fan.py b/klippy/extras/heater_fan.py index b93664425..34f1b2698 100644 --- a/klippy/extras/heater_fan.py +++ b/klippy/extras/heater_fan.py @@ -42,7 +42,9 @@ def _handle_ready(self): pheaters = self.printer.lookup_object("heaters") self.heaters = [pheaters.lookup_heater(n) for n in self.heater_names] reactor = self.printer.get_reactor() - reactor.register_timer(self.callback, reactor.monotonic() + PIN_MIN_TIME) + reactor.register_timer( + self.callback, reactor.monotonic() + PIN_MIN_TIME + ) def get_status(self, eventtime): status = self.fan.get_status(eventtime) @@ -71,7 +73,9 @@ def callback(self, eventtime): def cmd_SET_HEATER_FAN(self, gcmd): self.enabled = gcmd.get_int("ENABLE", self.enabled, minval=0, maxval=1) - self.fan_speed = gcmd.get_float("FAN_SPEED", self.fan_speed, minval=0, maxval=1) + self.fan_speed = gcmd.get_float( + "FAN_SPEED", self.fan_speed, minval=0, maxval=1 + ) if self.enabled: self.fan.set_speed(self.fan_speed) if not self.enabled: diff --git a/klippy/extras/heater_profile_manager.py b/klippy/extras/heater_profile_manager.py index 8f2c0a263..42c65043d 100644 --- a/klippy/extras/heater_profile_manager.py +++ b/klippy/extras/heater_profile_manager.py @@ -34,7 +34,8 @@ def _init_profile(self, config_section, name, force_control=None): else: raise self.heater.printer.config_error( "Unknown control type '%s' " - "in [heater_profile %s %s]." % (control, self.heater.sensor_name, name) + "in [heater_profile %s %s]." + % (control, self.heater.sensor_name, name) ) def _check_value_config( @@ -81,7 +82,9 @@ def _compute_section_name(self, profile_name): return ( self.heater.sensor_name if profile_name == "default" - else ("heater_profile " + self.heater.sensor_name + " " + profile_name) + else ( + "heater_profile " + self.heater.sensor_name + " " + profile_name + ) ) def _check_value_gcmd( @@ -205,7 +208,8 @@ def load_profile(self, profile_name, gcmd): if profile is None: raise self.heater.gcode.error( "heater_profile: Unknown default " - "profile [%s] for heater [%s]." % (default, self.heater.sensor_name) + "profile [%s] for heater [%s]." + % (default, self.heater.sensor_name) ) control = self.heater.lookup_control(profile, load_clean) self.heater.set_control(control, keep_target) @@ -234,15 +238,10 @@ def load_profile(self, profile_name, gcmd): if profile["smoothing_elements"] is None else profile["smoothing_elements"] ) - msg = ( - "Target: %.2f\n" - "Tolerance: %.4f\n" - "Control: %s\n" - % ( - profile["pid_target"], - profile["pid_tolerance"], - profile["control"], - ) + msg = "Target: %.2f\n" "Tolerance: %.4f\n" "Control: %s\n" % ( + profile["pid_target"], + profile["pid_tolerance"], + profile["control"], ) if smooth_time is not None: msg += "Smooth Time: %.3f\n" % smooth_time diff --git a/klippy/extras/heaters.py b/klippy/extras/heaters.py index bfc945454..0bdca920b 100644 --- a/klippy/extras/heaters.py +++ b/klippy/extras/heaters.py @@ -42,7 +42,12 @@ "mpc_target": (float, "%.2f", None, True), "control": (str, "%s", "mpc", False), "heater_power": (float, "%f", None, True), - "heater_powers": (("lists", (",", "\n"), float, 2), "%.2f, %.2f\n", None, True), + "heater_powers": ( + ("lists", (",", "\n"), float, 2), + "%.2f, %.2f\n", + None, + True, + ), "cooling_fan": (str, "%s", None, True), "ambient_temp_sensor": (str, "%s", None, True), "filament_temp_sensor": (str, "%s", None, True), @@ -80,7 +85,9 @@ def __init__(self, config, sensor, sensor_config=None): self.configfile = self.printer.lookup_object("configfile") # Setup sensor self.sensor = sensor - self.min_temp = sensor_config.getfloat("min_temp", minval=KELVIN_TO_CELSIUS) + self.min_temp = sensor_config.getfloat( + "min_temp", minval=KELVIN_TO_CELSIUS + ) self.max_temp = sensor_config.getfloat("max_temp", above=self.min_temp) self.max_set_temp = sensor_config.getfloat( "max_set_temp", @@ -98,16 +105,28 @@ def __init__(self, config, sensor, sensor_config=None): minval=self.min_temp, maxval=self.max_temp, ) - is_fileoutput = self.printer.get_start_args().get("debugoutput") is not None + is_fileoutput = ( + self.printer.get_start_args().get("debugoutput") is not None + ) self.can_extrude = self.min_extrude_temp <= 0.0 or is_fileoutput - self.enabled = True self.cold_extrude = False - self.max_power = sensor_config.getfloat("max_power", 1.0, above=0.0, maxval=1.0) - self.config_smooth_time = sensor_config.getfloat("smooth_time", 1.0, above=0.0) + self.disable_if_connected = [] + if hasattr(config, "getlist"): + self.disable_if_connected = config.getlist( + "disable_if_connected", self.disable_if_connected + ) + self.max_power = sensor_config.getfloat( + "max_power", 1.0, above=0.0, maxval=1.0 + ) + self.config_smooth_time = sensor_config.getfloat( + "smooth_time", 1.0, above=0.0 + ) self.config_smoothing_elements = sensor_config.getint( "smoothing_elements", 1, minval=1 ) - self.config_smoothing = sensor_config.getfloat("smoothing", 0.25, above=0.0) + self.config_smoothing = sensor_config.getfloat( + "smoothing", 0.25, above=0.0 + ) self.smooth_time = self.config_smooth_time self.smoothing_elements = self.config_smoothing_elements self.smoothing = self.config_smoothing @@ -167,9 +186,13 @@ def __init__(self, config, sensor, sensor_config=None): "mpc": ControlMPC, } self.pmgr = ProfileManager(self, control_types) - self.control = self.lookup_control(self.pmgr.init_default_profile(), True) + self.control = self.lookup_control( + self.pmgr.init_default_profile(), True + ) if self.control is None: - raise self.config.error("Default Heater-Profile could not be loaded.") + raise self.config.error( + "Default Heater-Profile could not be loaded." + ) self.gcode.register_mux_command( "SET_HEATER_TEMPERATURE", "HEATER", @@ -212,12 +235,14 @@ def __init__(self, config, sensor, sensor_config=None): self.cmd_MPC_SET, desc=self.cmd_MPC_SET_help, ) - self.printer.register_event_handler("klippy:shutdown", self._handle_shutdown) + self.printer.register_event_handler( + "klippy:shutdown", self._handle_shutdown + ) - def notify_disabled(self): + def notify_disabled(self, mcu_name): raise self.printer.command_error( - "Heater [%s] is disabled due to an " - "accelerometer being connected." % self.sensor_short_name + "Heater [%s] is disabled due to [%s] being connected." + % (self.short_name, mcu_name) ) def lookup_control(self, profile, load_clean=False): @@ -299,7 +324,9 @@ def set_temp(self, degrees): self.target_temp = degrees def get_temp(self, eventtime): - print_time = self.mcu_pwm.get_mcu().estimated_print_time(eventtime) - 5.0 + print_time = ( + self.mcu_pwm.get_mcu().estimated_print_time(eventtime) - 5.0 + ) with self.lock: if self.last_temp_time < print_time: return 0.0, self.target_temp @@ -358,9 +385,6 @@ def get_status(self, eventtime): ret["control_stats"] = control_stats return ret - def set_enabled(self, enabled): - self.enabled = enabled - def is_adc_faulty(self): if self.last_temp > self.max_temp or self.last_temp < self.min_temp: return True @@ -376,7 +400,12 @@ def cmd_SET_HEATER_TEMPERATURE(self, gcmd): cmd_SET_SMOOTH_TIME_help = "Set the smooth time for the given heater" def cmd_SET_SMOOTH_TIME(self, gcmd): - if self.get_control().get_type() not in ("watermark", "pid", "pid_v", "pid_p"): + if self.get_control().get_type() not in ( + "watermark", + "pid", + "pid_v", + "pid_p", + ): gcmd.respond_info( "SMOOTH_TIME is only valid for watermark, pid, pid_v and pid_p" ) @@ -418,9 +447,9 @@ def cmd_SET_SMOOTHING_ELEMENTS(self, gcmd): ) self.get_control().update_smoothing_elements() if save_to_profile: - self.get_control().get_profile()[ - "smoothing_elements" - ] = self.smoothing_elements + self.get_control().get_profile()["smoothing_elements"] = ( + self.smoothing_elements + ) self.pmgr.save_profile() cmd_SET_HEATER_PID_help = "Sets a heater PID parameter" @@ -489,7 +518,12 @@ def init_profile(config_section, name, pmgr=None): else: above = None temp_profile[key] = pmgr._check_value_config( - key, config_section, type, can_be_none, default=default, above=above + key, + config_section, + type, + can_be_none, + default=default, + above=above, ) if name != "default": profile_version = config_section.getint("profile_version", None) @@ -546,7 +580,9 @@ def save_profile(pmgr, temp_profile, profile_name=None, verbose=True): ) in WATERMARK_PROFILE_OPTIONS.items(): value = temp_profile[key] if value is not None: - pmgr.heater.configfile.set(section_name, key, placeholder % value) + pmgr.heater.configfile.set( + section_name, key, placeholder % value + ) temp_profile["name"] = profile_name pmgr.profiles[profile_name] = temp_profile if verbose: @@ -618,7 +654,12 @@ def init_profile(config_section, name, pmgr): else: above = None temp_profile[key] = pmgr._check_value_config( - key, config_section, type, can_be_none, default=default, above=above + key, + config_section, + type, + can_be_none, + default=default, + above=above, ) if name == "default": temp_profile["smooth_time"] = None @@ -647,7 +688,9 @@ def set_values(pmgr, gcmd, control, profile_name): kp = pmgr._check_value_gcmd("KP", None, gcmd, float, False) ki = pmgr._check_value_gcmd("KI", None, gcmd, float, False) kd = pmgr._check_value_gcmd("KD", None, gcmd, float, False) - smooth_time = pmgr._check_value_gcmd("SMOOTH_TIME", None, gcmd, float, True) + smooth_time = pmgr._check_value_gcmd( + "SMOOTH_TIME", None, gcmd, float, True + ) smoothing_elements = pmgr._check_value_gcmd( "SMOOTHING_ELEMENTS", None, gcmd, int, True ) @@ -702,7 +745,9 @@ def save_profile(pmgr, temp_profile, profile_name=None, verbose=True): ) in PID_PROFILE_OPTIONS.items(): value = temp_profile[key] if value is not None: - pmgr.heater.configfile.set(section_name, key, placeholder % value) + pmgr.heater.configfile.set( + section_name, key, placeholder % value + ) temp_profile["name"] = profile_name pmgr.profiles[profile_name] = temp_profile if verbose: @@ -747,7 +792,8 @@ def temperature_update(self, read_time, temp, target_temp): temp_deriv = temp_diff / time_diff else: temp_deriv = ( - self.prev_temp_deriv * (self.min_deriv_time - time_diff) + temp_diff + self.prev_temp_deriv * (self.min_deriv_time - time_diff) + + temp_diff ) / self.min_deriv_time # Calculate accumulated temperature "error" temp_err = target_temp - temp @@ -823,7 +869,8 @@ def median(temps): length = len(sorted_temps) return float( ( - sorted_temps[length // 2 - 1] / 2.0 + sorted_temps[length // 2] / 2.0, + sorted_temps[length // 2 - 1] / 2.0 + + sorted_temps[length // 2] / 2.0, sorted_temps[length // 2], )[length % 2] ) @@ -919,7 +966,9 @@ def temperature_update(self, read_time, temp, target_temp): def check_busy(self, eventtime, smoothed_temp, target_temp): temp_diff = target_temp - smoothed_temp - return abs(temp_diff) > PID_SETTLE_DELTA or abs(self.d1) > PID_SETTLE_SLOPE + return ( + abs(temp_diff) > PID_SETTLE_DELTA or abs(self.d1) > PID_SETTLE_SLOPE + ) def update_smooth_time(self): self.smooth_time = self.heater.get_smooth_time() # smoothing window @@ -974,9 +1023,13 @@ def __init__(self, profile, heater, load_clean=False): ) self.heater.set_inv_smooth_time(1.0 / smooth_time) self.smooth_time = smooth_time # smoothing window - self.prev_temp_time = 0.0 if load_clean else self.heater.reactor.monotonic() + self.prev_temp_time = ( + 0.0 if load_clean else self.heater.reactor.monotonic() + ) self.prev_temp = ( - AMBIENT_TEMP if load_clean else self.heater.get_temp(self.prev_temp_time)[0] + AMBIENT_TEMP + if load_clean + else self.heater.get_temp(self.prev_temp_time)[0] ) self.prev_err = 0.0 self.prev_der = 0.0 @@ -1027,7 +1080,8 @@ def temperature_update(self, read_time, temp, target_temp): def check_busy(self, eventtime, smoothed_temp, target_temp): temp_diff = target_temp - smoothed_temp return ( - abs(temp_diff) > PID_SETTLE_DELTA or abs(self.prev_der) > PID_SETTLE_SLOPE + abs(temp_diff) > PID_SETTLE_DELTA + or abs(self.prev_der) > PID_SETTLE_SLOPE ) def update_smooth_time(self): @@ -1092,12 +1146,15 @@ def init_profile(config_section, name, pmgr=None): if heater_power is not None and heater_powers is not None: raise config_section.error( "Option 'heater_power' and 'heater_powers' " - "in section '%s' can not be specified both" % config_section.get_name() + "in section '%s' can not be specified both" + % config_section.get_name() + " " + name ) - filament_temp_src_raw = temp_profile["filament_temp_source"].lower().strip() + filament_temp_src_raw = ( + temp_profile["filament_temp_source"].lower().strip() + ) if filament_temp_src_raw == "sensor_ambient": filament_temp_src = (FILAMENT_TEMP_SRC_SENSOR_AMBIENT,) elif filament_temp_src_raw == "sensor": @@ -1136,7 +1193,9 @@ def init_profile(config_section, name, pmgr=None): raise config_section.error( f"Unknown part_cooling_fan '{fan_name}' specified" ) - if not hasattr(fan_obj, "fan") or not hasattr(fan_obj.fan, "set_speed"): + if not hasattr(fan_obj, "fan") or not hasattr( + fan_obj.fan, "set_speed" + ): raise config_section.error( f"part_cooling_fan '{fan_name}' is not a valid fan object" ) @@ -1191,14 +1250,18 @@ def save_profile(pmgr, temp_profile, profile_name=None, verbose=True): ", ".join([placeholder % p for p in value]), ) elif key == "ambient_temp_sensor" or key == "cooling_fan": - pmgr.heater.configfile.set(section_name, key, value.full_name) + pmgr.heater.configfile.set( + section_name, key, value.full_name + ) elif key == "filament_temp_source": if value[-1] != default: pmgr.heater.configfile.set( section_name, key, placeholder % value[-1] ) elif key == "control": - pmgr.heater.configfile.set(section_name, key, placeholder % value) + pmgr.heater.configfile.set( + section_name, key, placeholder % value + ) else: if value != default: pmgr.heater.configfile.set( @@ -1218,9 +1281,9 @@ def save_profile(pmgr, temp_profile, profile_name=None, verbose=True): @staticmethod def get_power_at_temp(temperature, power_table): def _interpolate(below, above, temp): - return ((below[1] * (above[0] - temp)) + (above[1] * (temp - below[0]))) / ( - above[0] - below[0] - ) + return ( + (below[1] * (above[0] - temp)) + (above[1] * (temp - below[0])) + ) / (above[0] - below[0]) if temperature <= power_table[0][0]: return power_table[0][1] @@ -1251,7 +1314,9 @@ def __init__(self, profile, heater, load_clean=False): self._init_profile() self.want_ambient_refresh = self.ambient_sensor is not None - self.state_block_temp = AMBIENT_TEMP if load_clean else self._heater_temp() + self.state_block_temp = ( + AMBIENT_TEMP if load_clean else self._heater_temp() + ) self.state_sensor_temp = self.state_block_temp self.state_ambient_temp = AMBIENT_TEMP @@ -1285,7 +1350,9 @@ def _init_profile(self): self.const_steady_state_rate = self.profile["steady_state_rate"] self.const_filament_diameter = self.profile["filament_diameter"] self.const_filament_density = self.profile["filament_density"] - self.const_filament_heat_capacity = self.profile["filament_heat_capacity"] + self.const_filament_heat_capacity = self.profile[ + "filament_heat_capacity" + ] self.const_maximum_retract = self.profile["maximum_retract"] self.filament_temp_src = self.profile["filament_temp_source"] self.ambient_sensor = self.profile["ambient_temp_sensor"] @@ -1393,7 +1460,11 @@ def temperature_update(self, read_time, temp, target_temp): # Expected block dT since last period expected_block_dT = ( - (expected_heating - expected_ambient_transfer - expected_filament_transfer) + ( + expected_heating + - expected_ambient_transfer + - expected_filament_transfer + ) * dt / self.const_block_heat_capacity ) @@ -1423,9 +1494,13 @@ def temperature_update(self, read_time, temp, target_temp): expected_block_dT + adjustment_dT ) < self.const_steady_state_rate * dt: if adjustment_dT > 0.0: - ambient_delta = max(adjustment_dT, self.const_min_ambient_change * dt) + ambient_delta = max( + adjustment_dT, self.const_min_ambient_change * dt + ) else: - ambient_delta = min(adjustment_dT, -self.const_min_ambient_change * dt) + ambient_delta = min( + adjustment_dT, -self.const_min_ambient_change * dt + ) self.state_ambient_temp += ambient_delta # Output @@ -1454,14 +1529,18 @@ def temperature_update(self, read_time, temp, target_temp): power = max( 0.0, min( - ControlMPC.get_power_at_temp(target_temp, self.pwm_max_power), + ControlMPC.get_power_at_temp( + target_temp, self.pwm_max_power + ), heating_power + loss_ambient + loss_filament, ), ) else: power = 0 - heater_power = ControlMPC.get_power_at_temp(temp, self.const_heater_power) + heater_power = ControlMPC.get_power_at_temp( + temp, self.const_heater_power + ) duty = max(0.0, min(self.heater_max_power, power / heater_power)) @@ -1499,7 +1578,8 @@ def filament_temp(self, read_time, ambient_temp): ): return self.ambient_sensor.get_temp(read_time)[0] elif ( - src[0] == FILAMENT_TEMP_SRC_SENSOR and self.filament_temp_sensor is not None + src[0] == FILAMENT_TEMP_SRC_SENSOR + and self.filament_temp_sensor is not None ): return self.filament_temp_sensor.get_temp(read_time)[0] else: @@ -1590,7 +1670,9 @@ def setup_heater(self, config, gcode_id=None, heater_config=None): # Setup sensor sensor = self.setup_sensor(heater_config) # Create heater - self.heaters[heater_name] = heater = Heater(config, sensor, heater_config) + self.heaters[heater_name] = heater = Heater( + config, sensor, heater_config + ) self.register_sensor(config, heater, gcode_id) self.available_heaters.append(config.get_name()) return heater @@ -1602,7 +1684,9 @@ def lookup_heater(self, heater_name): if " " in heater_name: heater_name = heater_name.split(" ", 1)[1] if heater_name not in self.heaters: - raise self.printer.config_error("Unknown heater '%s'" % (heater_name,)) + raise self.printer.config_error( + "Unknown heater '%s'" % (heater_name,) + ) return self.heaters[heater_name] def setup_sensor(self, config): @@ -1682,9 +1766,16 @@ def check(eventtime): self.printer.wait_while(check) def set_temperature(self, heater, temp, wait=False): - if not heater.enabled: - heater.notify_disabled() - return + for mcu_name in heater.disable_if_connected: + if not mcu_name.startswith("mcu"): + mcu_name = "mcu " + mcu_name + mcu_object = self.printer.lookup_object(mcu_name, None) + if ( + mcu_object is not None + and not mcu_object.non_critical_disconnected + ): + heater.notify_disabled(mcu_name) + return toolhead = self.printer.lookup_object("toolhead") toolhead.register_lookahead_callback((lambda pt: None)) heater.set_temp(temp) @@ -1701,7 +1792,9 @@ def cmd_TEMPERATURE_WAIT(self, gcmd): max_temp = gcmd.get_float("MAXIMUM", float("inf"), above=min_temp) error_on_cancel = gcmd.get("ALLOW_CANCEL", None) is None if min_temp == float("-inf") and max_temp == float("inf"): - raise gcmd.error("Error on 'TEMPERATURE_WAIT': missing MINIMUM or MAXIMUM.") + raise gcmd.error( + "Error on 'TEMPERATURE_WAIT': missing MINIMUM or MAXIMUM." + ) if self.printer.get_start_args().get("debugoutput") is not None: return if sensor_name in self.heaters: diff --git a/klippy/extras/homing.py b/klippy/extras/homing.py index 0a4854bb3..939c486b1 100644 --- a/klippy/extras/homing.py +++ b/klippy/extras/homing.py @@ -24,7 +24,9 @@ def multi_complete(printer, completions): cp = reactor.register_callback(lambda e: [c.wait() for c in completions]) # If any completion indicates an error, then exit main completion early for c in completions: - reactor.register_callback(lambda e, c=c: cp.complete(1) if c.wait() else 0) + reactor.register_callback( + lambda e, c=c: cp.complete(1) if c.wait() else 0 + ) return cp @@ -179,7 +181,8 @@ def homing_move( if any(over_steps.values()): self.toolhead.set_position(movepos) halt_kin_spos = { - s.get_name(): s.get_commanded_position() for s in kin.get_steppers() + 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) @@ -203,12 +206,17 @@ def check_no_movement(self): def moved_less_than_dist(self, min_dist, homing_axes): homing_axis_distances = [ - dist for i, dist in enumerate(self.distance_elapsed) if i in homing_axes + dist + for i, dist in enumerate(self.distance_elapsed) + if i in homing_axes ] - distance_tolerance = get_danger_options().homing_elapsed_distance_tolerance + distance_tolerance = ( + get_danger_options().homing_elapsed_distance_tolerance + ) if any( [ - abs(dist) < min_dist and min_dist - abs(dist) >= distance_tolerance + abs(dist) < min_dist + and min_dist - abs(dist) >= distance_tolerance for dist in homing_axis_distances ] ): @@ -221,6 +229,7 @@ class Homing: def __init__(self, printer): self.printer = printer self.toolhead = printer.lookup_object("toolhead") + self.gcode = self.printer.lookup_object("gcode") self.changed_axes = [] self.trigger_mcu_pos = {} self.adjust_pos = {} @@ -313,13 +322,19 @@ def home_rails(self, rails, forcepos, movepos): axes_d = [hp - sp for hp, sp in zip(homepos, startpos)] move_d = math.sqrt(sum([d * d for d in axes_d[:3]])) retract_r = min(1.0, retract_dist / move_d) - retractpos = [hp - ad * retract_r for hp, ad in zip(homepos, axes_d)] + retractpos = [ + hp - ad * retract_r for hp, ad in zip(homepos, axes_d) + ] self.toolhead.move(retractpos, hi.retract_speed) # Home again - startpos = [rp - ad * retract_r for rp, ad in zip(retractpos, axes_d)] + startpos = [ + rp - ad * retract_r for rp, ad in zip(retractpos, axes_d) + ] self.toolhead.set_position(startpos) self._set_current_homing( - homing_axes, pre_homing=True, perform_dwell=hi.use_sensorless_homing + homing_axes, + pre_homing=True, + perform_dwell=hi.use_sensorless_homing, ) self._reset_endstop_states(endstops) hmove = HomingMove(self.printer, endstops) @@ -333,7 +348,9 @@ def home_rails(self, rails, forcepos, movepos): if ( hi.use_sensorless_homing and needs_rehome - and hmove.moved_less_than_dist(hi.min_home_dist, homing_axes) + and hmove.moved_less_than_dist( + hi.min_home_dist, homing_axes + ) ): raise self.printer.command_error( "Early homing trigger on second home!" @@ -355,7 +372,8 @@ def home_rails(self, rails, forcepos, movepos): homepos = self.toolhead.get_position() kin_spos = { s.get_name(): ( - s.get_commanded_position() + self.adjust_pos.get(s.get_name(), 0.0) + s.get_commanded_position() + + self.adjust_pos.get(s.get_name(), 0.0) ) for s in kin.get_steppers() } @@ -371,9 +389,12 @@ def home_rails(self, rails, forcepos, movepos): axes_d = [hp - sp for hp, sp in zip(homepos, startpos)] move_d = math.sqrt(sum([d * d for d in axes_d[:3]])) retract_r = min(1.0, hi.post_retract_dist / move_d) - retractpos = [hp - ad * retract_r for hp, ad in zip(homepos, axes_d)] + retractpos = [ + hp - ad * retract_r for hp, ad in zip(homepos, axes_d) + ] self.printer.lookup_object("gcode_move").last_position = retractpos self.toolhead.move(retractpos, hi.post_retract_speed) + self.gcode.run_script_from_command("M400") class PrinterHoming: @@ -383,7 +404,9 @@ def __init__(self, config): gcode = self.printer.lookup_object("gcode") gcode.register_command("G28", self.cmd_G28) - def manual_home(self, toolhead, endstops, pos, speed, triggered, check_triggered): + def manual_home( + self, toolhead, endstops, pos, speed, triggered, check_triggered + ): hmove = HomingMove(self.printer, endstops, toolhead) try: hmove.homing_move( @@ -408,7 +431,9 @@ def probing_move(self, mcu_probe, pos, speed): ) raise if hmove.check_no_movement() is not None: - raise self.printer.command_error("Probe triggered prior to movement") + raise self.printer.command_error( + "Probe triggered prior to movement" + ) return epos def cmd_G28(self, gcmd): diff --git a/klippy/extras/homing_heaters.py b/klippy/extras/homing_heaters.py index 502f572c5..554e6c5e9 100644 --- a/klippy/extras/homing_heaters.py +++ b/klippy/extras/homing_heaters.py @@ -8,7 +8,9 @@ class HomingHeaters: def __init__(self, config): self.printer = config.get_printer() - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.printer.register_event_handler( "homing:homing_move_begin", self.handle_homing_move_begin ) @@ -38,7 +40,8 @@ def _handle_connect(self): return if not all(x in all_steppers for x in self.flaky_steppers): raise self.printer.config_error( - "One or more of these steppers are unknown: %s" % (self.flaky_steppers,) + "One or more of these steppers are unknown: %s" + % (self.flaky_steppers,) ) def check_eligible(self, endstops): diff --git a/klippy/extras/homing_override.py b/klippy/extras/homing_override.py index a8acb31d7..d99e78889 100644 --- a/klippy/extras/homing_override.py +++ b/klippy/extras/homing_override.py @@ -8,7 +8,9 @@ class HomingOverride: def __init__(self, config): self.printer = config.get_printer() - self.start_pos = [config.getfloat("set_position_" + a, None) for a in "xyz"] + self.start_pos = [ + config.getfloat("set_position_" + a, None) for a in "xyz" + ] self.axes = config.get("axes", "XYZ").upper() gcode_macro = self.printer.load_object(config, "gcode_macro") self.template = gcode_macro.load_template(config, "gcode") diff --git a/klippy/extras/htu21d.py b/klippy/extras/htu21d.py index b104abe06..dd8b583cb 100644 --- a/klippy/extras/htu21d.py +++ b/klippy/extras/htu21d.py @@ -4,7 +4,6 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import logging -import threading import time from . import bus @@ -117,7 +116,9 @@ def __init__(self, config): ) self.ignore = self.name in get_danger_options().temp_ignore_limits self.printer.add_object("htu21d " + self.name, self) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): self._init_htu21d() @@ -193,7 +194,9 @@ def _sample_htu21d(self): rtemp = response[0] << 8 rtemp |= response[1] if self._chekCRC8(rtemp) != response[2]: - logging.warning("htu21d: Checksum error on Temperature reading!") + logging.warning( + "htu21d: Checksum error on Temperature reading!" + ) else: self.temp = 0.002681 * float(rtemp) - 46.85 logging.debug("htu21d: Temperature %.2f " % self.temp) diff --git a/klippy/extras/hx71x.py b/klippy/extras/hx71x.py index cefeafd4b..92b613c7a 100644 --- a/klippy/extras/hx71x.py +++ b/klippy/extras/hx71x.py @@ -126,7 +126,9 @@ def _start_measurements(self): # Start bulk reading rest_ticks = self.mcu.seconds_to_clock(1.0 / (10.0 * self.sps)) self.query_hx71x_cmd.send([self.oid, rest_ticks]) - logging.info("%s starting '%s' measurements", self.sensor_type, self.name) + logging.info( + "%s starting '%s' measurements", self.sensor_type, self.name + ) # Initialize clock tracking self.ffreader.note_start() @@ -137,7 +139,9 @@ def _finish_measurements(self): # Halt bulk reading self.query_hx71x_cmd.send_wait_ack([self.oid, 0]) self.ffreader.note_end() - logging.info("%s finished '%s' measurements", self.sensor_type, self.name) + logging.info( + "%s finished '%s' measurements", self.sensor_type, self.name + ) def _process_batch(self, eventtime): prev_overflows = self.ffreader.get_last_overflows() @@ -153,7 +157,9 @@ def _process_batch(self, eventtime): elif overflows > 0: self.consecutive_fails += 1 if self.consecutive_fails > 4: - logging.error("%s: Forced sensor restart due to overflows", self.name) + logging.error( + "%s: Forced sensor restart due to overflows", self.name + ) self._finish_measurements() self._start_measurements() else: diff --git a/klippy/extras/idle_timeout.py b/klippy/extras/idle_timeout.py index 87bd49940..0956a7001 100644 --- a/klippy/extras/idle_timeout.py +++ b/klippy/extras/idle_timeout.py @@ -25,7 +25,9 @@ def __init__(self, config): self.printer.register_event_handler("klippy:ready", self._handle_ready) self.idle_timeout = config.getfloat("timeout", 600.0, minval=0) gcode_macro = self.printer.load_object(config, "gcode_macro") - self.idle_gcode = gcode_macro.load_template(config, "gcode", DEFAULT_IDLE_GCODE) + self.idle_gcode = gcode_macro.load_template( + config, "gcode", DEFAULT_IDLE_GCODE + ) self.gcode.register_command( "SET_IDLE_TIMEOUT", self.cmd_SET_IDLE_TIMEOUT, @@ -106,7 +108,9 @@ def timeout_handler(self, eventtime): return eventtime + READY_TIMEOUT # Transition to "ready" state self.state = "Ready" - self.printer.send_event("idle_timeout:ready", est_print_time + PIN_MIN_TIME) + self.printer.send_event( + "idle_timeout:ready", est_print_time + PIN_MIN_TIME + ) return eventtime + self.idle_timeout def handle_sync_print_time(self, curtime, print_time, est_print_time): @@ -117,7 +121,9 @@ def handle_sync_print_time(self, curtime, print_time, est_print_time): self.last_print_start_systime = curtime check_time = READY_TIMEOUT + print_time - est_print_time self.reactor.update_timer(self.timeout_timer, curtime + check_time) - self.printer.send_event("idle_timeout:printing", est_print_time + PIN_MIN_TIME) + self.printer.send_event( + "idle_timeout:printing", est_print_time + PIN_MIN_TIME + ) cmd_SET_IDLE_TIMEOUT_help = "Set the idle timeout in seconds" diff --git a/klippy/extras/input_shaper.py b/klippy/extras/input_shaper.py index 37e61ba57..4eef881df 100644 --- a/klippy/extras/input_shaper.py +++ b/klippy/extras/input_shaper.py @@ -35,7 +35,9 @@ def __init__(self, axis, shaper_type, config): self.motor_freq = 0.0 if config is not None: if shaper_type not in self.shapers: - raise config.error("Unsupported shaper type: %s" % (shaper_type,)) + raise config.error( + "Unsupported shaper type: %s" % (shaper_type,) + ) global_damping_ratio = config.getfloat( "damping_ratio", self.damping_ratio, @@ -56,7 +58,10 @@ def __init__(self, axis, shaper_type, config): ) global_motor_damping = config.getfloat( - "motor_damping_ratio", self.motor_damping, minval=0.0, maxval=1.0 + "motor_damping_ratio", + self.motor_damping, + minval=0.0, + maxval=1.0, ) self.motor_damping = config.getfloat( "motor_damping_ratio_" + axis, @@ -99,14 +104,18 @@ def get_shaper(self): if not self.shaper_freq: A, T = shaper_defs.get_none_shaper() else: - A, T = self.shapers[self.shaper_type](self.shaper_freq, self.damping_ratio) + A, T = self.shapers[self.shaper_type]( + self.shaper_freq, self.damping_ratio + ) return len(A), A, T def get_motor_filter(self): if not self.motor_freq: A, T = shaper_defs.get_none_shaper() else: - A, T = shaper_defs.get_mzv_shaper(self.motor_freq, self.motor_damping) + A, T = shaper_defs.get_mzv_shaper( + self.motor_freq, self.motor_damping + ) return len(A), A, T def get_status(self): @@ -133,7 +142,11 @@ class CustomInputShaperParams: def __init__(self, axis, config): self.axis = axis self.n, self.A, self.T = 0, [], [] - self.motor_filter_n, self.motor_filter_A, self.motor_filter_T = 0, [], [] + self.motor_filter_n, self.motor_filter_A, self.motor_filter_T = ( + 0, + [], + [], + ) if config is not None: shaper_a_str = config.get("shaper_a_" + axis) shaper_t_str = config.get("shaper_t_" + axis) @@ -190,7 +203,9 @@ def _parse_custom_shaper(self, custom_a_str, custom_t_str, parse_error): if min([abs(a) for a in A]) < 0.001: raise parse_error("All shaper A coefficients must be non-zero") if sum(A) < 0.001: - raise parse_error("Shaper A parameter must sum up to a positive number") + raise parse_error( + "Shaper A parameter must sum up to a positive number" + ) T = parse_float_list(custom_t_str) if T is None: raise parse_error("Invalid shaper T string: '%s'" % (custom_t_str,)) @@ -207,9 +222,13 @@ def _parse_custom_shaper(self, custom_a_str, custom_t_str, parse_error): ) dur = T[-1] - T[0] if len(T) > 1 and dur < 0.001: - raise parse_error("Shaper duration is too small (%.6f sec)" % (dur,)) + raise parse_error( + "Shaper duration is too small (%.6f sec)" % (dur,) + ) if dur > 0.2: - raise parse_error("Shaper duration is too large (%.6f sec)" % (dur,)) + raise parse_error( + "Shaper duration is too large (%.6f sec)" % (dur,) + ) return len(A), A, T def get_shaper(self): @@ -271,7 +290,9 @@ def is_enabled(self): def update(self, shaper_type, gcmd): self.params.update(shaper_type, gcmd) self.axis_n, self.axis_A, self.axis_T = self.params.get_shaper() - self.motor_n, self.motor_A, self.motor_T = self.params.get_motor_filter() + self.motor_n, self.motor_A, self.motor_T = ( + self.params.get_motor_filter() + ) self.n, self.A, self.T = self.determine_shaper() self.t_offs = shaper_defs.get_shaper_offset(self.A, self.T) @@ -279,12 +300,16 @@ def update_stepper_kinematics(self, sk): ffi_main, ffi_lib = chelper.get_ffi() axis = self.get_axis().encode() success = ( - ffi_lib.input_shaper_set_shaper_params(sk, axis, self.n, self.A, self.T) + ffi_lib.input_shaper_set_shaper_params( + sk, axis, self.n, self.A, self.T + ) == 0 ) if not success: self.disable_shaping() - ffi_lib.input_shaper_set_shaper_params(sk, axis, self.n, self.A, self.T) + ffi_lib.input_shaper_set_shaper_params( + sk, axis, self.n, self.A, self.T + ) return success def update_extruder_kinematics(self, sk, exact_mode): @@ -300,7 +325,9 @@ def update_extruder_kinematics(self, sk, exact_mode): == 0 ) success = ( - ffi_lib.extruder_set_shaper_params(sk, axis, self.n, self.A, self.T) + ffi_lib.extruder_set_shaper_params( + sk, axis, self.n, self.A, self.T + ) == 0 ) else: @@ -350,7 +377,11 @@ def cache_shaping(self): self.axis_n, self.axis_A, self.axis_T = len(A), A, T was_enabled = True if self.cached_motor_filter is None and self.motor_n: - self.cached_motor_filter = (self.motor_n, self.motor_A, self.motor_T) + self.cached_motor_filter = ( + self.motor_n, + self.motor_A, + self.motor_T, + ) self.motor_n, self.motor_A, self.motor_T = len(A), A, T was_enabled = True self.n, self.A, self.T = len(A), A, T @@ -403,7 +434,9 @@ def __init__(self, axis, smoother_type, config): self.smoother_freq = 0.0 if config is not None: if smoother_type not in self.smoothers: - raise config.error("Unsupported shaper type: %s" % (smoother_type,)) + raise config.error( + "Unsupported shaper type: %s" % (smoother_type,) + ) self.smoother_freq = config.getfloat( "smoother_freq_" + axis, self.smoother_freq, minval=0.0 ) @@ -465,7 +498,9 @@ def update(self, shaper_type, gcmd): if shaper_type != self.SHAPER_TYPE: raise gcmd.error("Unsupported shaper type: %s" % (shaper_type,)) axis = self.axis.upper() - self.smooth_time = gcmd.get_float("SMOOTH_TIME_" + axis, self.smooth_time) + self.smooth_time = gcmd.get_float( + "SMOOTH_TIME_" + axis, self.smooth_time + ) coeffs_str = gcmd.get("COEFFS_" + axis, None) if coeffs_str is not None: try: @@ -608,9 +643,13 @@ def _create_shaper(self, axis, type_name, config=None): if type_name == CustomInputShaperParams.SHAPER_TYPE: return AxisInputShaper(CustomInputShaperParams(axis, config)) if type_name in TypedInputSmootherParams.smoothers: - return AxisInputSmoother(TypedInputSmootherParams(axis, type_name, config)) + return AxisInputSmoother( + TypedInputSmootherParams(axis, type_name, config) + ) if type_name in TypedInputShaperParams.shapers: - return AxisInputShaper(TypedInputShaperParams(axis, type_name, config)) + return AxisInputShaper( + TypedInputShaperParams(axis, type_name, config) + ) return None def create_shaper(self, axis, config): @@ -643,7 +682,9 @@ def update_shaper(self, shaper, gcmd): class InputShaper: def __init__(self, config): self.printer = config.get_printer() - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.toolhead = None self.extruders = [] self.exact_mode = 0 @@ -731,7 +772,9 @@ def _update_input_shaping(self, error=None): failed_shapers.append(shaper) new_delay = ffi_lib.input_shaper_get_step_gen_window(is_sk) if old_delay != new_delay: - self.toolhead.note_step_generation_scan_time(new_delay, old_delay) + self.toolhead.note_step_generation_scan_time( + new_delay, old_delay + ) for e in self.extruders: for es in e.get_extruder_steppers(): failed_shapers.extend( diff --git a/klippy/extras/ldc1612.py b/klippy/extras/ldc1612.py index f11fcded3..e0a936e39 100644 --- a/klippy/extras/ldc1612.py +++ b/klippy/extras/ldc1612.py @@ -163,13 +163,17 @@ def read_reg(self, reg): return (response[0] << 8) | response[1] def set_reg(self, reg, val, minclock=0): - self.i2c.i2c_write([reg, (val >> 8) & 0xFF, val & 0xFF], minclock=minclock) + self.i2c.i2c_write( + [reg, (val >> 8) & 0xFF, val & 0xFF], minclock=minclock + ) def add_client(self, cb): self.batch_bulk.add_client(cb) # Homing - def setup_home(self, print_time, trigger_freq, trsync_oid, hit_reason, err_reason): + def setup_home( + self, print_time, trigger_freq, trsync_oid, hit_reason, err_reason + ): clock = self.mcu.print_time_to_clock(print_time) tfreq = int(trigger_freq * (1 << 28) / float(LDC1612_FREQ) + 0.5) self.ldc1612_setup_home_cmd.send( @@ -212,7 +216,9 @@ def _start_measurements(self): rcount0 = LDC1612_FREQ / (16.0 * (self.data_rate - 4)) self.set_reg(REG_RCOUNT0, int(rcount0 + 0.5)) self.set_reg(REG_OFFSET0, 0) - self.set_reg(REG_SETTLECOUNT0, int(SETTLETIME * LDC1612_FREQ / 16.0 + 0.5)) + self.set_reg( + REG_SETTLECOUNT0, int(SETTLETIME * LDC1612_FREQ / 16.0 + 0.5) + ) self.set_reg(REG_CLOCK_DIVIDERS0, (1 << 12) | 1) self.set_reg(REG_ERROR_CONFIG, (0x1F << 11) | 1) self.set_reg(REG_MUX_CONFIG, 0x0208 | DEGLITCH) diff --git a/klippy/extras/led.py b/klippy/extras/led.py index bc6030ccd..fd8f2c47d 100644 --- a/klippy/extras/led.py +++ b/klippy/extras/led.py @@ -6,7 +6,6 @@ import logging from . import output_pin -from .display import display # Time between each led template update RENDER_TIME = 0.500 @@ -42,7 +41,11 @@ def __init__(self, config, update_func, led_count=1): self.name = config.get_name().split()[-1] gcode = self.printer.lookup_object("gcode") gcode.register_mux_command( - "SET_LED", "LED", self.name, self.cmd_SET_LED, desc=self.cmd_SET_LED_help + "SET_LED", + "LED", + self.name, + self.cmd_SET_LED, + desc=self.cmd_SET_LED_help, ) gcode.register_mux_command( "SET_LED_TEMPLATE", @@ -78,7 +81,9 @@ def check_step(self, step, min, max, gcmd): if i < 1: raise gcmd.error("step can not be less than 1(was '%d')" % i) if i > max - min: - raise gcmd.error("Steps can not be bigger than range " "(was '%d')" % i) + raise gcmd.error( + "Steps can not be bigger than range " "(was '%d')" % i + ) return i def get_indices(self, gcmd, led_count): @@ -90,12 +95,14 @@ def get_indices(self, gcmd, led_count): led_range = index.split("-") if len(led_range) > 2: raise gcmd.error( - "More than one '-' found in '%s', " "only one allowed" % index + "More than one '-' found in '%s', " + "only one allowed" % index ) elif len(led_range) == 1: if "|" in led_range[0]: raise gcmd.error( - "'|' specified without preceding " "range in '%s'" % index + "'|' specified without preceding " + "range in '%s'" % index ) indices.add(self.check_index(index, gcmd, led_count)) else: @@ -105,7 +112,8 @@ def get_indices(self, gcmd, led_count): range_steps = max_val.split("|") if len(range_steps) > 2: raise gcmd.error( - "More than one '|' found in '%s', " "only one allowed" % index + "More than one '|' found in '%s', " + "only one allowed" % index ) elif len(range_steps) == 2: step = range_steps[1] @@ -113,8 +121,12 @@ def get_indices(self, gcmd, led_count): min = self.check_index(min_val, gcmd, led_count) max = self.check_index(max_val, gcmd, led_count) if max < min: - raise gcmd.error("Min value greater than max value in '%s'" % index) - for i in range(min, (max + 1), self.check_step(step, min, max, gcmd)): + raise gcmd.error( + "Min value greater than max value in '%s'" % index + ) + for i in range( + min, (max + 1), self.check_step(step, min, max, gcmd) + ): indices.add(i) return indices @@ -164,7 +176,9 @@ def cmd_SET_LED(self, gcmd): green = gcmd.get_float("GREEN", 0.0, minval=0.0, maxval=1.0) blue = gcmd.get_float("BLUE", 0.0, minval=0.0, maxval=1.0) white = gcmd.get_float("WHITE", 0.0, minval=0.0, maxval=1.0) - disable_template = gcmd.get_int("DISABLE_TEMPLATE", 0, minval=0, maxval=1) + disable_template = gcmd.get_int( + "DISABLE_TEMPLATE", 0, minval=0, maxval=1 + ) transmit = gcmd.get_int("TRANSMIT", 1) sync = gcmd.get_int("SYNC", 1) color = (red, green, blue, white) diff --git a/klippy/extras/led_group.py b/klippy/extras/led_group.py index ee837a392..2de510c30 100644 --- a/klippy/extras/led_group.py +++ b/klippy/extras/led_group.py @@ -3,7 +3,6 @@ # Copyright (C) 2022 Julian Schill # # This file may be distributed under the terms of the GNU GPLv3 license. -import logging from . import led @@ -11,7 +10,9 @@ def parse_chain(chain): chain = chain.strip() leds = [] - parms = [parameter.strip() for parameter in chain.split() if parameter.strip()] + parms = [ + parameter.strip() for parameter in chain.split() if parameter.strip() + ] if parms: chainName = parms[0].replace(":", " ") ledIndices = "".join(parms[1:]).strip("()").split(",") @@ -43,7 +44,9 @@ def __init__(self, config): self.config_leds = config.get("leds") self.config_chains = self.config_leds.split("\n") self.led_helper = None - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): tcallbacks = [] @@ -54,12 +57,16 @@ def _handle_connect(self): for led_index in led_indices: tcallbacks.append(led_helper.tcallbacks[led_index]) self.ledCount = len(tcallbacks) - self.led_helper = led.LEDHelper(self.config, self.update_leds, self.ledCount) + self.led_helper = led.LEDHelper( + self.config, self.update_leds, self.ledCount + ) self.led_helper.tcallbacks = tcallbacks def update_leds(self, led_state, print_time): flush_callbacks = set() - for i, (_, flush_callback, set_color) in enumerate(self.led_helper.tcallbacks): + for i, (_, flush_callback, set_color) in enumerate( + self.led_helper.tcallbacks + ): set_color(led_state[i]) flush_callbacks.add(flush_callback) for flush_callback in flush_callbacks: diff --git a/klippy/extras/lis2dw.py b/klippy/extras/lis2dw.py index 57dfe5554..8392c54cb 100644 --- a/klippy/extras/lis2dw.py +++ b/klippy/extras/lis2dw.py @@ -48,7 +48,9 @@ def __init__(self, config): mcu.add_config_cmd( "config_lis2dw oid=%d spi_oid=%d" % (oid, self.spi.get_oid()) ) - mcu.add_config_cmd("query_lis2dw oid=%d rest_ticks=0" % (oid,), on_restart=True) + mcu.add_config_cmd( + "query_lis2dw oid=%d rest_ticks=0" % (oid,), on_restart=True + ) mcu.register_config_callback(self._build_config) # Bulk sample message reading chip_smooth = self.data_rate * BATCH_UPDATES * 2 @@ -95,7 +97,8 @@ def set_reg(self, reg, val, minclock=0): raise self.printer.command_error( "Failed to set LIS2DW register [0x%x] to 0x%x: got 0x%x. " "This is generally indicative of connection problems " - "(e.g. faulty wiring) or a faulty lis2dw chip." % (reg, val, stored_val) + "(e.g. faulty wiring) or a faulty lis2dw chip." + % (reg, val, stored_val) ) def start_internal_client(self): diff --git a/klippy/extras/lm75.py b/klippy/extras/lm75.py index 13b5fe02b..4b94e9f72 100644 --- a/klippy/extras/lm75.py +++ b/klippy/extras/lm75.py @@ -4,8 +4,6 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import logging -import threading -import time from . import bus @@ -33,7 +31,9 @@ def __init__(self, config): self.name = config.get_name().split()[-1] self.reactor = self.printer.get_reactor() self.klipper_threads = self.printer.get_klipper_threads() - self.i2c = bus.MCU_I2C_from_config(config, LM75_CHIP_ADDR, LM75_I2C_SPEED) + self.i2c = bus.MCU_I2C_from_config( + config, LM75_CHIP_ADDR, LM75_I2C_SPEED + ) self.mcu = self.i2c.get_mcu() self.report_time = config.getfloat( "lm75_report_time", LM75_REPORT_TIME, minval=LM75_MIN_REPORT_TIME @@ -44,7 +44,9 @@ def __init__(self, config): ) self.ignore = self.name in get_danger_options().temp_ignore_limits self.printer.add_object("lm75 " + self.name, self) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): self._init_lm75() diff --git a/klippy/extras/manual_probe.py b/klippy/extras/manual_probe.py index b6e7574eb..053d78509 100644 --- a/klippy/extras/manual_probe.py +++ b/klippy/extras/manual_probe.py @@ -106,7 +106,9 @@ def cmd_Z_OFFSET_APPLY_ENDSTOP(self, gcmd): "The SAVE_CONFIG command will update the printer config file\n" "with the above and restart the printer." % (new_calibrate) ) - configfile.set("stepper_z", "position_endstop", "%.3f" % (new_calibrate,)) + configfile.set( + "stepper_z", "position_endstop", "%.3f" % (new_calibrate,) + ) def cmd_Z_OFFSET_APPLY_DELTA_ENDSTOPS(self, gcmd): offset = self.gcode_move.get_status()["homing_origin"].z @@ -125,9 +127,15 @@ def cmd_Z_OFFSET_APPLY_DELTA_ENDSTOPS(self, gcmd): "with the above and restart the printer." % (new_a_calibrate, new_b_calibrate, new_c_calibrate) ) - configfile.set("stepper_a", "position_endstop", "%.3f" % (new_a_calibrate,)) - configfile.set("stepper_b", "position_endstop", "%.3f" % (new_b_calibrate,)) - configfile.set("stepper_c", "position_endstop", "%.3f" % (new_c_calibrate,)) + configfile.set( + "stepper_a", "position_endstop", "%.3f" % (new_a_calibrate,) + ) + configfile.set( + "stepper_b", "position_endstop", "%.3f" % (new_b_calibrate,) + ) + configfile.set( + "stepper_c", "position_endstop", "%.3f" % (new_c_calibrate,) + ) cmd_Z_OFFSET_APPLY_ENDSTOP_help = "Adjust the z endstop_position" @@ -163,8 +171,12 @@ def __init__(self, printer, gcmd, finalize_callback): "ACCEPT", self.cmd_ACCEPT, desc=self.cmd_ACCEPT_help ) self.gcode.register_command("NEXT", self.cmd_ACCEPT) - self.gcode.register_command("ABORT", self.cmd_ABORT, desc=self.cmd_ABORT_help) - self.gcode.register_command("TESTZ", self.cmd_TESTZ, desc=self.cmd_TESTZ_help) + self.gcode.register_command( + "ABORT", self.cmd_ABORT, desc=self.cmd_ABORT_help + ) + self.gcode.register_command( + "TESTZ", self.cmd_TESTZ, desc=self.cmd_TESTZ_help + ) self.gcode.respond_info( "Starting manual Z probe. Use TESTZ to adjust position.\n" "Finish with ACCEPT or ABORT command." diff --git a/klippy/extras/manual_stepper.py b/klippy/extras/manual_stepper.py index 4968cdf2f..cf89a67f2 100644 --- a/klippy/extras/manual_stepper.py +++ b/klippy/extras/manual_stepper.py @@ -21,7 +21,9 @@ def __init__(self, config): self.rail = stepper.PrinterStepper(config) self.steppers = [self.rail] self.velocity = config.getfloat("velocity", 5.0, above=0.0) - self.accel = self.homing_accel = config.getfloat("accel", 0.0, minval=0.0) + self.accel = self.homing_accel = config.getfloat( + "accel", 0.0, minval=0.0 + ) self.next_cmd_time = 0.0 # Setup iterative solver ffi_main, ffi_lib = chelper.get_ffi() @@ -102,12 +104,16 @@ def do_move(self, movepos, speed, accel, sync=True): def do_homing_move(self, movepos, speed, accel, triggered, check_trigger): if not self.can_home: - raise self.printer.command_error("No endstop for this manual stepper") + raise self.printer.command_error( + "No endstop for this manual stepper" + ) self.homing_accel = accel pos = [movepos, 0.0, 0.0, 0.0] endstops = self.rail.get_endstops() phoming = self.printer.lookup_object("homing") - phoming.manual_home(self, endstops, pos, speed, triggered, check_trigger) + phoming.manual_home( + self, endstops, pos, speed, triggered, check_trigger + ) cmd_MANUAL_STEPPER_help = "Command a manually configured stepper" diff --git a/klippy/extras/mcp4018.py b/klippy/extras/mcp4018.py index ffef0742d..69aed56f5 100644 --- a/klippy/extras/mcp4018.py +++ b/klippy/extras/mcp4018.py @@ -28,7 +28,8 @@ def __init__(self, config, addr): self.sda_oid = self.mcu.create_oid() if sda_params["chip"] != self.mcu: raise ppins.error( - "%s: scl_pin and sda_pin must be on same mcu" % (config.get_name(),) + "%s: scl_pin and sda_pin must be on same mcu" + % (config.get_name(),) ) self.mcu.add_config_cmd( "config_digital_out oid=%d pin=%s" @@ -42,7 +43,8 @@ def get_mcu(self): def build_config(self): self.mcu.add_config_cmd( "config_digital_out oid=%d pin=%s value=%d" - " default_value=%d max_duration=%d" % (self.scl_oid, self.scl_pin, 1, 1, 0) + " default_value=%d max_duration=%d" + % (self.scl_oid, self.scl_pin, 1, 1, 0) ) self.update_pin_cmd = self.mcu.lookup_command( "update_digital_out oid=%c value=%c", cq=self.cmd_queue @@ -84,7 +86,9 @@ def __init__(self, config): self.printer = config.get_printer() self.i2c = SoftwareI2C(config, 0x2F) self.scale = config.getfloat("scale", 1.0, above=0.0) - self.start_value = config.getfloat("wiper", minval=0.0, maxval=self.scale) + self.start_value = config.getfloat( + "wiper", minval=0.0, maxval=self.scale + ) config.get_printer().register_event_handler( "klippy:connect", self._handle_connect ) diff --git a/klippy/extras/mcp4451.py b/klippy/extras/mcp4451.py index ab6e43ef4..6ff160f9c 100644 --- a/klippy/extras/mcp4451.py +++ b/klippy/extras/mcp4451.py @@ -19,7 +19,9 @@ def __init__(self, config): self.set_register(0x04, 0xFF) self.set_register(0x0A, 0xFF) for i in range(4): - val = config.getfloat("wiper_%d" % (i,), None, minval=0.0, maxval=scale) + val = config.getfloat( + "wiper_%d" % (i,), None, minval=0.0, maxval=scale + ) if val is not None: val = int(val * 255.0 / scale + 0.5) self.set_register(WiperRegisters[i], val) diff --git a/klippy/extras/motion_report.py b/klippy/extras/motion_report.py index ee246e2ca..40ad13742 100644 --- a/klippy/extras/motion_report.py +++ b/klippy/extras/motion_report.py @@ -336,7 +336,9 @@ def __init__(self, config): "trapq": [], } # Register handlers - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.printer.register_event_handler("klippy:shutdown", self._shutdown) def register_stepper(self, config, mcu_stepper): diff --git a/klippy/extras/mpc_ambient_temperature.py b/klippy/extras/mpc_ambient_temperature.py index d777bd2ca..cfaa690fe 100644 --- a/klippy/extras/mpc_ambient_temperature.py +++ b/klippy/extras/mpc_ambient_temperature.py @@ -69,7 +69,9 @@ def _sample_ambient_temperature(self): measured_time = self.reactor.monotonic() self.temperature_callback( - self.printer.lookup_object("mcu").estimated_print_time(measured_time), + self.printer.lookup_object("mcu").estimated_print_time( + measured_time + ), self.temp, ) @@ -81,4 +83,6 @@ def set_report_time(self, report_time): def load_config(config): pheaters = config.get_printer().load_object(config, "heaters") - pheaters.add_sensor_factory("mpc_ambient_temperature", MPC_AMBIENT_TEMP_WRAPPER) + pheaters.add_sensor_factory( + "mpc_ambient_temperature", MPC_AMBIENT_TEMP_WRAPPER + ) diff --git a/klippy/extras/mpc_block_temperature.py b/klippy/extras/mpc_block_temperature.py index 656eb9494..3e9be35b3 100644 --- a/klippy/extras/mpc_block_temperature.py +++ b/klippy/extras/mpc_block_temperature.py @@ -55,13 +55,23 @@ def _sample_block_temperature(self): if not self.ignore: self.printer.invoke_shutdown( "MPC Heater Block %s\nTemperature %0.1f outside range of %0.1f-%.01f" - % (self.name, self.temp, self.min_temp, self.max_temp) + % ( + self.name, + self.temp, + self.min_temp, + self.max_temp, + ) ) elif get_danger_options().echo_limits_to_console: gcode = self.printer.lookup_object("gcode") gcode.respond_error( "MPC Heater Block %s\nTemperature %0.1f outside range of %0.1f-%.01f" - % (self.name, self.temp, self.min_temp, self.max_temp) + % ( + self.name, + self.temp, + self.min_temp, + self.max_temp, + ) ) else: self.temp = 0.0 @@ -69,7 +79,9 @@ def _sample_block_temperature(self): measured_time = self.reactor.monotonic() self.temperature_callback( - self.printer.lookup_object("mcu").estimated_print_time(measured_time), + self.printer.lookup_object("mcu").estimated_print_time( + measured_time + ), self.temp, ) diff --git a/klippy/extras/mpc_calibrate.py b/klippy/extras/mpc_calibrate.py index 864022b15..305656466 100644 --- a/klippy/extras/mpc_calibrate.py +++ b/klippy/extras/mpc_calibrate.py @@ -39,7 +39,9 @@ def __init__(self, printer, heater, config): self.temp_control = None self.fan = None self.max_error = self.config.getfloat("calibrate_max_error", None) - self.check_gain_time = self.config.getfloat("calibrate_check_gain_time", None) + self.check_gain_time = self.config.getfloat( + "calibrate_check_gain_time", None + ) self.hysteresis = self.config.getfloat("calibrate_hysteresis", None) self.heating_gain = self.config.getfloat("calibrate_heating_gain", None) @@ -64,7 +66,9 @@ def run(self, gcmd): self.orig_control = self.heater.set_control(control) self.temp_control = self.orig_control if self.temp_control.get_type() != "mpc": - self.temp_control = self.pmgr._init_profile(self.config, "autotune", "mpc") + self.temp_control = self.pmgr._init_profile( + self.config, "autotune", "mpc" + ) self.fan = self.temp_control.cooling_fan ambient_sensor_name = gcmd.get("AMBIENT_TEMP_SENSOR", None) if ambient_sensor_name is not None: @@ -77,7 +81,9 @@ def run(self, gcmd): else: ambient_sensor = self.temp_control.ambient_sensor max_error = gcmd.get_float("MAX_ERROR", self.max_error) - check_gain_time = gcmd.get_float("CHECK_GAIN_TIME", self.check_gain_time) + check_gain_time = gcmd.get_float( + "CHECK_GAIN_TIME", self.check_gain_time + ) hysteresis = gcmd.get_float("HYSTERESIS", self.hysteresis) heating_gain = gcmd.get_float("HEATING_GAIN", self.heating_gain) @@ -170,8 +176,12 @@ def run(self, gcmd): profile["name"] = profile_name profile["mpc_target"] = target_temp - self.heater.set_control(self.heater.lookup_control(profile, True), False) - self.heater.pmgr.save_profile(profile_name=profile_name, verbose=False) + self.heater.set_control( + self.heater.lookup_control(profile, True), False + ) + self.heater.pmgr.save_profile( + profile_name=profile_name, verbose=False + ) msg = ( f"Finished MPC calibration of heater '{self.heater.short_name}'\n" @@ -315,7 +325,8 @@ def transfer_test( target_temp = round(first_pass_results["post_block_temp"]) self.heater.set_temp(target_temp) gcmd.respond_info( - "Performing ambient transfer tests, target is %.1f degrees" % (target_temp,) + "Performing ambient transfer tests, target is %.1f degrees" + % (target_temp,) ) self.wait_stable(5) @@ -338,7 +349,9 @@ def transfer_test( power = self.measure_power( ambient_max_measure_time, ambient_measure_sample_time ) - gcmd.respond_info(f"{speed*100.:.0f}% fan average power: {power:.2f} W") + gcmd.respond_info( + f"{speed*100.:.0f}% fan average power: {power:.2f} W" + ) fan_powers.append((speed, power)) self.fan.set_speed(0.0) power_base = fan_powers[0][1] @@ -355,7 +368,9 @@ def measure_power(self, max_time, sample_time): last_time = [None] def process(eventtime): - dt = eventtime - (last_time[0] if last_time[0] is not None else eventtime) + dt = eventtime - ( + last_time[0] if last_time[0] is not None else eventtime + ) last_time[0] = eventtime status = self.heater.get_status(eventtime) samples.append((dt, status["control_stats"]["power"] * dt)) @@ -431,11 +446,17 @@ def process_first_pass( ) # Differential method - if not use_analytic or block_heat_capacity < 0 or sensor_responsiveness < 0: + if ( + not use_analytic + or block_heat_capacity < 0 + or sensor_responsiveness < 0 + ): fastest_rate = self.fastest_rate(samples) block_heat_capacity = heater_power / fastest_rate[2] sensor_responsiveness = fastest_rate[2] / ( - fastest_rate[2] * fastest_rate[0] + ambient_temp - fastest_rate[0] + fastest_rate[2] * fastest_rate[0] + + ambient_temp + - fastest_rate[0] ) heat_time = all_samples[-1][0] - all_samples[0][0] @@ -459,7 +480,9 @@ def process_first_pass( "dt": dt, } - def process_second_pass(self, first_res, transfer_res, ambient_temp, heater_power): + def process_second_pass( + self, first_res, transfer_res, ambient_temp, heater_power + ): target_ambient_temp = transfer_res["target_temp"] - ambient_temp ambient_transfer = transfer_res["base_power"] / target_ambient_temp asymp_T = ambient_temp + heater_power / ambient_transfer diff --git a/klippy/extras/multi_pin.py b/klippy/extras/multi_pin.py index d8d5bcb73..36a02b43f 100644 --- a/klippy/extras/multi_pin.py +++ b/klippy/extras/multi_pin.py @@ -32,7 +32,8 @@ def setup_pin(self, pin_type, pin_params): if pin_params["invert"]: invert = "!" self.mcu_pins = [ - ppins.setup_pin(pin_type, invert + pin_desc) for pin_desc in self.pin_list + ppins.setup_pin(pin_type, invert + pin_desc) + for pin_desc in self.pin_list ] return self diff --git a/klippy/extras/neopixel.py b/klippy/extras/neopixel.py index 5354b9f78..19451223b 100644 --- a/klippy/extras/neopixel.py +++ b/klippy/extras/neopixel.py @@ -97,7 +97,9 @@ def send_data(self, print_time=None): if new_data == old_data: return # Find the position of all changed bytes in this framebuffer - diffs = [[i, 1] for i, (n, o) in enumerate(zip(new_data, old_data)) if n != o] + diffs = [ + [i, 1] for i, (n, o) in enumerate(zip(new_data, old_data)) if n != o + ] # Batch together changes that are close to each other for i in range(len(diffs) - 2, -1, -1): pos, count = diffs[i] diff --git a/klippy/extras/output_pin.py b/klippy/extras/output_pin.py index 1b7178f7b..366891b9b 100644 --- a/klippy/extras/output_pin.py +++ b/klippy/extras/output_pin.py @@ -117,7 +117,12 @@ def _activate_timer(self): def _activate_template(self, callback, template, lparams, flush_callback): if template is not None: uid = (template,) + tuple(sorted(lparams.items())) - self.active_templates[callback] = (uid, template, lparams, flush_callback) + self.active_templates[callback] = ( + uid, + template, + lparams, + flush_callback, + ) return if callback in self.active_templates: del self.active_templates[callback] @@ -222,22 +227,31 @@ def __init__(self, config): self.mcu_pin.setup_max_duration(0.0) # Determine start and shutdown values self.last_value = ( - config.getfloat("value", 0.0, minval=0.0, maxval=self.scale) / self.scale + config.getfloat("value", 0.0, minval=0.0, maxval=self.scale) + / self.scale ) self.shutdown_value = ( - config.getfloat("shutdown_value", 0.0, minval=0.0, maxval=self.scale) + config.getfloat( + "shutdown_value", 0.0, minval=0.0, maxval=self.scale + ) / self.scale ) self.mcu_pin.setup_start_value(self.last_value, self.shutdown_value) # Create gcode request queue - self.gcrq = GCodeRequestQueue(config, self.mcu_pin.get_mcu(), self._set_pin) + self.gcrq = GCodeRequestQueue( + config, self.mcu_pin.get_mcu(), self._set_pin + ) # Template handling self.template_eval = lookup_template_eval(config) # Register commands pin_name = config.get_name().split()[1] gcode = self.printer.lookup_object("gcode") gcode.register_mux_command( - "SET_PIN", "PIN", pin_name, self.cmd_SET_PIN, desc=self.cmd_SET_PIN_help + "SET_PIN", + "PIN", + pin_name, + self.cmd_SET_PIN, + desc=self.cmd_SET_PIN_help, ) def get_status(self, eventtime): diff --git a/klippy/extras/pa_test.py b/klippy/extras/pa_test.py index 035bc016b..acf7dce87 100644 --- a/klippy/extras/pa_test.py +++ b/klippy/extras/pa_test.py @@ -51,7 +51,9 @@ def __init__(self, config): self.fast_velocity = config.getfloat( "fast_velocity", 80.0, above=self.medium_velocity ) - self.filament_diameter = config.getfloat("filament_diameter", 1.75, above=0.0) + self.filament_diameter = config.getfloat( + "filament_diameter", 1.75, above=0.0 + ) # Register commands self.gcode = self.printer.lookup_object("gcode") self.gcode.register_command( @@ -151,7 +153,9 @@ def get_gcode(self): # Get tower params with overrides from the GCode command origin_x = gcmd.get_float("ORIGIN_X", self.origin_x) origin_y = gcmd.get_float("ORIGIN_Y", self.origin_y) - size_x = gcmd.get_float("SIZE_X", self.size_x, minval=SLOW_NOTCH_SIZE * 4) + size_x = gcmd.get_float( + "SIZE_X", self.size_x, minval=SLOW_NOTCH_SIZE * 4 + ) size_y = gcmd.get_float( "SIZE_Y", self.size_y, @@ -159,7 +163,9 @@ def get_gcode(self): maxval=MAX_YX_SIZE_RATIO * size_x, ) perimeters = gcmd.get_int("PERIMETERS", self.perimeters, minval=1) - slow_velocity = gcmd.get_float("SLOW_VELOCITY", self.slow_velocity, above=0.0) + slow_velocity = gcmd.get_float( + "SLOW_VELOCITY", self.slow_velocity, above=0.0 + ) medium_velocity = gcmd.get_float( "MEDIUM_VELOCITY", self.medium_velocity, above=slow_velocity ) @@ -172,7 +178,9 @@ def get_gcode(self): filament_diameter = gcmd.get_float( "FILAMENT_DIAMETER", self.filament_diameter, above=0.0 ) - layer_height = gcmd.get_float("LAYER_HEIGHT", self.layer_height, above=0.0) + layer_height = gcmd.get_float( + "LAYER_HEIGHT", self.layer_height, above=0.0 + ) first_layer_height = gcmd.get_float( "FIRST_LAYER_HEIGHT", self.first_layer_height, above=layer_height ) @@ -269,7 +277,10 @@ def gen_tower(): perimeter_x_offset -= extra_offs perimeter_y_offset -= extra_offs extr_r = ( - 4.0 * layer_height * line_width / (math.pi * filament_diameter**2) + 4.0 + * layer_height + * line_width + / (math.pi * filament_diameter**2) ) # Move to the start of the perimeter yield "G1 X%.3f Y%.3f F%.f" % ( @@ -357,7 +368,8 @@ def gen_tower(): yield "G1 X%.3f Y%.3f E%.6f F%.f" % ( origin_x + perimeter_x_offset, origin_y - perimeter_y_offset, - (perimeter_x_offset - x_switching_pos - VERY_SLOW_SEG) * extr_r, + (perimeter_x_offset - x_switching_pos - VERY_SLOW_SEG) + * extr_r, fast_velocity * 60.0, ) yield "G1 X%.3f Y%.3f E%.6f F%.f" % ( @@ -424,7 +436,9 @@ def gen_tower(): for line in gen_tower(): yield line if final_gcode_id is not None: - yield "UPDATE_DELAYED_GCODE ID='%s' DURATION=0.01" % (final_gcode_id,) + yield "UPDATE_DELAYED_GCODE ID='%s' DURATION=0.01" % ( + final_gcode_id, + ) self.progress = 1.0 diff --git a/klippy/extras/palette2.py b/klippy/extras/palette2.py index e9fedbd7c..761194269 100644 --- a/klippy/extras/palette2.py +++ b/klippy/extras/palette2.py @@ -45,7 +45,9 @@ def __init__(self, config): self.printer = config.get_printer() self.reactor = self.printer.get_reactor() try: - self.virtual_sdcard = self.printer.load_object(config, "virtual_sdcard") + self.virtual_sdcard = self.printer.load_object( + config, "virtual_sdcard" + ) except config.error: raise self.printer.config_error( "Palette 2 requires [virtual_sdcard] to work," @@ -71,7 +73,9 @@ def __init__(self, config): self.gcode.register_command( "PALETTE_CLEAR", self.cmd_Clear, desc=self.cmd_Clear_Help ) - self.gcode.register_command("PALETTE_CUT", self.cmd_Cut, desc=self.cmd_Cut_Help) + self.gcode.register_command( + "PALETTE_CUT", self.cmd_Cut, desc=self.cmd_Cut_Help + ) self.gcode.register_command( "PALETTE_SMART_LOAD", self.cmd_Smart_Load, @@ -170,7 +174,9 @@ def cmd_Connect(self, gcmd): with self.read_queue.mutex: self.read_queue.queue.clear() - self.read_timer = self.reactor.register_timer(self._run_Read, self.reactor.NOW) + self.read_timer = self.reactor.register_timer( + self._run_Read, self.reactor.NOW + ) self.write_timer = self.reactor.register_timer( self._run_Write, self.reactor.NOW ) @@ -219,7 +225,9 @@ def cmd_Cut(self, gcmd): def cmd_Smart_Load(self, gcmd): if self._check_P2(gcmd): if not self.is_loading: - gcmd.respond_info("Cannot auto load when the Palette 2 is not ready") + gcmd.respond_info( + "Cannot auto load when the Palette 2 is not ready" + ) return self.p2cmd_O102(params=None) @@ -241,7 +249,9 @@ def _wait_for_heartbeat(self): self.signal_disconnect = True raise self.printer.command_error("No response from Palette 2") - cmd_O1_help = "Initialize the print, and check connection with the Palette 2" + cmd_O1_help = ( + "Initialize the print, and check connection with the Palette 2" + ) def cmd_O1(self, gcmd): logging.info("Initializing print with Pallete 2") @@ -314,13 +324,16 @@ def cmd_O30(self, gcmd): param_drive = gcmd.get_commandline()[5:6] param_distance = gcmd.get_commandline()[8:] except IndexError: - gcmd.respond_info("Incorrect number of arguments for splice command") + gcmd.respond_info( + "Incorrect number of arguments for splice command" + ) try: self.omega_splices.append((int(param_drive), param_distance)) except ValueError: gcmd.respond_info("Incorrectly formatted splice command") logging.debug( - "Omega splice command drive %s distance %s" % (param_drive, param_distance) + "Omega splice command drive %s distance %s" + % (param_drive, param_distance) ) def cmd_O31(self, gcmd): @@ -360,11 +373,17 @@ def p2cmd_O20(self, params): self.write_queue.put("O30 D%d D%s" % (splice[0], splice[1])) self.omega_splices_counter = self.omega_splices_counter + 1 elif n == 2: - logging.info("Sending current ping info %s" % self.omega_current_ping) + logging.info( + "Sending current ping info %s" % self.omega_current_ping + ) self.write_queue.put(self.omega_current_ping) elif n == 4: - logging.info("Sending algorithm info %s" % self.omega_algorithms_counter) - self.write_queue.put(self.omega_algorithms[self.omega_algorithms_counter]) + logging.info( + "Sending algorithm info %s" % self.omega_algorithms_counter + ) + self.write_queue.put( + self.omega_algorithms[self.omega_algorithms_counter] + ) self.omega_algorithms_counter = self.omega_algorithms_counter + 1 elif n == 8: logging.info("Resending the last command to Palette 2") @@ -379,7 +398,9 @@ def check_ping_variation(last_ping): ping_max = 100.0 + (self.auto_cancel_variation * 100.0) ping_min = 100.0 - (self.auto_cancel_variation * 100.0) if last_ping < ping_min or last_ping > ping_max: - logging.info("Ping variation is too high, " "cancelling print") + logging.info( + "Ping variation is too high, " "cancelling print" + ) self.gcode.run_script("CANCEL_PRINT") if len(params) > 2: @@ -410,7 +431,8 @@ def p2cmd_O50(self, params): if fw < "9.0.9": raise self.printer.command_error( - "Palette 2 firmware version is too old, " "update to at least 9.0.9" + "Palette 2 firmware version is too old, " + "update to at least 9.0.9" ) else: self.files = [ @@ -457,7 +479,9 @@ def loadingOffsetStart(params): def loadingOffset(params): self.remaining_load_length = int(params[1][1:]) - logging.debug("Loading filamant remaining %d" % self.remaining_load_length) + logging.debug( + "Loading filamant remaining %d" % self.remaining_load_length + ) if self.remaining_load_length >= 0 and self.smart_load_timer: logging.info("Smart load filament is complete") self.reactor.unregister_timer(self.smart_load_timer) @@ -465,12 +489,16 @@ def loadingOffset(params): self.is_loading = False def feedrateStart(params): - logging.info("Setting feedrate to %f for splice" % self.feedrate_splice) + logging.info( + "Setting feedrate to %f for splice" % self.feedrate_splice + ) self.is_splicing = True self.gcode.run_script("M220 S%d" % (self.feedrate_splice * 100)) def feedrateEnd(params): - logging.info("Setting feedrate to %f splice done" % self.feedrate_normal) + logging.info( + "Setting feedrate to %f splice done" % self.feedrate_normal + ) self.is_splicing = False self.gcode.run_script("M220 S%d" % (self.feedrate_normal * 100)) @@ -528,7 +556,10 @@ def _param_Matcher(self, matchers, params): if len(params) >= matcher[1]: match_params = matcher[2:] res = all( - [match_params[i] == params[i] for i in range(len(match_params))] + [ + match_params[i] == params[i] + for i in range(len(match_params)) + ] ) if res: matcher[0](params) @@ -549,7 +580,9 @@ def _run_Read(self, eventtime): self.cmd_Disconnect() return self.reactor.NEVER if len(raw_bytes): - new_buffer = str(raw_bytes.decode(encoding="UTF-8", errors="ignore")) + new_buffer = str( + raw_bytes.decode(encoding="UTF-8", errors="ignore") + ) text_buffer = self.read_buffer + new_buffer while True: i = text_buffer.find("\n") @@ -604,7 +637,9 @@ def _run_Write(self, eventtime): self.omega_last_command = text_line l = text_line.strip() if COMMAND_HEARTBEAT not in l: - logging.debug("%s -> P2 : %s" % (self.reactor.monotonic(), l)) + logging.debug( + "%s -> P2 : %s" % (self.reactor.monotonic(), l) + ) terminated_line = "%s\n" % (l) try: self.serial.write(terminated_line.encode()) @@ -619,10 +654,14 @@ def _run_Smart_Load(self, eventtime): if not self.is_splicing and self.remaining_load_length < 0: # Make sure toolhead class isn't busy toolhead = self.printer.lookup_object("toolhead") - print_time, est_print_time, lookahead_empty = toolhead.check_busy(eventtime) + print_time, est_print_time, lookahead_empty = toolhead.check_busy( + eventtime + ) idle_time = est_print_time - print_time if not lookahead_empty or idle_time < 0.5: - return eventtime + max(0.0, min(1.0, print_time - est_print_time)) + return eventtime + max( + 0.0, min(1.0, print_time - est_print_time) + ) extrude = abs(self.remaining_load_length) extrude = min(50, extrude / 2) @@ -634,7 +673,9 @@ def _run_Smart_Load(self, eventtime): ) self.gcode.run_script("G92 E0") - self.gcode.run_script("G1 E%d F%d" % (extrude, self.auto_load_speed * 60)) + self.gcode.run_script( + "G1 E%d F%d" % (extrude, self.auto_load_speed * 60) + ) return self.reactor.NOW return eventtime + AUTOLOAD_TIMER diff --git a/klippy/extras/pause_resume.py b/klippy/extras/pause_resume.py index cc52bae4b..16c0f73d6 100644 --- a/klippy/extras/pause_resume.py +++ b/klippy/extras/pause_resume.py @@ -14,8 +14,12 @@ def __init__(self, config): self.is_paused = False self.sd_paused = False self.pause_command_sent = False - self.printer.register_event_handler("klippy:connect", self._handle_connect) - self.gcode.register_command("PAUSE", self.cmd_PAUSE, desc=self.cmd_PAUSE_help) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) + self.gcode.register_command( + "PAUSE", self.cmd_PAUSE, desc=self.cmd_PAUSE_help + ) self.gcode.register_command( "RESUME", self.cmd_RESUME, desc=self.cmd_RESUME_help ) @@ -28,9 +32,15 @@ def __init__(self, config): desc=self.cmd_CANCEL_PRINT_help, ) webhooks = self.printer.lookup_object("webhooks") - webhooks.register_endpoint("pause_resume/cancel", self._handle_cancel_request) - webhooks.register_endpoint("pause_resume/pause", self._handle_pause_request) - webhooks.register_endpoint("pause_resume/resume", self._handle_resume_request) + webhooks.register_endpoint( + "pause_resume/cancel", self._handle_cancel_request + ) + webhooks.register_endpoint( + "pause_resume/pause", self._handle_pause_request + ) + webhooks.register_endpoint( + "pause_resume/resume", self._handle_resume_request + ) def _handle_connect(self): self.v_sd = self.printer.lookup_object("virtual_sdcard", None) @@ -91,12 +101,15 @@ def cmd_RESUME(self, gcmd): return velocity = gcmd.get_float("VELOCITY", self.recover_velocity) self.gcode.run_script_from_command( - "RESTORE_GCODE_STATE NAME=PAUSE_STATE MOVE=1 MOVE_SPEED=%.4f" % (velocity) + "RESTORE_GCODE_STATE NAME=PAUSE_STATE MOVE=1 MOVE_SPEED=%.4f" + % (velocity) ) self.send_resume_command() self.is_paused = False - cmd_CLEAR_PAUSE_help = "Clears the current paused state without resuming the print" + cmd_CLEAR_PAUSE_help = ( + "Clears the current paused state without resuming the print" + ) def cmd_CLEAR_PAUSE(self, gcmd): self.is_paused = self.pause_command_sent = False diff --git a/klippy/extras/pid_calibrate.py b/klippy/extras/pid_calibrate.py index 3b306aa15..b60fa4e48 100644 --- a/klippy/extras/pid_calibrate.py +++ b/klippy/extras/pid_calibrate.py @@ -41,7 +41,9 @@ def cmd_PID_CALIBRATE(self, gcmd): ) algorithm = gcmd.get("ALGORITHM", None) if algorithm is not None and algorithm not in ALGORITHMS: - raise gcmd.error("Invalid algorithm, valid algorithms are: %s" % ALGORITHMS) + raise gcmd.error( + "Invalid algorithm, valid algorithms are: %s" % ALGORITHMS + ) profile_name = gcmd.get("PROFILE", "default") pheaters = self.printer.lookup_object("heaters") try: @@ -164,7 +166,9 @@ def temperature_update(self, read_time, temp, target_temp): if self.done: return # store test data - self.data.append((read_time, temp, self.heater.last_pwm_value, self.target)) + self.data.append( + (read_time, temp, self.heater.last_pwm_value, self.target) + ) # ensure the starting temp is low enough to run the test. if not self.started and temp >= self.temp_low: self.errored = True @@ -349,7 +353,9 @@ def calc_pid(self, calculation_method): Km = -math.sqrt(tau**2 * Wu**2 + 1.0) / Ku # log the extra details logging.info("Ziegler-Nichols constants: Ku=%f Tu=%f", Ku, Tu) - logging.info("Cohen-Coon constants: Km=%f Theta=%f Tau=%f", Km, theta, tau) + logging.info( + "Cohen-Coon constants: Km=%f Theta=%f Tau=%f", Km, theta, tau + ) Ti, Td, Kp = CALCULATION_METHODS[calculation_method](Tu, Ku) Ki = Kp / Ti Kd = Kp * Td diff --git a/klippy/extras/print_stats.py b/klippy/extras/print_stats.py index 9e5c67a8a..412eefef7 100644 --- a/klippy/extras/print_stats.py +++ b/klippy/extras/print_stats.py @@ -22,7 +22,9 @@ def __init__(self, config): def _update_filament_usage(self, eventtime): gc_status = self.gcode_move.get_status(eventtime) cur_epos = gc_status["position"].e - self.filament_used += (cur_epos - self.last_epos) / gc_status["extrude_factor"] + self.filament_used += (cur_epos - self.last_epos) / gc_status[ + "extrude_factor" + ] self.last_epos = cur_epos def set_current_file(self, filename): @@ -84,8 +86,12 @@ def _note_finish(self, state, error_message=""): ) def cmd_SET_PRINT_STATS_INFO(self, gcmd): - total_layer = gcmd.get_int("TOTAL_LAYER", self.info_total_layer, minval=0) - current_layer = gcmd.get_int("CURRENT_LAYER", self.info_current_layer, minval=0) + total_layer = gcmd.get_int( + "TOTAL_LAYER", self.info_total_layer, minval=0 + ) + current_layer = gcmd.get_int( + "CURRENT_LAYER", self.info_current_layer, minval=0 + ) if total_layer == 0: self.info_total_layer = None self.info_current_layer = None diff --git a/klippy/extras/probe.py b/klippy/extras/probe.py index 95adcf961..4aeccefdd 100644 --- a/klippy/extras/probe.py +++ b/klippy/extras/probe.py @@ -37,7 +37,9 @@ def __init__(self, config, mcu_probe): # Infer Z position to move to during a probe if config.has_section("stepper_z"): zconfig = config.getsection("stepper_z") - self.z_position = zconfig.getfloat("position_min", 0.0, note_valid=False) + self.z_position = zconfig.getfloat( + "position_min", 0.0, note_valid=False + ) else: pconfig = config.getsection("printer") self.z_position = pconfig.getfloat( @@ -49,9 +51,15 @@ def __init__(self, config, mcu_probe): "sample_retract_dist", 2.0, above=0.0 ) atypes = ["median", "average"] - self.samples_result = config.getchoice("samples_result", atypes, "average") - self.samples_tolerance = config.getfloat("samples_tolerance", 0.100, minval=0.0) - self.samples_retries = config.getint("samples_tolerance_retries", 0, minval=0) + self.samples_result = config.getchoice( + "samples_result", atypes, "average" + ) + self.samples_tolerance = config.getfloat( + "samples_tolerance", 0.100, minval=0.0 + ) + self.samples_retries = config.getint( + "samples_tolerance_retries", 0, minval=0 + ) # Register z_virtual_endstop pin self.printer.lookup_object("pins").register_chip("probe", self) # Register homing event handlers @@ -72,7 +80,9 @@ def __init__(self, config, mcu_probe): ) # Register PROBE/QUERY_PROBE commands self.gcode = self.printer.lookup_object("gcode") - self.gcode.register_command("PROBE", self.cmd_PROBE, desc=self.cmd_PROBE_help) + 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 ) @@ -163,7 +173,9 @@ def _probe(self, speed): ) z_compensation = 0 if axis_twist_compensation is not None: - z_compensation = axis_twist_compensation.get_z_compensation_value(pos) + z_compensation = axis_twist_compensation.get_z_compensation_value( + pos + ) # add z compensation to probe position epos[2] += z_compensation self.gcode.respond_info( @@ -247,7 +259,9 @@ def run_probe(self, gcmd): cmd_PROBE_help = "Probe Z-height at current XY position" def cmd_PROBE(self, gcmd): - drop_first_result = gcmd.get_int("DROP_FIRST_RESULT", self.drop_first_result) + drop_first_result = gcmd.get_int( + "DROP_FIRST_RESULT", self.drop_first_result + ) original_drop_first_result = self.drop_first_result self.drop_first_result = drop_first_result @@ -276,7 +290,9 @@ def get_status(self, eventtime): cmd_PROBE_ACCURACY_help = "Probe Z-height accuracy at current XY position" def cmd_PROBE_ACCURACY(self, gcmd): - drop_first_result = gcmd.get_int("DROP_FIRST_RESULT", self.drop_first_result) + drop_first_result = gcmd.get_int( + "DROP_FIRST_RESULT", self.drop_first_result + ) original_drop_first_result = self.drop_first_result self.drop_first_result = drop_first_result @@ -357,7 +373,9 @@ def probe_calibrate_finalize(self, kin_pos): cmd_PROBE_CALIBRATE_help = "Calibrate the probe's z_offset" def cmd_PROBE_CALIBRATE(self, gcmd): - drop_first_result = gcmd.get_int("DROP_FIRST_RESULT", self.drop_first_result) + drop_first_result = gcmd.get_int( + "DROP_FIRST_RESULT", self.drop_first_result + ) original_drop_first_result = self.drop_first_result self.drop_first_result = drop_first_result @@ -390,7 +408,8 @@ def cmd_Z_OFFSET_APPLY_PROBE(self, gcmd): self.gcode.respond_info( "%s: z_offset: %.3f\n" "The SAVE_CONFIG command will update the printer config file\n" - "with the above and restart the printer." % (self.name, new_calibrate) + "with the above and restart the printer." + % (self.name, new_calibrate) ) configfile.set(self.name, "z_offset", "%.3f" % (new_calibrate,)) @@ -402,9 +421,13 @@ 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) + 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.activate_gcode = gcode_macro.load_template( + config, "activate_gcode", "" + ) self.deactivate_gcode = gcode_macro.load_template( config, "deactivate_gcode", "" ) @@ -492,6 +515,7 @@ def __init__( default_points=None, option_name="points", enable_adaptive_move_z=False, + use_probe_offsets=False, ): self.printer = config.get_printer() self.enable_adaptive_move_z = enable_adaptive_move_z @@ -505,7 +529,9 @@ def __init__( option_name, seps=(",", "\n"), parser=float, count=2 ) self.z_move_speed = config.getfloat("z_move_speed", None, above=0.0) - self.default_horizontal_move_z = config.getfloat("horizontal_move_z", 5.0) + self.default_horizontal_move_z = config.getfloat( + "horizontal_move_z", 5.0 + ) if self.enable_adaptive_move_z: self.def_adaptive_horizontal_move_z = config.getboolean( "adaptive_horizontal_move_z", False @@ -541,7 +567,9 @@ def __init__( else self.def_additional_horizontal_move_z ) self.speed = config.getfloat("speed", 50.0, above=0.0) - self.use_offsets = False + self.use_offsets = config.getboolean( + "use_probe_offsets", use_probe_offsets + ) # Internal probing state self.lift_speed = self.speed self.probe_offsets = (0.0, 0.0, 0.0) @@ -587,7 +615,10 @@ def _move_next(self, speed=None): if isinstance(res, (int, float)): if res == 0: done = True - if self.enable_adaptive_move_z and self.adaptive_horizontal_move_z: + if ( + self.enable_adaptive_move_z + and self.adaptive_horizontal_move_z + ): # then res is error error = math.ceil(res) or 1.0 self.horizontal_move_z = ( @@ -624,9 +655,12 @@ def start_probe(self, gcmd, speed=None, horizontal_move_z=None): ) if self.enable_adaptive_move_z: self.adaptive_horizontal_move_z = gcmd.get_int( - "ADAPTIVE_HORIZONTAL_MOVE_Z", self.def_adaptive_horizontal_move_z + "ADAPTIVE_HORIZONTAL_MOVE_Z", + self.def_adaptive_horizontal_move_z, + ) + self.min_horizontal_move_z = gcmd.get_float( + "MIN_HORIZONTAL_MOVE_Z", None ) - self.min_horizontal_move_z = gcmd.get_float("MIN_HORIZONTAL_MOVE_Z", None) if ( self.min_horizontal_move_z is not None and not self.adaptive_horizontal_move_z @@ -666,7 +700,9 @@ def start_probe(self, gcmd, speed=None, horizontal_move_z=None): self.lift_speed = probe.get_lift_speed(gcmd) self.probe_offsets = probe.get_offsets() if self.horizontal_move_z < self.probe_offsets[2]: - raise gcmd.error("horizontal_move_z can't be less than probe's z_offset") + raise gcmd.error( + "horizontal_move_z can't be less than probe's z_offset" + ) probe.multi_probe_begin() while True: done = self._move_next(speed=speed) diff --git a/klippy/extras/probe_eddy_current.py b/klippy/extras/probe_eddy_current.py index e932e605f..2e9bed3c9 100644 --- a/klippy/extras/probe_eddy_current.py +++ b/klippy/extras/probe_eddy_current.py @@ -18,7 +18,10 @@ def __init__(self, config): self.cal_zpos = [] cal = config.get("calibrate", None) if cal is not None: - cal = [list(map(float, d.strip().split(":", 1))) for d in cal.split(",")] + cal = [ + list(map(float, d.strip().split(":", 1))) + for d in cal.split(",") + ] self.load_calibration(cal) # Probe calibrate state self.probe_speed = 0.0 @@ -65,7 +68,9 @@ def height_to_freq(self, height): rev_freqs = list(reversed(self.cal_freqs)) pos = bisect.bisect(rev_zpos, height) if pos == 0 or pos >= len(rev_zpos): - raise self.printer.command_error("Invalid probe_eddy_current height") + raise self.printer.command_error( + "Invalid probe_eddy_current height" + ) this_freq = rev_freqs[pos] prev_freq = rev_freqs[pos - 1] this_zpos = rev_zpos[pos] @@ -111,7 +116,8 @@ def handle_batch(msg): # Find Z position based on actual commanded stepper position toolhead.flush_step_generation() kin_spos = { - s.get_name(): s.get_commanded_position() for s in kin.get_steppers() + s.get_name(): s.get_commanded_position() + for s in kin.get_steppers() } kin_pos = kin.calc_position(kin_spos) times.append((start_query_time, end_query_time, kin_pos[2])) @@ -198,7 +204,9 @@ def post_manual_probe(self, kin_pos): def cmd_EDDY_CALIBRATE(self, gcmd): self.probe_speed = gcmd.get_float("PROBE_SPEED", 5.0, above=0.0) # Start manual probe - manual_probe.ManualProbeHelper(self.printer, gcmd, self.post_manual_probe) + manual_probe.ManualProbeHelper( + self.printer, gcmd, self.post_manual_probe + ) # Helper for implementing PROBE style commands @@ -279,7 +287,9 @@ def home_wait(self, home_end_time): self._stop_measurements(is_home=True) res = self._dispatch.stop() if res >= mcu.MCU_trsync.REASON_COMMS_TIMEOUT: - raise self._printer.command_error("Communication timeout during homing") + raise self._printer.command_error( + "Communication timeout during homing" + ) if res != mcu.MCU_trsync.REASON_ENDSTOP_HIT: return 0.0 if self._mcu.is_fileoutput(): @@ -307,7 +317,9 @@ def probing_move(self, pos, speed): systime = reactor.monotonic() est_print_time = self._mcu.estimated_print_time(systime) if est_print_time > self._trigger_time + 1.0: - raise self._printer.command_error("probe_eddy_current sensor outage") + raise self._printer.command_error( + "probe_eddy_current sensor outage" + ) reactor.pause(systime + 0.010) # Find position since trigger samples = self._samples @@ -337,7 +349,9 @@ def probing_move(self, pos, speed): def multi_probe_begin(self): if not self._calibration.is_calibrated(): - raise self._printer.command_error("Must calibrate probe_eddy_current first") + raise self._printer.command_error( + "Must calibrate probe_eddy_current first" + ) self._start_measurements() def multi_probe_end(self): @@ -363,7 +377,9 @@ def __init__(self, config): sensor_type = config.getchoice("sensor_type", {s: s for s in sensors}) self.sensor_helper = sensors[sensor_type](config, self.calibration) # Probe interface - self.probe = EddyEndstopWrapper(config, self.sensor_helper, self.calibration) + self.probe = EddyEndstopWrapper( + config, self.sensor_helper, self.calibration + ) self.printer.add_object("probe", probe.PrinterProbe(config, self.probe)) def add_client(self, cb): diff --git a/klippy/extras/pwm_cycle_time.py b/klippy/extras/pwm_cycle_time.py index 548817649..b68be813a 100644 --- a/klippy/extras/pwm_cycle_time.py +++ b/klippy/extras/pwm_cycle_time.py @@ -41,7 +41,9 @@ def _build_config(self): "shutdown value must be 0.0 or 1.0 on soft pwm" ) if cycle_ticks >= 1 << 31: - raise self._mcu.get_printer().config_error("PWM pin cycle time too large") + raise self._mcu.get_printer().config_error( + "PWM pin cycle time too large" + ) self._mcu.request_move_queue_slot() self._oid = self._mcu.create_oid() self._mcu.add_config_cmd( @@ -56,7 +58,8 @@ def _build_config(self): ) ) self._mcu.add_config_cmd( - "set_digital_out_pwm_cycle oid=%d cycle_ticks=%d" % (self._oid, cycle_ticks) + "set_digital_out_pwm_cycle oid=%d cycle_ticks=%d" + % (self._oid, cycle_ticks) ) self._cycle_ticks = cycle_ticks svalue = int(self._start_value * cycle_ticks + 0.5) @@ -79,7 +82,9 @@ def set_pwm_cycle(self, print_time, value, cycle_time): cycle_ticks = self._mcu.seconds_to_clock(cycle_time) if cycle_ticks != self._cycle_ticks: if cycle_ticks >= 1 << 31: - raise self._mcu.get_printer().command_error("PWM cycle time too large") + raise self._mcu.get_printer().command_error( + "PWM cycle time too large" + ) self._set_cycle_ticks.send( [self._oid, cycle_ticks], minclock=minclock, reqclock=clock ) @@ -105,10 +110,13 @@ def __init__(self, config): # Determine start and shutdown values self.scale = config.getfloat("scale", 1.0, above=0.0) self.last_value = ( - config.getfloat("value", 0.0, minval=0.0, maxval=self.scale) / self.scale + config.getfloat("value", 0.0, minval=0.0, maxval=self.scale) + / self.scale ) self.shutdown_value = ( - config.getfloat("shutdown_value", 0.0, minval=0.0, maxval=self.scale) + config.getfloat( + "shutdown_value", 0.0, minval=0.0, maxval=self.scale + ) / self.scale ) # Create pwm pin object diff --git a/klippy/extras/pwm_tool.py b/klippy/extras/pwm_tool.py index 11c121818..00567af7d 100644 --- a/klippy/extras/pwm_tool.py +++ b/klippy/extras/pwm_tool.py @@ -61,7 +61,8 @@ def _build_config(self): config_error = self._mcu.get_printer().config_error if self._max_duration and self._start_value != self._shutdown_value: raise config_error( - "Pin with max duration must have start " "value equal to shutdown value" + "Pin with max duration must have start " + "value equal to shutdown value" ) cmd_queue = self._mcu.alloc_command_queue() curtime = self._mcu.get_printer().get_reactor().monotonic() @@ -116,7 +117,8 @@ def _build_config(self): ) self._default_value = int(self._shutdown_value >= 0.5) * cycle_ticks self._mcu.add_config_cmd( - "set_digital_out_pwm_cycle oid=%d cycle_ticks=%d" % (self._oid, cycle_ticks) + "set_digital_out_pwm_cycle oid=%d cycle_ticks=%d" + % (self._oid, cycle_ticks) ) self._pwm_max = float(cycle_ticks) self._last_value = int(self._start_value * self._pwm_max + 0.5) @@ -133,7 +135,9 @@ def _send_update(self, clock, val): self._last_clock = clock = max(self._last_clock, clock) self._last_value = val data = (self._set_cmd_tag, self._oid, clock & 0xFFFFFFFF, val) - ret = self._stepcompress_queue_mq_msg(self._stepqueue, clock, data, len(data)) + ret = self._stepcompress_queue_mq_msg( + self._stepqueue, clock, data, len(data) + ) if ret: raise error("Internal error in stepcompress") # Notify toolhead so that it will flush this update @@ -180,10 +184,13 @@ def __init__(self, config): self.mcu_pin.setup_max_duration(max_mcu_duration) # Determine start and shutdown values self.last_value = ( - config.getfloat("value", 0.0, minval=0.0, maxval=self.scale) / self.scale + config.getfloat("value", 0.0, minval=0.0, maxval=self.scale) + / self.scale ) self.shutdown_value = ( - config.getfloat("shutdown_value", 0.0, minval=0.0, maxval=self.scale) + config.getfloat( + "shutdown_value", 0.0, minval=0.0, maxval=self.scale + ) / self.scale ) self.mcu_pin.setup_start_value(self.last_value, self.shutdown_value) @@ -191,7 +198,11 @@ def __init__(self, config): pin_name = config.get_name().split()[1] gcode = self.printer.lookup_object("gcode") gcode.register_mux_command( - "SET_PIN", "PIN", pin_name, self.cmd_SET_PIN, desc=self.cmd_SET_PIN_help + "SET_PIN", + "PIN", + pin_name, + self.cmd_SET_PIN, + desc=self.cmd_SET_PIN_help, ) def get_status(self, eventtime): diff --git a/klippy/extras/quad_gantry_level.py b/klippy/extras/quad_gantry_level.py index eb0d13d07..1557df378 100644 --- a/klippy/extras/quad_gantry_level.py +++ b/klippy/extras/quad_gantry_level.py @@ -35,14 +35,18 @@ def __init__(self, config): config, self.probe_finalize, enable_adaptive_move_z=True ) if len(self.probe_helper.probe_points) != 4: - raise config.error("Need exactly 4 probe points for quad_gantry_level") + raise config.error( + "Need exactly 4 probe points for quad_gantry_level" + ) self.z_status = z_tilt.ZAdjustStatus(self.printer) self.z_helper = z_tilt.ZAdjustHelper(config, 4) self.gantry_corners = config.getlists( "gantry_corners", parser=float, seps=(",", "\n"), count=2 ) if len(self.gantry_corners) < 2: - raise config.error("quad_gantry_level requires at least two gantry_corners") + raise config.error( + "quad_gantry_level requires at least two gantry_corners" + ) # Register QUAD_GANTRY_LEVEL command self.gcode = self.printer.lookup_object("gcode") self.gcode.register_command( @@ -81,7 +85,9 @@ def probe_finalize(self, offsets, positions): ppx1 = [positions[1][0] + offsets[0], z_positions[1]] ppx2 = [positions[2][0] + offsets[0], z_positions[2]] slope_x_pp12 = self.linefit(ppx1, ppx2) - logging.info("quad_gantry_level f1: %s, f2: %s" % (slope_x_pp03, slope_x_pp12)) + logging.info( + "quad_gantry_level f1: %s, f2: %s" % (slope_x_pp03, slope_x_pp12) + ) # Calculate gantry slope along Y axis between stepper 0 and 1 a1 = [ positions[0][1] + offsets[1], @@ -102,7 +108,9 @@ def probe_finalize(self, offsets, positions): self.plot(slope_x_pp12, self.gantry_corners[1][0]), ] slope_y_s23 = self.linefit(b1, b2) - logging.info("quad_gantry_level af: %s, bf: %s" % (slope_y_s01, slope_y_s23)) + logging.info( + "quad_gantry_level af: %s, bf: %s" % (slope_y_s01, slope_y_s23) + ) # Calculate z height of each stepper z_height = [0, 0, 0, 0] z_height[0] = self.plot(slope_y_s01, self.gantry_corners[0][1]) @@ -125,7 +133,8 @@ def probe_finalize(self, offsets, positions): raise self.gcode.error( "Aborting quad_gantry_level" " required adjustment %0.6f" - " is greater than max_adjust %0.6f" % (adjust_max, self.max_adjust) + " is greater than max_adjust %0.6f" + % (adjust_max, self.max_adjust) ) speed = self.probe_helper.get_lift_speed() diff --git a/klippy/extras/query_endstops.py b/klippy/extras/query_endstops.py index d79588656..6e34fee82 100644 --- a/klippy/extras/query_endstops.py +++ b/klippy/extras/query_endstops.py @@ -12,7 +12,9 @@ def __init__(self, config): self.last_state = [] # Register webhook if server is available webhooks = self.printer.lookup_object("webhooks") - webhooks.register_endpoint("query_endstops/status", self._handle_web_request) + webhooks.register_endpoint( + "query_endstops/status", self._handle_web_request + ) gcode = self.printer.lookup_object("gcode") gcode.register_command( "QUERY_ENDSTOPS", @@ -37,7 +39,10 @@ def _handle_web_request(self, web_request): for mcu_endstop, name in self.endstops ] web_request.send( - {name: ["open", "TRIGGERED"][not not t] for name, t in self.last_state} + { + name: ["open", "TRIGGERED"][not not t] + for name, t in self.last_state + } ) cmd_QUERY_ENDSTOPS_help = "Report on the status of each endstop" diff --git a/klippy/extras/replicape.py b/klippy/extras/replicape.py index 8f62a9590..6d0ba4e59 100644 --- a/klippy/extras/replicape.py +++ b/klippy/extras/replicape.py @@ -96,7 +96,10 @@ def set_pwm(self, print_time, value): self._is_enable = is_enable self._reactor.register_async_callback( ( - lambda e, s=self, pt=print_time, ie=is_enable: s._replicape.note_pwm_enable( + lambda e, + s=self, + pt=print_time, + ie=is_enable: s._replicape.note_pwm_enable( pt, s._channel, ie ) ) @@ -252,7 +255,10 @@ def __init__(self, config): if [i for i in [3, 4] if 11 + i in self.stepper_dacs]: # Enable eh steppers shift_registers[3] &= ~1 - if config.getboolean("standstill_power_down", False) and self.stepper_dacs: + if ( + config.getboolean("standstill_power_down", False) + and self.stepper_dacs + ): shift_registers[4] &= ~1 self.sr_enabled = list(reversed(shift_registers)) sr_spi_bus = "spidev1.1" @@ -286,7 +292,9 @@ def note_pwm_enable(self, print_time, channel, is_enable): # Check if need to set the stepper enable lines if channel not in self.stepper_dacs: return - on_dacs = [1 for c in self.stepper_dacs.keys() if self.enabled_channels[c]] + on_dacs = [ + 1 for c in self.stepper_dacs.keys() if self.enabled_channels[c] + ] if not on_dacs: sr = self.sr_disabled elif is_enable and len(on_dacs) == 1: diff --git a/klippy/extras/resonance_tester.py b/klippy/extras/resonance_tester.py index bd9802947..42ec8819b 100644 --- a/klippy/extras/resonance_tester.py +++ b/klippy/extras/resonance_tester.py @@ -130,7 +130,9 @@ def __init__(self, config): "max_freq", 10000.0 / 75.0, minval=self.min_freq, maxval=300.0 ) self.accel_per_hz = config.getfloat("accel_per_hz", 75.0, above=0.0) - self.hz_per_sec = config.getfloat("hz_per_sec", 1.0, minval=0.1, maxval=2.0) + self.hz_per_sec = config.getfloat( + "hz_per_sec", 1.0, minval=0.1, maxval=2.0 + ) self.probe_points = config.getlists( "probe_points", seps=(",", "\n"), parser=float, count=3 @@ -140,7 +142,9 @@ def get_start_test_points(self): return self.probe_points def prepare_test(self, gcmd): - self.freq_start = gcmd.get_float("FREQ_START", self.min_freq, minval=1.0) + self.freq_start = gcmd.get_float( + "FREQ_START", self.min_freq, minval=1.0 + ) self.freq_end = gcmd.get_float( "FREQ_END", self.max_freq, minval=self.freq_start, maxval=300.0 ) @@ -221,7 +225,9 @@ def __init__(self, config): self.cmd_SHAPER_CALIBRATE, desc=self.cmd_SHAPER_CALIBRATE_help, ) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): self.accel_chips = [ @@ -264,7 +270,9 @@ def _run_test( for point in test_points: toolhead.manual_move(point, self.move_speed) if len(test_points) > 1 or test_point is not None: - gcmd.respond_info("Probing point (%.3f, %.3f, %.3f)" % tuple(point)) + gcmd.respond_info( + "Probing point (%.3f, %.3f, %.3f)" % tuple(point) + ) for axis in axes: toolhead.wait_moves() toolhead.dwell(0.500) @@ -296,7 +304,8 @@ def _run_test( ) aclient.write_to_file(raw_name) gcmd.respond_info( - "Writing raw accelerometer data to " "%s file" % (raw_name,) + "Writing raw accelerometer data to " + "%s file" % (raw_name,) ) if helper is None: continue @@ -333,7 +342,8 @@ def _check_chip_connection(self, chip, toolhead, gcmd): values = aclient.get_samples() if not values: raise gcmd.error( - "No accelerometer measurements found for chip " "[%s]" % chip.name + "No accelerometer measurements found for chip " + "[%s]" % chip.name ) cmd_TEST_RESONANCES_help = "Runs the resonance test for a specifed axis" @@ -403,7 +413,9 @@ def cmd_TEST_RESONANCES(self, gcmd): max_freq=self._get_max_calibration_freq(), accel_per_hz=self.test.get_accel_per_hz(), ) - gcmd.respond_info("Resonances data written to %s file" % (csv_name,)) + gcmd.respond_info( + "Resonances data written to %s file" % (csv_name,) + ) cmd_SHAPER_CALIBRATE_help = ( "Simular to TEST_RESONANCES but suggest input shaper config" @@ -421,8 +433,12 @@ def cmd_SHAPER_CALIBRATE(self, gcmd): chips_str = gcmd.get("CHIPS", None) accel_chips = self._parse_chips(chips_str) if chips_str else None - max_smoothing = gcmd.get_float("MAX_SMOOTHING", self.max_smoothing, minval=0.05) - include_smoothers = gcmd.get_int("INCLUDE_SMOOTHERS", 0, minval=0, maxval=1) + max_smoothing = gcmd.get_float( + "MAX_SMOOTHING", self.max_smoothing, minval=0.05 + ) + include_smoothers = gcmd.get_int( + "INCLUDE_SMOOTHERS", 0, minval=0, maxval=1 + ) name_suffix = gcmd.get("NAME", time.strftime("%Y%m%d_%H%M%S")) if not self.is_valid_name_suffix(name_suffix): @@ -487,7 +503,9 @@ def cmd_SHAPER_CALIBRATE(self, gcmd): "with these parameters and restart the printer." ) - cmd_MEASURE_AXES_NOISE_help = "Measures noise of all enabled accelerometer chips" + cmd_MEASURE_AXES_NOISE_help = ( + "Measures noise of all enabled accelerometer chips" + ) def cmd_MEASURE_AXES_NOISE(self, gcmd): meas_time = gcmd.get_float("MEAS_TIME", 2.0) @@ -516,7 +534,9 @@ def cmd_MEASURE_AXES_NOISE(self, gcmd): def is_valid_name_suffix(self, name_suffix): return name_suffix.replace("-", "").replace("_", "").isalnum() - def get_filename(self, base, name_suffix, axis=None, point=None, chip_name=None): + def get_filename( + self, base, name_suffix, axis=None, point=None, chip_name=None + ): name = base if axis: name += "_" + axis.get_name() diff --git a/klippy/extras/respond.py b/klippy/extras/respond.py index 30f39e4ef..1433210a7 100644 --- a/klippy/extras/respond.py +++ b/klippy/extras/respond.py @@ -19,7 +19,9 @@ class HostResponder: def __init__(self, config): self.printer = config.get_printer() self.reactor = self.printer.get_reactor() - self.default_prefix = config.getchoice("default_type", respond_types, "echo") + self.default_prefix = config.getchoice( + "default_type", respond_types, "echo" + ) self.default_prefix = config.get("default_prefix", self.default_prefix) self.no_space = config.getboolean("no_space", False) diff --git a/klippy/extras/ringing_test.py b/klippy/extras/ringing_test.py index 4b69608f2..5b3c730f6 100644 --- a/klippy/extras/ringing_test.py +++ b/klippy/extras/ringing_test.py @@ -33,10 +33,16 @@ def __init__(self, config): "first_layer_height", 0.2, above=self.layer_height ) self.perimeters = config.getint("perimeters", 2, minval=1) - self.brim_width = config.getfloat("brim_width", 10.0, minval=self.notch + 2.0) + self.brim_width = config.getfloat( + "brim_width", 10.0, minval=self.notch + 2.0 + ) self.brim_velocity = config.getfloat("brim_velocity", 30.0, above=0.0) - self.filament_diameter = config.getfloat("filament_diameter", 1.75, above=0.0) - self.deceleration_points = config.getint("deceleration_points", 100, minval=10) + self.filament_diameter = config.getfloat( + "filament_diameter", 1.75, above=0.0 + ) + self.deceleration_points = config.getint( + "deceleration_points", 100, minval=10 + ) # Register commands self.gcode = self.printer.lookup_object("gcode") self.gcode.register_command( @@ -77,7 +83,8 @@ def _connect(self): self.notch_offset = self.size * DEFAULT_NOTCH_OFFSET_RATIO if self.notch_offset < 2.0 or self.notch_offset > 0.5 * self.size: raise self.printer.config_error( - "notch_offset must not be in range [2.0, %.3f]" % (0.5 * self.size,) + "notch_offset must not be in range [2.0, %.3f]" + % (0.5 * self.size,) ) cmd_PRINT_RINGING_TOWER_help = "Start Ringing Tower print" @@ -138,11 +145,15 @@ def get_gcode(self): center_y = gcmd.get_float("CENTER_Y", self.center_y) size = gcmd.get_float("SIZE", self.size, minval=50.0) perimeters = gcmd.get_int("PERIMETERS", self.perimeters, minval=1) - brim_velocity = gcmd.get_float("BRIM_VELOCITY", self.brim_velocity, above=0.0) + brim_velocity = gcmd.get_float( + "BRIM_VELOCITY", self.brim_velocity, above=0.0 + ) filament_diameter = gcmd.get_float( "FILAMENT_DIAMETER", self.filament_diameter, above=0.0 ) - layer_height = gcmd.get_float("LAYER_HEIGHT", self.layer_height, above=0.0) + layer_height = gcmd.get_float( + "LAYER_HEIGHT", self.layer_height, above=0.0 + ) first_layer_height = gcmd.get_float( "FIRST_LAYER_HEIGHT", self.first_layer_height, above=layer_height ) @@ -165,7 +176,9 @@ def get_gcode(self): accel_step = gcmd.get_float("ACCEL_STEP", self.accel_step) brim_width = gcmd.get_float("BRIM_WIDTH", self.brim_width) min_brim_width = (notch_offset - notch) / (1.0 + 1.0 / TAN_TEST_ANGLE) - brim_width = max(brim_width, min_brim_width + perimeters * line_width + 1.0) + brim_width = max( + brim_width, min_brim_width + perimeters * line_width + 1.0 + ) final_gcode_id = gcmd.get("FINAL_GCODE_ID", None) deceleration_points = gcmd.get_int( "DECELERATION_POINTS", self.deceleration_points, minval=10 @@ -272,7 +285,12 @@ def gen_brim(): def gen_tower(): prev_z = first_layer_height z = first_layer_height + layer_height - extr_r = 4.0 * layer_height * line_width / (math.pi * filament_diameter**2) + extr_r = ( + 4.0 + * layer_height + * line_width + / (math.pi * filament_diameter**2) + ) letter_offset = 0.5 * (size - band) - notch_offset * TAN_TEST_ANGLE while z < height - 0.00000001: next_z = z + layer_height @@ -307,8 +325,12 @@ def gen_tower(): def rotated_G1(x, y, e, v): return "G1 X%.6f Y%.6f E%.9f F%.3f" % ( - center_x + notch_axis[0] * x + other_axis[0] * y, - center_y + notch_axis[1] * x + other_axis[1] * y, + center_x + + notch_axis[0] * x + + other_axis[0] * y, + center_y + + notch_axis[1] * x + + other_axis[1] * y, e * extr_r, v * 60.0, ) @@ -323,11 +345,18 @@ def rotated_G1(x, y, e, v): yield rotated_G1( notch_pos - d_x - 1.0 - 0.5 * size, perimeter_offset - d_y - TAN_TEST_ANGLE, - (notch_pos - d_x - 1.0 - 0.5 * size + perimeter_offset), + ( + notch_pos + - d_x + - 1.0 + - 0.5 * size + + perimeter_offset + ), recipr_cos * velocity, ) yield ( - "SET_VELOCITY_LIMIT ACCEL=%.6f" + " ACCEL_TO_DECEL=%.6f" + "SET_VELOCITY_LIMIT ACCEL=%.6f" + + " ACCEL_TO_DECEL=%.6f" ) % (INFINITE_ACCEL, INFINITE_ACCEL) yield rotated_G1( notch_pos - d_x - 0.5 * size, @@ -354,7 +383,8 @@ def rotated_G1(x, y, e, v): ) old_x, old_y = x, y yield ( - "SET_VELOCITY_LIMIT ACCEL=%.6f" + " ACCEL_TO_DECEL=%.6f" + "SET_VELOCITY_LIMIT ACCEL=%.6f" + + " ACCEL_TO_DECEL=%.6f" ) % (max_accel, 0.5 * max_accel) if i < perimeters - 1 or ( abs(band_part - 0.5) >= 0.5 * LETTER_BAND_PART @@ -403,25 +433,41 @@ def rotated_G1(x, y, e, v): ) if letter_width > 2.0 * elem_size: yield rotated_G1( - (letter_offset - letter_width * 0.5 + elem_size), + ( + letter_offset + - letter_width * 0.5 + + elem_size + ), perimeter_offset - letter_perimeter_offset, elem_size, velocity, ) yield rotated_G1( - (letter_offset - letter_width * 0.5 + elem_size), + ( + letter_offset + - letter_width * 0.5 + + elem_size + ), perimeter_offset, abs(letter_perimeter_offset), velocity, ) yield rotated_G1( - (letter_offset + letter_width * 0.5 - elem_size), + ( + letter_offset + + letter_width * 0.5 + - elem_size + ), perimeter_offset, letter_width - 2.0 * elem_size, velocity, ) yield rotated_G1( - (letter_offset + letter_width * 0.5 - elem_size), + ( + letter_offset + + letter_width * 0.5 + - elem_size + ), perimeter_offset - letter_perimeter_offset, abs(letter_perimeter_offset), velocity, @@ -448,14 +494,19 @@ def rotated_G1(x, y, e, v): yield rotated_G1( next_y_offset, perimeter_offset, - (next_y_offset - letter_offset - letter_width * 0.5), + ( + next_y_offset + - letter_offset + - letter_width * 0.5 + ), velocity, ) perimeter_offset += line_width self.progress = z / height prev_z, z = z, next_z yield ( - "SET_VELOCITY_LIMIT ACCEL=%.3f ACCEL_TO_DECEL=%.f" + " VELOCITY=%.3f" + "SET_VELOCITY_LIMIT ACCEL=%.3f ACCEL_TO_DECEL=%.f" + + " VELOCITY=%.3f" ) % (old_max_accel, old_max_accel_to_decel, old_max_velocity) yield "M83" @@ -466,7 +517,9 @@ def rotated_G1(x, y, e, v): for line in gen_tower(): yield line if final_gcode_id is not None: - yield "UPDATE_DELAYED_GCODE ID='%s' DURATION=0.01" % (final_gcode_id,) + yield "UPDATE_DELAYED_GCODE ID='%s' DURATION=0.01" % ( + final_gcode_id, + ) self.progress = 1.0 diff --git a/klippy/extras/safe_z_home.py b/klippy/extras/safe_z_home.py index 9c3f93ffc..34037c8dc 100644 --- a/klippy/extras/safe_z_home.py +++ b/klippy/extras/safe_z_home.py @@ -28,7 +28,8 @@ def __init__(self, config): if config.has_section("homing_override"): raise config.error( - "homing_override and safe_z_homing cannot" + " be used simultaneously" + "homing_override and safe_z_homing cannot" + + " be used simultaneously" ) def cmd_G28(self, gcmd): @@ -53,7 +54,9 @@ def cmd_G28(self, gcmd): toolhead.manual_move([None, None, self.z_hop], self.z_hop_speed) # Determine which axes we need to home - need_x, need_y, need_z = [gcmd.get(axis, None) is not None for axis in "XYZ"] + need_x, need_y, need_z = [ + gcmd.get(axis, None) is not None for axis in "XYZ" + ] if not need_x and not need_y and not need_z: need_x = need_y = need_z = True @@ -64,10 +67,14 @@ def cmd_G28(self, gcmd): axis_order = "xy" for axis in axis_order: if axis == "x" and need_x: - g28_gcmd = self.gcode.create_gcode_command("G28", "G28", {"X": "0"}) + g28_gcmd = self.gcode.create_gcode_command( + "G28", "G28", {"X": "0"} + ) self.prev_G28(g28_gcmd) elif axis == "y" and need_y: - g28_gcmd = self.gcode.create_gcode_command("G28", "G28", {"Y": "0"}) + g28_gcmd = self.gcode.create_gcode_command( + "G28", "G28", {"Y": "0"} + ) self.prev_G28(g28_gcmd) # Home Z axis if necessary @@ -93,7 +100,9 @@ def cmd_G28(self, gcmd): if self.z_hop: pos = toolhead.get_position() if pos[2] < self.z_hop: - toolhead.manual_move([None, None, self.z_hop], self.z_hop_speed) + toolhead.manual_move( + [None, None, self.z_hop], self.z_hop_speed + ) # Move XY back to previous positions if self.move_to_previous: diff --git a/klippy/extras/screws_tilt_adjust.py b/klippy/extras/screws_tilt_adjust.py index 7408a9a6c..38732635a 100644 --- a/klippy/extras/screws_tilt_adjust.py +++ b/klippy/extras/screws_tilt_adjust.py @@ -26,7 +26,9 @@ def __init__(self, config): screw_name = config.get(prefix + "_name", screw_name) self.screws.append((screw_coord, screw_name)) if len(self.screws) < 3: - raise config.error("screws_tilt_adjust: Must have " "at least three screws") + raise config.error( + "screws_tilt_adjust: Must have " "at least three screws" + ) self.threads = { "CW-M3": 0, "CCW-M3": 1, @@ -39,7 +41,9 @@ def __init__(self, config): "CW-M8": 8, "CCW-M8": 9, } - self.thread = config.getchoice("screw_thread", self.threads, default="CW-M3") + self.thread = config.getchoice( + "screw_thread", self.threads, default="CW-M3" + ) # Initialize ProbePointsHelper points = [coord for coord, name in self.screws] self.probe_helper = probe.ProbePointsHelper( diff --git a/klippy/extras/sdcard_loop.py b/klippy/extras/sdcard_loop.py index 5e21c53a7..47220523a 100644 --- a/klippy/extras/sdcard_loop.py +++ b/klippy/extras/sdcard_loop.py @@ -56,7 +56,9 @@ def loop_begin(self, count): ): # Can only run inside of an SD file return False - self.loop_stack.append((count, self.sdcard_gcode_provider.get_file_position())) + self.loop_stack.append( + (count, self.sdcard_gcode_provider.get_file_position()) + ) return True def loop_end(self): @@ -85,7 +87,10 @@ def loop_end(self): return True def loop_desist(self): - if self.sdcard.is_cmd_from_sd() and self.sdcard_gcode_provider.is_active(): + if ( + self.sdcard.is_cmd_from_sd() + and self.sdcard_gcode_provider.is_active() + ): # Can only run outside of an SD file return False logging.info("Desisting existing SD loops") diff --git a/klippy/extras/servo.py b/klippy/extras/servo.py index a444861e2..50787ddda 100644 --- a/klippy/extras/servo.py +++ b/klippy/extras/servo.py @@ -27,7 +27,9 @@ def __init__(self, config): self.width_to_value = 1.0 / SERVO_SIGNAL_PERIOD self.last_value = 0.0 initial_pwm = 0.0 - iangle = config.getfloat("initial_angle", None, minval=0.0, maxval=360.0) + iangle = config.getfloat( + "initial_angle", None, minval=0.0, maxval=360.0 + ) if iangle is not None: initial_pwm = self._get_pwm_from_angle(iangle) else: @@ -69,7 +71,9 @@ def _template_update(self, text): self.gcrq.send_async_request(self._get_pwm_from_angle(angle)) elif type == "WIDTH": width = float(value.strip()) - self.gcrq.send_async_request(self._get_pwm_from_pulse_width(width)) + self.gcrq.send_async_request( + self._get_pwm_from_pulse_width(width) + ) except ValueError as e: logging.exception("servo template render error") diff --git a/klippy/extras/shaper_calibrate.py b/klippy/extras/shaper_calibrate.py index a9ef4326b..72b269a11 100644 --- a/klippy/extras/shaper_calibrate.py +++ b/klippy/extras/shaper_calibrate.py @@ -54,7 +54,9 @@ def add_data(self, other): for psd, other_psd in zip(self._psd_list, other._psd_list): # `other` data may be defined at different frequency bins, # interpolating to fix that. - other_normalized = np.interp(self.freq_bins, other.freq_bins, other_psd) + other_normalized = np.interp( + self.freq_bins, other.freq_bins, other_psd + ) psd[:] = np.maximum(psd, other_normalized) def set_numpy(self, numpy): @@ -64,7 +66,9 @@ def normalize_to_frequencies(self): freq_bins = self.freq_bins for psd in self._psd_list: # Avoid division by zero errors and remove low-frequency noise - psd *= self.numpy.tanh(0.5 / MIN_FREQ * freq_bins) / (freq_bins + 0.1) + psd *= self.numpy.tanh(0.5 / MIN_FREQ * freq_bins) / ( + freq_bins + 0.1 + ) def get_psd(self, axis="all"): return self._psd_map[axis] @@ -133,7 +137,9 @@ def estimate_shaper(np, shaper, test_damping_ratio, test_freqs): s_r = step_response(np, time - T[i], omega, test_damping_ratio) response += A[i] * s_r response *= inv_D - velocity = (response[:, 1:] - response[:, :-1]) / (omega * dt)[:, np.newaxis] + velocity = (response[:, 1:] - response[:, :-1]) / (omega * dt)[ + :, np.newaxis + ] res = np.zeros(shape=test_freqs.shape) res[test_freqs > 0.0] = -velocity.min(axis=-1) / min_v res[test_freqs <= 0.0] = 1.0 @@ -201,7 +207,9 @@ def get_windows(m, wl): s_r = step_response(np, time, omega, test_damping_ratio) w_dt = w[:, wm:wp] * (np.reciprocal(norms) * dt)[:, np.newaxis] response = np.einsum("ijk,ik->ij", get_windows(s_r, wp - wm), w_dt[:, ::-1]) - velocity = (response[:, 1:] - response[:, :-1]) / (omega * dt)[:, np.newaxis] + velocity = (response[:, 1:] - response[:, :-1]) / (omega * dt)[ + :, np.newaxis + ] res = np.zeros(shape=test_freqs.shape) res[test_freqs > 0.0] = -velocity.min(axis=-1) / min_v res[test_freqs <= 0.0] = 1.0 @@ -367,9 +375,13 @@ def _get_shaper_smoothing(self, shaper, accel=5000, scv=5.0): for i in range(n): if T[i] >= ts: # Calculate offset for one of the axes - offset_90_x += A[i] * (scv + half_accel * (T[i] - ts)) * (T[i] - ts) + offset_90_x += ( + A[i] * (scv + half_accel * (T[i] - ts)) * (T[i] - ts) + ) else: - offset_90_y += A[i] * (scv - half_accel * (T[i] - ts)) * (T[i] - ts) + offset_90_y += ( + A[i] * (scv - half_accel * (T[i] - ts)) * (T[i] - ts) + ) offset_180 += A[i] * half_accel * (T[i] - ts) ** 2 offset_90 = inv_D * math.sqrt(offset_90_x**2 + offset_90_y**2) offset_180 *= inv_D @@ -417,7 +429,9 @@ def fit_shaper( shaper_freqs = (None, None, None) if isinstance(shaper_freqs, tuple): freq_end = shaper_freqs[1] or MAX_SHAPER_FREQ - freq_start = min(shaper_freqs[0] or shaper_cfg.min_freq, freq_end - 1e-7) + freq_start = min( + shaper_freqs[0] or shaper_cfg.min_freq, freq_end - 1e-7 + ) freq_step = shaper_freqs[2] or 0.2 test_freqs = np.arange(freq_start, freq_end, freq_step) else: @@ -481,7 +495,8 @@ def fit_shaper( selected = best_res for res in results[::-1]: if res.score < selected.score and ( - res.vibrs < best_res.vibrs * 1.2 or res.vibrs < best_res.vibrs + 0.0075 + res.vibrs < best_res.vibrs * 1.2 + or res.vibrs < best_res.vibrs + 0.0075 ): selected = res return selected @@ -509,7 +524,8 @@ def find_max_accel(self, s, get_smoothing, scv): # for max_accel without much smoothing TARGET_SMOOTHING = 0.12 max_accel = self._bisect( - lambda test_accel: get_smoothing(s, test_accel, scv) <= TARGET_SMOOTHING, + lambda test_accel: get_smoothing(s, test_accel, scv) + <= TARGET_SMOOTHING, 1e-2, ) return max_accel diff --git a/klippy/extras/shaper_defs.py b/klippy/extras/shaper_defs.py index 36e8da046..e6580e307 100644 --- a/klippy/extras/shaper_defs.py +++ b/klippy/extras/shaper_defs.py @@ -104,7 +104,9 @@ def get_3hump_ei_shaper(shaper_freq, damping_ratio): t_d = 1.0 / (shaper_freq * df) K2 = K * K - a1 = 0.0625 * (1.0 + 3.0 * v_tol + 2.0 * math.sqrt(2.0 * (v_tol + 1.0) * v_tol)) + a1 = 0.0625 * ( + 1.0 + 3.0 * v_tol + 2.0 * math.sqrt(2.0 * (v_tol + 1.0) * v_tol) + ) a2 = 0.25 * (1.0 - v_tol) * K a3 = (0.5 * (1.0 + v_tol) - 2.0 * a1) * K2 a4 = a2 * K2 @@ -162,7 +164,9 @@ def get_none_smoother(): # of the extruder with the toolhead motion). -def get_zv_smoother(shaper_freq, damping_ratio_unused=None, normalize_coeffs=True): +def get_zv_smoother( + shaper_freq, damping_ratio_unused=None, normalize_coeffs=True +): coeffs = [ -118.4265334338076, 5.861885495127615, @@ -173,7 +177,9 @@ def get_zv_smoother(shaper_freq, damping_ratio_unused=None, normalize_coeffs=Tru return init_smoother(coeffs, 0.8025 / shaper_freq, normalize_coeffs) -def get_mzv_smoother(shaper_freq, damping_ratio_unused=None, normalize_coeffs=True): +def get_mzv_smoother( + shaper_freq, damping_ratio_unused=None, normalize_coeffs=True +): coeffs = [ -1906.717580206364, 125.8892756660212, @@ -186,7 +192,9 @@ def get_mzv_smoother(shaper_freq, damping_ratio_unused=None, normalize_coeffs=Tr return init_smoother(coeffs, 0.95625 / shaper_freq, normalize_coeffs) -def get_ei_smoother(shaper_freq, damping_ratio_unused=None, normalize_coeffs=True): +def get_ei_smoother( + shaper_freq, damping_ratio_unused=None, normalize_coeffs=True +): coeffs = [ -1797.048868963208, 120.5310596109878, @@ -216,7 +224,9 @@ def get_2hump_ei_smoother( return init_smoother(coeffs, 1.14875 / shaper_freq, normalize_coeffs) -def get_si_smoother(shaper_freq, damping_ratio_unused=None, normalize_coeffs=True): +def get_si_smoother( + shaper_freq, damping_ratio_unused=None, normalize_coeffs=True +): coeffs = [ -6186.76006449789, 1206.747198930197, @@ -231,7 +241,9 @@ def get_si_smoother(shaper_freq, damping_ratio_unused=None, normalize_coeffs=Tru return init_smoother(coeffs, 1.245 / shaper_freq, normalize_coeffs) -def get_zvd_ei_smoother(shaper_freq, damping_ratio_unused=None, normalize_coeffs=True): +def get_zvd_ei_smoother( + shaper_freq, damping_ratio_unused=None, normalize_coeffs=True +): coeffs = [ -18835.07746719777, 1914.349309746547, diff --git a/klippy/extras/sht3x.py b/klippy/extras/sht3x.py index f2e750cb8..70b546bfa 100644 --- a/klippy/extras/sht3x.py +++ b/klippy/extras/sht3x.py @@ -5,8 +5,6 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import logging -import threading -import time from . import bus @@ -72,7 +70,9 @@ def __init__(self, config): ) self.ignore = self.name in get_danger_options().temp_ignore_limits self.printer.add_object("sht3x " + self.name, self) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): self._init_sht3x() diff --git a/klippy/extras/skew_correction.py b/klippy/extras/skew_correction.py index 22a5ebc0a..933625c0c 100644 --- a/klippy/extras/skew_correction.py +++ b/klippy/extras/skew_correction.py @@ -15,7 +15,8 @@ def calc_skew_factor(ac, bd, ad): side = math.sqrt(2 * ac * ac + 2 * bd * bd - 4 * ad * ad) / 2.0 return math.tan( - math.pi / 2 - math.acos((ac * ac - side * side - ad * ad) / (2 * side * ad)) + math.pi / 2 + - math.acos((ac * ac - side * side - ad * ad) / (2 * side * ad)) ) @@ -29,7 +30,9 @@ def __init__(self, config): self.yz_factor = 0.0 self.skew_profiles = {} self._load_storage(config) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.next_transform = None gcode = self.printer.lookup_object("gcode") gcode.register_command( @@ -152,7 +155,8 @@ def cmd_SKEW_PROFILE(self, gcmd): prof = self.skew_profiles.get(name) if prof is None: gcmd.respond_info( - "skew_correction: Load failed, unknown profile [%s]" % (name) + "skew_correction: Load failed, unknown profile [%s]" + % (name) ) return self._update_skew(prof["xy_skew"], prof["xz_skew"], prof["yz_skew"]) @@ -172,7 +176,8 @@ def cmd_SKEW_PROFILE(self, gcmd): gcmd.respond_info( "Skew Correction state has been saved to profile [%s]\n" "for the current session. The SAVE_CONFIG command will\n" - "update the printer config file and restart the printer." % (name) + "update the printer config file and restart the printer." + % (name) ) elif gcmd.get("REMOVE", None) is not None: name = gcmd.get("REMOVE") diff --git a/klippy/extras/smart_effector.py b/klippy/extras/smart_effector.py index a71afaba7..cf7ee1307 100644 --- a/klippy/extras/smart_effector.py +++ b/klippy/extras/smart_effector.py @@ -99,13 +99,17 @@ def probe_prepare(self, hmove): systime = self.printer.get_reactor().monotonic() toolhead_info = toolhead.get_status(systime) self.old_max_accel = toolhead_info["max_accel"] - self.gcode.run_script_from_command("M204 S%.3f" % (self.probe_accel,)) + self.gcode.run_script_from_command( + "M204 S%.3f" % (self.probe_accel,) + ) if self.recovery_time: toolhead.dwell(self.recovery_time) def probe_finish(self, hmove): if self.probe_accel: - self.gcode.run_script_from_command("M204 S%.3f" % (self.old_max_accel,)) + self.gcode.run_script_from_command( + "M204 S%.3f" % (self.old_max_accel,) + ) self.probe_wrapper.probe_finish(hmove) def _send_command(self, buf): @@ -150,11 +154,15 @@ def cmd_SET_SMART_EFFECTOR(self, gcmd): "RECOVERY_TIME", self.recovery_time, minval=0.0 ) if self.probe_accel: - respond_info.append("probing accelartion: %.3f" % (self.probe_accel,)) + respond_info.append( + "probing accelartion: %.3f" % (self.probe_accel,) + ) else: respond_info.append("probing acceleration control disabled") if self.recovery_time: - respond_info.append("probe recovery time: %.3f" % (self.recovery_time,)) + respond_info.append( + "probe recovery time: %.3f" % (self.recovery_time,) + ) else: respond_info.append("probe recovery time disabled") gcmd.respond_info("SmartEffector:\n" + "\n".join(respond_info)) @@ -169,5 +177,7 @@ def cmd_RESET_SMART_EFFECTOR(self, gcmd): def load_config(config): smart_effector = SmartEffectorEndstopWrapper(config) - config.get_printer().add_object("probe", probe.PrinterProbe(config, smart_effector)) + config.get_printer().add_object( + "probe", probe.PrinterProbe(config, smart_effector) + ) return smart_effector diff --git a/klippy/extras/spi_temperature.py b/klippy/extras/spi_temperature.py index f5e15d4e0..354c9a49b 100644 --- a/klippy/extras/spi_temperature.py +++ b/klippy/extras/spi_temperature.py @@ -8,7 +8,6 @@ from . import bus from extras.danger_options import get_danger_options -from extras.danger_options import get_danger_options ###################################################################### # SensorBase @@ -34,8 +33,12 @@ def __init__(self, config, chip_type, config_cmd=None, spi_mode=1): self.mcu = mcu = self.spi.get_mcu() # Reader chip configuration self.oid = oid = mcu.create_oid() - self.printer.register_event_handler("klippy:connect", self._handle_connect) - mcu.register_response(self._handle_spi_response, "thermocouple_result", oid) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) + mcu.register_response( + self._handle_spi_response, "thermocouple_result", oid + ) self._is_connected = False mcu.register_config_callback(self._build_config) @@ -155,7 +158,9 @@ def report_fault(self, msg): class MAX31856(SensorBase): def __init__(self, config): - SensorBase.__init__(self, config, "MAX31856", self.build_spi_init(config)) + SensorBase.__init__( + self, config, "MAX31856", self.build_spi_init(config) + ) def handle_fault(self, adc, fault): if fault & MAX31856_FAULT_CJRANGE: @@ -344,9 +349,13 @@ def handle_fault(self, adc, fault): "Max31865 VREF- is greater than 0.85 * VBIAS, FORCE- open" ) if fault & 0x10: - self.report_fault("Max31865 VREF- is less than 0.85 * VBIAS, FORCE- open") + self.report_fault( + "Max31865 VREF- is less than 0.85 * VBIAS, FORCE- open" + ) if fault & 0x08: - self.report_fault("Max31865 VRTD- is less than 0.85 * VBIAS, FORCE- open") + self.report_fault( + "Max31865 VRTD- is less than 0.85 * VBIAS, FORCE- open" + ) if fault & 0x04: self.report_fault("Max31865 Overvoltage or undervoltage fault") if not fault & 0xFC: @@ -377,7 +386,9 @@ def calc_adc(self, temp): def build_spi_init(self, config): value = ( - MAX31865_CONFIG_BIAS | MAX31865_CONFIG_MODEAUTO | MAX31865_CONFIG_FAULTCLEAR + MAX31865_CONFIG_BIAS + | MAX31865_CONFIG_MODEAUTO + | MAX31865_CONFIG_FAULTCLEAR ) if config.getboolean("rtd_use_50Hz_filter", False): value |= MAX31865_CONFIG_FILT50HZ diff --git a/klippy/extras/statistics.py b/klippy/extras/statistics.py index 7323cf914..db2309ef6 100644 --- a/klippy/extras/statistics.py +++ b/klippy/extras/statistics.py @@ -69,7 +69,9 @@ def __init__(self, config): def _handle_ready(self): self.stats_cb = [ - o.stats for n, o in self.printer.lookup_objects() if hasattr(o, "stats") + o.stats + for n, o in self.printer.lookup_objects() + if hasattr(o, "stats") ] if self.printer.get_start_args().get("debugoutput") is None: reactor = self.printer.get_reactor() @@ -78,7 +80,9 @@ def _handle_ready(self): def generate_stats(self, eventtime): stats = [cb(eventtime) for cb in self.stats_cb] if max([s[0] for s in stats]) and get_danger_options().log_statistics: - logging.info("Stats %.1f: %s", eventtime, " ".join([s[1] for s in stats])) + logging.info( + "Stats %.1f: %s", eventtime, " ".join([s[1] for s in stats]) + ) return eventtime + 1.0 diff --git a/klippy/extras/stepper_enable.py b/klippy/extras/stepper_enable.py index 68a84d99f..ff3e42712 100644 --- a/klippy/extras/stepper_enable.py +++ b/klippy/extras/stepper_enable.py @@ -81,7 +81,9 @@ def _build_config(self): curtime = self._mcu.get_printer().get_reactor().monotonic() printtime = self._mcu.estimated_print_time(curtime) self._last_clock = self._mcu.print_time_to_clock(printtime + 0.200) - self._duration_ticks = self._mcu.seconds_to_clock(self._max_duration - 1) + self._duration_ticks = self._mcu.seconds_to_clock( + self._max_duration - 1 + ) if self._duration_ticks >= 1 << 31: raise config_error("PWM pin max duration too large") if self._duration_ticks: @@ -110,7 +112,9 @@ def _send_update(self, clock, val): self._last_clock = clock = max(self._last_clock, clock) self._last_value = val data = (self._set_cmd_tag, self._oid, clock & 0xFFFFFFFF, val) - ret = self._stepcompress_queue_mq_msg(self._stepqueue, clock, data, len(data)) + ret = self._stepcompress_queue_mq_msg( + self._stepqueue, clock, data, len(data) + ) if ret: raise error("Internal error in stepcompress") # Notify toolhead so that it will flush this update @@ -161,7 +165,9 @@ def setup_enable_pin(printer, pin, max_enable_time=0.0): enable.is_dedicated = False return enable ppins = printer.lookup_object("pins") - pin_params = ppins.lookup_pin(pin, can_invert=True, share_type="stepper_enable") + pin_params = ppins.lookup_pin( + pin, can_invert=True, share_type="stepper_enable" + ) enable = pin_params.get("class") if enable is not None: # Shared enable line @@ -235,7 +241,10 @@ def __init__(self, config): def register_stepper(self, config, mcu_stepper): name = mcu_stepper.get_name() max_enable_time = config.getfloat( - "max_enable_time", 0.0, minval=MIN_ENABLE_TIME, maxval=MAX_ENABLE_TIME + "max_enable_time", + 0.0, + minval=MIN_ENABLE_TIME, + maxval=MAX_ENABLE_TIME, ) disable_on_error = config.getboolean("disable_on_error", False) if disable_on_error: @@ -283,7 +292,9 @@ def axes_off(self, axes=None): steppers = rail.get_steppers() rail_name = rail.mcu_stepper.get_name(True) for stepper in steppers: - self.stepper_off(stepper.get_name(), print_time, rail_name) + self.stepper_off( + stepper.get_name(), print_time, rail_name + ) except IndexError: continue else: @@ -326,7 +337,8 @@ def motor_debug_enable(self, steppers, enable, notify=True): def get_status(self, eventtime): steppers = { - name: et.is_motor_enabled() for (name, et) in self.enable_lines.items() + name: et.is_motor_enabled() + for (name, et) in self.enable_lines.items() } return {"steppers": steppers} diff --git a/klippy/extras/sx1509.py b/klippy/extras/sx1509.py index d90552e5a..4bd52fc37 100644 --- a/klippy/extras/sx1509.py +++ b/klippy/extras/sx1509.py @@ -200,7 +200,9 @@ def __init__(self, sx1509, pin_params): self._sx1509.set_bits_in_register(REG_INPUT_DISABLE, self._bitmask) self._sx1509.clear_bits_in_register(REG_PULLUP, self._bitmask) self._sx1509.clear_bits_in_register(REG_DIR, self._bitmask) - self._sx1509.set_bits_in_register(REG_ANALOG_DRIVER_ENABLE, self._bitmask) + self._sx1509.set_bits_in_register( + REG_ANALOG_DRIVER_ENABLE, self._bitmask + ) self._sx1509.clear_bits_in_register(REG_DATA, self._bitmask) def _build_config(self): @@ -209,7 +211,9 @@ def _build_config(self): if self._max_duration: raise pins.error("SX1509 pins are not suitable for heaters") # Send initial value - self._sx1509.set_register(self._i_on_reg, ~int(255 * self._start_value) & 0xFF) + self._sx1509.set_register( + self._i_on_reg, ~int(255 * self._start_value) & 0xFF + ) self._mcu.add_config_cmd( "i2c_write oid=%d data=%02x%02x" % ( diff --git a/klippy/extras/temperature_combined.py b/klippy/extras/temperature_combined.py index f068c1a0d..44e99217e 100644 --- a/klippy/extras/temperature_combined.py +++ b/klippy/extras/temperature_combined.py @@ -44,7 +44,9 @@ def __init__(self, config): target=self._temperature_update_event ) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.printer.register_event_handler("klippy:ready", self._handle_ready) def _handle_connect(self): @@ -52,9 +54,9 @@ def _handle_connect(self): sensor = self.printer.lookup_object(sensor_name) # check if sensor has get_status function and # get_status has a 'temperature' value - if hasattr(sensor, "get_status") and "temperature" in sensor.get_status( - self.reactor.monotonic() - ): + if hasattr( + sensor, "get_status" + ) and "temperature" in sensor.get_status(self.reactor.monotonic()): self.sensors.append(sensor) else: raise self.printer.config_error( @@ -147,7 +149,9 @@ def _temperature_update_event(self): # get mcu and measured / current(?) time mcu = self.printer.lookup_object("mcu") # convert to print time?! for the callback??? - self.temperature_callback(mcu.estimated_print_time(eventtime), self.last_temp) + self.temperature_callback( + mcu.estimated_print_time(eventtime), self.last_temp + ) # set next update time return REPORT_TIME diff --git a/klippy/extras/temperature_driver.py b/klippy/extras/temperature_driver.py index a45f5816d..d10fb011e 100644 --- a/klippy/extras/temperature_driver.py +++ b/klippy/extras/temperature_driver.py @@ -3,8 +3,6 @@ # Copyright (C) 2020 Kevin O'Connor # # This file may be distributed under the terms of the GNU GPLv3 license. -import threading -import time from extras.danger_options import get_danger_options @@ -32,7 +30,9 @@ def __init__(self, config): ) self.ignore = self.name in get_danger_options().temp_ignore_limits - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): self.driver = self.printer.lookup_object(self.driver_name) @@ -56,13 +56,23 @@ def _sample_driver_temperature(self): if not self.ignore: self.printer.invoke_shutdown( "[%s] temperature %0.1f outside range of %0.1f-%.01f" - % (self.full_name, self.temp, self.min_temp, self.max_temp) + % ( + self.full_name, + self.temp, + self.min_temp, + self.max_temp, + ) ) elif get_danger_options().echo_limits_to_console: gcode = self.printer.lookup_object("gcode") gcode.respond_error( "[%s] temperature %0.1f outside range of %0.1f-%.01f" - % (self.full_name, self.temp, self.min_temp, self.max_temp) + % ( + self.full_name, + self.temp, + self.min_temp, + self.max_temp, + ) ) measured_time = self.reactor.monotonic() @@ -71,7 +81,9 @@ def _sample_driver_temperature(self): self.temp = 0.0 mcu = self.driver.get_mcu() - self.temperature_callback(mcu.estimated_print_time(measured_time), self.temp) + self.temperature_callback( + mcu.estimated_print_time(measured_time), self.temp + ) return self.report_time diff --git a/klippy/extras/temperature_fan.py b/klippy/extras/temperature_fan.py index 1a5957e9b..d494eb3d7 100644 --- a/klippy/extras/temperature_fan.py +++ b/klippy/extras/temperature_fan.py @@ -30,9 +30,13 @@ def __init__(self, config, defined_fan=None, super_fan=None): self.sensor.setup_callback(self.temperature_callback) pheaters.register_sensor(config, self) self.speed_delay = self.sensor.get_report_time_delta() - self.max_speed_conf = config.getfloat("max_speed", 1.0, above=0.0, maxval=1.0) + self.max_speed_conf = config.getfloat( + "max_speed", 1.0, above=0.0, maxval=1.0 + ) self.max_speed = self.max_speed_conf - self.min_speed_conf = config.getfloat("min_speed", 0.3, minval=0.0, maxval=1.0) + self.min_speed_conf = config.getfloat( + "min_speed", 0.3, minval=0.0, maxval=1.0 + ) self.min_speed = self.min_speed_conf self.mode = "automatic" self.manual_speed = None @@ -91,9 +95,9 @@ def set_tf_speed(self, read_time, value): value = self.min_speed if self.target_temp <= 0.0: value = 0.0 - if (read_time < self.next_speed_time or not self.last_speed_value) and abs( - value - self.last_speed_value - ) < 0.05: + if ( + read_time < self.next_speed_time or not self.last_speed_value + ) and abs(value - self.last_speed_value) < 0.05: # No significant change in value - can suppress update return speed_time = read_time + self.speed_delay @@ -134,9 +138,7 @@ def is_adc_faulty(self): return True return False - cmd_SET_TEMPERATURE_FAN_help = ( - "Sets a temperature fan target and fan speed limits and enable or disable it" - ) + cmd_SET_TEMPERATURE_FAN_help = "Sets a temperature fan target and fan speed limits and enable or disable it" def cmd_SET_TEMPERATURE_FAN(self, gcmd): target = gcmd.get_float("TARGET", None) @@ -217,9 +219,15 @@ def __init__(self, temperature_fan, config, controlled_fan=None): def temperature_callback(self, read_time, temp): current_temp, target_temp = self.temperature_fan.get_temp(read_time) - if self.heating != self.reverse and temp >= target_temp + self.max_delta: + if ( + self.heating != self.reverse + and temp >= target_temp + self.max_delta + ): self.heating = self.reverse - elif self.heating == self.reverse and temp <= target_temp - self.max_delta: + elif ( + self.heating == self.reverse + and temp <= target_temp - self.max_delta + ): self.heating = not self.reverse if self.heating: self.controlled_fan.set_speed(0.0, read_time) @@ -269,7 +277,8 @@ def temperature_callback(self, read_time, temp): temp_deriv = temp_diff / time_diff else: temp_deriv = ( - self.prev_temp_deriv * (self.min_deriv_time - time_diff) + temp_diff + self.prev_temp_deriv * (self.min_deriv_time - time_diff) + + temp_diff ) / self.min_deriv_time # Calculate accumulated temperature "error" temp_err = target_temp - temp @@ -308,7 +317,9 @@ def __init__(self, temperature_fan, config, controlled_fan=None): temperature_fan if controlled_fan is None else controlled_fan ) self.curve_table = [] - points = config.getlists("points", seps=(",", "\n"), parser=float, count=2) + points = config.getlists( + "points", seps=(",", "\n"), parser=float, count=2 + ) for temp, pwm in points: current_point = [temp, pwm] if current_point is None: @@ -348,9 +359,9 @@ def __init__(self, temperature_fan, config, controlled_fan=None): def temperature_callback(self, read_time, temp): def _interpolate(below, above, temp): - return ((below[1] * (above[0] - temp)) + (above[1] * (temp - below[0]))) / ( - above[0] - below[0] - ) + return ( + (below[1] * (above[0] - temp)) + (above[1] * (temp - below[0])) + ) / (above[0] - below[0]) temp = self.smooth_temps(temp) if temp <= self.curve_table[0][0]: @@ -374,7 +385,9 @@ def _interpolate(below, above, temp): else: above = config_temp break - self.controlled_fan.set_speed(_interpolate(below, above, temp), read_time) + self.controlled_fan.set_speed( + _interpolate(below, above, temp), read_time + ) def smooth_temps(self, current_temp): if ( diff --git a/klippy/extras/temperature_host.py b/klippy/extras/temperature_host.py index e2ca947d2..bdc42ef2c 100644 --- a/klippy/extras/temperature_host.py +++ b/klippy/extras/temperature_host.py @@ -5,7 +5,6 @@ # This file may be distributed under the terms of the GNU GPLv3 license. import logging -import threading import time from extras.danger_options import get_danger_options @@ -39,9 +38,13 @@ def __init__(self, config): try: self.file_handle = open(self.path, "r") except: - raise config.error("Unable to open temperature file '%s'" % (self.path,)) + raise config.error( + "Unable to open temperature file '%s'" % (self.path,) + ) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _run_sample_timer(self): wait_time = self._sample_pi_temperature() diff --git a/klippy/extras/temperature_mcu.py b/klippy/extras/temperature_mcu.py index 8cc9a033e..f5b3169e2 100644 --- a/klippy/extras/temperature_mcu.py +++ b/klippy/extras/temperature_mcu.py @@ -43,16 +43,22 @@ def __init__(self, config): "klippy:ready", self.handle_beacon_ready ) return - self.reference_voltage = config.getfloat("reference_voltage", default=3.3) + self.reference_voltage = config.getfloat( + "reference_voltage", default=3.3 + ) self.temp1 = config.getfloat("sensor_temperature1", None) if self.temp1 is not None: self.adc1 = config.getfloat("sensor_adc1", minval=0.0, maxval=1.0) self.temp2 = config.getfloat("sensor_temperature2", None) if self.temp2 is not None: - self.adc2 = config.getfloat("sensor_adc2", minval=0.0, maxval=1.0) + self.adc2 = config.getfloat( + "sensor_adc2", minval=0.0, maxval=1.0 + ) # Setup ADC port ppins = config.get_printer().lookup_object("pins") - self.mcu_adc = ppins.setup_pin("adc", "%s:ADC_TEMPERATURE" % (mcu_name,)) + self.mcu_adc = ppins.setup_pin( + "adc", "%s:ADC_TEMPERATURE" % (mcu_name,) + ) self.mcu_adc.setup_adc_callback(self.report_time, self.adc_callback) query_adc = config.get_printer().load_object(config, "query_adc") query_adc.register_adc(config.get_name(), self.mcu_adc) @@ -69,7 +75,9 @@ def __init__(self, config): range_check_count=self._danger_check_count, ) return - self.printer.register_event_handler("klippy:mcu_identify", self._mcu_identify) + self.printer.register_event_handler( + "klippy:mcu_identify", self._mcu_identify + ) self.mcu_adc.get_mcu().register_config_callback(self._build_config) def handle_beacon_ready(self): @@ -179,19 +187,27 @@ def config_unknown(self): def config_rp2040(self): self.slope = self.reference_voltage / -0.001721 - self.base_temperature = self.calc_base(27.0, 0.706 / self.reference_voltage) + self.base_temperature = self.calc_base( + 27.0, 0.706 / self.reference_voltage + ) def config_sam3(self): self.slope = self.reference_voltage / 0.002650 - self.base_temperature = self.calc_base(27.0, 0.8 / self.reference_voltage) + self.base_temperature = self.calc_base( + 27.0, 0.8 / self.reference_voltage + ) def config_sam4(self): self.slope = self.reference_voltage / 0.004700 - self.base_temperature = self.calc_base(27.0, 1.44 / self.reference_voltage) + self.base_temperature = self.calc_base( + 27.0, 1.44 / self.reference_voltage + ) def config_same70(self): self.slope = self.reference_voltage / 0.002330 - self.base_temperature = self.calc_base(25.0, 0.72 / self.reference_voltage) + self.base_temperature = self.calc_base( + 25.0, 0.72 / self.reference_voltage + ) def config_samd21(self, addr=0x00806030): def get1v(val): @@ -205,8 +221,12 @@ def get1v(val): hot_temp = ((cal1 >> 12) & 0xFF) + ((cal1 >> 20) & 0xF) / 10.0 room_1v = get1v((cal1 >> 24) & 0xFF) hot_1v = get1v((cal2 >> 0) & 0xFF) - room_adc = ((cal2 >> 8) & 0xFFF) * room_1v / (self.reference_voltage * 4095.0) - hot_adc = ((cal2 >> 20) & 0xFFF) * hot_1v / (self.reference_voltage * 4095.0) + room_adc = ( + ((cal2 >> 8) & 0xFFF) * room_1v / (self.reference_voltage * 4095.0) + ) + hot_adc = ( + ((cal2 >> 20) & 0xFFF) * hot_1v / (self.reference_voltage * 4095.0) + ) self.slope = (hot_temp - room_temp) / (hot_adc - room_adc) self.base_temperature = self.calc_base(room_temp, room_adc) @@ -215,15 +235,23 @@ def config_samd51(self): def config_stm32f1(self): self.slope = self.reference_voltage / -0.004300 - self.base_temperature = self.calc_base(25.0, 1.43 / self.reference_voltage) + self.base_temperature = self.calc_base( + 25.0, 1.43 / self.reference_voltage + ) def config_stm32f2(self): self.slope = self.reference_voltage / 0.002500 - self.base_temperature = self.calc_base(25.0, 0.76 / self.reference_voltage) + self.base_temperature = self.calc_base( + 25.0, 0.76 / self.reference_voltage + ) def config_stm32f4(self, addr1=0x1FFF7A2C, addr2=0x1FFF7A2E): - cal_adc_30 = self.read16(addr1) * 3.3 / (self.reference_voltage * 4095.0) - cal_adc_110 = self.read16(addr2) * 3.3 / (self.reference_voltage * 4095.0) + cal_adc_30 = ( + self.read16(addr1) * 3.3 / (self.reference_voltage * 4095.0) + ) + cal_adc_110 = ( + self.read16(addr2) * 3.3 / (self.reference_voltage * 4095.0) + ) self.slope = (110.0 - 30.0) / (cal_adc_110 - cal_adc_30) self.base_temperature = self.calc_base(30.0, cal_adc_30) @@ -236,20 +264,32 @@ def config_stm32f070(self): self.base_temperature = self.calc_base(30.0, cal_adc_30) def config_stm32g0(self): - cal_adc_30 = self.read16(0x1FFF75A8) * 3.0 / (self.reference_voltage * 4095.0) - cal_adc_130 = self.read16(0x1FFF75CA) * 3.0 / (self.reference_voltage * 4095.0) + cal_adc_30 = ( + self.read16(0x1FFF75A8) * 3.0 / (self.reference_voltage * 4095.0) + ) + cal_adc_130 = ( + self.read16(0x1FFF75CA) * 3.0 / (self.reference_voltage * 4095.0) + ) self.slope = (130.0 - 30.0) / (cal_adc_130 - cal_adc_30) self.base_temperature = self.calc_base(30.0, cal_adc_30) def config_stm32h723(self): - cal_adc_30 = self.read16(0x1FF1E820) * 3.3 / (self.reference_voltage * 4095.0) - cal_adc_130 = self.read16(0x1FF1E840) * 3.3 / (self.reference_voltage * 4095.0) + cal_adc_30 = ( + self.read16(0x1FF1E820) * 3.3 / (self.reference_voltage * 4095.0) + ) + cal_adc_130 = ( + self.read16(0x1FF1E840) * 3.3 / (self.reference_voltage * 4095.0) + ) self.slope = (130.0 - 30.0) / (cal_adc_130 - cal_adc_30) self.base_temperature = self.calc_base(30.0, cal_adc_30) def config_stm32h7(self): - cal_adc_30 = self.read16(0x1FF1E820) * 3.3 / (self.reference_voltage * 65535.0) - cal_adc_110 = self.read16(0x1FF1E840) * 3.3 / (self.reference_voltage * 65535.0) + cal_adc_30 = ( + self.read16(0x1FF1E820) * 3.3 / (self.reference_voltage * 65535.0) + ) + cal_adc_110 = ( + self.read16(0x1FF1E840) * 3.3 / (self.reference_voltage * 65535.0) + ) self.slope = (110.0 - 30.0) / (cal_adc_110 - cal_adc_30) self.base_temperature = self.calc_base(30.0, cal_adc_30) diff --git a/klippy/extras/temperature_sensor.py b/klippy/extras/temperature_sensor.py index 9aa4ae54e..2b40a7dc3 100644 --- a/klippy/extras/temperature_sensor.py +++ b/klippy/extras/temperature_sensor.py @@ -17,7 +17,9 @@ def __init__(self, config): self.min_temp = config.getfloat( "min_temp", KELVIN_TO_CELSIUS, minval=KELVIN_TO_CELSIUS ) - self.max_temp = config.getfloat("max_temp", 99999999.9, above=self.min_temp) + self.max_temp = config.getfloat( + "max_temp", 99999999.9, above=self.min_temp + ) if hasattr(self.sensor, "set_report_time"): report_time = config.getfloat("report_time", None) if report_time is not None: diff --git a/klippy/extras/thermistor.py b/klippy/extras/thermistor.py index 077ff574d..99a2a23ee 100644 --- a/klippy/extras/thermistor.py +++ b/klippy/extras/thermistor.py @@ -36,7 +36,9 @@ def setup_coefficients(self, t1, r1, t2, r2, t3, r3, name=""): ) if self.c3 <= 0.0: beta = ln_r13 / inv_t13 - logging.warning("Using thermistor beta %.3f in heater %s", beta, name) + logging.warning( + "Using thermistor beta %.3f in heater %s", beta, name + ) self.setup_coefficients_beta(t1, r1, beta) return self.c2 = (inv_t12 - self.c3 * ln3_r12) / ln_r12 @@ -80,7 +82,9 @@ def PrinterThermistor(config, params): inline_resistor = config.getfloat("inline_resistor", 0.0, minval=0.0) thermistor = Thermistor(pullup, inline_resistor) if "beta" in params: - thermistor.setup_coefficients_beta(params["t1"], params["r1"], params["beta"]) + thermistor.setup_coefficients_beta( + params["t1"], params["r1"], params["beta"] + ) else: thermistor.setup_coefficients( params["t1"], diff --git a/klippy/extras/tmc.py b/klippy/extras/tmc.py index c12be0309..5c8ee2171 100644 --- a/klippy/extras/tmc.py +++ b/klippy/extras/tmc.py @@ -42,7 +42,10 @@ def get_field(self, field_name, reg_value=None, reg_name=None): reg_value = self.registers.get(reg_name, 0) mask = self.all_fields[reg_name][field_name] field_value = (reg_value & mask) >> ffs(mask) - if field_name in self.signed_fields and ((reg_value & mask) << 1) > mask: + if ( + field_name in self.signed_fields + and ((reg_value & mask) << 1) > mask + ): field_value -= 1 << field_value.bit_length() return field_value @@ -147,9 +150,13 @@ def __init__(self, config, mcu_tmc): if self.adc_temp_reg is not None: pheaters = self.printer.load_object(config, "heaters") pheaters.register_monitor(config) - self.query_while_disabled = config.getboolean("query_while_disabled", False) + self.query_while_disabled = config.getboolean( + "query_while_disabled", False + ) if self.query_while_disabled: - self.printer.register_event_handler("klippy:ready", self._handle_ready) + self.printer.register_event_handler( + "klippy:ready", self._handle_ready + ) def _handle_ready(self): self.printer.get_reactor().register_callback(self.start_checks) @@ -179,7 +186,9 @@ def _query_register(self, reg_info, try_clear=False): irun = self.fields.get_field(self.irun_field) if self.check_timer is None or irun < 4: break - if self.irun_field == "irun" and not self.fields.get_field("ihold"): + if self.irun_field == "irun" and not self.fields.get_field( + "ihold" + ): break # CS_ACTUAL field of zero - indicates a driver reset count += 1 @@ -224,7 +233,9 @@ def start_check_timer(self): ) def stop_check_timer(self, force=False): - if self.check_timer is None or (self.query_while_disabled and not force): + if self.check_timer is None or ( + self.query_while_disabled and not force + ): return self.printer.get_reactor().unregister_timer(self.check_timer) self.check_timer = None @@ -256,10 +267,14 @@ def get_temperature(self): def get_status(self, eventtime=None): if self.check_timer is None: measured_min = ( - 0.0 if self.measured_min is None else round(self.measured_min, 2) + 0.0 + if self.measured_min is None + else round(self.measured_min, 2) ) measured_max = ( - 0.0 if self.measured_max is None else round(self.measured_max, 2) + 0.0 + if self.measured_max is None + else round(self.measured_max, 2) ) return { "drv_status": None, @@ -275,13 +290,18 @@ def get_status(self, eventtime=None): self.last_drv_fields = {n: v for n, v in fields.items() if v} if temp: self.measured_min = min( - 99999999.0 if self.measured_min is None else self.measured_min, temp + 99999999.0 if self.measured_min is None else self.measured_min, + temp, ) self.measured_max = max( 0.0 if self.measured_max is None else self.measured_max, temp ) - measured_min = 0.0 if self.measured_min is None else round(self.measured_min, 2) - measured_max = 0.0 if self.measured_max is None else round(self.measured_max, 2) + measured_min = ( + 0.0 if self.measured_min is None else round(self.measured_min, 2) + ) + measured_max = ( + 0.0 if self.measured_max is None else round(self.measured_max, 2) + ) return { "drv_status": self.last_drv_fields, "temperature": temp, @@ -318,7 +338,9 @@ def __init__(self, config, mcu_tmc, current_helper): self.printer.register_event_handler( "klippy:mcu_identify", self._handle_mcu_identify ) - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) # Set microstep config options TMCMicrostepHelper(config, mcu_tmc) # Register commands @@ -371,8 +393,12 @@ def cmd_SET_TMC_FIELD(self, gcmd): raise gcmd.error("Specify either VALUE or VELOCITY") if velocity is not None: if self.mcu_tmc.get_tmc_frequency() is None: - raise gcmd.error("VELOCITY parameter not supported by this driver") - value = TMCtstepHelper(self.mcu_tmc, velocity, pstepper=self.stepper) + raise gcmd.error( + "VELOCITY parameter not supported by this driver" + ) + value = TMCtstepHelper( + self.mcu_tmc, velocity, pstepper=self.stepper + ) reg_val = self.fields.set_field(field_name, value) print_time = self.printer.lookup_object("toolhead").get_last_move_time() self.mcu_tmc.set_register(reg_name, reg_val, print_time) @@ -388,9 +414,15 @@ def cmd_SET_TMC_CURRENT(self, gcmd): max_cur, prev_home_cur, ) = ch.get_current() - run_current = gcmd.get_float("CURRENT", None, minval=0.0, maxval=max_cur) - hold_current = gcmd.get_float("HOLDCURRENT", None, above=0.0, maxval=max_cur) - home_current = gcmd.get_float("HOMECURRENT", None, above=0.0, maxval=max_cur) + run_current = gcmd.get_float( + "CURRENT", None, minval=0.0, maxval=max_cur + ) + hold_current = gcmd.get_float( + "HOLDCURRENT", None, above=0.0, maxval=max_cur + ) + home_current = gcmd.get_float( + "HOMECURRENT", None, above=0.0, maxval=max_cur + ) verbose = gcmd.get("VERBOSE", "low") if ( run_current is not None @@ -541,7 +573,9 @@ def _handle_connect(self): if not enable_line.has_dedicated_enable(): self.toff = self.fields.get_field("toff") self.fields.set_field("toff", 0) - logging.info("Enabling TMC virtual enable for '%s'", self.stepper_name) + logging.info( + "Enabling TMC virtual enable for '%s'", self.stepper_name + ) # Send init try: if self.mcu_tmc.mcu.non_critical_disconnected: @@ -877,10 +911,14 @@ def set_current_for_homing( self, print_time, pre_homing, get_dwell_time=False ) -> float: if pre_homing and self.needs_home_current_change(): - self.set_current(self.req_home_current, self.req_hold_current, print_time) + self.set_current( + self.req_home_current, self.req_hold_current, print_time + ) return self.current_change_dwell_time elif not pre_homing and self.needs_run_current_change(): - self.set_current(self.req_run_current, self.req_hold_current, print_time) + self.set_current( + self.req_run_current, self.req_hold_current, print_time + ) return self.current_change_dwell_time if get_dwell_time: return self.current_change_dwell_time diff --git a/klippy/extras/tmc2130.py b/klippy/extras/tmc2130.py index 4c54cda90..8c6b3ba9e 100644 --- a/klippy/extras/tmc2130.py +++ b/klippy/extras/tmc2130.py @@ -228,7 +228,10 @@ def _calc_current_bits(self, current, vsense): vref = 0.32 if vsense: vref = 0.18 - cs = int(32.0 * sense_resistor * current * math.sqrt(2.0) / vref + 0.5) - 1 + cs = ( + int(32.0 * sense_resistor * current * math.sqrt(2.0) / vref + 0.5) + - 1 + ) return max(0, min(31, cs)) def _calc_current_from_bits(self, cs, vsense): @@ -310,7 +313,10 @@ def reg_read(self, reg, chain_pos): return 0 params = self.spi.spi_transfer(cmd) pr = bytearray(params["response"]) - pr = pr[(self.chain_len - chain_pos) * 5 : (self.chain_len - chain_pos + 1) * 5] + pr = pr[ + (self.chain_len - chain_pos) * 5 : (self.chain_len - chain_pos + 1) + * 5 + ] return (pr[1] << 24) | (pr[2] << 16) | (pr[3] << 8) | pr[4] def reg_write(self, reg, val, chain_pos, print_time=None): @@ -333,7 +339,10 @@ def reg_write(self, reg, val, chain_pos, print_time=None): write_cmd, dummy_read, minclock=minclock ) pr = bytearray(params["response"]) - pr = pr[(self.chain_len - chain_pos) * 5 : (self.chain_len - chain_pos + 1) * 5] + pr = pr[ + (self.chain_len - chain_pos) * 5 : (self.chain_len - chain_pos + 1) + * 5 + ] return (pr[1] << 24) | (pr[2] << 16) | (pr[3] << 8) | pr[4] def get_mcu(self): @@ -349,7 +358,9 @@ def lookup_tmc_spi_chain(config): # Shared SPI bus - lookup existing MCU_TMC_SPI_chain ppins = config.get_printer().lookup_object("pins") - cs_pin_params = ppins.lookup_pin(config.get("cs_pin"), share_type="tmc_spi_cs") + cs_pin_params = ppins.lookup_pin( + config.get("cs_pin"), share_type="tmc_spi_cs" + ) tmc_spi = cs_pin_params.get("class") if tmc_spi is None: tmc_spi = cs_pin_params["class"] = MCU_TMC_SPI_chain(config, chain_len) @@ -410,7 +421,9 @@ class TMC2130: def __init__(self, config): # Setup mcu communication self.fields = tmc.FieldHelper(Fields, SignedFields, FieldFormatters) - self.mcu_tmc = MCU_TMC_SPI(config, Registers, self.fields, TMC_FREQUENCY) + self.mcu_tmc = MCU_TMC_SPI( + config, Registers, self.fields, TMC_FREQUENCY + ) # Allow virtual pins to be created tmc.TMCVirtualPinHelper(config, self.mcu_tmc) # Register commands diff --git a/klippy/extras/tmc2208.py b/klippy/extras/tmc2208.py index 4a13c0ebd..e90e4b5fa 100644 --- a/klippy/extras/tmc2208.py +++ b/klippy/extras/tmc2208.py @@ -189,7 +189,9 @@ def __init__(self, config): ) self.fields.set_field("pdn_disable", True) # Register commands - current_helper = tmc2130.TMC2130CurrentHelper(config, self.mcu_tmc, "tmc2208") + current_helper = tmc2130.TMC2130CurrentHelper( + config, self.mcu_tmc, "tmc2208" + ) cmdhelper = tmc.TMCCommandHelper(config, self.mcu_tmc, current_helper) cmdhelper.setup_register_dump(ReadRegisters, self.read_translate) self.get_phase_offset = cmdhelper.get_phase_offset diff --git a/klippy/extras/tmc2209.py b/klippy/extras/tmc2209.py index 7470c83bc..168238686 100644 --- a/klippy/extras/tmc2209.py +++ b/klippy/extras/tmc2209.py @@ -48,7 +48,9 @@ class TMC2209: def __init__(self, config): # Setup mcu communication - self.fields = tmc.FieldHelper(Fields, tmc2208.SignedFields, FieldFormatters) + self.fields = tmc.FieldHelper( + Fields, tmc2208.SignedFields, FieldFormatters + ) self.mcu_tmc = tmc_uart.MCU_TMC_uart( config, Registers, self.fields, 3, TMC_FREQUENCY ) @@ -58,7 +60,9 @@ def __init__(self, config): # Allow virtual pins to be created tmc.TMCVirtualPinHelper(config, self.mcu_tmc) # Register commands - current_helper = tmc2130.TMC2130CurrentHelper(config, self.mcu_tmc, "tmc2209") + current_helper = tmc2130.TMC2130CurrentHelper( + config, self.mcu_tmc, "tmc2209" + ) cmdhelper = tmc.TMCCommandHelper(config, self.mcu_tmc, current_helper) cmdhelper.setup_register_dump(ReadRegisters) self.get_phase_offset = cmdhelper.get_phase_offset diff --git a/klippy/extras/tmc2240.py b/klippy/extras/tmc2240.py index 1316001f3..88dafed13 100644 --- a/klippy/extras/tmc2240.py +++ b/klippy/extras/tmc2240.py @@ -272,7 +272,9 @@ def __init__(self, config, mcu_tmc, type="tmc2240"): self.name = config.get_name().split()[-1] self.mcu_tmc = mcu_tmc self.fields = mcu_tmc.get_fields() - self.Rref = config.getfloat("rref", None, minval=12000.0, maxval=60000.0) + self.Rref = config.getfloat( + "rref", None, minval=12000.0, maxval=60000.0 + ) if self.Rref is None: pconfig.warn( "config", @@ -339,7 +341,9 @@ def _calc_current_bits(self, current, globalscaler): ifs_rms = self._get_ifs_rms() if not globalscaler: globalscaler = 256 - cs = int((current * 256.0 * 32.0) / (globalscaler * ifs_rms) - 1.0 + 0.5) + cs = int( + (current * 256.0 * 32.0) / (globalscaler * ifs_rms) - 1.0 + 0.5 + ) return max(0, min(31, cs)) def _calc_current(self, run_current, hold_current): diff --git a/klippy/extras/tmc2660.py b/klippy/extras/tmc2660.py index 5d8ef3a2e..201692934 100644 --- a/klippy/extras/tmc2660.py +++ b/klippy/extras/tmc2660.py @@ -179,7 +179,9 @@ def _handle_printing(self, print_time): ) def _handle_ready(self, print_time): - current = self.req_run_current * float(self.idle_current_percentage) / 100.0 + current = ( + self.req_run_current * float(self.idle_current_percentage) / 100.0 + ) self.printer.get_reactor().register_callback( (lambda ev: self._update_current(current, print_time)) ) @@ -289,7 +291,9 @@ def __init__(self, config): set_config_field(config, "hstrt", 3) set_config_field(config, "toff", 4) if not self.fields.get_field("chm"): - if (self.fields.get_field("hstrt") + self.fields.get_field("hend")) > 15: + if ( + self.fields.get_field("hstrt") + self.fields.get_field("hend") + ) > 15: raise config.error("driver_HEND + driver_HSTRT must be <= 15") # SMARTEN set_config_field(config, "seimin", 0) diff --git a/klippy/extras/tmc5160.py b/klippy/extras/tmc5160.py index 6c20b1592..825bbdd18 100644 --- a/klippy/extras/tmc5160.py +++ b/klippy/extras/tmc5160.py @@ -279,7 +279,8 @@ def __init__(self, config, mcu_tmc, type="tmc5160"): def _calc_globalscaler(self, current): globalscaler = int( - (current * 256.0 * math.sqrt(2.0) * self.sense_resistor / VREF) + 0.5 + (current * 256.0 * math.sqrt(2.0) * self.sense_resistor / VREF) + + 0.5 ) globalscaler = max(32, globalscaler) if globalscaler >= 256: diff --git a/klippy/extras/tmc_uart.py b/klippy/extras/tmc_uart.py index de4ff3d86..ee04a4b1b 100644 --- a/klippy/extras/tmc_uart.py +++ b/klippy/extras/tmc_uart.py @@ -99,7 +99,9 @@ def __init__(self, rx_pin_params, tx_pin_params, select_pins_desc): self.cmd_queue = self.mcu.alloc_command_queue() self.analog_mux = None if select_pins_desc is not None: - self.analog_mux = MCU_analog_mux(self.mcu, self.cmd_queue, select_pins_desc) + self.analog_mux = MCU_analog_mux( + self.mcu, self.cmd_queue, select_pins_desc + ) self.instances = {} self.tmcuart_send_cmd = None self.mcu.register_config_callback(self.build_config) @@ -122,7 +124,9 @@ def build_config(self): is_async=True, ) - def register_instance(self, rx_pin_params, tx_pin_params, select_pins_desc, addr): + def register_instance( + self, rx_pin_params, tx_pin_params, select_pins_desc, addr + ): if ( rx_pin_params["pin"] != self.rx_pin or tx_pin_params["pin"] != self.tx_pin @@ -248,7 +252,9 @@ def lookup_tmc_uart_bitbang(config, max_addr): addr = config.getint("uart_address", 0, minval=0, maxval=max_addr) mcu_uart = rx_pin_params.get("class") if mcu_uart is None: - mcu_uart = MCU_TMC_uart_bitbang(rx_pin_params, tx_pin_params, select_pins_desc) + mcu_uart = MCU_TMC_uart_bitbang( + rx_pin_params, tx_pin_params, select_pins_desc + ) rx_pin_params["class"] = mcu_uart instance_id = mcu_uart.register_instance( rx_pin_params, tx_pin_params, select_pins_desc, addr diff --git a/klippy/extras/trad_rack.py b/klippy/extras/trad_rack.py index 5bd0012b4..56404e8a6 100644 --- a/klippy/extras/trad_rack.py +++ b/klippy/extras/trad_rack.py @@ -31,7 +31,9 @@ class TradRack: def __init__(self, config): self.printer = config.get_printer() self.reactor = self.printer.get_reactor() - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.printer.register_event_handler("klippy:ready", self._handle_ready) # read spool and buffer pull speeds @@ -74,12 +76,16 @@ def __init__(self, config): query_endstops.register_endstop(mcu_endstop, name) # add filament driver stepper to endstop - for stepper in self.tr_kinematics.get_fil_driver_rail().get_steppers(): + for ( + stepper + ) in self.tr_kinematics.get_fil_driver_rail().get_steppers(): mcu_endstop.add_stepper(stepper) # set up selector sensor as a runout sensor pin = config.getsection(FIL_DRIVER_STEPPER_NAME).get("endstop_pin") - self.selector_sensor = TradRackRunoutSensor(config, self.handle_runout, pin) + self.selector_sensor = TradRackRunoutSensor( + config, self.handle_runout, pin + ) # read lane count and get lane positions self.lane_count = config.getint("lane_count", minval=2) @@ -89,7 +95,9 @@ def __init__(self, config): self.lane_positions = self.lane_position_manager.get_lane_positions() # create bowden length filters - bowden_samples = config.getint("bowden_length_samples", default=10, minval=1) + bowden_samples = config.getint( + "bowden_length_samples", default=10, minval=1 + ) self.bowden_load_length_filter = MovingAverageFilter(bowden_samples) self.bowden_unload_length_filter = MovingAverageFilter(bowden_samples) @@ -112,12 +120,18 @@ def __init__(self, config): self.selector_unload_length_extra = config.getfloat( "selector_unload_length_extra", default=0.0, minval=0.0 ) - self.eject_length = config.getfloat("eject_length", default=30.0, above=0.0) + self.eject_length = config.getfloat( + "eject_length", default=30.0, above=0.0 + ) self.config_bowden_length = self.bowden_load_length = ( self.bowden_unload_length ) = config.getfloat("bowden_length", above=0.0) - self.extruder_load_length = config.getfloat("extruder_load_length", above=0.0) - self.hotend_load_length = config.getfloat("hotend_load_length", above=0.0) + self.extruder_load_length = config.getfloat( + "extruder_load_length", above=0.0 + ) + self.hotend_load_length = config.getfloat( + "hotend_load_length", above=0.0 + ) if self.toolhead_fil_endstops: self.toolhead_unload_length = config.getfloat( "toolhead_unload_length", minval=0.0 @@ -134,7 +148,9 @@ def __init__(self, config): self.selector_unload_speed = config.getfloat( "selector_unload_speed", default=60.0, above=0.0 ) - self.eject_speed = config.getfloat("eject_speed", default=80.0, above=0.0) + self.eject_speed = config.getfloat( + "eject_speed", default=80.0, above=0.0 + ) self.toolhead_sense_speed = config.getfloat( "toolhead_sense_speed", default=self.selector_sense_speed, above=0.0 ) @@ -169,7 +185,8 @@ def __init__(self, config): config.getint( "load_lane_time", default=15, - minval=self.selector_unload_length / self.selector_sense_speed, + minval=self.selector_unload_length + / self.selector_sense_speed, ) * self.selector_sense_speed ), @@ -190,12 +207,15 @@ def __init__(self, config): ), "unload toolhead": config.getfloat( "unload_toolhead_homing_dist", - default=(self.extruder_load_length + self.hotend_load_length) * 2, + default=(self.extruder_load_length + self.hotend_load_length) + * 2, above=0.0, ), } self.sync_to_extruder = config.getboolean("sync_to_extruder", False) - self.user_wait_time = config.getint("user_wait_time", default=15, minval=-1) + self.user_wait_time = config.getint( + "user_wait_time", default=15, minval=-1 + ) register_toolchange_commands = config.getboolean( "register_toolchange_commands", default=True ) @@ -252,10 +272,18 @@ def __init__(self, config): self.post_unload_macro = gcode_macro.load_template( config, "post_unload_gcode", "" ) - self.pre_load_macro = gcode_macro.load_template(config, "pre_load_gcode", "") - self.post_load_macro = gcode_macro.load_template(config, "post_load_gcode", "") - self.pause_macro = gcode_macro.load_template(config, "pause_gcode", "PAUSE") - self.resume_macro = gcode_macro.load_template(config, "resume_gcode", "RESUME") + self.pre_load_macro = gcode_macro.load_template( + config, "pre_load_gcode", "" + ) + self.post_load_macro = gcode_macro.load_template( + config, "post_load_gcode", "" + ) + self.pause_macro = gcode_macro.load_template( + config, "pause_gcode", "PAUSE" + ) + self.resume_macro = gcode_macro.load_template( + config, "resume_gcode", "RESUME" + ) # register gcode commands self.gcode = self.printer.lookup_object("gcode") @@ -390,26 +418,36 @@ def _handle_ready(self): def _load_saved_state(self): # load bowden lengths if the user has not changed the config value - prev_config_bowden_length = self.variables.get(self.VARS_CONFIG_BOWDEN_LENGTH) + prev_config_bowden_length = self.variables.get( + self.VARS_CONFIG_BOWDEN_LENGTH + ) if ( prev_config_bowden_length and self.config_bowden_length == prev_config_bowden_length ): # update load length - load_length_stats = self.variables.get(self.VARS_CALIB_BOWDEN_LOAD_LENGTH) + load_length_stats = self.variables.get( + self.VARS_CALIB_BOWDEN_LOAD_LENGTH + ) if load_length_stats: self.bowden_load_length = load_length_stats["new_set_length"] for _ in range(load_length_stats["sample_count"]): - self.bowden_load_length_filter.update(self.bowden_load_length) + self.bowden_load_length_filter.update( + self.bowden_load_length + ) # update unload length unload_length_stats = self.variables.get( self.VARS_CALIB_BOWDEN_UNLOAD_LENGTH ) if unload_length_stats: - self.bowden_unload_length = unload_length_stats["new_set_length"] + self.bowden_unload_length = unload_length_stats[ + "new_set_length" + ] for _ in range(unload_length_stats["sample_count"]): - self.bowden_unload_length_filter.update(self.bowden_unload_length) + self.bowden_unload_length_filter.update( + self.bowden_unload_length + ) else: # save bowden_length config value self.gcode.run_script_from_command( @@ -418,7 +456,9 @@ def _load_saved_state(self): ) # load last heater target - self.last_heater_target = self.variables.get(self.VARS_HEATER_TARGET, 0.0) + self.last_heater_target = self.variables.get( + self.VARS_HEATER_TARGET, 0.0 + ) def handle_runout(self, eventtime): # send pause command @@ -452,7 +492,9 @@ def handle_runout(self, eventtime): def cmd_TR_HOME(self, gcmd): # check for filament in the selector if self._query_selector_sensor(): - raise self.printer.command_error("Cannot home with filament in selector") + raise self.printer.command_error( + "Cannot home with filament in selector" + ) # reset current lane self.curr_lane = None @@ -515,7 +557,9 @@ def cmd_TR_LOAD_TOOLHEAD(self, gcmd): # set up resume callback and pause the print # (and wait for user to resume) resume_kwargs = { - "condition": (lambda t=tool: self.default_lanes[t] is not None), + "condition": ( + lambda t=tool: self.default_lanes[t] is not None + ), "action": lambda g=gcmd: self.cmd_TR_LOAD_TOOLHEAD(g), "fail_msg": ( "Cannot resume. Please use TR_ASSIGN_LANE to assign a" @@ -706,7 +750,8 @@ def cmd_TR_RESET_ACTIVE_LANE(self, gcmd): self.printer.send_event("trad_rack:reset_active_lane") cmd_TR_RESUME_help = ( - "Completes necessary actions for Trad Rack to recover and resumes the" " print" + "Completes necessary actions for Trad Rack to recover and resumes the" + " print" ) def cmd_TR_RESUME(self, gcmd): @@ -824,7 +869,8 @@ def cmd_TR_LOCATE_SELECTOR(self, gcmd): ) cmd_TR_CALIBRATE_SELECTOR_help = ( - "Calibrate lane_spacing and the selector's min, endstop, and max" " positions" + "Calibrate lane_spacing and the selector's min, endstop, and max" + " positions" ) def cmd_TR_CALIBRATE_SELECTOR(self, gcmd): @@ -856,7 +902,9 @@ def cmd_TR_SET_HOTEND_LOAD_LENGTH(self, gcmd): if value is None: adjust = gcmd.get_float("ADJUST", None) if adjust is None: - raise self.printer.command_error("VALUE or ADJUST must be specified") + raise self.printer.command_error( + "VALUE or ADJUST must be specified" + ) value = max(0.0, self.hotend_load_length + adjust) self.hotend_load_length = value gcmd.respond_info("hotend_load_length: %f" % (self.hotend_load_length)) @@ -889,7 +937,9 @@ def cmd_TR_DISCARD_BOWDEN_LENGTHS(self, gcmd): % (self.VARS_CALIB_BOWDEN_UNLOAD_LENGTH, {}) ) - cmd_TR_SYNC_TO_EXTRUDER_help = "Sync Trad Rack's filament driver to the extruder" + cmd_TR_SYNC_TO_EXTRUDER_help = ( + "Sync Trad Rack's filament driver to the extruder" + ) def cmd_TR_SYNC_TO_EXTRUDER(self, gcmd): self.toolhead.wait_moves() @@ -1022,9 +1072,9 @@ def _raise_servo( def _is_selector_homed(self): return ( "x" - in self.tr_toolhead.get_kinematics().get_status(self.reactor.monotonic())[ - "homed_axes" - ] + in self.tr_toolhead.get_kinematics().get_status( + self.reactor.monotonic() + )["homed_axes"] ) def _query_selector_sensor(self): @@ -1132,7 +1182,9 @@ def _load_lane(self, lane, reset_speed=False, user_load=False): self._reset_fil_driver() self.tr_toolhead.get_last_move_time() pos = self.tr_toolhead.get_position() - pos[1] -= self.selector_unload_length + self.selector_unload_length_extra + pos[1] -= ( + self.selector_unload_length + self.selector_unload_length_extra + ) self.tr_toolhead.move(pos, self.selector_unload_speed) # undo extra unload length offset @@ -1255,23 +1307,32 @@ def _load_toolhead( "Failed to unload. Please either pull the filament in" " lane {lane} out of the toolhead and selector or retry" " with TR_UNLOAD_TOOLHEAD, then use TR_RESUME to reload" - " lane {lane} and continue.".format(lane=str(self.curr_lane)) + " lane {lane} and continue.".format( + lane=str(self.curr_lane) + ) ) self.lanes_unloaded[self.curr_lane] = False self.retry_lane = self.curr_lane - logging.warning("trad_rack: Failed to unload toolhead", exc_info=True) + logging.warning( + "trad_rack: Failed to unload toolhead", exc_info=True + ) raise TradRackLoadError( - "Failed to load toolhead. Could not unload toolhead before" " load" + "Failed to load toolhead. Could not unload toolhead before" + " load" ) # home if selector position is uncertain if self.selector_pos_uncertain: try: self.cmd_TR_HOME( - self.gcode.create_gcode_command("TR_HOME", "TR_HOME", {}) + self.gcode.create_gcode_command( + "TR_HOME", "TR_HOME", {} + ) ) except: - logging.warning("trad_rack: Failed to home selector", exc_info=True) + logging.warning( + "trad_rack: Failed to home selector", exc_info=True + ) raise SelectorNotHomedError("Failed to home selector") # notify toolhead load started @@ -1305,7 +1366,8 @@ def _load_toolhead( ) logging.warning("trad_rack: Failed to load selector", exc_info=True) raise TradRackLoadError( - "Failed to load toolhead. Could not load selector from lane %d" % lane + "Failed to load toolhead. Could not load selector from lane %d" + % lane ) # update lane and next_lane in case the selector was loaded from a lane @@ -1376,10 +1438,15 @@ def _load_toolhead( # update bowden_load_length length = ( - trigpos[1] - move_start + base_length - self.target_toolhead_homing_dist + trigpos[1] + - move_start + + base_length + - self.target_toolhead_homing_dist ) old_set_length = self.bowden_load_length - self.bowden_load_length = self.bowden_load_length_filter.update(length) + self.bowden_load_length = self.bowden_load_length_filter.update( + length + ) samples = self.bowden_load_length_filter.get_entry_count() if self.log_bowden_lengths: self._write_bowden_length_data( @@ -1393,7 +1460,9 @@ def _load_toolhead( if not (self.bowden_load_calibrated or reached_sensor_early): self.bowden_load_calibrated = True self.gcode.respond_info( - "Calibrated bowden_load_length: {}".format(self.bowden_load_length) + "Calibrated bowden_load_length: {}".format( + self.bowden_load_length + ) ) # finish loading filament into extruder @@ -1409,16 +1478,22 @@ def _load_toolhead( # check whether servo move might overlap extruder loading move if hotend_load_length: if hasattr(toolhead, "LookAheadQueue"): - hotend_load_time = self.tr_toolhead.lookahead.get_last().min_move_t + hotend_load_time = ( + self.tr_toolhead.lookahead.get_last().min_move_t + ) else: - hotend_load_time = self.tr_toolhead.move_queue.get_last().min_move_t + hotend_load_time = ( + self.tr_toolhead.move_queue.get_last().min_move_t + ) else: hotend_load_time = 0.0 servo_delay = max(0.0, self.servo_wait - hotend_load_time) # flush lookahead and raise servo before move ends print_time = ( - self.tr_toolhead.get_last_move_time() - self.servo_wait + servo_delay + self.tr_toolhead.get_last_move_time() + - self.servo_wait + + servo_delay ) if not self.sync_to_extruder: self._raise_servo( @@ -1453,7 +1528,9 @@ def _load_toolhead( # restore gcode state self.gcode.run_script_from_command( - "RESTORE_GCODE_STATE NAME={} MOVE=1".format(self.GCODE_STATE_TOOLCHANGE) + "RESTORE_GCODE_STATE NAME={} MOVE=1".format( + self.GCODE_STATE_TOOLCHANGE + ) ) # reset next lane and tool @@ -1470,7 +1547,9 @@ def _load_selector(self, lane, tool=None, user_load=False): if tool is None: raise else: - lane = self._find_replacement_lane(lane, check_runout_lane=False) + lane = self._find_replacement_lane( + lane, check_runout_lane=False + ) if lane is None: raise self.printer.command_error( "Failed to load filament into selector from any of the" @@ -1488,13 +1567,17 @@ def _do_load_selector(self, lane, user_load=False): # prompt user to insert filament if user_load: - self.gcode.respond_info("Please insert filament in lane %d" % (lane)) + self.gcode.respond_info( + "Please insert filament in lane %d" % (lane) + ) # turn the drive gear until filament is detected self._reset_fil_driver() self.tr_toolhead.get_last_move_time() pos = self.tr_toolhead.get_position() - hmove = HomingMove(self.printer, self.fil_driver_endstops, self.tr_toolhead) + hmove = HomingMove( + self.printer, self.fil_driver_endstops, self.tr_toolhead + ) if user_load: length_key = "user load lane" else: @@ -1504,18 +1587,26 @@ def _do_load_selector(self, lane, user_load=False): hmove.homing_move(pos, self.selector_sense_speed) except self.printer.command_error: self._raise_servo() - logging.warning("trad_rack: Selector homing move failed", exc_info=True) + logging.warning( + "trad_rack: Selector homing move failed", exc_info=True + ) raise self.printer.command_error( "Failed to load filament into selector. No trigger on selector" " sensor after full movement" ) - def _unload_selector(self, base_length=None, mark_calibrated=False, eject=False): + def _unload_selector( + self, base_length=None, mark_calibrated=False, eject=False + ): # check for filament in selector if not self._query_selector_sensor(): - self.gcode.respond_info("No filament detected. Attempting to load selector") + self.gcode.respond_info( + "No filament detected. Attempting to load selector" + ) self._load_selector(self.curr_lane) - self.gcode.respond_info("Loaded selector. Retracting filament into module") + self.gcode.respond_info( + "Loaded selector. Retracting filament into module" + ) else: # lower servo and turn the drive gear until filament # is no longer detected @@ -1524,7 +1615,9 @@ def _unload_selector(self, base_length=None, mark_calibrated=False, eject=False) self.tr_toolhead.get_last_move_time() pos = self.tr_toolhead.get_position() move_start = pos[1] - hmove = HomingMove(self.printer, self.fil_driver_endstops, self.tr_toolhead) + hmove = HomingMove( + self.printer, self.fil_driver_endstops, self.tr_toolhead + ) pos[1] -= self.fil_homing_lengths["bowden unload"] try: trigpos = hmove.homing_move( @@ -1535,7 +1628,9 @@ def _unload_selector(self, base_length=None, mark_calibrated=False, eject=False) ) except self.printer.command_error: self._raise_servo() - logging.warning("trad_rack: Selector homing move failed", exc_info=True) + logging.warning( + "trad_rack: Selector homing move failed", exc_info=True + ) raise self.printer.command_error( "Failed to unload filament from selector. Selector sensor" " still triggered after full movement" @@ -1550,8 +1645,8 @@ def _unload_selector(self, base_length=None, mark_calibrated=False, eject=False) - self.target_selector_homing_dist ) old_set_length = self.bowden_unload_length - self.bowden_unload_length = self.bowden_unload_length_filter.update( - length + self.bowden_unload_length = ( + self.bowden_unload_length_filter.update(length) ) samples = self.bowden_unload_length_filter.get_entry_count() if self.log_bowden_lengths: @@ -1562,7 +1657,9 @@ def _unload_selector(self, base_length=None, mark_calibrated=False, eject=False) self.bowden_unload_length, samples, ) - self._save_bowden_length("unload", self.bowden_unload_length, samples) + self._save_bowden_length( + "unload", self.bowden_unload_length, samples + ) if mark_calibrated: self.bowden_unload_calibrated = True self.gcode.respond_info( @@ -1578,7 +1675,9 @@ def _unload_selector(self, base_length=None, mark_calibrated=False, eject=False) pos[1] -= self.selector_unload_length + self.eject_length speed = self.eject_speed else: - pos[1] -= self.selector_unload_length + self.selector_unload_length_extra + pos[1] -= ( + self.selector_unload_length + self.selector_unload_length_extra + ) speed = self.selector_unload_speed self.tr_toolhead.move(pos, speed) @@ -1670,7 +1769,9 @@ def _unload_toolhead( self.printer, self.toolhead_fil_endstops, self.tr_toolhead ) try: - hmove.homing_move(pos, self.toolhead_sense_speed, triggered=False) + hmove.homing_move( + pos, self.toolhead_sense_speed, triggered=False + ) except self.printer.command_error: self._raise_servo() self.extruder_sync_manager.unsync() @@ -1698,7 +1799,9 @@ def _unload_toolhead( pos = self.tr_toolhead.get_position() move_start = pos[1] pos[1] -= self.bowden_unload_length - hmove = HomingMove(self.printer, self.fil_driver_endstops, self.tr_toolhead) + hmove = HomingMove( + self.printer, self.fil_driver_endstops, self.tr_toolhead + ) reached_sensor_early = True try: # move and check for early sensor trigger @@ -1713,7 +1816,9 @@ def _unload_toolhead( self.tr_toolhead.move(pos, self.buffer_pull_speed) # unload selector - mark_calibrated = not (self.bowden_unload_calibrated or reached_sensor_early) + mark_calibrated = not ( + self.bowden_unload_calibrated or reached_sensor_early + ) self._unload_selector(move_start - pos[1], mark_calibrated, eject) # note that the current lane's buffer has been filled @@ -1743,7 +1848,9 @@ def _send_pause(self): # with the state from right before the toolchange was initiated if not self._is_next_toolchange_done(): saved_states = self.printer.lookup_object("gcode_move").saved_states - saved_states["PAUSE_STATE"] = saved_states[self.GCODE_STATE_TOOLCHANGE] + saved_states["PAUSE_STATE"] = saved_states[ + self.GCODE_STATE_TOOLCHANGE + ] def _send_resume(self, resume_msg=None): pause_resume = self.printer.lookup_object("pause_resume") @@ -1757,7 +1864,8 @@ def _set_active_lane(self, lane): self.active_lane = lane if self.save_active_lane: self.gcode.run_script_from_command( - 'SAVE_VARIABLE VARIABLE=%s VALUE="%s"' % (self.VARS_ACTIVE_LANE, lane) + 'SAVE_VARIABLE VARIABLE=%s VALUE="%s"' + % (self.VARS_ACTIVE_LANE, lane) ) def _reset_tool_map(self): @@ -1770,7 +1878,9 @@ def _find_replacement_lane(self, runout_lane, check_runout_lane=True): # home if selector position is uncertain if self.selector_pos_uncertain: - self.cmd_TR_HOME(self.gcode.create_gcode_command("TR_HOME", "TR_HOME", {})) + self.cmd_TR_HOME( + self.gcode.create_gcode_command("TR_HOME", "TR_HOME", {}) + ) # 1st pass - check lanes not marked as dead lane = (runout_lane + 1) % self.lane_count @@ -1855,7 +1965,9 @@ def _runout_replace_filament(self): " toolhead and selector, then use TR_RESUME to " " continue.".format(self.runout_lane) ) - logging.warning("trad_rack: Failed to unload toolhead", exc_info=True) + logging.warning( + "trad_rack: Failed to unload toolhead", exc_info=True + ) return False self.runout_steps_done = 1 @@ -1941,7 +2053,9 @@ def _calibrate_selector(self): # measure position of lane 0 relative to endstop pos_endstop = ( - self.tr_kinematics.get_selector_rail().get_homing_info().position_endstop + self.tr_kinematics.get_selector_rail() + .get_homing_info() + .position_endstop ) max_travel = self.lane_positions[0] - pos_endstop + extra_travel_base endstop_to_lane0 = self._measure_selector_to_endstop(max_travel) @@ -1969,8 +2083,12 @@ def _calibrate_selector(self): # round new config values pos_endstop = round(pos_endstop, 3) - pos_min = math.floor(min(pos_endstop, self.lane_positions[0]) * 1000) / 1000 - pos_max = math.ceil(self.lane_positions[self.lane_count - 1] * 1000) / 1000 + pos_min = ( + math.floor(min(pos_endstop, self.lane_positions[0]) * 1000) / 1000 + ) + pos_max = ( + math.ceil(self.lane_positions[self.lane_count - 1] * 1000) / 1000 + ) # set new selector values rail = self.tr_kinematics.get_selector_rail() @@ -2002,7 +2120,9 @@ def _calibrate_selector(self): def _prompt_selector_calibration(self, lane): # go to lane if not self._is_selector_homed(): - self.cmd_TR_HOME(self.gcode.create_gcode_command("TR_HOME", "TR_HOME", {})) + self.cmd_TR_HOME( + self.gcode.create_gcode_command("TR_HOME", "TR_HOME", {}) + ) self._go_to_lane(lane) # disable selector motor @@ -2066,7 +2186,9 @@ def _measure_selector_to_endstop(self, max_travel): speed = hi.speed # retract first if endstop is already triggered - self.selector_endstops = self.tr_kinematics.get_selector_rail().get_endstops() + self.selector_endstops = ( + self.tr_kinematics.get_selector_rail().get_endstops() + ) move_time = self.tr_toolhead.get_last_move_time() if not not self.selector_endstops[0][0].query_endstop(move_time): curr_pos = self.tr_toolhead.get_position() @@ -2139,7 +2261,9 @@ def _set_up_resume_and_pause(self, resume_type, resume_kwargs): self.resume_stack.clear() # add resume callback and arguments - self.resume_stack.append((self.resume_callbacks[resume_type], resume_kwargs)) + self.resume_stack.append( + (self.resume_callbacks[resume_type], resume_kwargs) + ) # pause the print self._send_pause() @@ -2159,7 +2283,9 @@ def _unload_toolhead_and_resume(self): def _resume_act_locate_selector(self): if not self._is_selector_homed(): - self.cmd_TR_HOME(self.gcode.create_gcode_command("TR_HOME", "TR_HOME", {})) + self.cmd_TR_HOME( + self.gcode.create_gcode_command("TR_HOME", "TR_HOME", {}) + ) self.ignore_next_unload_length = False # other functions @@ -2185,7 +2311,9 @@ def __init__(self, config, buffer_pull_speed, is_extruder_synced): self.printer = config.get_printer() self.danger_options = self.printer.lookup_object("danger_options") self.reactor = self.printer.get_reactor() - self.all_mcus = [m for n, m in self.printer.lookup_objects(module="mcu")] + self.all_mcus = [ + m for n, m in self.printer.lookup_objects(module="mcu") + ] self.mcu = self.all_mcus[0] if hasattr(toolhead, "LookAheadQueue"): self.lookahead = toolhead.LookAheadQueue(self) @@ -2196,7 +2324,9 @@ def __init__(self, config, buffer_pull_speed, is_extruder_synced): self.commanded_pos = [0.0, 0.0, 0.0, 0.0] # Velocity and acceleration control tr_config = config.getsection("trad_rack") - self.sel_max_velocity = tr_config.getfloat("selector_max_velocity", above=0.0) + self.sel_max_velocity = tr_config.getfloat( + "selector_max_velocity", above=0.0 + ) self.fil_max_velocity = tr_config.getfloat( "filament_max_velocity", default=buffer_pull_speed, above=0.0 ) @@ -2211,7 +2341,9 @@ def __init__(self, config, buffer_pull_speed, is_extruder_synced): ) if self.min_cruise_ratio is None: self.min_cruise_ratio = 0.5 - req_accel_to_decel = config.getfloat("max_accel_to_decel", None, above=0.0) + req_accel_to_decel = config.getfloat( + "max_accel_to_decel", None, above=0.0 + ) if req_accel_to_decel is not None: config.deprecate("max_accel_to_decel") self.min_cruise_ratio = 1.0 - min( @@ -2239,8 +2371,12 @@ def __init__(self, config, buffer_pull_speed, is_extruder_synced): # Flush tracking self.flush_timer = self.reactor.register_timer(self._flush_handler) self.do_kick_flush_timer = True - self.last_flush_time = self.last_sg_flush_time = self.min_restart_time = 0.0 - self.need_flush_time = self.step_gen_time = self.clear_history_time = 0.0 + self.last_flush_time = self.last_sg_flush_time = ( + self.min_restart_time + ) = 0.0 + self.need_flush_time = self.step_gen_time = self.clear_history_time = ( + 0.0 + ) # Kinematic step generation scan window time tracking self.kin_flush_delay = toolhead.SDS_CHECK_TIME self.kin_flush_times = [] @@ -2264,7 +2400,9 @@ def __init__(self, config, buffer_pull_speed, is_extruder_synced): msg = "Error loading kinematics 'trad_rack'" logging.exception(msg) raise config.error(msg) - self.printer.register_event_handler("klippy:shutdown", self._handle_shutdown) + self.printer.register_event_handler( + "klippy:shutdown", self._handle_shutdown + ) def set_position(self, newpos, homing_axes=()): for _ in range(4 - len(newpos)): @@ -2292,11 +2430,17 @@ def __init__(self, toolhead, config, is_extruder_synced): for s in self.get_steppers(): s.set_trapq(toolhead.get_trapq()) toolhead.register_step_generator(s.generate_steps) - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) # Setup boundary checks - self.sel_max_velocity, self.sel_max_accel = toolhead.get_sel_max_velocity() - self.fil_max_velocity, self.fil_max_accel = toolhead.get_fil_max_velocity() + self.sel_max_velocity, self.sel_max_accel = ( + toolhead.get_sel_max_velocity() + ) + self.fil_max_velocity, self.fil_max_accel = ( + toolhead.get_fil_max_velocity() + ) self.stepper_count = len(self.rails) self.limits = [(1.0, -1.0)] * self.stepper_count self.selector_min = selector_stepper_section.getfloat( @@ -2371,7 +2515,9 @@ def check_move(self, move): # Get filament driver speed and accel limits if self.is_extruder_synced(): extruder = self.printer.lookup_object("toolhead").get_extruder() - fil_max_velocity = min(self.fil_max_velocity, extruder.max_e_velocity) + fil_max_velocity = min( + self.fil_max_velocity, extruder.max_e_velocity + ) fil_max_accel = min(self.fil_max_accel, extruder.max_e_accel) else: fil_max_velocity = self.fil_max_velocity @@ -2438,10 +2584,14 @@ def home_rails(self, rails, forcepos, movepos): axes_d = [hp - sp for hp, sp in zip(homepos, startpos)] move_d = math.sqrt(sum([d * d for d in axes_d[:3]])) retract_r = min(1.0, hi.retract_dist / move_d) - retractpos = [hp - ad * retract_r for hp, ad in zip(homepos, axes_d)] + retractpos = [ + hp - ad * retract_r for hp, ad in zip(homepos, axes_d) + ] self.toolhead.move(retractpos, hi.retract_speed) # Home again - startpos = [rp - ad * retract_r for rp, ad in zip(retractpos, axes_d)] + startpos = [ + rp - ad * retract_r for rp, ad in zip(retractpos, axes_d) + ] self.toolhead.set_position(startpos) hmove = HomingMove(self.printer, endstops, self.toolhead) hmove.homing_move(homepos, hi.second_homing_speed) @@ -2481,9 +2631,13 @@ def set_servo(self, width=None, angle=None, print_time=None): if print_time is None: print_time = self.toolhead.get_last_move_time() if width is not None: - self.servo._set_pwm(print_time, self.servo._get_pwm_from_pulse_width(width)) + self.servo._set_pwm( + print_time, self.servo._get_pwm_from_pulse_width(width) + ) else: - self.servo._set_pwm(print_time, self.servo._get_pwm_from_angle(angle)) + self.servo._set_pwm( + print_time, self.servo._get_pwm_from_angle(angle) + ) def get_max_angle(self): return self.servo.max_angle @@ -2545,7 +2699,9 @@ def __init__(self, printer, tr_toolhead, fil_driver_rail): self.tr_toolhead = tr_toolhead self.fil_driver_rail = fil_driver_rail - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.sync_state = None self._prev_sks = None self._prev_trapq = None @@ -2608,7 +2764,9 @@ def _sync(self, sync_type): for stepper in steppers: stepper_kinematics = ffi_main.gc(stepper_alloc, ffi_lib.free) self._prev_rotation_dists.append(stepper.get_rotation_distance()[0]) - self._prev_sks.append(stepper.set_stepper_kinematics(stepper_kinematics)) + self._prev_sks.append( + stepper.set_stepper_kinematics(stepper_kinematics) + ) stepper.set_trapq(external_trapq) stepper.set_position(new_pos) prev_toolhead.step_generators.remove(stepper.generate_steps) @@ -2664,7 +2822,9 @@ def set_fil_driver_multiplier(self, multiplier): ) steppers = self.fil_driver_rail.get_steppers() for i in range(len(steppers)): - steppers[i].set_rotation_distance(self._prev_rotation_dists[i] / multiplier) + steppers[i].set_rotation_distance( + self._prev_rotation_dists[i] / multiplier + ) class RunIfNoActivity: @@ -2672,7 +2832,9 @@ def __init__(self, toolhead, reactor, callback, delay): self.toolhead = toolhead self.initial_print_time = self.toolhead.get_last_move_time() self.callback = callback - reactor.register_callback(self._run_if_no_activity, reactor.monotonic() + delay) + reactor.register_callback( + self._run_if_no_activity, reactor.monotonic() + delay + ) def _run_if_no_activity(self, eventtime): print_time, _, lookahead_empty = self.toolhead.check_busy(eventtime) diff --git a/klippy/extras/tsl1401cl_filament_width_sensor.py b/klippy/extras/tsl1401cl_filament_width_sensor.py index 868a05537..097534a5c 100644 --- a/klippy/extras/tsl1401cl_filament_width_sensor.py +++ b/klippy/extras/tsl1401cl_filament_width_sensor.py @@ -19,9 +19,15 @@ def __init__(self, config): "default_nominal_filament_diameter", above=1.0 ) self.measurement_delay = config.getfloat("measurement_delay", above=0.0) - self.measurement_max_difference = config.getfloat("max_difference", above=0.0) - self.max_diameter = self.nominal_filament_dia + self.measurement_max_difference - self.min_diameter = self.nominal_filament_dia - self.measurement_max_difference + self.measurement_max_difference = config.getfloat( + "max_difference", above=0.0 + ) + self.max_diameter = ( + self.nominal_filament_dia + self.measurement_max_difference + ) + self.min_diameter = ( + self.nominal_filament_dia - self.measurement_max_difference + ) self.is_active = True # filament array [position, filamentWidth] self.filament_array = [] @@ -44,8 +50,12 @@ def __init__(self, config): self.gcode.register_command( "RESET_FILAMENT_WIDTH_SENSOR", self.cmd_ClearFilamentArray ) - self.gcode.register_command("DISABLE_FILAMENT_WIDTH_SENSOR", self.cmd_M406) - self.gcode.register_command("ENABLE_FILAMENT_WIDTH_SENSOR", self.cmd_M405) + self.gcode.register_command( + "DISABLE_FILAMENT_WIDTH_SENSOR", self.cmd_M406 + ) + self.gcode.register_command( + "ENABLE_FILAMENT_WIDTH_SENSOR", self.cmd_M405 + ) # Initialization def _handle_ready(self): @@ -53,7 +63,9 @@ def _handle_ready(self): self.toolhead = self.printer.lookup_object("toolhead") # Start extrude factor update timer - self.reactor.update_timer(self.extrude_factor_update_timer, self.reactor.NOW) + self.reactor.update_timer( + self.extrude_factor_update_timer, self.reactor.NOW + ) def adc_callback(self, read_time, read_value): # read sensor value @@ -64,7 +76,9 @@ def update_filament_array(self, last_epos): if len(self.filament_array) > 0: # Get last reading position in array & calculate next # reading position - next_reading_position = self.filament_array[-1][0] + MEASUREMENT_INTERVAL_MM + next_reading_position = ( + self.filament_array[-1][0] + MEASUREMENT_INTERVAL_MM + ) if next_reading_position <= (last_epos + self.measurement_delay): self.filament_array.append( [ @@ -100,7 +114,9 @@ def extrude_factor_update_event(self, eventtime): filament_width >= self.min_diameter ): percentage = round( - self.nominal_filament_dia**2 / filament_width**2 * 100 + self.nominal_filament_dia**2 + / filament_width**2 + * 100 ) self.gcode.run_script("M221 S" + str(percentage)) else: diff --git a/klippy/extras/tuning_tower.py b/klippy/extras/tuning_tower.py index 60bec55d1..1a131c091 100644 --- a/klippy/extras/tuning_tower.py +++ b/klippy/extras/tuning_tower.py @@ -40,7 +40,9 @@ def cmd_TUNING_TOWER(self, gcmd): self.step_height = gcmd.get_float("STEP_HEIGHT", 0.0, minval=0.0) self.skip = gcmd.get_float("SKIP", 0.0, minval=0.0) if self.factor and (self.step_height or self.step_delta): - raise gcmd.error("Cannot specify both FACTOR and STEP_DELTA/STEP_HEIGHT") + raise gcmd.error( + "Cannot specify both FACTOR and STEP_DELTA/STEP_HEIGHT" + ) if (self.step_delta != 0.0) != (self.step_height != 0.0): raise gcmd.error("Must specify both STEP_DELTA and STEP_HEIGHT") # Enable test mode @@ -64,7 +66,9 @@ def cmd_TUNING_TOWER(self, gcmd): message_parts.append("step_height=%.6f" % (self.step_height,)) if self.skip: message_parts.append("skip=%.6f" % (self.skip,)) - gcmd.respond_info("Starting tuning test (" + " ".join(message_parts) + ")") + gcmd.respond_info( + "Starting tuning test (" + " ".join(message_parts) + ")" + ) def get_position(self): pos = self.normal_transform.get_position() @@ -75,7 +79,9 @@ def calc_value(self, z): if self.skip: z = max(0.0, z - self.skip) if self.step_height: - return self.start + self.step_delta * math.floor(z / self.step_height) + return self.start + self.step_delta * math.floor( + z / self.step_height + ) if self.band: z = (math.floor(z / self.band) + 0.5) * self.band return self.start + z * self.factor @@ -99,7 +105,9 @@ def move(self, newpos, speed): self.last_z = z if newval != self.last_command_value: self.last_command_value = newval - self.gcode.run_script_from_command(self.command_fmt % (newval,)) + self.gcode.run_script_from_command( + self.command_fmt % (newval,) + ) # Forward move to actual handler self.last_position[:] = newpos normal_transform.move(newpos, speed) diff --git a/klippy/extras/unhome.py b/klippy/extras/unhome.py index e2822a4a5..b9cfc0089 100644 --- a/klippy/extras/unhome.py +++ b/klippy/extras/unhome.py @@ -45,7 +45,11 @@ def cmd_MARK_AS_UNHOMED(self, gcmd): axes = axes_str.split(",") invalid_axis = [] for axis in axes: - if axis.lower() != "x" and axis.lower() != "y" and axis.lower() != "z": + if ( + axis.lower() != "x" + and axis.lower() != "y" + and axis.lower() != "z" + ): invalid_axis.append(axis) if invalid_axis: gcmd.respond_info("UNHOME: Invalid axis %s" % invalid_axis) diff --git a/klippy/extras/verify_heater.py b/klippy/extras/verify_heater.py index f39124f36..732b1801b 100644 --- a/klippy/extras/verify_heater.py +++ b/klippy/extras/verify_heater.py @@ -14,8 +14,12 @@ class HeaterCheck: def __init__(self, config): self.printer = config.get_printer() - self.printer.register_event_handler("klippy:connect", self._handle_connect) - self.printer.register_event_handler("klippy:shutdown", self._handle_shutdown) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) + self.printer.register_event_handler( + "klippy:shutdown", self._handle_shutdown + ) self.heater_name = config.get_name().split()[1] self.heater = None self.hysteresis = config.getfloat("hysteresis", 5.0, minval=0.0) @@ -52,7 +56,9 @@ def check_event(self, eventtime): if temp >= target - self.hysteresis or target <= 0.0: # Temperature near target - reset checks if self.approaching_target and target: - logging.info("Heater %s within range of %.3f", self.heater_name, target) + logging.info( + "Heater %s within range of %.3f", self.heater_name, target + ) self.approaching_target = self.starting_approach = False if temp <= target + self.hysteresis: self.error = 0.0 diff --git a/klippy/extras/virtual_sdcard.py b/klippy/extras/virtual_sdcard.py index 553a585b8..a0fd562e1 100644 --- a/klippy/extras/virtual_sdcard.py +++ b/klippy/extras/virtual_sdcard.py @@ -123,7 +123,9 @@ def get_gcode(self): def get_file_list(self, check_subdirs=False): if check_subdirs: flist = [] - for root, dirs, files in os.walk(self.sdcard_dirname, followlinks=True): + for root, dirs, files in os.walk( + self.sdcard_dirname, followlinks=True + ): for name in files: ext = name[name.rfind(".") + 1 :] if ext not in VALID_GCODE_EXTS: @@ -238,7 +240,9 @@ def cmd_M27(self, gcmd): class VirtualSD: def __init__(self, config): self.printer = config.get_printer() - self.printer.register_event_handler("klippy:shutdown", self._handle_shutdown) + self.printer.register_event_handler( + "klippy:shutdown", self._handle_shutdown + ) # Print Stat Tracking self.print_stats = self.printer.load_object(config, "print_stats") # sdcard state @@ -315,7 +319,9 @@ def do_cancel(self): def _set_gcode_provider(self, gcode_provider): if self.gcode_provider is not None: - raise self.gcode.error("Print is active when resetting GCode provider") + raise self.gcode.error( + "Print is active when resetting GCode provider" + ) self.gcode_provider = gcode_provider self.print_stats.set_current_file(gcode_provider.get_name()) self.gcode_lines = gcode_provider.get_gcode() @@ -345,7 +351,8 @@ def cmd_SDCARD_RESET_FILE(self, gcmd): self._reset_print() cmd_SDCARD_PRINT_FILE_help = ( - "Loads a SD file and starts the print. May " "include files in subdirectories." + "Loads a SD file and starts the print. May " + "include files in subdirectories." ) def cmd_SDCARD_PRINT_FILE(self, gcmd): @@ -355,7 +362,9 @@ def cmd_SDCARD_PRINT_FILE(self, gcmd): filename = gcmd.get("FILENAME") if filename[0] == "/": filename = filename[1:] - self.virtualsd_gcode_provider.load_file(gcmd, filename, check_subdirs=True) + self.virtualsd_gcode_provider.load_file( + gcmd, filename, check_subdirs=True + ) self._set_gcode_provider(self.virtualsd_gcode_provider) self.printer.send_event("virtual_sdcard:load_file") self.do_resume() @@ -368,7 +377,9 @@ def cmd_M23(self, gcmd): filename = gcmd.get_raw_command_parameters().strip() if filename.startswith("/"): filename = filename[1:] - self.virtualsd_gcode_provider.load_file(gcmd, filename, check_subdirs=True) + self.virtualsd_gcode_provider.load_file( + gcmd, filename, check_subdirs=True + ) self._set_gcode_provider(self.virtualsd_gcode_provider) def cmd_M24(self, gcmd): diff --git a/klippy/extras/z_calibration.py b/klippy/extras/z_calibration.py index 7610853a4..5f1326756 100644 --- a/klippy/extras/z_calibration.py +++ b/klippy/extras/z_calibration.py @@ -21,7 +21,9 @@ def __init__(self, config): # max_deviation is deprecated self.max_deviation = config.getfloat("max_deviation", None, above=0.0) config.deprecate("max_deviation") - self.offset_margins = self._get_offset_margins("offset_margins", "-1.0,1.0") + self.offset_margins = self._get_offset_margins( + "offset_margins", "-1.0,1.0" + ) self.speed = config.getfloat("speed", 50.0, above=0.0) # clearance is deprecated self.clearance = config.getfloat("clearance", None, above=0.0) @@ -29,13 +31,19 @@ def __init__(self, config): self.safe_z_height = config.getfloat("safe_z_height", None, above=0.0) self.samples = config.getint("samples", None, minval=1) self.tolerance = config.getfloat("samples_tolerance", None, above=0.0) - self.retries = config.getint("samples_tolerance_retries", None, minval=0) + self.retries = config.getint( + "samples_tolerance_retries", None, minval=0 + ) atypes = {"none": None, "median": "median", "average": "average"} self.samples_result = config.getchoice("samples_result", atypes, "none") self.lift_speed = config.getfloat("lift_speed", None, above=0.0) self.probing_speed = config.getfloat("probing_speed", None, above=0.0) - self.second_speed = config.getfloat("probing_second_speed", None, above=0.0) - self.retract_dist = config.getfloat("probing_retract_dist", None, above=0.0) + self.second_speed = config.getfloat( + "probing_second_speed", None, above=0.0 + ) + self.retract_dist = config.getfloat( + "probing_retract_dist", None, above=0.0 + ) self.position_min = config.getfloat("position_min", None) self.first_fast = config.getboolean("probing_first_fast", False) self.nozzle_site = self._get_xy("nozzle_xy_position", True) @@ -45,10 +53,14 @@ def __init__(self, config): self.wiggle_offsets = self._get_xy("wiggle_xy_offsets", True) gcode_macro = self.printer.load_object(config, "gcode_macro") self.start_gcode = gcode_macro.load_template(config, "start_gcode", "") - self.switch_gcode = gcode_macro.load_template(config, "before_switch_gcode", "") + self.switch_gcode = gcode_macro.load_template( + config, "before_switch_gcode", "" + ) self.end_gcode = gcode_macro.load_template(config, "end_gcode", "") self.query_endstops = self.printer.load_object(config, "query_endstops") - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.printer.register_event_handler( "homing:home_rails_end", self.handle_home_rails_end ) @@ -86,10 +98,13 @@ def _handle_connect(self): self.z_endstop = EndstopWrapper(self.config, endstop) # get z-endstop position from safe_z_home if self.nozzle_site is None: - safe_z_home = self.printer.lookup_object("safe_z_home", default=None) + safe_z_home = self.printer.lookup_object( + "safe_z_home", default=None + ) if safe_z_home is None: raise self.printer.config_error( - "No nozzle position" " configured for %s" % (self.config.get_name()) + "No nozzle position" + " configured for %s" % (self.config.get_name()) ) self.nozzle_site = [ safe_z_home.home_x_pos, @@ -100,7 +115,8 @@ def _handle_connect(self): if self.switch_site is None: if self.switch_xy_offsets is None: raise self.printer.config_error( - "No switch position" " configured for %s" % (self.config.get_name()) + "No switch position" + " configured for %s" % (self.config.get_name()) ) self.switch_site = [ self.nozzle_site[0] + self.switch_xy_offsets[0], @@ -192,7 +208,9 @@ def cmd_CALIBRATE_Z(self, gcmd): state = CalibrationState(self, gcmd) state.calibrate_z() - cmd_PROBE_Z_ACCURACY_help = "Probe Z-Endstop accuracy at" " Nozzle-Endstop position" + cmd_PROBE_Z_ACCURACY_help = ( + "Probe Z-Endstop accuracy at" " Nozzle-Endstop position" + ) def cmd_PROBE_Z_ACCURACY(self, gcmd): if self.z_homing is None: @@ -463,7 +481,9 @@ def _probe_on_site( if retries >= self.helper.retries: self.helper.end_gcode.run_gcode_from_command() raise self.gcmd.error("Probe samples exceed tolerance") - self.gcmd.respond_info("Probe samples exceed tolerance." " Retrying...") + self.gcmd.respond_info( + "Probe samples exceed tolerance." " Retrying..." + ) retries += 1 positions = [] # calculate result @@ -515,7 +535,9 @@ def calibrate_z(self): ) self.probe.multi_probe_end() # calculate the offset - offset = probe_zero - (switch_zero - nozzle_zero + self.helper.switch_offset) + offset = probe_zero - ( + switch_zero - nozzle_zero + self.helper.switch_offset + ) # print result self.gcmd.respond_info( "Z-CALIBRATION: probe=%.3f - (switch=%.3f" diff --git a/klippy/extras/z_thermal_adjust.py b/klippy/extras/z_thermal_adjust.py index c9334b94f..e086fc8f1 100644 --- a/klippy/extras/z_thermal_adjust.py +++ b/klippy/extras/z_thermal_adjust.py @@ -20,12 +20,16 @@ def __init__(self, config): self.config = config # Get config parameters, convert to SI units where necessary - self.temp_coeff = config.getfloat("temp_coeff", minval=-1, maxval=1, default=0) + self.temp_coeff = config.getfloat( + "temp_coeff", minval=-1, maxval=1, default=0 + ) self.off_above_z = config.getfloat("z_adjust_off_above", 99999999.0) self.max_z_adjust_mm = config.getfloat("max_z_adjustment", 99999999.0) # Register printer events - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) self.printer.register_event_handler( "homing:home_rails_end", self.handle_homing_move_end ) @@ -38,7 +42,7 @@ def __init__(self, config): pheaters = self.printer.load_object(config, "heaters") self.sensor = pheaters.setup_sensor(config) self.sensor.setup_minmax(self.min_temp, self.max_temp) - self.sensor.setup_callback(self.temperature_callback) + self.sensor.setup_callback(self.init_temperature_callback) pheaters.register_sensor(config, self) self.last_temp = 0.0 @@ -51,7 +55,6 @@ def __init__(self, config): # Z transformation self.z_adjust_mm = 0.0 - self.last_z_adjust_mm = 0.0 self.adjust_enable = True self.last_position = [0.0, 0.0, 0.0, 0.0] self.next_transform = None @@ -107,11 +110,12 @@ def calc_adjust(self, pos): # Don't apply adjustments smaller than step distance if abs(adjust - self.z_adjust_mm) > self.z_step_dist: - self.z_adjust_mm = min([self.max_z_adjust_mm * sign, adjust], key=abs) + self.z_adjust_mm = min( + [self.max_z_adjust_mm * sign, adjust], key=abs + ) # Apply Z adjustment new_z = pos[2] + self.z_adjust_mm - self.last_z_adjust_mm = self.z_adjust_mm return [pos[0], pos[1], new_z, pos[3]] def calc_unadjust(self, pos): @@ -126,8 +130,8 @@ def get_position(self): def move(self, newpos, speed): # don't apply to extrude only moves or when disabled - if (newpos[0:2] == self.last_position[0:2]) or not self.adjust_enable: - z = newpos[2] + self.last_z_adjust_mm + if (newpos[0:3] == self.last_position[0:3]) or not self.adjust_enable: + z = newpos[2] + self.z_adjust_mm adjusted_pos = [newpos[0], newpos[1], z, newpos[3]] self.next_transform.move(adjusted_pos, speed) else: @@ -135,6 +139,12 @@ def move(self, newpos, speed): self.next_transform.move(adjusted_pos, speed) self.last_position[:] = newpos + def init_temperature_callback(self, read_time, temp): + "Initialize Z adjust thermistor ref temp" + with self.lock: + self.ref_temperature = temp + self.sensor.setup_callback(self.temperature_callback) + def temperature_callback(self, read_time, temp): "Called everytime the Z adjust thermistor is read" with self.lock: diff --git a/klippy/extras/z_tilt.py b/klippy/extras/z_tilt.py index a1b6e4647..6903ab116 100644 --- a/klippy/extras/z_tilt.py +++ b/klippy/extras/z_tilt.py @@ -19,14 +19,17 @@ def __init__(self, config, z_count): self.name = config.get_name() self.z_count = z_count self.z_steppers = [] - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): kin = self.printer.lookup_object("toolhead").get_kinematics() z_steppers = [s for s in kin.get_steppers() if s.is_active_axis("z")] if len(z_steppers) != self.z_count: raise self.printer.config_error( - "%s z_positions needs exactly %d items" % (self.name, len(z_steppers)) + "%s z_positions needs exactly %d items" + % (self.name, len(z_steppers)) ) if len(z_steppers) < 2: raise self.printer.config_error( @@ -80,9 +83,15 @@ def adjust_steppers(self, adjustments, speed): class ZAdjustStatus: def __init__(self, printer): self.applied = False - printer.register_event_handler("stepper_enable:motor_off", self._motor_off) - printer.register_event_handler("stepper_enable:disable_z", self._motor_off) - printer.register_event_handler("unhome:mark_as_unhomed_z", self._motor_off) + printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) + printer.register_event_handler( + "stepper_enable:disable_z", self._motor_off + ) + printer.register_event_handler( + "unhome:mark_as_unhomed_z", self._motor_off + ) def check_retry_result(self, retry_result): if (isinstance(retry_result, str) and retry_result == "done") or ( @@ -194,13 +203,6 @@ def __init__(self, config): self.z_positions = config.getlists( "z_positions", seps=(",", "\n"), parser=float, count=2 ) - self.use_probe_offsets = config.getboolean("use_probe_offsets", None) - if self.use_probe_offsets is None: - self.use_probe_offsets = config.getboolean("use_offsets", None) - if self.use_probe_offsets is not None: - config.deprecate("use_offsets") - else: - self.use_probe_offsets = False self.retry_helper = RetryHelper(config) self.probe_helper = probe.ProbePointsHelper( config, self.probe_finalize, enable_adaptive_move_z=True @@ -221,11 +223,7 @@ def __init__(self, config): def cmd_Z_TILT_ADJUST(self, gcmd): self.z_status.reset() self.retry_helper.start(gcmd) - use_probe_offsets = self.probe_helper.use_offsets - if self.use_probe_offsets: - self.probe_helper.use_xy_offsets(True) self.probe_helper.start_probe(gcmd) - self.probe_helper.use_xy_offsets(use_probe_offsets) def probe_finalize(self, offsets, positions): # Setup for coordinate descent analysis @@ -237,7 +235,10 @@ def probe_finalize(self, offsets, positions): def adjusted_height(pos, params): x, y, z = pos return ( - z - x * params["x_adjust"] - y * params["y_adjust"] - params["z_adjust"] + z + - x * params["x_adjust"] + - y * params["y_adjust"] + - params["z_adjust"] ) def errorfunc(params): @@ -246,7 +247,9 @@ def errorfunc(params): total_error += adjusted_height(pos, params) ** 2 return total_error - new_params = mathutil.coordinate_descent(params.keys(), params, errorfunc) + new_params = mathutil.coordinate_descent( + params.keys(), params, errorfunc + ) # Apply results speed = self.probe_helper.get_lift_speed() logging.info("Calculated bed tilt parameters: %s", new_params) diff --git a/klippy/extras/z_tilt_ng.py b/klippy/extras/z_tilt_ng.py index ac8688014..e6209c925 100644 --- a/klippy/extras/z_tilt_ng.py +++ b/klippy/extras/z_tilt_ng.py @@ -35,7 +35,9 @@ def __init__(self, config, z_count): self.name = config.get_name() self.z_count = z_count self.z_steppers = [] - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) def _handle_connect(self): kin = self.printer.lookup_object("toolhead").get_kinematics() @@ -43,11 +45,13 @@ def _handle_connect(self): if self.z_count is None: if len(z_steppers) != 3: raise self.printer.config_error( - "%s z_positions needs exactly 3 items for calibration" % (self.name) + "%s z_positions needs exactly 3 items for calibration" + % (self.name) ) elif len(z_steppers) != self.z_count: raise self.printer.config_error( - "%s z_positions needs exactly %d items" % (self.name, len(z_steppers)) + "%s z_positions needs exactly %d items" + % (self.name, len(z_steppers)) ) if len(z_steppers) < 2: raise self.printer.config_error( @@ -71,7 +75,9 @@ def adjust_steppers(self, adjustments, speed): for s in self.z_steppers: s.set_trapq(None) # Move each z stepper (sorted from lowest to highest) until they match - positions = [(float(-a), s) for a, s in zip(adjustments, self.z_steppers)] + positions = [ + (float(-a), s) for a, s in zip(adjustments, self.z_steppers) + ] positions.sort(key=(lambda k: k[0])) first_stepper_offset, first_stepper = positions[0] z_low = curpos[2] - first_stepper_offset @@ -101,9 +107,15 @@ def adjust_steppers(self, adjustments, speed): class ZAdjustStatus: def __init__(self, printer): self.applied = False - printer.register_event_handler("stepper_enable:motor_off", self._motor_off) - printer.register_event_handler("stepper_enable:disable_z", self._motor_off) - printer.register_event_handler("unhome:mark_as_unhomed_z", self._motor_off) + printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) + printer.register_event_handler( + "stepper_enable:disable_z", self._motor_off + ) + printer.register_event_handler( + "unhome:mark_as_unhomed_z", self._motor_off + ) def check_retry_result(self, retry_result): if (isinstance(retry_result, str) and retry_result == "done") or ( @@ -214,13 +226,6 @@ def __init__(self, config): self.z_positions = config.getlists( "z_positions", seps=(",", "\n"), parser=float, count=2 ) - self.use_probe_offsets = config.getboolean("use_probe_offsets", None) - if self.use_probe_offsets is None: - self.use_probe_offsets = config.getboolean("use_offsets", None) - if self.use_probe_offsets is not None: - config.deprecate("use_offsets") - else: - self.use_probe_offsets = False self.z_count = len(self.z_positions) self.retry_helper = RetryHelper(config) @@ -254,7 +259,9 @@ def __init__(self, config): ) self.ad_helper.update_probe_points(cal_probe_points, 3) self.cal_conf_avg_len = config.getint("averaging_len", 3, minval=1) - self.ad_conf_delta = config.getfloat("autodetect_delta", 1.0, minval=0.1) + self.ad_conf_delta = config.getfloat( + "autodetect_delta", 1.0, minval=0.1 + ) # Register Z_TILT_ADJUST command gcode = self.printer.lookup_object("gcode") @@ -281,21 +288,21 @@ def __init__(self, config): ) cmd_Z_TILT_ADJUST_help = "Adjust the Z tilt" - cmd_Z_TILT_CALIBRATE_help = "Calibrate Z tilt with additional probing " "points" + cmd_Z_TILT_CALIBRATE_help = ( + "Calibrate Z tilt with additional probing " "points" + ) cmd_Z_TILT_AUTODETECT_help = "Autodetect pivot point of Z motors" cmd_Z_TILT_SET_OFFSETS_help = "Set the offsets for the z_positions" def cmd_Z_TILT_ADJUST(self, gcmd): if self.z_positions is None: - gcmd.respond_info("No z_positions configured. Run Z_TILT_AUTODETECT first") + gcmd.respond_info( + "No z_positions configured. Run Z_TILT_AUTODETECT first" + ) return self.z_status.reset() self.retry_helper.start(gcmd) - use_probe_offsets = self.probe_helper.use_offsets - if self.use_probe_offsets: - self.probe_helper.use_xy_offsets(True) self.probe_helper.start_probe(gcmd) - self.probe_helper.use_xy_offsets(use_probe_offsets) def perform_coordinate_descent(self, offsets, positions): # Setup for coordinate descent analysis @@ -307,7 +314,10 @@ def perform_coordinate_descent(self, offsets, positions): def adjusted_height(pos, params): x, y, z = pos return ( - z - x * params["x_adjust"] - y * params["y_adjust"] - params["z_adjust"] + z + - x * params["x_adjust"] + - y * params["y_adjust"] + - params["z_adjust"] ) def errorfunc(params): @@ -316,7 +326,9 @@ def errorfunc(params): total_error += adjusted_height(pos, params) ** 2 return total_error - new_params = mathutil.coordinate_descent(params.keys(), params, errorfunc) + new_params = mathutil.coordinate_descent( + params.keys(), params, errorfunc + ) # Apply results logging.info("Calculated bed tilt parameters: %s", new_params) @@ -341,7 +353,8 @@ def apply_adjustments(self, offsets, new_params): def probe_finalize(self, offsets, positions): if self.z_offsets is not None: positions = [ - [p[0], p[1], p[2] - o] for (p, o) in zip(positions, self.z_offsets) + [p[0], p[1], p[2] - o] + for (p, o) in zip(positions, self.z_offsets) ] new_params = self.perform_coordinate_descent(offsets, positions) self.apply_adjustments(offsets, new_params) @@ -353,11 +366,7 @@ def cmd_Z_TILT_CALIBRATE(self, gcmd): self.cal_avg_len = gcmd.get_int("AVGLEN", self.cal_conf_avg_len) self.cal_gcmd = gcmd self.cal_runs = [] - use_probe_offsets = self.cal_helper.use_offsets - if self.use_probe_offsets: - self.cal_helper.use_xy_offsets(True) self.cal_helper.start_probe(gcmd) - self.cal_helper.use_xy_offsets(use_probe_offsets) def cal_finalize(self, offsets, positions): avlen = self.cal_avg_len @@ -371,14 +380,17 @@ def cal_finalize(self, offsets, positions): this_error = np.std(self.cal_runs[-avlen:], axis=0) this_error = np.std(this_error) self.cal_gcmd.respond_info( - "previous error: %.6f current error: %.6f" % (prev_error, this_error) + "previous error: %.6f current error: %.6f" + % (prev_error, this_error) ) if this_error < prev_error: return "retry" z_offsets = np.mean(self.cal_runs[-avlen:], axis=0).tolist() z_offsets = [z - offsets[2] for z in z_offsets] self.z_offsets = z_offsets - s_zoff = ", ".join(["%.6f" % off for off in z_offsets[: self.num_probe_points]]) + s_zoff = ", ".join( + ["%.6f" % off for off in z_offsets[: self.num_probe_points]] + ) self.cal_gcmd.respond_info("final z_offsets are: %s" % s_zoff) configfile = self.printer.lookup_object("configfile") section = self.section @@ -400,11 +412,7 @@ def cmd_Z_TILT_AUTODETECT(self, gcmd): self.ad_runs = [] self.ad_points = [] self.ad_error = None - use_probe_offsets = self.ad_helper.use_offsets - if self.use_probe_offsets: - self.ad_helper.use_xy_offsets(True) self.ad_helper.start_probe(gcmd) - self.ad_helper.use_xy_offsets(use_probe_offsets) ad_adjustments = [ [0.5, -0.5, -0.5], # p1 up @@ -426,7 +434,9 @@ def ad_finalize(self, offsets, positions): if self.ad_phase in range(4, 7): new_params["z_adjust"] += delta / 2 if self.ad_phase == 0: - self.ad_points.append([z for _, _, z in positions[: self.num_probe_points]]) + self.ad_points.append( + [z for _, _, z in positions[: self.num_probe_points]] + ) self.ad_params.append(new_params) adjustments = [_a * delta for _a in self.ad_adjustments[self.ad_phase]] self.z_helper.adjust_steppers(adjustments, speed) @@ -499,7 +509,8 @@ def ad_finalize(self, offsets, positions): self.ad_gcmd.respond_info("current error: %.6f" % (error)) else: self.ad_gcmd.respond_info( - "previous error: %.6f current error: %.6f" % (self.ad_error, error) + "previous error: %.6f current error: %.6f" + % (self.ad_error, error) ) if self.ad_error is not None: if error >= self.ad_error: diff --git a/klippy/gcode.py b/klippy/gcode.py index 7205a6826..d84bd6cd5 100644 --- a/klippy/gcode.py +++ b/klippy/gcode.py @@ -99,11 +99,13 @@ def get( ) if above is not None and value <= above: raise self.error( - "Error on '%s': %s must be above %s" % (self._commandline, name, above) + "Error on '%s': %s must be above %s" + % (self._commandline, name, above) ) if below is not None and value >= below: raise self.error( - "Error on '%s': %s must be below %s" % (self._commandline, name, below) + "Error on '%s': %s must be below %s" + % (self._commandline, name, below) ) return value @@ -140,7 +142,9 @@ def __init__(self, printer): self.is_fileinput = not not printer.get_start_args().get("debuginput") printer.register_event_handler("klippy:ready", self._handle_ready) printer.register_event_handler("klippy:shutdown", self._handle_shutdown) - printer.register_event_handler("klippy:disconnect", self._handle_disconnect) + printer.register_event_handler( + "klippy:disconnect", self._handle_disconnect + ) # Command handling self.is_printer_ready = False self.mutex = printer.get_reactor().mutex() @@ -294,7 +298,9 @@ def _process_commands(self, commands, need_ack=True): parts.append("") numparts += 1 # Build gcode "params" dictionary - params = {parts[i]: parts[i + 1].strip() for i in range(1, numparts, 2)} + params = { + parts[i]: parts[i + 1].strip() for i in range(1, numparts, 2) + } gcmd = GCodeCommand(self, cmd, origline, params, need_ack) # Invoke handler for command handler = self.gcode_handlers.get(cmd, self.cmd_default) @@ -371,7 +377,9 @@ def _respond_state(self, state): def _get_extended_params(self, gcmd): m = self.extended_r.match(gcmd.get_commandline()) if m is None: - raise self.error("Malformed command '%s'" % (gcmd.get_commandline(),)) + raise self.error( + "Malformed command '%s'" % (gcmd.get_commandline(),) + ) eargs = m.group("args") try: eparams = [earg.split("=", 1) for earg in shlex.split(eargs)] @@ -380,7 +388,9 @@ def _get_extended_params(self, gcmd): gcmd._params.update(eparams) return gcmd except ValueError as e: - raise self.error("Malformed command '%s'" % (gcmd.get_commandline(),)) + raise self.error( + "Malformed command '%s'" % (gcmd.get_commandline(),) + ) # G-Code special command handlers def cmd_default(self, gcmd): @@ -410,7 +420,8 @@ def cmd_default(self, gcmd): # Don't warn about requests to turn off heaters when not present return elif cmd == "M107" or ( - cmd == "M106" and (not gcmd.get_float("S", 1.0) or self.is_fileinput) + cmd == "M106" + and (not gcmd.get_float("S", 1.0) or self.is_fileinput) ): # Don't warn about requests to turn off fan when fan not present return @@ -423,7 +434,9 @@ def _cmd_mux(self, command, gcmd): else: key_param = gcmd.get(key) if key_param not in values: - raise gcmd.error("The value '%s' is not valid for %s" % (key_param, key)) + raise gcmd.error( + "The value '%s' is not valid for %s" % (key_param, key) + ) values[key_param](gcmd) # Low-level G-Code commands that are needed before the config file is loaded @@ -511,7 +524,9 @@ def __init__(self, printer): self.fd_handle = None if not self.is_fileinput: self.gcode.register_output_handler(self._respond_raw) - self.fd_handle = self.reactor.register_fd(self.fd, self._process_data) + self.fd_handle = self.reactor.register_fd( + self.fd, self._process_data + ) self.partial_input = "" self.pending_commands = [] self.bytes_read = 0 @@ -520,7 +535,9 @@ def __init__(self, printer): def _handle_ready(self): self.is_printer_ready = True if self.is_fileinput and self.fd_handle is None: - self.fd_handle = self.reactor.register_fd(self.fd, self._process_data) + self.fd_handle = self.reactor.register_fd( + self.fd, self._process_data + ) def _dump_debug(self): out = [] @@ -583,7 +600,9 @@ def _process_data(self, eventtime): pending_commands = self.pending_commands self.is_processing_data = False if self.fd_handle is None: - self.fd_handle = self.reactor.register_fd(self.fd, self._process_data) + self.fd_handle = self.reactor.register_fd( + self.fd, self._process_data + ) def _respond_raw(self, msg): if self.pipe_is_active: diff --git a/klippy/kinematics/cartesian.py b/klippy/kinematics/cartesian.py index fea60646e..5d82709ed 100644 --- a/klippy/kinematics/cartesian.py +++ b/klippy/kinematics/cartesian.py @@ -40,7 +40,9 @@ def __init__(self, toolhead, config): self.dual_carriage_axis = {"x": 0, "y": 1}[dc_axis] # setup second dual carriage rail self.rails.append(stepper.LookupMultiRail(dc_config)) - self.rails[3].setup_itersolve("cartesian_stepper_alloc", dc_axis.encode()) + self.rails[3].setup_itersolve( + "cartesian_stepper_alloc", dc_axis.encode() + ) dc_rail_0 = idex_modes.DualCarriagesRail( self.rails[self.dual_carriage_axis], axis=self.dual_carriage_axis, @@ -55,7 +57,9 @@ def __init__(self, toolhead, config): for s in self.get_steppers(): s.set_trapq(toolhead.get_trapq()) toolhead.register_step_generator(s.generate_steps) - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) self.printer.register_event_handler( "stepper_enable:disable_x", self._set_unhomed_x @@ -152,7 +156,13 @@ def home_axis(self, homing_state, axis, rail): forcepos[axis] += 1.5 * (position_max - hi.position_endstop) # Perform homing axis_name = ( - "x" if axis == 0 else "y" if axis == 1 else "z" if axis == 2 else None + "x" + if axis == 0 + else "y" + if axis == 1 + else "z" + if axis == 2 + else None ) if axis_name is not None: self.printer.send_event("homing:homing_move_begin_%s" % axis_name) @@ -217,7 +227,9 @@ def check_move(self, move): # Move with Z - update velocity and accel for slower Z axis self._check_endstops(move) z_ratio = move.move_d / abs(move.axes_d[2]) - move.limit_speed(self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio + ) def get_status(self, eventtime): axes = [a for a, (l, h) in zip("xyz", self.limits) if l <= h] diff --git a/klippy/kinematics/corexy.py b/klippy/kinematics/corexy.py index 53bd9bc05..5aeec0756 100644 --- a/klippy/kinematics/corexy.py +++ b/klippy/kinematics/corexy.py @@ -51,7 +51,9 @@ def __init__(self, toolhead, config): for s in self.get_steppers(): s.set_trapq(toolhead.get_trapq()) toolhead.register_step_generator(s.generate_steps) - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) if self.improved_axes_def: self.printer.register_event_handler( @@ -148,12 +150,16 @@ def home(self, homing_state): # Perform homing axis_name = AXIS_NAMES[axis] if axis in AXIS_NAMES else None if axis_name is not None: - self.printer.send_event("homing:homing_move_begin_%s" % axis_name) + self.printer.send_event( + "homing:homing_move_begin_%s" % axis_name + ) try: homing_state.home_rails([rail], forcepos, homepos) finally: if axis_name is not None: - self.printer.send_event("homing:homing_move_end_%s" % axis_name) + self.printer.send_event( + "homing:homing_move_end_%s" % axis_name + ) def _motor_off(self, print_time): self.limits = [(1.0, -1.0)] * 3 @@ -206,7 +212,9 @@ def check_move(self, move): # Move with Z - update velocity and accel for slower Z axis self._check_endstops(move) z_ratio = move.move_d / abs(move.axes_d[2]) - move.limit_speed(self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio + ) def get_status(self, eventtime): axes = [a for a, (l, h) in zip("xyz", self.limits) if l <= h] diff --git a/klippy/kinematics/corexz.py b/klippy/kinematics/corexz.py index d687800c6..5db9b1b4a 100644 --- a/klippy/kinematics/corexz.py +++ b/klippy/kinematics/corexz.py @@ -41,7 +41,9 @@ def __init__(self, toolhead, config): for s in self.get_steppers(): s.set_trapq(toolhead.get_trapq()) toolhead.register_step_generator(s.generate_steps) - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) self.printer.register_event_handler( "stepper_enable:disable_x", self._disable_xz @@ -130,12 +132,16 @@ def home(self, homing_state): # Perform homing axis_name = AXIS_NAMES[axis] if axis in AXIS_NAMES else None if axis_name is not None: - self.printer.send_event("homing:homing_move_begin_%s" % axis_name) + self.printer.send_event( + "homing:homing_move_begin_%s" % axis_name + ) try: homing_state.home_rails([rail], forcepos, homepos) finally: if axis_name is not None: - self.printer.send_event("homing:homing_move_end_%s" % axis_name) + self.printer.send_event( + "homing:homing_move_end_%s" % axis_name + ) def _motor_off(self, print_time): self.limits = [(1.0, -1.0)] * 3 @@ -188,7 +194,9 @@ def check_move(self, move): # Move with Z - update velocity and accel for slower Z axis self._check_endstops(move) z_ratio = move.move_d / abs(move.axes_d[2]) - move.limit_speed(self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio + ) def get_status(self, eventtime): axes = [a for a, (l, h) in zip("xyz", self.limits) if l <= h] diff --git a/klippy/kinematics/delta.py b/klippy/kinematics/delta.py index e8274f446..445d01e15 100644 --- a/klippy/kinematics/delta.py +++ b/klippy/kinematics/delta.py @@ -16,7 +16,9 @@ def __init__(self, toolhead, config): self.improved_axes_def = config.getboolean("improved_axes_def", False) # Setup tower rails stepper_configs = [config.getsection("stepper_" + a) for a in "abc"] - rail_a = stepper.LookupMultiRail(stepper_configs[0], need_position_minmax=False) + rail_a = stepper.LookupMultiRail( + stepper_configs[0], need_position_minmax=False + ) a_endstop = rail_a.get_homing_info().position_endstop rail_b = stepper.LookupMultiRail( stepper_configs[1], @@ -29,7 +31,9 @@ def __init__(self, toolhead, config): default_position_endstop=a_endstop, ) self.rails = [rail_a, rail_b, rail_c] - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) self.printer.register_event_handler( "stepper_enable:disable_a", self._set_unhomed @@ -81,7 +85,10 @@ def __init__(self, toolhead, config): ] self.arm2 = [arm**2 for arm in arm_lengths] self.abs_endstops = [ - (rail.get_homing_info().position_endstop + math.sqrt(arm2 - radius**2)) + ( + rail.get_homing_info().position_endstop + + math.sqrt(arm2 - radius**2) + ) for rail, arm2 in zip(self.rails, self.arm2) ] # Determine tower locations in cartesian space @@ -104,7 +111,9 @@ def __init__(self, toolhead, config): # Setup boundary checks self.need_home = True self.limit_xy2 = -1.0 - self.home_position = tuple(self._actuator_to_cartesian(self.abs_endstops)) + self.home_position = tuple( + self._actuator_to_cartesian(self.abs_endstops) + ) self.max_z = min( [rail.get_homing_info().position_endstop for rail in self.rails] ) @@ -226,11 +235,15 @@ def check_move(self, move): limit_xy2 = -1.0 if move.axes_d[2]: z_ratio = move.move_d / abs(move.axes_d[2]) - move.limit_speed(self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio + ) limit_xy2 = -1.0 # Limit the speed/accel of this move if is is at the extreme # end of the build envelope - extreme_xy2 = max(end_xy2, move.start_pos[0] ** 2 + move.start_pos[1] ** 2) + extreme_xy2 = max( + end_xy2, move.start_pos[0] ** 2 + move.start_pos[1] ** 2 + ) if extreme_xy2 > self.slow_xy2: r = 0.5 if extreme_xy2 > self.very_slow_xy2: @@ -250,8 +263,12 @@ def get_status(self, eventtime): } def get_calibration(self): - endstops = [rail.get_homing_info().position_endstop for rail in self.rails] - stepdists = [rail.get_steppers()[0].get_step_dist() for rail in self.rails] + endstops = [ + rail.get_homing_info().position_endstop for rail in self.rails + ] + stepdists = [ + rail.get_steppers()[0].get_step_dist() for rail in self.rails + ] return DeltaCalibration( self.radius, self.angles, self.arm_lengths, endstops, stepdists ) @@ -318,7 +335,8 @@ def get_position_from_stable(self, stable_position): def calc_stable_position(self, coord): # Return a stable_position from a cartesian coordinate steppos = [ - math.sqrt(a**2 - (t[0] - coord[0]) ** 2 - (t[1] - coord[1]) ** 2) + coord[2] + math.sqrt(a**2 - (t[0] - coord[0]) ** 2 - (t[1] - coord[1]) ** 2) + + coord[2] for t, a in zip(self.towers, self.arms) ] return [ @@ -330,8 +348,12 @@ def save_state(self, configfile): # Save the current parameters (for use with SAVE_CONFIG) configfile.set("printer", "delta_radius", "%.6f" % (self.radius,)) for i, axis in enumerate("abc"): - configfile.set("stepper_" + axis, "angle", "%.6f" % (self.angles[i],)) - configfile.set("stepper_" + axis, "arm_length", "%.6f" % (self.arms[i],)) + configfile.set( + "stepper_" + axis, "angle", "%.6f" % (self.angles[i],) + ) + configfile.set( + "stepper_" + axis, "arm_length", "%.6f" % (self.arms[i],) + ) configfile.set( "stepper_" + axis, "position_endstop", diff --git a/klippy/kinematics/deltesian.py b/klippy/kinematics/deltesian.py index 1b8a4f765..c3187b894 100644 --- a/klippy/kinematics/deltesian.py +++ b/klippy/kinematics/deltesian.py @@ -33,18 +33,28 @@ def __init__(self, toolhead, config): self.rails[2] = stepper.LookupMultiRail(stepper_configs[2]) arm_x = self.arm_x = [None] * 2 arm_x[0] = stepper_configs[0].getfloat("arm_x_length", above=0.0) - arm_x[1] = stepper_configs[1].getfloat("arm_x_length", arm_x[0], above=0.0) + arm_x[1] = stepper_configs[1].getfloat( + "arm_x_length", arm_x[0], above=0.0 + ) arm = [None] * 2 arm[0] = stepper_configs[0].getfloat("arm_length", above=arm_x[0]) - arm[1] = stepper_configs[1].getfloat("arm_length", arm[0], above=arm_x[1]) + arm[1] = stepper_configs[1].getfloat( + "arm_length", arm[0], above=arm_x[1] + ) arm2 = self.arm2 = [a**2 for a in arm] - self.rails[0].setup_itersolve("deltesian_stepper_alloc", arm2[0], -arm_x[0]) - self.rails[1].setup_itersolve("deltesian_stepper_alloc", arm2[1], arm_x[1]) + self.rails[0].setup_itersolve( + "deltesian_stepper_alloc", arm2[0], -arm_x[0] + ) + self.rails[1].setup_itersolve( + "deltesian_stepper_alloc", arm2[1], arm_x[1] + ) self.rails[2].setup_itersolve("cartesian_stepper_alloc", b"y") for s in self.get_steppers(): s.set_trapq(toolhead.get_trapq()) toolhead.register_step_generator(s.generate_steps) - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) self.printer.register_event_handler( "stepper_enable:disable_left", self._disable_towers @@ -77,7 +87,9 @@ def __init__(self, toolhead, config): ) self.limits = [(1.0, -1.0)] * 3 # X axis limits - min_angle = config.getfloat("min_angle", MIN_ANGLE, minval=0.0, maxval=90.0) + min_angle = config.getfloat( + "min_angle", MIN_ANGLE, minval=0.0, maxval=90.0 + ) cos_angle = math.cos(math.radians(min_angle)) x_kin_min = math.ceil(-min(arm_x[0], cos_angle * arm[1] - arm_x[1])) x_kin_max = math.floor(min(arm_x[1], cos_angle * arm[0] - arm_x[0])) @@ -125,7 +137,8 @@ def __init__(self, toolhead, config): ) logging.info( "Deltesian kinematics: moves slowed past %.2fmm" - " and %.2fmm" % (math.sqrt(self.slow_x2), math.sqrt(self.very_slow_x2)) + " and %.2fmm" + % (math.sqrt(self.slow_x2), math.sqrt(self.very_slow_x2)) ) # Setup boundary checks max_velocity, max_accel = toolhead.get_max_velocity() @@ -192,7 +205,11 @@ def home(self, homing_state): forceaxes = ( [0, 1, 2] if (home_xz and home_y) - else [0, 2] if home_xz else [1] if home_y else [] + else [0, 2] + if home_xz + else [1] + if home_y + else [] ) homing_state.set_axes(forceaxes) homepos = [None] * 4 @@ -203,12 +220,16 @@ def home(self, homing_state): dz2 = [(a2 - ax**2) for a2, ax in zip(self.arm2, self.arm_x)] forcepos[2] = -1.5 * math.sqrt(max(dz2)) for axis_name in ("x", "z"): - self.printer.send_event("homing:homing_move_begin_%s" % axis_name) + self.printer.send_event( + "homing:homing_move_begin_%s" % axis_name + ) try: homing_state.home_rails(self.rails[:2], forcepos, homepos) finally: for axis_name in ("x", "z"): - self.printer.send_event("homing:homing_move_end_%s" % axis_name) + self.printer.send_event( + "homing:homing_move_end_%s" % axis_name + ) if home_y: position_min, position_max = self.rails[2].get_range() hi = self.rails[2].get_homing_info() @@ -268,14 +289,20 @@ def check_move(self, move): raise move.move_error() if move.axes_d[2]: z_ratio = move.move_d / abs(move.axes_d[2]) - move.limit_speed(self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio + ) # Limit the speed/accel if is is at the extreme values of the x axis if move.axes_d[0] and self.slow_x2 and self.very_slow_x2: move_x2 = max(spos[0] ** 2, epos[0] ** 2) if move_x2 > self.very_slow_x2: - move.limit_speed(self.max_velocity * 0.25, self.max_accel * 0.25) + move.limit_speed( + self.max_velocity * 0.25, self.max_accel * 0.25 + ) elif move_x2 > self.slow_x2: - move.limit_speed(self.max_velocity * 0.50, self.max_accel * 0.50) + move.limit_speed( + self.max_velocity * 0.50, self.max_accel * 0.50 + ) def get_status(self, eventtime): axes = [a for a, b in zip("xyz", self.homed_axis) if b] diff --git a/klippy/kinematics/extruder.py b/klippy/kinematics/extruder.py index a419e9d07..babf6e8fb 100644 --- a/klippy/kinematics/extruder.py +++ b/klippy/kinematics/extruder.py @@ -60,7 +60,9 @@ class PALinearModel: def __init__(self, config=None): self.pa_enabled = True if config: - self.pressure_advance = config.getfloat("pressure_advance", 0.0, minval=0.0) + self.pressure_advance = config.getfloat( + "pressure_advance", 0.0, minval=0.0 + ) else: self.pressure_advance = 0.0 @@ -96,8 +98,12 @@ class PANonLinearModel: def __init__(self, config=None): self.pa_enabled = True if config: - self.linear_advance = config.getfloat("linear_advance", 0.0, minval=0.0) - self.linear_offset = config.getfloat("linear_offset", 0.0, minval=0.0) + self.linear_advance = config.getfloat( + "linear_advance", 0.0, minval=0.0 + ) + self.linear_offset = config.getfloat( + "linear_offset", 0.0, minval=0.0 + ) if self.linear_offset: self.linearization_velocity = config.getfloat( "linearization_velocity", above=0.0 @@ -115,14 +121,19 @@ def set_enabled(self, enable): self.pa_enabled = enable def update(self, gcmd): - self.linear_advance = gcmd.get_float("ADVANCE", self.linear_advance, minval=0.0) - self.linear_offset = gcmd.get_float("OFFSET", self.linear_offset, minval=0.0) + self.linear_advance = gcmd.get_float( + "ADVANCE", self.linear_advance, minval=0.0 + ) + self.linear_offset = gcmd.get_float( + "OFFSET", self.linear_offset, minval=0.0 + ) self.linearization_velocity = gcmd.get_float( "VELOCITY", self.linearization_velocity ) if self.linear_offset and self.linearization_velocity <= 0.0: raise gcmd.error( - "VELOCITY must be set to a positive value " "when OFFSET is non-zero" + "VELOCITY must be set to a positive value " + "when OFFSET is non-zero" ) def enabled(self): @@ -210,7 +221,9 @@ def __init__(self, config): # Setup stepper self.stepper = stepper.PrinterStepper(config) ffi_main, ffi_lib = chelper.get_ffi() - self.sk_extruder = ffi_main.gc(ffi_lib.extruder_stepper_alloc(), ffi_lib.free) + self.sk_extruder = ffi_main.gc( + ffi_lib.extruder_stepper_alloc(), ffi_lib.free + ) self.stepper.set_stepper_kinematics(self.sk_extruder) ffi_lib.extruder_set_pressure_advance_model_func( self.sk_extruder, self.pa_model.get_func() @@ -218,7 +231,9 @@ def __init__(self, config): self.motion_queue = None self.extruder = None # Register commands - self.printer.register_event_handler("klippy:connect", self._handle_connect) + self.printer.register_event_handler( + "klippy:connect", self._handle_connect + ) gcode = self.printer.lookup_object("gcode") if self.name == "extruder": gcode.register_mux_command( @@ -267,7 +282,9 @@ def __init__(self, config): def _handle_connect(self): toolhead = self.printer.lookup_object("toolhead") toolhead.register_step_generator(self.stepper.generate_steps) - self._update_pressure_advance(self.pa_model, self.pressure_advance_time_offset) + self._update_pressure_advance( + self.pa_model, self.pressure_advance_time_offset + ) self.smoother.update_extruder_kinematics(self.sk_extruder) def get_status(self, eventtime): @@ -310,7 +327,9 @@ def _update_pressure_advance(self, pa_model, time_offset): old_delay = ffi_lib.extruder_get_step_gen_window(self.sk_extruder) if self.pa_model.name != pa_model.name: pa_func = pa_model.get_func() - ffi_lib.extruder_set_pressure_advance_model_func(self.sk_extruder, pa_func) + ffi_lib.extruder_set_pressure_advance_model_func( + self.sk_extruder, pa_func + ) pa_params = pa_model.get_pa_params() ffi_lib.extruder_set_pressure_advance( self.sk_extruder, len(pa_params), pa_params, time_offset @@ -328,7 +347,9 @@ def update_input_shaping(self, shapers, exact_mode): old_delay = ffi_lib.extruder_get_step_gen_window(self.sk_extruder) failed_shapers = [] for shaper in shapers: - if not shaper.update_extruder_kinematics(self.sk_extruder, exact_mode): + if not shaper.update_extruder_kinematics( + self.sk_extruder, exact_mode + ): failed_shapers.append(shaper) # Pressure advance requires extruder smoothing, make sure that # some smoothing is enabled @@ -407,7 +428,8 @@ def cmd_SET_E_ROTATION_DISTANCE(self, gcmd): if invert_dir != orig_invert_dir: rotation_dist = -rotation_dist gcmd.respond_info( - "Extruder '%s' rotation distance set to %0.6f" % (self.name, rotation_dist) + "Extruder '%s' rotation distance set to %0.6f" + % (self.name, rotation_dist) ) cmd_SYNC_EXTRUDER_MOTION_help = "Set extruder stepper motion queue" @@ -415,7 +437,9 @@ def cmd_SET_E_ROTATION_DISTANCE(self, gcmd): def cmd_SYNC_EXTRUDER_MOTION(self, gcmd): ename = gcmd.get("MOTION_QUEUE") self.sync_to_extruder(ename) - gcmd.respond_info("Extruder '%s' now syncing with '%s'" % (self.name, ename)) + gcmd.respond_info( + "Extruder '%s' now syncing with '%s'" % (self.name, ename) + ) cmd_SET_E_STEP_DISTANCE_help = "Set extruder step distance" @@ -437,7 +461,9 @@ def cmd_SET_E_STEP_DISTANCE(self, gcmd): def cmd_SYNC_STEPPER_TO_EXTRUDER(self, gcmd): ename = gcmd.get("EXTRUDER") self.sync_to_extruder(ename) - gcmd.respond_info("Extruder '%s' now syncing with '%s'" % (self.name, ename)) + gcmd.respond_info( + "Extruder '%s' now syncing with '%s'" % (self.name, ename) + ) # Tracking for hotend heater, extrusion motion queue, and extruder stepper @@ -462,7 +488,9 @@ def __init__(self, config, extruder_num): config.deprecate("shared_heater") self.heater = pheaters.lookup_heater(shared_heater) # Setup kinematic checks - self.nozzle_diameter = hotend_config.getfloat("nozzle_diameter", above=0.0) + self.nozzle_diameter = hotend_config.getfloat( + "nozzle_diameter", above=0.0 + ) filament_diameter = hotend_config.getfloat( "filament_diameter", minval=self.nozzle_diameter ) @@ -485,7 +513,9 @@ def __init__(self, config, extruder_num): max_accel * def_max_extrude_ratio, above=0.0, ) - self.max_e_dist = config.getfloat("max_extrude_only_distance", 50.0, minval=0.0) + self.max_e_dist = config.getfloat( + "max_extrude_only_distance", 50.0, minval=0.0 + ) self.instant_corner_v = config.getfloat( "instantaneous_corner_velocity", 1.0, minval=0.0 ) @@ -680,7 +710,9 @@ def cmd_ACTIVATE_EXTRUDER(self, gcmd): toolhead.set_extruder(self, sum(self.last_position)) self.printer.send_event("extruder:activate_extruder") - cmd_CHANGE_MAX_EXTRUDE_ONLY_VALUES_help = "Change the maximum extrude only values" + cmd_CHANGE_MAX_EXTRUDE_ONLY_VALUES_help = ( + "Change the maximum extrude only values" + ) def cmd_CHANGE_MAX_EXTRUDE_ONLY_VALUES(self, gcmd): self.max_cross_section = gcmd.get_float( @@ -696,7 +728,9 @@ def cmd_CHANGE_MAX_EXTRUDE_ONLY_VALUES(self, gcmd): "ACCEL", self.max_e_accel, ) - self.max_e_dist = gcmd.get_float("DISTANCE", self.max_e_dist, minval=0.0) + self.max_e_dist = gcmd.get_float( + "DISTANCE", self.max_e_dist, minval=0.0 + ) gcmd.respond_info( "New maximum extrude values for extruder %s:\n" "Cross section: %.2f\n" diff --git a/klippy/kinematics/hybrid_corexy.py b/klippy/kinematics/hybrid_corexy.py index 4ade11cf2..bd679281f 100644 --- a/klippy/kinematics/hybrid_corexy.py +++ b/klippy/kinematics/hybrid_corexy.py @@ -19,7 +19,9 @@ def __init__(self, toolhead, config): stepper.LookupMultiRail(config.getsection("stepper_y")), stepper.LookupMultiRail(config.getsection("stepper_z")), ] - self.rails[1].get_endstops()[0][0].add_stepper(self.rails[0].get_steppers()[0]) + self.rails[1].get_endstops()[0][0].add_stepper( + self.rails[0].get_steppers()[0] + ) self.rails[0].setup_itersolve("corexy_stepper_alloc", b"-") self.rails[1].setup_itersolve("cartesian_stepper_alloc", b"y") self.rails[2].setup_itersolve("cartesian_stepper_alloc", b"z") @@ -38,7 +40,9 @@ def __init__(self, toolhead, config): self.rails[3].get_steppers()[0] ) self.rails[3].setup_itersolve("corexy_stepper_alloc", b"+") - dc_rail_0 = idex_modes.DualCarriagesRail(self.rails[0], axis=0, active=True) + dc_rail_0 = idex_modes.DualCarriagesRail( + self.rails[0], axis=0, active=True + ) dc_rail_1 = idex_modes.DualCarriagesRail( self.rails[3], axis=0, active=False ) @@ -48,7 +52,9 @@ def __init__(self, toolhead, config): for s in self.get_steppers(): s.set_trapq(toolhead.get_trapq()) toolhead.register_step_generator(s.generate_steps) - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) self.printer.register_event_handler( "stepper_enable:disable_x", self._disable_xy @@ -147,7 +153,13 @@ def home_axis(self, homing_state, axis, rail): forcepos[axis] += 1.5 * (position_max - hi.position_endstop) # Perform homing axis_name = ( - "x" if axis == 0 else "y" if axis == 1 else "z" if axis == 2 else None + "x" + if axis == 0 + else "y" + if axis == 1 + else "z" + if axis == 2 + else None ) if axis_name is not None: self.printer.send_event("homing:homing_move_begin_%s" % axis_name) @@ -215,7 +227,9 @@ def check_move(self, move): # Move with Z - update velocity and accel for slower Z axis self._check_endstops(move) z_ratio = move.move_d / abs(move.axes_d[2]) - move.limit_speed(self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio + ) def get_status(self, eventtime): axes = [a for a, (l, h) in zip("xyz", self.limits) if l <= h] diff --git a/klippy/kinematics/hybrid_corexz.py b/klippy/kinematics/hybrid_corexz.py index c303f2981..c44c44f2e 100644 --- a/klippy/kinematics/hybrid_corexz.py +++ b/klippy/kinematics/hybrid_corexz.py @@ -19,7 +19,9 @@ def __init__(self, toolhead, config): stepper.LookupMultiRail(config.getsection("stepper_y")), stepper.LookupMultiRail(config.getsection("stepper_z")), ] - self.rails[2].get_endstops()[0][0].add_stepper(self.rails[0].get_steppers()[0]) + self.rails[2].get_endstops()[0][0].add_stepper( + self.rails[0].get_steppers()[0] + ) self.rails[0].setup_itersolve("corexz_stepper_alloc", b"-") self.rails[1].setup_itersolve("cartesian_stepper_alloc", b"y") self.rails[2].setup_itersolve("cartesian_stepper_alloc", b"z") @@ -38,7 +40,9 @@ def __init__(self, toolhead, config): self.rails[3].get_steppers()[0] ) self.rails[3].setup_itersolve("corexz_stepper_alloc", b"+") - dc_rail_0 = idex_modes.DualCarriagesRail(self.rails[0], axis=0, active=True) + dc_rail_0 = idex_modes.DualCarriagesRail( + self.rails[0], axis=0, active=True + ) dc_rail_1 = idex_modes.DualCarriagesRail( self.rails[3], axis=0, active=False ) @@ -48,7 +52,9 @@ def __init__(self, toolhead, config): for s in self.get_steppers(): s.set_trapq(toolhead.get_trapq()) toolhead.register_step_generator(s.generate_steps) - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) self.printer.register_event_handler( "stepper_enable:disable_x", self._disable_xz @@ -147,7 +153,13 @@ def home_axis(self, homing_state, axis, rail): forcepos[axis] += 1.5 * (position_max - hi.position_endstop) # Perform homing axis_name = ( - "x" if axis == 0 else "y" if axis == 1 else "z" if axis == 2 else None + "x" + if axis == 0 + else "y" + if axis == 1 + else "z" + if axis == 2 + else None ) if axis_name is not None: self.printer.send_event("homing:homing_move_begin_%s" % axis_name) @@ -215,7 +227,9 @@ def check_move(self, move): # Move with Z - update velocity and accel for slower Z axis self._check_endstops(move) z_ratio = move.move_d / abs(move.axes_d[2]) - move.limit_speed(self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio + ) def get_status(self, eventtime): axes = [a for a, (l, h) in zip("xyz", self.limits) if l <= h] diff --git a/klippy/kinematics/idex_modes.py b/klippy/kinematics/idex_modes.py index f0bc6e4fb..ab317e4cb 100644 --- a/klippy/kinematics/idex_modes.py +++ b/klippy/kinematics/idex_modes.py @@ -95,7 +95,9 @@ def home(self, homing_state): self.toggle_active_dc_rail(0) def get_status(self, eventtime=None): - return {("carriage_%d" % (i,)): dc.mode for (i, dc) in enumerate(self.dc)} + return { + ("carriage_%d" % (i,)): dc.mode for (i, dc) in enumerate(self.dc) + } def get_kin_range(self, toolhead, mode): pos = toolhead.get_position() @@ -122,10 +124,14 @@ def get_kin_range(self, toolhead, mode): elif mode == MIRROR: if self.get_dc_order(0, 1) > 0: range_min = max(range_min, 0.5 * (sum(axes_pos) + safe_dist)) - range_max = min(range_max, sum(axes_pos) - dc1_rail.position_min) + range_max = min( + range_max, sum(axes_pos) - dc1_rail.position_min + ) else: range_max = min(range_max, 0.5 * (sum(axes_pos) - safe_dist)) - range_min = max(range_min, sum(axes_pos) - dc1_rail.position_max) + range_min = max( + range_min, sum(axes_pos) - dc1_rail.position_max + ) else: # mode == PRIMARY active_idx = 1 if self.dc[1].is_active() else 0 @@ -193,17 +199,22 @@ def cmd_SET_DUAL_CARRIAGE(self, gcmd): raise gcmd.error("Invalid mode=%s specified" % (mode,)) if mode in [COPY, MIRROR]: if index == 0: - raise gcmd.error("Mode=%s is not supported for carriage=0" % (mode,)) + raise gcmd.error( + "Mode=%s is not supported for carriage=0" % (mode,) + ) curtime = self.printer.get_reactor().monotonic() kin = self.printer.lookup_object("toolhead").get_kinematics() axis = "xyz"[self.axis] if axis not in kin.get_status(curtime)["homed_axes"]: raise gcmd.error( - "Axis %s must be homed prior to enabling mode=%s" % (axis, mode) + "Axis %s must be homed prior to enabling mode=%s" + % (axis, mode) ) self.activate_dc_mode(index, mode) - cmd_SAVE_DUAL_CARRIAGE_STATE_help = "Save dual carriages modes and positions" + cmd_SAVE_DUAL_CARRIAGE_STATE_help = ( + "Save dual carriages modes and positions" + ) def cmd_SAVE_DUAL_CARRIAGE_STATE(self, gcmd): state_name = gcmd.get("NAME", "default") @@ -213,7 +224,9 @@ def cmd_SAVE_DUAL_CARRIAGE_STATE(self, gcmd): "axes_positions": [dc.get_axis_position(pos) for dc in self.dc], } - cmd_RESTORE_DUAL_CARRIAGE_STATE_help = "Restore dual carriages modes and positions" + cmd_RESTORE_DUAL_CARRIAGE_STATE_help = ( + "Restore dual carriages modes and positions" + ) def cmd_RESTORE_DUAL_CARRIAGE_STATE(self, gcmd): state_name = gcmd.get("NAME", "default") @@ -241,7 +254,9 @@ def cmd_RESTORE_DUAL_CARRIAGE_STATE(self, gcmd): dc_mode = ( INACTIVE if min(abs(dl[0]), abs(dl[1])) < 0.000000001 - else COPY if dl[0] * dl[1] > 0 else MIRROR + else COPY + if dl[0] * dl[1] > 0 + else MIRROR ) if dc_mode != INACTIVE: self.dc[1 - primary_ind].activate(dc_mode, cur_pos[primary_ind]) @@ -276,7 +291,9 @@ def __init__(self, rail, axis, active): orig_sk = s.get_stepper_kinematics() ffi_lib.dual_carriage_set_sk(sk, orig_sk) # Set the default transform for the other axis - ffi_lib.dual_carriage_set_transform(sk, self.ENC_AXES[1 - axis], 1.0, 0.0) + ffi_lib.dual_carriage_set_transform( + sk, self.ENC_AXES[1 - axis], 1.0, 0.0 + ) self.dc_stepper_kinematics.append(sk) self.orig_stepper_kinematics.append(orig_sk) s.set_stepper_kinematics(sk) diff --git a/klippy/kinematics/limited_cartesian.py b/klippy/kinematics/limited_cartesian.py index 4426ddf29..e7b1d3ba9 100644 --- a/klippy/kinematics/limited_cartesian.py +++ b/klippy/kinematics/limited_cartesian.py @@ -74,7 +74,9 @@ def __init__(self, toolhead, config): for ax in "xyz" ] self.max_accels = [ - config.getfloat(f"max_{ax}_accel", max_accel, above=0.0, maxval=max_accel) + config.getfloat( + f"max_{ax}_accel", max_accel, above=0.0, maxval=max_accel + ) for ax in "xyz" ] self.xy_hypot_accel = hypot(*self.max_accels[:2]) @@ -109,7 +111,9 @@ def cmd_SET_KINEMATICS_LIMIT(self, gcmd): f"x,y,z max_accels: {self.max_accels!r}", ] if self.scale_per_axis: - msg.append("Per axis accelerations limits scale with current acceleration.") + msg.append( + "Per axis accelerations limits scale with current acceleration." + ) else: msg.append( "Per axis accelerations limits are independent of current acceleration." diff --git a/klippy/kinematics/limited_corexy.py b/klippy/kinematics/limited_corexy.py index 3a1674352..51581d92d 100644 --- a/klippy/kinematics/limited_corexy.py +++ b/klippy/kinematics/limited_corexy.py @@ -52,9 +52,15 @@ def __init__(self, toolhead, config): cmd_SET_KINEMATICS_LIMIT_help = "Set/get CoreXY per axis velocity limits" def cmd_SET_KINEMATICS_LIMIT(self, gcmd): - self.max_x_accel = gcmd.get_float("X_ACCEL", self.max_x_accel, above=0.0) - self.max_y_accel = gcmd.get_float("Y_ACCEL", self.max_y_accel, above=0.0) - self.max_z_accel = gcmd.get_float("Z_ACCEL", self.max_z_accel, above=0.0) + self.max_x_accel = gcmd.get_float( + "X_ACCEL", self.max_x_accel, above=0.0 + ) + self.max_y_accel = gcmd.get_float( + "Y_ACCEL", self.max_y_accel, above=0.0 + ) + self.max_z_accel = gcmd.get_float( + "Z_ACCEL", self.max_z_accel, above=0.0 + ) self.scale_per_axis = bool( gcmd.get_int("SCALE", self.scale_per_axis, minval=0, maxval=1) ) @@ -68,12 +74,16 @@ def cmd_SET_KINEMATICS_LIMIT(self, gcmd): return msg = [f"x,y,z max_accels: {max_accels!r}"] if self.scale_per_axis: - msg.append("Per axis accelerations limits scale with current acceleration.") + msg.append( + "Per axis accelerations limits scale with current acceleration." + ) else: msg.append( "Per axis accelerations limits are independent of current acceleration." ) - min_accel = 1 / sqrt(self.max_x_accel ** (-2) + self.max_y_accel ** (-2)) + min_accel = 1 / sqrt( + self.max_x_accel ** (-2) + self.max_y_accel ** (-2) + ) min_angle = atan2(self.max_x_accel, self.max_y_accel) msg.append( f"Minimum XY acceleration of {min_accel:.0f} mm/s² reached on {180 * min_angle / pi:.0f}° diagonals." diff --git a/klippy/kinematics/limited_corexz.py b/klippy/kinematics/limited_corexz.py index 97cbc18b2..ccb2ec160 100644 --- a/klippy/kinematics/limited_corexz.py +++ b/klippy/kinematics/limited_corexz.py @@ -32,7 +32,8 @@ def __init__(self, toolhead, config): for ax in "xyz" ] self.max_accels = [ - config.getfloat("max_%s_accel" % ax, max_accel, above=0.0) for ax in "xyz" + config.getfloat("max_%s_accel" % ax, max_accel, above=0.0) + for ax in "xyz" ] self.xy_hypot_accel = hypot(*self.max_accels[:2]) self.scale_per_axis = config.getboolean("scale_xy_accel", False) diff --git a/klippy/kinematics/polar.py b/klippy/kinematics/polar.py index 11e11bea4..db56c64a8 100644 --- a/klippy/kinematics/polar.py +++ b/klippy/kinematics/polar.py @@ -27,7 +27,9 @@ def __init__(self, toolhead, config): for s in self.get_steppers(): s.set_trapq(toolhead.get_trapq()) toolhead.register_step_generator(s.generate_steps) - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) self.printer.register_event_handler( "stepper_enable:disable_bed", self._set_unhomed_xy @@ -124,7 +126,13 @@ def _home_axis(self, homing_state, axis, rail): forcepos[axis] += position_max - hi.position_endstop # Perform homing axis_name = ( - "x" if axis == 0 else "y" if axis == 1 else "z" if axis == 2 else None + "x" + if axis == 0 + else "y" + if axis == 1 + else "z" + if axis == 2 + else None ) if axis_name is not None: self.printer.send_event("homing:homing_move_begin_%s" % axis_name) @@ -181,7 +189,9 @@ def check_move(self, move): raise move.move_error() # Move with Z - update velocity and accel for slower Z axis z_ratio = move.move_d / abs(move.axes_d[2]) - move.limit_speed(self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio) + move.limit_speed( + self.max_z_velocity * z_ratio, self.max_z_accel * z_ratio + ) def get_status(self, eventtime): xy_home = "xy" if self.limit_xy2 >= 0.0 else "" diff --git a/klippy/kinematics/rotary_delta.py b/klippy/kinematics/rotary_delta.py index d5306927f..df871bcd7 100644 --- a/klippy/kinematics/rotary_delta.py +++ b/klippy/kinematics/rotary_delta.py @@ -32,7 +32,9 @@ def __init__(self, toolhead, config): units_in_radians=True, ) self.rails = [rail_a, rail_b, rail_c] - self.printer.register_event_handler("stepper_enable:motor_off", self._motor_off) + self.printer.register_event_handler( + "stepper_enable:motor_off", self._motor_off + ) self.printer.register_event_handler( "stepper_enable:disable_a", self._set_unhomed @@ -85,8 +87,12 @@ def __init__(self, toolhead, config): for sconfig, angle in zip(stepper_configs, [30.0, 150.0, 270.0]) ] # Setup rotary delta calibration helper - endstops = [rail.get_homing_info().position_endstop for rail in self.rails] - stepdists = [rail.get_steppers()[0].get_step_dist() for rail in self.rails] + endstops = [ + rail.get_homing_info().position_endstop for rail in self.rails + ] + stepdists = [ + rail.get_steppers()[0].get_step_dist() for rail in self.rails + ] self.calibration = RotaryDeltaCalibration( shoulder_radius, shoulder_height, @@ -116,13 +122,18 @@ def __init__(self, toolhead, config): r.calc_position_from_coord([0.0, 0.0, ep]) for r, ep in zip(self.rails, endstops) ] - self.home_position = tuple(self.calibration.actuator_to_cartesian(eangles)) + self.home_position = tuple( + self.calibration.actuator_to_cartesian(eangles) + ) self.max_z = min(endstops) self.min_z = config.getfloat("minimum_z_position", 0, maxval=self.max_z) min_ua = min([shoulder_radius + ua for ua in upper_arms]) min_la = min([la - shoulder_radius for la in lower_arms]) self.max_xy2 = min(min_ua, min_la) ** 2 - arm_z = [self.calibration.elbow_coord(i, ea)[2] for i, ea in enumerate(eangles)] + arm_z = [ + self.calibration.elbow_coord(i, ea)[2] + for i, ea in enumerate(eangles) + ] self.limit_z = min([az - la for az, la in zip(arm_z, lower_arms)]) logging.info( "Delta max build height %.2fmm (radius tapered above %.2fmm)" @@ -312,7 +323,9 @@ def get_position_from_stable(self, stable_position): # Return cartesian coordinates for the given stable_position spos = [ ea - sp * sd - for ea, sp, sd in zip(self.abs_endstops, stable_position, self.stepdists) + for ea, sp, sd in zip( + self.abs_endstops, stable_position, self.stepdists + ) ] return self.actuator_to_cartesian(spos) @@ -325,15 +338,22 @@ def calc_stable_position(self, coord): for sk in self.sks ] return [ - (ep - sp) / sd for sd, ep, sp in zip(self.stepdists, self.abs_endstops, pos) + (ep - sp) / sd + for sd, ep, sp in zip(self.stepdists, self.abs_endstops, pos) ] def save_state(self, configfile): # Save the current parameters (for use with SAVE_CONFIG) - configfile.set("printer", "shoulder_radius", "%.6f" % (self.shoulder_radius,)) - configfile.set("printer", "shoulder_height", "%.6f" % (self.shoulder_height,)) + configfile.set( + "printer", "shoulder_radius", "%.6f" % (self.shoulder_radius,) + ) + configfile.set( + "printer", "shoulder_height", "%.6f" % (self.shoulder_height,) + ) for i, axis in enumerate("abc"): - configfile.set("stepper_" + axis, "angle", "%.6f" % (self.angles[i],)) + configfile.set( + "stepper_" + axis, "angle", "%.6f" % (self.angles[i],) + ) configfile.set( "stepper_" + axis, "position_endstop", diff --git a/klippy/klipper_threads.py b/klippy/klipper_threads.py index 6d4455df3..f1cdc78ec 100644 --- a/klippy/klipper_threads.py +++ b/klippy/klipper_threads.py @@ -13,7 +13,14 @@ def run(self): self.running = True def register_job( - self, group=None, target=None, name=None, args=(), kwargs=None, *, daemon=None + self, + group=None, + target=None, + name=None, + args=(), + kwargs=None, + *, + daemon=None, ): return KlipperThread( self, @@ -47,7 +54,7 @@ def __init__( args=(), kwargs=None, *, - daemon=None + daemon=None, ): self.k_threads = k_threads self.thread = threading.Thread( diff --git a/klippy/klippy.py b/klippy/klippy.py index c08aab2b7..02c194f3c 100644 --- a/klippy/klippy.py +++ b/klippy/klippy.py @@ -108,12 +108,17 @@ def is_shutdown(self): def _set_state(self, msg): if self.state_message in (message_ready, message_startup): self.state_message = msg - if msg != message_ready and self.start_args.get("debuginput") is not None: + if ( + msg != message_ready + and self.start_args.get("debuginput") is not None + ): self.request_exit("error_exit") def add_object(self, name, obj): if name in self.objects: - raise self.config_error("Printer object '%s' already created" % (name,)) + raise self.config_error( + "Printer object '%s' already created" % (name,) + ) self.objects[name] = obj def lookup_object(self, name, default=configfile.sentinel): @@ -127,7 +132,9 @@ def lookup_objects(self, module=None): if module is None: return list(self.objects.items()) prefix = module + " " - objs = [(n, self.objects[n]) for n in self.objects if n.startswith(prefix)] + objs = [ + (n, self.objects[n]) for n in self.objects if n.startswith(prefix) + ] if module in self.objects: return [(module, self.objects[module])] + objs return objs @@ -313,7 +320,9 @@ def _connect(self, eventtime): cb() except Exception as e: logging.exception("Unhandled exception during ready callback") - self.invoke_shutdown("Internal error during ready callback: %s" % (str(e),)) + self.invoke_shutdown( + "Internal error during ready callback: %s" % (str(e),) + ) def run(self): systime = time.time() @@ -334,7 +343,9 @@ def run(self): logging.exception(msg) # Exception from a reactor callback - try to shutdown try: - self.reactor.register_callback((lambda pt: self.invoke_shutdown(msg))) + self.reactor.register_callback( + (lambda pt: self.invoke_shutdown(msg)) + ) self.klipper_threads.run() self.reactor.run() except: @@ -371,10 +382,14 @@ def invoke_shutdown(self, msg): cb() except: logging.exception("Exception during shutdown handler") - logging.info("Reactor garbage collection: %s", self.reactor.get_gc_stats()) + logging.info( + "Reactor garbage collection: %s", self.reactor.get_gc_stats() + ) def invoke_async_shutdown(self, msg): - self.reactor.register_async_callback((lambda e: self.invoke_shutdown(msg))) + self.reactor.register_async_callback( + (lambda e: self.invoke_shutdown(msg)) + ) def register_event_handler(self, event, callback): self.event_handlers.setdefault(event, []).append(callback) @@ -557,7 +572,9 @@ def main(): ) logging.info(versions) elif not options.debugoutput: - logging.warning("No log file specified!" " Severe timing issues may result!") + logging.warning( + "No log file specified!" " Severe timing issues may result!" + ) gc.disable() # Start Printer() class diff --git a/klippy/mathutil.py b/klippy/mathutil.py index 9d3bc49e8..a53ad6d79 100644 --- a/klippy/mathutil.py +++ b/klippy/mathutil.py @@ -44,7 +44,9 @@ def coordinate_descent(adj_params, params, error_func): continue params[param_name] = orig dp[param_name] *= 0.9 - logging.info("Coordinate descent best_err: %s rounds: %d", best_err, rounds) + logging.info( + "Coordinate descent best_err: %s rounds: %d", best_err, rounds + ) return params diff --git a/klippy/mcu.py b/klippy/mcu.py index 0456f4444..022ff94bf 100644 --- a/klippy/mcu.py +++ b/klippy/mcu.py @@ -181,7 +181,8 @@ def _build_config(self): ) # Lookup commands self._trsync_start_cmd = mcu.lookup_command( - "trsync_start oid=%c report_clock=%u report_ticks=%u" " expire_reason=%c", + "trsync_start oid=%c report_clock=%u report_ticks=%u" + " expire_reason=%c", cq=self._cmd_queue, ) self._trsync_set_timeout_cmd = mcu.lookup_command( @@ -241,9 +242,13 @@ def _handle_trsync_state(self, params): clock = self._mcu.clock32_to_clock64(params["clock"]) if clock >= self._home_end_clock: self._home_end_clock = None - self._trsync_trigger_cmd.send([self._oid, self.REASON_PAST_END_TIME]) + self._trsync_trigger_cmd.send( + [self._oid, self.REASON_PAST_END_TIME] + ) - def start(self, print_time, report_offset, trigger_completion, expire_timeout): + def start( + self, print_time, report_offset, trigger_completion, expire_timeout + ): self._trigger_completion = trigger_completion self._home_end_clock = None clock = self._mcu.print_time_to_clock(print_time) @@ -281,7 +286,9 @@ def stop(self): self._trigger_completion = None if self._mcu.is_fileoutput(): return self.REASON_ENDSTOP_HIT - params = self._trsync_query_cmd.send([self._oid, self.REASON_HOST_REQUEST]) + params = self._trsync_query_cmd.send( + [self._oid, self.REASON_HOST_REQUEST] + ) for s in self._steppers: s.note_homing_end() return params["trigger_reason"] @@ -319,7 +326,8 @@ def add_stepper(self, stepper): if ot is not trsync and s.get_name().startswith(sname[:9]): cerror = self._mcu.get_printer().config_error raise cerror( - "Multi-mcu homing not supported on" " multi-mcu shared axis" + "Multi-mcu homing not supported on" + " multi-mcu shared axis" ) def get_steppers(self): @@ -390,7 +398,8 @@ def _build_config(self): ) self._mcu.add_config_cmd( "endstop_home oid=%d clock=0 sample_ticks=0 sample_count=0" - " rest_ticks=0 pin_value=0 trsync_oid=0 trigger_reason=0" % (self._oid,), + " rest_ticks=0 pin_value=0 trsync_oid=0 trigger_reason=0" + % (self._oid,), on_restart=True, ) # Lookup commands @@ -411,7 +420,9 @@ def home_start( self, print_time, sample_time, sample_count, rest_time, triggered=True ): clock = self._mcu.print_time_to_clock(print_time) - rest_ticks = self._mcu.print_time_to_clock(print_time + rest_time) - clock + rest_ticks = ( + self._mcu.print_time_to_clock(print_time + rest_time) - clock + ) self._rest_ticks = rest_ticks trigger_completion = self._dispatch.start(print_time) self._home_cmd.send( @@ -477,7 +488,8 @@ def setup_start_value(self, start_value, shutdown_value): def _build_config(self): if self._max_duration and self._start_value != self._shutdown_value: raise pins.error( - "Pin with max duration must have start" " value equal to shutdown value" + "Pin with max duration must have start" + " value equal to shutdown value" ) mdur_ticks = self._mcu.seconds_to_clock(self._max_duration) if mdur_ticks >= 1 << 31: @@ -496,7 +508,8 @@ def _build_config(self): ) ) self._mcu.add_config_cmd( - "update_digital_out oid=%d value=%d" % (self._oid, self._start_value), + "update_digital_out oid=%d value=%d" + % (self._oid, self._start_value), on_restart=True, ) cmd_queue = self._mcu.alloc_command_queue() @@ -549,7 +562,8 @@ def setup_start_value(self, start_value, shutdown_value): def _build_config(self): if self._max_duration and self._start_value != self._shutdown_value: raise pins.error( - "Pin with max duration must have start" " value equal to shutdown value" + "Pin with max duration must have start" + " value equal to shutdown value" ) cmd_queue = self._mcu.alloc_command_queue() curtime = self._mcu.get_printer().get_reactor().monotonic() @@ -604,7 +618,8 @@ def _build_config(self): ) ) self._mcu.add_config_cmd( - "set_digital_out_pwm_cycle oid=%d cycle_ticks=%d" % (self._oid, cycle_ticks) + "set_digital_out_pwm_cycle oid=%d cycle_ticks=%d" + % (self._oid, cycle_ticks) ) self._pwm_max = float(cycle_ticks) svalue = int(self._start_value * cycle_ticks + 0.5) @@ -679,7 +694,9 @@ def _build_config(self): self._inv_max_adc = 1.0 / max_adc self._report_clock = self._mcu.seconds_to_clock(self._report_time) min_sample = max(0, min(0xFFFF, int(self._min_sample * max_adc))) - max_sample = max(0, min(0xFFFF, int(math.ceil(self._max_sample * max_adc)))) + max_sample = max( + 0, min(0xFFFF, int(math.ceil(self._max_sample * max_adc))) + ) self._mcu.add_config_cmd( "query_analog_in oid=%d clock=%d sample_ticks=%d sample_count=%d" " rest_ticks=%d min_value=%d max_value=%d range_check_count=%d" @@ -729,7 +746,9 @@ def __init__(self, config, clocksync): self._name = self._name[4:] # Serial port wp = "mcu '%s': " % (self._name) - self._serial = serialhdl.SerialReader(self._reactor, warn_prefix=wp, mcu=self) + self._serial = serialhdl.SerialReader( + self._reactor, warn_prefix=wp, mcu=self + ) self._baud = 0 self._canbus_iface = None canbus_uuid = config.get("canbus_uuid", None) @@ -830,7 +849,9 @@ def __init__(self, config, clocksync): printer.register_event_handler( "klippy:firmware_restart", self._firmware_restart ) - printer.register_event_handler("klippy:mcu_identify", self._mcu_identify) + printer.register_event_handler( + "klippy:mcu_identify", self._mcu_identify + ) printer.register_event_handler("klippy:connect", self._connect) printer.register_event_handler("klippy:shutdown", self._shutdown) printer.register_event_handler("klippy:disconnect", self._disconnect) @@ -873,7 +894,9 @@ def _handle_shutdown(self, params): "Thermocouple reader fault" ): pheaters = self._printer.lookup_object("heaters") - heaters = [pheaters.lookup_heater(n) for n in pheaters.available_heaters] + heaters = [ + pheaters.lookup_heater(n) for n in pheaters.available_heaters + ] for heater in heaters: if hasattr(heater, "is_adc_faulty") and heater.is_adc_faulty(): append_msgs.append( @@ -919,7 +942,9 @@ def _check_restart(self, reason): start_reason = self._printer.get_start_args().get("start_reason") if start_reason == "firmware_restart": return - logging.info("Attempting automated MCU '%s' restart: %s", self._name, reason) + logging.info( + "Attempting automated MCU '%s' restart: %s", self._name, reason + ) self._printer.request_exit("firmware_restart") self._reactor.pause(self._reactor.monotonic() + 2.000) raise error("Attempt MCU '%s' restart failed" % (self._name,)) @@ -952,14 +977,18 @@ def handle_non_critical_disconnect(self): self._clocksync.disconnect() self._disconnect() if self.hot_plug: - self._reactor.update_timer(self.non_critical_recon_timer, self._reactor.NOW) + self._reactor.update_timer( + self.non_critical_recon_timer, self._reactor.NOW + ) self._printer.send_event(self._non_critical_disconnect_event_name) self.gcode.respond_info(f"mcu: '{self._name}' disconnected!", log=True) def non_critical_recon_event(self, eventtime): success = self.recon_mcu() if success: - self.gcode.respond_info(f"mcu: '{self._name}' reconnected!", log=True) + self.gcode.respond_info( + f"mcu: '{self._name}' reconnected!", log=True + ) return self._reactor.NEVER else: return eventtime + self.reconnect_interval @@ -979,7 +1008,9 @@ def _send_config(self, prev_crc): local_config_cmds = self._config_cmds.copy() - local_config_cmds.insert(0, "allocate_oids count=%d" % (self._oid_count,)) + local_config_cmds.insert( + 0, "allocate_oids count=%d" % (self._oid_count,) + ) # Resolve pin names ppins = self._printer.lookup_object("pins") @@ -999,7 +1030,9 @@ def _send_config(self, prev_crc): self.register_response(self._handle_starting, "starting") try: if prev_crc is None: - logging.info("Sending MCU '%s' printer configuration...", self._name) + logging.info( + "Sending MCU '%s' printer configuration...", self._name + ) for c in local_config_cmds: self._serial.send(c) else: @@ -1028,11 +1061,13 @@ def _send_get_config(self): config_params = get_config_cmd.send() if self._is_shutdown: raise error( - "MCU '%s' error during config: %s" % (self._name, self._shutdown_msg) + "MCU '%s' error during config: %s" + % (self._name, self._shutdown_msg) ) if config_params["is_shutdown"]: raise error( - "Can not update MCU '%s' config as it is shutdown" % (self._name,) + "Can not update MCU '%s' config as it is shutdown" + % (self._name,) ) return config_params @@ -1046,7 +1081,9 @@ def _log_info(self): "MCU '%s' config: %s" % ( self._name, - " ".join(["%s=%s" % (k, v) for k, v in self.get_constants().items()]), + " ".join( + ["%s=%s" % (k, v) for k, v in self.get_constants().items()] + ), ), ] return "\n".join(log_info) @@ -1091,7 +1128,9 @@ def _connect(self): else: start_reason = self._printer.get_start_args().get("start_reason") if start_reason == "firmware_restart": - raise error("Failed automated reset of MCU '%s'" % (self._name,)) + raise error( + "Failed automated reset of MCU '%s'" % (self._name,) + ) # Already configured - send init commands self._send_config(config_params["crc"]) # Setup steppersync with the move_count returned by get_config @@ -1317,7 +1356,9 @@ def _disconnect(self): self._steppersync = None def _shutdown(self, force=False): - if self._emergency_stop_cmd is None or (self._is_shutdown and not force): + if self._emergency_stop_cmd is None or ( + self._is_shutdown and not force + ): return self._emergency_stop_cmd.send() @@ -1335,7 +1376,9 @@ def _restart_via_command(self): if ( self._reset_cmd is None and self._config_reset_cmd is None ) or not self._clocksync.is_active(): - logging.info("Unable to issue reset command on MCU '%s'", self._name) + logging.info( + "Unable to issue reset command on MCU '%s'", self._name + ) return if self._reset_cmd is None: # Attempt reset via config_reset command @@ -1395,19 +1438,27 @@ def flush_moves(self, print_time, clear_history_time): return for cb in self._flush_callbacks: cb(print_time, clock) - clear_history_clock = max(0, self.print_time_to_clock(clear_history_time)) + clear_history_clock = max( + 0, self.print_time_to_clock(clear_history_time) + ) ret = self._ffi_lib.steppersync_flush( self._steppersync, clock, clear_history_clock ) if ret: - raise error("Internal error in MCU '%s' stepcompress" % (self._name,)) + raise error( + "Internal error in MCU '%s' stepcompress" % (self._name,) + ) def check_active(self, print_time, eventtime): if self._steppersync is None: return offset, freq = self._clocksync.calibrate_clock(print_time, eventtime) self._ffi_lib.steppersync_set_time(self._steppersync, offset, freq) - if self._clocksync.is_active() or self.is_fileoutput() or self._is_timeout: + if ( + self._clocksync.is_active() + or self.is_fileoutput() + or self._is_timeout + ): return if self.is_non_critical: self.handle_non_critical_disconnect() @@ -1416,7 +1467,9 @@ def check_active(self, print_time, eventtime): self.handle_non_critical_disconnect() return self._is_timeout = True - logging.info("Timeout with MCU '%s' (eventtime=%f)", self._name, eventtime) + logging.info( + "Timeout with MCU '%s' (eventtime=%f)", self._name, eventtime + ) self._printer.invoke_shutdown( "Lost communication with MCU '%s'" % (self._name,) ) @@ -1454,16 +1507,12 @@ def stats(self, eventtime): Common_MCU_errors = { - ( - "Timer too close", - ): """ + ("Timer too close",): """ This often indicates the host computer is overloaded. Check for other processes consuming excessive CPU time, high swap usage, disk errors, overheating, unstable voltage, or similar system problems on the host computer.""", - ( - "Missed scheduling of next ", - ): """ + ("Missed scheduling of next ",): """ This is generally indicative of an intermittent communication failure between micro-controller and host.""", ( @@ -1479,9 +1528,7 @@ def stats(self, eventtime): This generally occurs when the micro-controller has been requested to step at a rate higher than it is capable of obtaining.""", - ( - "Command request", - ): """ + ("Command request",): """ This generally occurs in response to an M112 G-Code command or in response to an internal error in the host software.""", } @@ -1496,7 +1543,10 @@ def error_help(msg, append_msgs=[]): line = append if isinstance(append, dict): line = ", ".join( - [f"\n{str(k)}: {str(v)}" for k, v in append.items()] + [ + f"\n{str(k)}: {str(v)}" + for k, v in append.items() + ] ) line += "\n" help_msg = "\n".join([help_msg, str(line)]) diff --git a/klippy/msgproto.py b/klippy/msgproto.py index 4a6d09084..a49a0d572 100644 --- a/klippy/msgproto.py +++ b/klippy/msgproto.py @@ -308,7 +308,9 @@ def check_packet(self, s): return 0 if s[msglen - MESSAGE_TRAILER_SYNC] != MESSAGE_SYNC: return -1 - msgcrc = s[msglen - MESSAGE_TRAILER_CRC : msglen - MESSAGE_TRAILER_CRC + 2] + msgcrc = s[ + msglen - MESSAGE_TRAILER_CRC : msglen - MESSAGE_TRAILER_CRC + 2 + ] crc = crc16_ccitt(s[: msglen - MESSAGE_TRAILER_SIZE]) if crc != list(msgcrc): # logging.debug("got crc %s vs %s", repr(crc), repr(msgcrc)) @@ -373,7 +375,9 @@ def lookup_command(self, msgformat): if mp is None: self._error("Unknown command: %s", msgname) if msgformat != mp.msgformat: - self._error("Command format mismatch: %s vs %s", msgformat, mp.msgformat) + self._error( + "Command format mismatch: %s vs %s", msgformat, mp.msgformat + ) return mp def lookup_msgid(self, msgformat): @@ -446,7 +450,9 @@ def _init_messages(self, messages, command_ids=[], output_ids=[]): msgid_bytes = [] self.msgid_parser.encode(msgid_bytes, msgid) if msgtype == "output": - self.messages_by_id[msgid] = OutputFormat(msgid_bytes, msgformat) + self.messages_by_id[msgid] = OutputFormat( + msgid_bytes, msgformat + ) else: msg = MessageFormat(msgid_bytes, msgformat, self.enumerations) self.messages_by_id[msgid] = msg @@ -465,7 +471,9 @@ def process_identify(self, data, decompress=True): all_messages = dict(commands) all_messages.update(responses) all_messages.update(output) - self._init_messages(all_messages, commands.values(), output.values()) + self._init_messages( + all_messages, commands.values(), output.values() + ) self.config.update(data.get("config", {})) self.app = data.get("app", "") self.version = data.get("version", "") diff --git a/klippy/pins.py b/klippy/pins.py index ff2cfb968..40e2c2f12 100644 --- a/klippy/pins.py +++ b/klippy/pins.py @@ -56,10 +56,13 @@ def pin_fixup(m): and self.validate_aliases ): raise error( - "pin %s is an alias for %s" % (name, self.active_pins[pin_id]) + "pin %s is an alias for %s" + % (name, self.active_pins[pin_id]) ) if pin_id in self.reserved: - raise error("pin %s is reserved for %s" % (name, self.reserved[pin_id])) + raise error( + "pin %s is reserved for %s" % (name, self.reserved[pin_id]) + ) return m.group("prefix") + str(pin_id) return re_pin.sub(pin_fixup, cmd) @@ -115,7 +118,9 @@ def parse_pin(self, pin_desc, can_invert=False, can_pullup=False): } return pin_params - def lookup_pin(self, pin_desc, can_invert=False, can_pullup=False, share_type=None): + def lookup_pin( + self, pin_desc, can_invert=False, can_pullup=False, share_type=None + ): pin_params = self.parse_pin(pin_desc, can_invert, can_pullup) pin = pin_params["pin"] share_name = "%s:%s" % (pin_params["chip_name"], pin) diff --git a/klippy/queuelogger.py b/klippy/queuelogger.py index 5ee2795d0..7716b92ef 100644 --- a/klippy/queuelogger.py +++ b/klippy/queuelogger.py @@ -61,12 +61,17 @@ def clear_rollover_info(self): def doRollover(self): logging.handlers.TimedRotatingFileHandler.doRollover(self) - lines = [self.rollover_info[name] for name in sorted(self.rollover_info)] + lines = [ + self.rollover_info[name] for name in sorted(self.rollover_info) + ] lines.append( - "=============== Log rollover at %s ===============" % (time.asctime(),) + "=============== Log rollover at %s ===============" + % (time.asctime(),) ) self.emit( - logging.makeLogRecord({"msg": "\n".join(lines), "level": logging.INFO}) + logging.makeLogRecord( + {"msg": "\n".join(lines), "level": logging.INFO} + ) ) @@ -75,7 +80,9 @@ def doRollover(self): def setup_bg_logging(filename, debuglevel, rotate_log_at_restart): global MainQueueHandler - ql = QueueListener(filename=filename, rotate_log_at_restart=rotate_log_at_restart) + ql = QueueListener( + filename=filename, rotate_log_at_restart=rotate_log_at_restart + ) MainQueueHandler = QueueHandler(ql.bg_queue) root = logging.getLogger() root.addHandler(MainQueueHandler) diff --git a/klippy/reactor.py b/klippy/reactor.py index 06c5574ab..970504e57 100644 --- a/klippy/reactor.py +++ b/klippy/reactor.py @@ -196,7 +196,9 @@ def register_callback(self, callback, waketime=NOW): # Asynchronous (from another thread) callbacks and completions def register_async_callback(self, callback, waketime=NOW): - self._async_queue.put_nowait((ReactorCallback, (self, callback, waketime))) + self._async_queue.put_nowait( + (ReactorCallback, (self, callback, waketime)) + ) try: os.write(self._pipe_fds[1], b".") except os.error: diff --git a/klippy/serialhdl.py b/klippy/serialhdl.py index aa1c7d23a..c055ddd92 100644 --- a/klippy/serialhdl.py +++ b/klippy/serialhdl.py @@ -62,7 +62,9 @@ def _bg_thread(self): hdl = self.handlers.get(hdl, self.handle_default) hdl(params) except: - logging.exception("%sException in serial callback", self.warn_prefix) + logging.exception( + "%sException in serial callback", self.warn_prefix + ) def _error(self, msg, *params): raise error(self.warn_prefix + (msg % params)) @@ -75,7 +77,9 @@ def _get_identify_data(self, eventtime): try: params = self.send_with_response(msg, "identify_response") except error as e: - logging.exception("%sWait for identify_response", self.warn_prefix) + logging.exception( + "%sWait for identify_response", self.warn_prefix + ) return None if params["offset"] == len(identify_data): msgdata = params["data"] @@ -111,7 +115,9 @@ def _start_session(self, serial_dev, serial_fd_type=b"u", client_id=0): else: wire_freq = msgparser.get_constant_float("SERIAL_BAUD", None) if wire_freq is not None: - self.ffi_lib.serialqueue_set_wire_frequency(self.serialqueue, wire_freq) + self.ffi_lib.serialqueue_set_wire_frequency( + self.serialqueue, wire_freq + ) receive_window = msgparser.get_constant_int("RECEIVE_WINDOW", None) if receive_window is not None: self.ffi_lib.serialqueue_set_receive_window( @@ -119,7 +125,9 @@ def _start_session(self, serial_dev, serial_fd_type=b"u", client_id=0): ) return True - def check_canbus_connect(self, canbus_uuid, canbus_nodeid, canbus_iface="can0"): + def check_canbus_connect( + self, canbus_uuid, canbus_nodeid, canbus_iface="can0" + ): # this doesn't work # because we don't have a way to query for the _existence_ of a device # on the network, without "assigning" the device. @@ -181,7 +189,9 @@ def check_canbus_connect(self, canbus_uuid, canbus_nodeid, canbus_iface="can0"): or msg.data[0] != RESP_NEED_NODEID ): continue - found_uuid = sum([v << ((5 - i) * 8) for i, v in enumerate(msg.data[1:7])]) + found_uuid = sum( + [v << ((5 - i) * 8) for i, v in enumerate(msg.data[1:7])] + ) logging.info(f"found_uuid: {found_uuid}") if found_uuid == uuid: self.disconnect() @@ -226,7 +236,9 @@ def connect_canbus(self, canbus_uuid, canbus_nodeid, canbus_iface="can0"): ) bus.send(set_id_msg) except (can.CanError, os.error) as e: - logging.warning("%sUnable to open CAN port: %s", self.warn_prefix, e) + logging.warning( + "%sUnable to open CAN port: %s", self.warn_prefix, e + ) self.reactor.pause(self.reactor.monotonic() + 5.0) continue bus.close = bus.shutdown # XXX @@ -240,8 +252,12 @@ def connect_canbus(self, canbus_uuid, canbus_nodeid, canbus_iface="can0"): if got_uuid == bytearray(uuid): break except: - logging.exception("%sError in canbus_uuid check", self.warn_prefix) - logging.info("%sFailed to match canbus_uuid - retrying..", self.warn_prefix) + logging.exception( + "%sError in canbus_uuid check", self.warn_prefix + ) + logging.info( + "%sFailed to match canbus_uuid - retrying..", self.warn_prefix + ) self.disconnect() def connect_pipe(self, filename): @@ -253,7 +269,9 @@ def connect_pipe(self, filename): try: fd = os.open(filename, os.O_RDWR | os.O_NOCTTY) except OSError as e: - logging.warning("%sUnable to open port: %s", self.warn_prefix, e) + logging.warning( + "%sUnable to open port: %s", self.warn_prefix, e + ) self.reactor.pause(self.reactor.monotonic() + 5.0) continue serial_dev = os.fdopen(fd, "rb+", 0) @@ -266,17 +284,23 @@ def connect_uart(self, serialport, baud, rts=True): logging.info("%sStarting serial connect", self.warn_prefix) start_time = self.reactor.monotonic() while 1: - if self.serialqueue is not None: # if we're already connected, don't recon + if ( + self.serialqueue is not None + ): # if we're already connected, don't recon break if self.reactor.monotonic() > start_time + 90.0: self._error("Unable to connect") try: - serial_dev = serial.Serial(baudrate=baud, timeout=0, exclusive=True) + serial_dev = serial.Serial( + baudrate=baud, timeout=0, exclusive=True + ) serial_dev.port = serialport serial_dev.rts = rts serial_dev.open() except (OSError, IOError, serial.SerialException) as e: - logging.warning("%sUnable to open serial port: %s", self.warn_prefix, e) + logging.warning( + "%sUnable to open serial port: %s", self.warn_prefix, e + ) self.reactor.pause(self.reactor.monotonic() + 5.0) continue stk500v2_leave(serial_dev, self.reactor) @@ -396,7 +420,9 @@ def alloc_command_queue(self): # Dumping debug lists def dump_debug(self): out = [] - out.append("Dumping serial stats: %s" % (self.stats(self.reactor.monotonic()),)) + out.append( + "Dumping serial stats: %s" % (self.stats(self.reactor.monotonic()),) + ) sdata = self.ffi_main.new("struct pull_queue_message[1024]") rdata = self.ffi_main.new("struct pull_queue_message[1024]") scount = self.ffi_lib.serialqueue_extract_old( @@ -441,7 +467,9 @@ def handle_unknown(self, params): ) def handle_output(self, params): - logging.info("%s%s: %s", self.warn_prefix, params["#name"], params["#msg"]) + logging.info( + "%s%s: %s", self.warn_prefix, params["#name"], params["#msg"] + ) def handle_default(self, params): if get_danger_options().log_serial_reader_warnings: @@ -466,7 +494,9 @@ def get_response(self, cmds, cmd_queue, minclock=0, reqclock=0): while True: for cmd in cmds[:-1]: self.serial.raw_send(cmd, minclock, reqclock, cmd_queue) - self.serial.raw_send_wait_ack(cmds[-1], minclock, reqclock, cmd_queue) + self.serial.raw_send_wait_ack( + cmds[-1], minclock, reqclock, cmd_queue + ) params = self.last_params if params is not None: self.serial.register_response(None, self.name, self.oid) diff --git a/klippy/stepper.py b/klippy/stepper.py index 427c090e0..8c5c56d79 100644 --- a/klippy/stepper.py +++ b/klippy/stepper.py @@ -4,7 +4,6 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import collections -import logging import math import chelper, msgproto @@ -279,7 +278,9 @@ def _query_mcu_position(self): print_time = self._mcu.estimated_print_time(params["#receive_time"]) clock = self._mcu.print_time_to_clock(print_time) ffi_main, ffi_lib = chelper.get_ffi() - ret = ffi_lib.stepcompress_set_last_position(self._stepqueue, clock, last_pos) + ret = ffi_lib.stepcompress_set_last_position( + self._stepqueue, clock, last_pos + ) if ret: raise error("Internal error in stepcompress") self._set_mcu_position(last_pos) @@ -343,7 +344,9 @@ def PrinterStepper(config, units_in_radians=False): step_pulse_duration = config.getfloat( "step_pulse_duration", None, minval=0.0, maxval=0.001 ) - high_precision_stepcompr = config.getboolean("high_precision_step_compress", False) + high_precision_stepcompr = config.getboolean( + "high_precision_step_compress", False + ) mcu_stepper = MCU_stepper( name, high_precision_stepcompr, @@ -401,7 +404,8 @@ def parse_step_distance(config, units_in_radians=None, note_valid=False): ) if full_steps % 4: raise config.error( - "full_steps_per_rotation invalid in section '%s'" % (config.get_name(),) + "full_steps_per_rotation invalid in section '%s'" + % (config.get_name(),) ) gearing = parse_gear_ratio(config, note_valid) return rotation_dist, full_steps * microsteps * gearing @@ -434,7 +438,9 @@ def __init__( self._tmc_current_helpers = None self.get_name = self.mcu_stepper.get_name self.get_commanded_position = self.mcu_stepper.get_commanded_position - self.calc_position_from_coord = self.mcu_stepper.calc_position_from_coord + self.calc_position_from_coord = ( + self.mcu_stepper.calc_position_from_coord + ) # Primary endstop position mcu_endstop = self.endstops[0][0] if hasattr(mcu_endstop, "get_position_endstop"): @@ -452,7 +458,8 @@ def __init__( ) endstop_is_beacon = endstop_pin is not None and ( endstop_pin == "probe:z_virtual_endstop" - and config.get_printer().load_object(config, "beacon", None) is not None + and config.get_printer().load_object(config, "beacon", None) + is not None ) default_homing_retract_dist = 5.0 if endstop_is_beacon else 5.0 @@ -460,7 +467,9 @@ def __init__( # Axis range if need_position_minmax: self.position_min = config.getfloat("position_min", 0.0) - self.position_max = config.getfloat("position_max", above=self.position_min) + self.position_max = config.getfloat( + "position_max", above=self.position_min + ) else: self.position_min = 0.0 self.position_max = self.position_endstop @@ -489,7 +498,9 @@ def __init__( self.post_homing_retract_dist = config.getfloat( "post_homing_retract_dist", self.homing_retract_dist, minval=0.0 ) - self.homing_positive_dir = config.getboolean("homing_positive_dir", None) + self.homing_positive_dir = config.getboolean( + "homing_positive_dir", None + ) self.use_sensorless_homing = config.getboolean( "use_sensorless_homing", endstop_is_virtual ) @@ -510,9 +521,11 @@ def __init__( ) config.getboolean("homing_positive_dir", self.homing_positive_dir) elif ( - self.homing_positive_dir and self.position_endstop == self.position_min + self.homing_positive_dir + and self.position_endstop == self.position_min ) or ( - not self.homing_positive_dir and self.position_endstop == self.position_max + not self.homing_positive_dir + and self.position_endstop == self.position_max ): raise config.error( "Invalid homing_positive_dir / position_endstop in '%s'" diff --git a/klippy/toolhead.py b/klippy/toolhead.py index 958bf17a2..a3b8270fd 100644 --- a/klippy/toolhead.py +++ b/klippy/toolhead.py @@ -88,7 +88,9 @@ def calc_junction(self, prev_move): sin_theta_d2 = math.sqrt(0.5 * (1.0 - junction_cos_theta)) R_jd = sin_theta_d2 / (1.0 - sin_theta_d2) # Approximated circle must contact moves no further away than mid-move - tan_theta_d2 = sin_theta_d2 / math.sqrt(0.5 * (1.0 + junction_cos_theta)) + tan_theta_d2 = sin_theta_d2 / math.sqrt( + 0.5 * (1.0 + junction_cos_theta) + ) move_centripetal_v2 = 0.5 * self.move_d * tan_theta_d2 * self.accel prev_move_centripetal_v2 = ( 0.5 * prev_move.move_d * tan_theta_d2 * prev_move.accel @@ -167,7 +169,10 @@ def flush(self, lazy=False): smoothed_v2 = min(move.max_smoothed_v2, reachable_smoothed_v2) if smoothed_v2 < reachable_smoothed_v2: # It's possible for this move to accelerate - if smoothed_v2 + move.smooth_delta_v2 > next_smoothed_v2 or delayed: + if ( + smoothed_v2 + move.smooth_delta_v2 > next_smoothed_v2 + or delayed + ): # This move can decelerate or this is a full accel # move after a full decel move if update_flush_count and peak_cruise_v2: @@ -245,7 +250,9 @@ class ToolHead: def __init__(self, config): self.printer = config.get_printer() self.reactor = self.printer.get_reactor() - self.all_mcus = [m for n, m in self.printer.lookup_objects(module="mcu")] + self.all_mcus = [ + m for n, m in self.printer.lookup_objects(module="mcu") + ] self.mcu = self.all_mcus[0] self.lookahead = LookAheadQueue(self) self.lookahead.set_flush_time(BUFFER_TIME_HIGH) @@ -255,10 +262,14 @@ def __init__(self, config): self.max_accel = config.getfloat("max_accel", above=0.0) min_cruise_ratio = 0.5 if config.getfloat("minimum_cruise_ratio", None) is None: - req_accel_to_decel = config.getfloat("max_accel_to_decel", None, above=0.0) + req_accel_to_decel = config.getfloat( + "max_accel_to_decel", None, above=0.0 + ) if req_accel_to_decel is not None: config.deprecate("max_accel_to_decel") - min_cruise_ratio = 1.0 - min(1.0, (req_accel_to_decel / self.max_accel)) + min_cruise_ratio = 1.0 - min( + 1.0, (req_accel_to_decel / self.max_accel) + ) self.min_cruise_ratio = config.getfloat( "minimum_cruise_ratio", min_cruise_ratio, below=1.0, minval=0.0 ) @@ -285,7 +296,9 @@ def __init__(self, config): self.flush_timer = self.reactor.register_timer(self._flush_handler) self.do_kick_flush_timer = True self.last_flush_time = self.min_restart_time = 0.0 - self.need_flush_time = self.step_gen_time = self.clear_history_time = 0.0 + self.need_flush_time = self.step_gen_time = self.clear_history_time = ( + 0.0 + ) # Kinematic step generation scan window time tracking self.kin_flush_delay = SDS_CHECK_TIME self.kin_flush_times = [] @@ -311,9 +324,13 @@ def __init__(self, config): msg = "Error loading kinematics '%s'" % (kin_name,) logging.exception(msg) raise config.error(msg) - if config.has_section("dual_carriage") and not self.kin.supports_dual_carriage: + if ( + config.has_section("dual_carriage") + and not self.kin.supports_dual_carriage + ): raise config.error( - "dual_carriage not compatible with '%s' kinematics system" % (kin_name,) + "dual_carriage not compatible with '%s' kinematics system" + % (kin_name,) ) # Register commands gcode.register_command("G4", self.cmd_G4) @@ -324,7 +341,9 @@ def __init__(self, config): desc=self.cmd_SET_VELOCITY_LIMIT_help, ) gcode.register_command("M204", self.cmd_M204) - self.printer.register_event_handler("klippy:shutdown", self._handle_shutdown) + self.printer.register_event_handler( + "klippy:shutdown", self._handle_shutdown + ) # Load some default modules modules = [ "gcode_move", @@ -476,7 +495,9 @@ def _check_pause(self): self.special_queuing_state = "Priming" self.need_check_pause = -1.0 if self.priming_timer is None: - self.priming_timer = self.reactor.register_timer(self._priming_handler) + self.priming_timer = self.reactor.register_timer( + self._priming_handler + ) wtime = eventtime + max(0.100, buffer_time - BUFFER_TIME_LOW) self.reactor.update_timer(self.priming_timer, wtime) # Check if there are lots of queued moves and pause if so @@ -523,7 +544,8 @@ def _flush_handler(self, eventtime): # In "NeedPrime"/"Priming" state - flush queues if needed while 1: end_flush = ( - self.need_flush_time + get_danger_options().bgflush_extra_time + self.need_flush_time + + get_danger_options().bgflush_extra_time ) if self.last_flush_time >= end_flush: self.do_kick_flush_timer = True @@ -585,6 +607,10 @@ def wait_moves(self): not self.special_queuing_state or self.print_time >= self.mcu.estimated_print_time(eventtime) ): + if self.printer.is_shutdown(): + raise self.printer.command_error( + "Wait_Moves failed due to printer shutdown" + ) if not self.can_pause: break eventtime = self.reactor.pause(eventtime + 0.100) @@ -606,7 +632,10 @@ def _update_drip_move_time(self, next_print_time): curtime = self.reactor.monotonic() est_print_time = self.mcu.estimated_print_time(curtime) wait_time = self.print_time - est_print_time - flush_delay - if wait_time > get_danger_options().drip_move_wait_time and self.can_pause: + if ( + wait_time > get_danger_options().drip_move_wait_time + and self.can_pause + ): # Pause before sending more steps self.drip_completion.wait(curtime + wait_time) continue @@ -753,11 +782,17 @@ def cmd_SET_VELOCITY_LIMIT(self, gcmd): "MINIMUM_CRUISE_RATIO", None, minval=0.0, below=1.0 ) if min_cruise_ratio is None: - req_accel_to_decel = gcmd.get_float("ACCEL_TO_DECEL", None, above=0.0) + req_accel_to_decel = gcmd.get_float( + "ACCEL_TO_DECEL", None, above=0.0 + ) if req_accel_to_decel is not None and max_accel is not None: - min_cruise_ratio = 1.0 - min(1.0, req_accel_to_decel / max_accel) + min_cruise_ratio = 1.0 - min( + 1.0, req_accel_to_decel / max_accel + ) elif req_accel_to_decel is not None and max_accel is None: - min_cruise_ratio = 1.0 - min(1.0, (req_accel_to_decel / self.max_accel)) + min_cruise_ratio = 1.0 - min( + 1.0, (req_accel_to_decel / self.max_accel) + ) if max_velocity is not None: self.max_velocity = max_velocity if max_accel is not None: diff --git a/klippy/util.py b/klippy/util.py index 2de80d574..e40f493c9 100644 --- a/klippy/util.py +++ b/klippy/util.py @@ -23,7 +23,9 @@ def fix_sigint(): # Set a file-descriptor as non-blocking def set_nonblock(fd): - fcntl.fcntl(fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK) + fcntl.fcntl( + fd, fcntl.F_SETFL, fcntl.fcntl(fd, fcntl.F_GETFL) | os.O_NONBLOCK + ) # Clear HUPCL flag @@ -79,7 +81,8 @@ def dump_mcu_build(): data = f.read(32 * 1024) f.close() logging.info( - "========= Last MCU build config =========\n%s" "=======================", + "========= Last MCU build config =========\n%s" + "=======================", data, ) except: @@ -131,7 +134,9 @@ def get_cpu_info(): data = f.read() f.close() except (IOError, OSError) as e: - logging.debug("Exception on read /proc/cpuinfo: %s", traceback.format_exc()) + logging.debug( + "Exception on read /proc/cpuinfo: %s", traceback.format_exc() + ) return "?" lines = [l.split(":", 1) for l in data.split("\n")] lines = [(l[0].strip(), l[1].strip()) for l in lines if len(l) == 2] @@ -243,7 +248,9 @@ def get_git_version(from_file=True): prog_status, stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stat, err = process.communicate() - status = [l.split(None, 1) for l in str(stat.strip().decode()).split("\n")] + status = [ + l.split(None, 1) for l in str(stat.strip().decode()).split("\n") + ] retcode = process.wait() if retcode == 0: git_info["file_status"] = status diff --git a/klippy/webhooks.py b/klippy/webhooks.py index d8d5a4f27..7633760c9 100644 --- a/klippy/webhooks.py +++ b/klippy/webhooks.py @@ -70,7 +70,11 @@ def get(self, item, default=Sentinel, types=None): value = self.params.get(item, default) if value is Sentinel: raise WebRequestError("Missing Argument [%s]" % (item,)) - if types is not None and type(value) not in types and item in self.params: + if ( + types is not None + and type(value) not in types + and item in self.params + ): raise WebRequestError("Invalid Argument Type [%s]" % (item,)) return value @@ -132,7 +136,9 @@ def __init__(self, webhooks, printer): self.fd_handle = self.reactor.register_fd( self.sock.fileno(), self._handle_accept ) - printer.register_event_handler("klippy:disconnect", self._handle_disconnect) + printer.register_event_handler( + "klippy:disconnect", self._handle_disconnect + ) printer.register_event_handler("klippy:shutdown", self._handle_shutdown) def _handle_accept(self, eventtime): @@ -260,7 +266,9 @@ def process_received(self, eventtime): try: web_request = WebRequest(self, req) except Exception: - logging.exception("webhooks: Error decoding Server Request %s" % (req)) + logging.exception( + "webhooks: Error decoding Server Request %s" % (req) + ) continue self.reactor.register_callback( lambda e, s=self, wr=web_request: s._process_request(wr) @@ -273,7 +281,9 @@ def _process_request(self, web_request): except self.printer.command_error as e: web_request.set_error(WebRequestError(str(e))) except Exception as e: - msg = "Internal Error on WebRequest: %s" % (web_request.get_method()) + msg = "Internal Error on WebRequest: %s" % ( + web_request.get_method() + ) logging.exception(msg) web_request.set_error(WebRequestError(str(e))) self.printer.invoke_shutdown(msg) @@ -324,7 +334,9 @@ def __init__(self, printer): self._mux_endpoints = {} self.register_endpoint("info", self._handle_info_request) self.register_endpoint("emergency_stop", self._handle_estop_request) - self.register_endpoint("register_remote_method", self._handle_rpc_registration) + self.register_endpoint( + "register_remote_method", self._handle_rpc_registration + ) self.sconn = ServerSocket(self, printer) def register_endpoint(self, path, callback): @@ -453,8 +465,12 @@ def __init__(self, printer): wh.register_endpoint("gcode/help", self._handle_help) wh.register_endpoint("gcode/script", self._handle_script) wh.register_endpoint("gcode/restart", self._handle_restart) - wh.register_endpoint("gcode/firmware_restart", self._handle_firmware_restart) - wh.register_endpoint("gcode/subscribe_output", self._handle_subscribe_output) + wh.register_endpoint( + "gcode/firmware_restart", self._handle_firmware_restart + ) + wh.register_endpoint( + "gcode/subscribe_output", self._handle_subscribe_output + ) def _handle_help(self, web_request): web_request.send(self.gcode.get_command_help()) @@ -504,7 +520,9 @@ def __init__(self, printer): def _handle_list(self, web_request): objects = [ - n for n, o in self.printer.lookup_objects() if hasattr(o, "get_status") + n + for n, o in self.printer.lookup_objects() + if hasattr(o, "get_status") ] web_request.send({"objects": objects}) diff --git a/scripts/get_extruder_smoother.py b/scripts/get_extruder_smoother.py index 5e9eaaa0a..785d2a3e1 100644 --- a/scripts/get_extruder_smoother.py +++ b/scripts/get_extruder_smoother.py @@ -5,64 +5,88 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. -import optparse, importlib, math, os, sys +import optparse, importlib, os, sys import numpy as np, matplotlib -sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), - '..', 'klippy')) -shaper_defs = importlib.import_module('.shaper_defs', 'extras') -shaper_calibrate = importlib.import_module('.shaper_calibrate', 'extras') -extruder_smoother = importlib.import_module('.extruder_smoother', 'extras') + +sys.path.append( + os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "klippy") +) +shaper_defs = importlib.import_module(".shaper_defs", "extras") +shaper_calibrate = importlib.import_module(".shaper_calibrate", "extras") +extruder_smoother = importlib.import_module(".extruder_smoother", "extras") + def plot_shaper(shaper_name, damping_ratio): (C_e, t_sm), (t, velocities) = extruder_smoother.get_extruder_smoother( - shaper_name.lower(), 1.0, damping_ratio, return_velocities=True) - tau = np.linspace(-.5 * t_sm, .5 * t_sm, t.shape[0]) + shaper_name.lower(), 1.0, damping_ratio, return_velocities=True + ) + tau = np.linspace(-0.5 * t_sm, 0.5 * t_sm, t.shape[0]) w_e = np.zeros(shape=tau.shape) for c in C_e[::-1]: - w_e = (w_e * tau + c) + w_e = w_e * tau + c normalized_velocities = velocities / ( - velocities.sum(axis=-1)[:,np.newaxis] * (t[1] - t[0])) + velocities.sum(axis=-1)[:, np.newaxis] * (t[1] - t[0]) + ) mean_velocity = normalized_velocities.mean(axis=0) - fig, ax = matplotlib.pyplot.subplots(figsize=(10,9)) + fig, ax = matplotlib.pyplot.subplots(figsize=(10, 9)) ax.set_title("Unit step input") - styles = ['dotted', 'dashed', 'dashdot'] + styles = ["dotted", "dashed", "dashdot"] dr_i = 0 for i in range(normalized_velocities.shape[0]): - ax.plot(t, normalized_velocities[i,:], linestyle=styles[dr_i]) - ax.plot(t, mean_velocity, 'b', linewidth=2.0) - ax.plot(t, w_e / (t[-1] - t[0]), 'r', linewidth=2.0) - ax.set_xlabel('Time, sec') - ax.set_ylabel('Amplitude') + ax.plot(t, normalized_velocities[i, :], linestyle=styles[dr_i]) + ax.plot(t, mean_velocity, "b", linewidth=2.0) + ax.plot(t, w_e / (t[-1] - t[0]), "r", linewidth=2.0) + ax.set_xlabel("Time, sec") + ax.set_ylabel("Amplitude") ax.grid() return fig + def setup_matplotlib(output_to_file): global matplotlib if output_to_file: - matplotlib.use('Agg') + matplotlib.use("Agg") import matplotlib.pyplot, matplotlib.dates, matplotlib.font_manager import matplotlib.ticker + def main(): # Parse command-line arguments usage = "%prog [options]" opts = optparse.OptionParser(usage) - opts.add_option("-o", "--output", type="string", dest="output", - default=None, help="filename of output graph") - opts.add_option("-s", "--shaper", type="string", dest="shaper", - default="ei", help="name of the shaper to plot") - opts.add_option("--damping_ratio", type="float", dest="damping_ratio", - default=shaper_defs.DEFAULT_DAMPING_RATIO, - help="the damping ratio of the system to adapt smoother to") + opts.add_option( + "-o", + "--output", + type="string", + dest="output", + default=None, + help="filename of output graph", + ) + opts.add_option( + "-s", + "--shaper", + type="string", + dest="shaper", + default="ei", + help="name of the shaper to plot", + ) + opts.add_option( + "--damping_ratio", + type="float", + dest="damping_ratio", + default=shaper_defs.DEFAULT_DAMPING_RATIO, + help="the damping ratio of the system to adapt smoother to", + ) options, args = opts.parse_args() if len(args) != 0: opts.error("Incorrect number of arguments") - if (options.shaper.lower() not in - [s.name for s in shaper_defs.INPUT_SHAPERS] and - options.shaper.lower() not in - [s.name for s in shaper_defs.INPUT_SMOOTHERS]): + if options.shaper.lower() not in [ + s.name for s in shaper_defs.INPUT_SHAPERS + ] and options.shaper.lower() not in [ + s.name for s in shaper_defs.INPUT_SMOOTHERS + ]: opts.error("Invalid shaper name '%s'" % (opts.shaper,)) # Draw graph @@ -76,5 +100,6 @@ def main(): fig.set_size_inches(8, 6) fig.savefig(options.output) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/scripts/graph_motion_extruder.py b/scripts/graph_motion_extruder.py index be7888358..2d436cda4 100644 --- a/scripts/graph_motion_extruder.py +++ b/scripts/graph_motion_extruder.py @@ -5,23 +5,25 @@ # Copyright (C) 2020-2024 Dmitry Butyugin # # This file may be distributed under the terms of the GNU GPLv3 license. -import optparse, datetime, importlib, math, os, sys +import optparse, importlib, math, os, sys import numpy as np import matplotlib -sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), - '..', 'klippy')) -shaper_defs = importlib.import_module('.shaper_defs', 'extras') -shaper_calibrate = importlib.import_module('.shaper_calibrate', 'extras') -extruder_smoother = importlib.import_module('.extruder_smoother', 'extras') -SEG_TIME = .00002 -INV_SEG_TIME = 1. / SEG_TIME +sys.path.append( + os.path.join(os.path.dirname(os.path.realpath(__file__)), "..", "klippy") +) +shaper_defs = importlib.import_module(".shaper_defs", "extras") +shaper_calibrate = importlib.import_module(".shaper_calibrate", "extras") +extruder_smoother = importlib.import_module(".extruder_smoother", "extras") -SPRING_FREQ=43.0 -DAMPING_RATIO=0.095 +SEG_TIME = 0.00002 +INV_SEG_TIME = 1.0 / SEG_TIME -SHAPER_FREQ=45.0 -SHAPER_DAMPING_RATIO=0.10 +SPRING_FREQ = 43.0 +DAMPING_RATIO = 0.095 + +SHAPER_FREQ = 45.0 +SHAPER_DAMPING_RATIO = 0.10 ###################################################################### # Basic trapezoid motion @@ -29,28 +31,36 @@ # List of moves: [(start_v, end_v, move_t), ...] Moves = [ - (0., 0., .100), - (6.869, 90., None), (90., 90., .120), (90., 5., None), - (5., 5., 0.002), - (5., 90., None), (90., 90., .130), (90., 50., None), - (50., 50., .100), (50., .5, None), - (0., 0., .200) + (0.0, 0.0, 0.100), + (6.869, 90.0, None), + (90.0, 90.0, 0.120), + (90.0, 5.0, None), + (5.0, 5.0, 0.002), + (5.0, 90.0, None), + (90.0, 90.0, 0.130), + (90.0, 50.0, None), + (50.0, 50.0, 0.100), + (50.0, 0.5, None), + (0.0, 0.0, 0.200), ] -ACCEL = 3000. +ACCEL = 3000.0 LAYER_H = 0.3 -EXTRUDE_R = (.4 * LAYER_H * 1.0) / (math.pi * (1.75 / 2.)**2) +EXTRUDE_R = (0.4 * LAYER_H * 1.0) / (math.pi * (1.75 / 2.0) ** 2) + def get_acc(start_v, end_v): return ACCEL + # Standard constant acceleration generator def get_acc_pos(rel_t, start_v, accel, move_t): return (start_v + 0.5 * accel * rel_t) * rel_t + # Calculate positions based on 'Moves' list def gen_positions(): out = [] - start_d = start_t = t = 0. + start_d = start_t = t = 0.0 for start_v, end_v, move_t in Moves: if move_t is None: move_t = abs(end_v - start_v) / get_acc(start_v, end_v) @@ -69,10 +79,11 @@ def gen_positions(): # Estimated motion with belt as spring ###################################################################### + def estimate_spring(positions, freq, damping_ratio): - ang_freq2 = (freq * 2. * math.pi)**2 - damping_factor = 4. * math.pi * damping_ratio * freq - head_pos = head_v = 0. + ang_freq2 = (freq * 2.0 * math.pi) ** 2 + damping_factor = 4.0 * math.pi * damping_ratio * freq + head_pos = head_v = 0.0 out = [] for stepper_pos in positions: head_pos += head_v * SEG_TIME @@ -87,39 +98,45 @@ def estimate_spring(positions, freq, damping_ratio): # Pressure advance ###################################################################### -SMOOTH_TIME = .02 -SYSTEM_PRESSURE_ADVANCE = .045 -LINEAR_ADVANCE = .045 +SMOOTH_TIME = 0.02 +SYSTEM_PRESSURE_ADVANCE = 0.045 +LINEAR_ADVANCE = 0.045 LINEAR_VELOCITY = 0.5 -LINEAR_OFFSET = 0. #0.16 +LINEAR_OFFSET = 0.0 # 0.16 + # Calculate raw pressure advance positions def calc_pa_raw(positions): pa = LINEAR_ADVANCE * INV_SEG_TIME recipr_lin_vel = INV_SEG_TIME / LINEAR_VELOCITY - out = [0.] * len(positions) + out = [0.0] * len(positions) for i in indexes(positions): - de = positions[i+1] - positions[i] + de = positions[i + 1] - positions[i] out[i] = positions[i] + pa * de out[i] += LINEAR_OFFSET * math.tanh(de * recipr_lin_vel) - #out[i] += LINEAR_OFFSET * (1. - 1. / (1. + de * recipr_lin_vel)) + # out[i] += LINEAR_OFFSET * (1. - 1. / (1. + de * recipr_lin_vel)) return out + # Pressure advance after smoothing def calc_pa(positions, smooth_time): return calc_weighted(calc_pa_raw(positions), smooth_time) + + def calc_pa2(positions, smooth_time): return calc_weighted2(calc_pa_raw(positions), smooth_time) + # Nozzle flow assuming nozzle follows simple pressure advance model def calc_nozzle_flow(positions, pressure_advance): pa = pressure_advance * INV_SEG_TIME - last = 0. - out = [0.] * len(positions) + last = 0.0 + out = [0.0] * len(positions) for i in range(1, len(positions)): - out[i] = last = (positions[i] - last)/pa + last + out[i] = last = (positions[i] - last) / pa + last return out + ###################################################################### # Toolhead positions and extrusion widths ###################################################################### @@ -127,39 +144,47 @@ def calc_nozzle_flow(positions, pressure_advance): TH_POSITION_BUCKET = 0.200 TH_OFFSET = 10 + # Map toolhead locations def calc_toolhead_positions(positions): th_max = round(max(positions) / TH_POSITION_BUCKET) - th_index = [i * TH_POSITION_BUCKET - for i in range(-TH_OFFSET, th_max + TH_OFFSET)] + th_index = [ + i * TH_POSITION_BUCKET for i in range(-TH_OFFSET, th_max + TH_OFFSET) + ] return th_index + # Determing extrusion amount at each toolhead position def calc_extruded(th_index, th_positions, e_velocities): - e_adjust = SEG_TIME / TH_POSITION_BUCKET * ( - math.pi * (1.75 / 2.)**2) / LAYER_H - out = [0.] * len(th_index) + e_adjust = ( + SEG_TIME / TH_POSITION_BUCKET * (math.pi * (1.75 / 2.0) ** 2) / LAYER_H + ) + out = [0.0] * len(th_index) for th_pos, e in zip(th_positions, e_velocities): bucket = TH_OFFSET + round(th_pos / TH_POSITION_BUCKET) - if e > 0.: + if e > 0.0: out[bucket] += e * e_adjust return out + ###################################################################### # List helper functions ###################################################################### MARGIN_TIME = 0.050 + def time_to_index(t): - return int(t * INV_SEG_TIME + .5) + return int(t * INV_SEG_TIME + 0.5) + def indexes(positions): drop = time_to_index(MARGIN_TIME) - return range(drop, len(positions)-drop) + return range(drop, len(positions) - drop) + def trim_lists(*lists): - keep = len(lists[0]) - time_to_index(2. * MARGIN_TIME) + keep = len(lists[0]) - time_to_index(2.0 * MARGIN_TIME) for l in lists: del l[keep:] @@ -168,70 +193,87 @@ def trim_lists(*lists): # Common data filters ###################################################################### + # Generate estimated first order derivative def gen_deriv(data): - return [0.] + [(data[i+1] - data[i]) * INV_SEG_TIME - for i in range(len(data)-1)] + return [0.0] + [ + (data[i + 1] - data[i]) * INV_SEG_TIME for i in range(len(data) - 1) + ] + # Simple average between two points smooth_time away def calc_average(positions, smooth_time): - offset = time_to_index(smooth_time * .5) - out = [0.] * len(positions) + offset = time_to_index(smooth_time * 0.5) + out = [0.0] * len(positions) for i in indexes(positions): - out[i] = .5 * (positions[i-offset] + positions[i+offset]) + out[i] = 0.5 * (positions[i - offset] + positions[i + offset]) return out + # Average (via integration) of smooth_time range def calc_smooth(positions, smooth_time): - offset = time_to_index(smooth_time * .5) - weight = 1. / (2*offset - 1) - out = [0.] * len(positions) + offset = time_to_index(smooth_time * 0.5) + weight = 1.0 / (2 * offset - 1) + out = [0.0] * len(positions) for i in indexes(positions): - out[i] = sum(positions[i-offset+1:i+offset]) * weight + out[i] = sum(positions[i - offset + 1 : i + offset]) * weight return out + # Time weighted average (via integration) of smooth_time range def calc_weighted(positions, smooth_time): - offset = time_to_index(smooth_time * .5) - weight = 1. / offset**2 - out = [0.] * len(positions) + offset = time_to_index(smooth_time * 0.5) + weight = 1.0 / offset**2 + out = [0.0] * len(positions) for i in indexes(positions): - weighted_data = [positions[j] * (offset - abs(j-i)) - for j in range(i-offset, i+offset)] + weighted_data = [ + positions[j] * (offset - abs(j - i)) + for j in range(i - offset, i + offset) + ] out[i] = sum(weighted_data) * weight return out + # Weighted average (`h**2 - (t-T)**2`) of smooth_time range def calc_weighted2(positions, smooth_time): - offset = time_to_index(smooth_time * .5) - weight = .75 / offset**3 - out = [0.] * len(positions) + offset = time_to_index(smooth_time * 0.5) + weight = 0.75 / offset**3 + out = [0.0] * len(positions) for i in indexes(positions): - weighted_data = [positions[j] * (offset**2 - (j-i)**2) - for j in range(i-offset, i+offset)] + weighted_data = [ + positions[j] * (offset**2 - (j - i) ** 2) + for j in range(i - offset, i + offset) + ] out[i] = sum(weighted_data) * weight return out + # Weighted average (`(h**2 - (t-T)**2)**2`) of smooth_time range def calc_weighted4(positions, smooth_time): - offset = time_to_index(smooth_time * .5) - weight = 15 / (16. * offset**5) - out = [0.] * len(positions) + offset = time_to_index(smooth_time * 0.5) + weight = 15 / (16.0 * offset**5) + out = [0.0] * len(positions) for i in indexes(positions): - weighted_data = [positions[j] * ((offset**2 - (j-i)**2))**2 - for j in range(i-offset, i+offset)] + weighted_data = [ + positions[j] * (offset**2 - (j - i) ** 2) ** 2 + for j in range(i - offset, i + offset) + ] out[i] = sum(weighted_data) * weight return out + # Weighted average (`(h - abs(t-T))**2 * (2 * abs(t-T) + h)`) of range def calc_weighted3(positions, smooth_time): - offset = time_to_index(smooth_time * .5) - weight = 1. / offset**4 - out = [0.] * len(positions) + offset = time_to_index(smooth_time * 0.5) + weight = 1.0 / offset**4 + out = [0.0] * len(positions) for i in indexes(positions): - weighted_data = [positions[j] * (offset - abs(j-i))**2 - * (2. * abs(j-i) + offset) - for j in range(i-offset, i+offset)] + weighted_data = [ + positions[j] + * (offset - abs(j - i)) ** 2 + * (2.0 * abs(j - i) + offset) + for j in range(i - offset, i + offset) + ] out[i] = sum(weighted_data) * weight return out @@ -240,45 +282,60 @@ def calc_weighted3(positions, smooth_time): # Spring motion estimation ###################################################################### + def calc_spring_raw(positions, freq, damping_ratio): - sa = (INV_SEG_TIME / (freq * 2. * math.pi))**2 - ra = 2. * damping_ratio * math.sqrt(sa) - out = [0.] * len(positions) + sa = (INV_SEG_TIME / (freq * 2.0 * math.pi)) ** 2 + ra = 2.0 * damping_ratio * math.sqrt(sa) + out = [0.0] * len(positions) for i in indexes(positions): - out[i] = (positions[i] - + sa * (positions[i-1] - 2.*positions[i] + positions[i+1]) - + ra * (positions[i+1] - positions[i])) + out[i] = ( + positions[i] + + sa * (positions[i - 1] - 2.0 * positions[i] + positions[i + 1]) + + ra * (positions[i + 1] - positions[i]) + ) return out + def calc_spring_double_weighted(positions, freq, smooth_time): - offset = time_to_index(smooth_time * .25) - sa = (INV_SEG_TIME / (offset * freq * 2. * math.pi))**2 - ra = 2. * damping_ratio * math.sqrt(sa) - out = [0.] * len(positions) + offset = time_to_index(smooth_time * 0.25) + sa = (INV_SEG_TIME / (offset * freq * 2.0 * math.pi)) ** 2 + ra = 2.0 * damping_ratio * math.sqrt(sa) # noqa: F821 + out = [0.0] * len(positions) for i in indexes(positions): - out[i] = (positions[i] - + sa * (positions[i-offset] - 2.*positions[i] - + positions[i+offset]) - + ra * (positions[i+1] - positions[i])) - return calc_weighted(out, smooth_time=.5 * smooth_time) + out[i] = ( + positions[i] + + sa + * ( + positions[i - offset] + - 2.0 * positions[i] + + positions[i + offset] + ) + + ra * (positions[i + 1] - positions[i]) + ) + return calc_weighted(out, smooth_time=0.5 * smooth_time) + ###################################################################### # Input shapers ###################################################################### + def calc_shaper(shaper, positions): t_offs = shaper_defs.get_shaper_offset(shaper[0], shaper[1]) A = shaper[0] - inv_D = 1. / sum(A) + inv_D = 1.0 / sum(A) n = len(A) T = [time_to_index(-shaper[1][j]) for j in range(n)] t_offs_ind = time_to_index(t_offs) - out = [0.] * len(positions) + out = [0.0] * len(positions) for i in indexes(positions): - out[i] = sum([positions[i + T[j] + t_offs_ind] * A[j] - for j in range(n)]) * inv_D + out[i] = ( + sum([positions[i + T[j] + t_offs_ind] * A[j] for j in range(n)]) + * inv_D + ) return out + def calc_smoother(smoother, positions): C, t_sm, t_offs, _ = smoother hst = 0.5 * t_sm @@ -292,16 +349,20 @@ def calc_smoother(smoother, positions): pos = np.asarray(positions) t_offs_ind = time_to_index(t_offs) if t_offs_ind < 0: - smoothed = np.convolve(pos[:t_offs_ind], w_dt, mode='same') + smoothed = np.convolve(pos[:t_offs_ind], w_dt, mode="same") else: - smoothed = np.convolve(pos[t_offs_ind:], w_dt, mode='same') - return np.concatenate((np.zeros(shape=(abs(t_offs_ind),)), - smoothed)).tolist() + smoothed = np.convolve(pos[t_offs_ind:], w_dt, mode="same") + return np.concatenate( + (np.zeros(shape=(abs(t_offs_ind),)), smoothed) + ).tolist() + # Ideal values -def gen_updated_position(positions, shaper_name, - shaper_freq, shaper_damping_ratio): + +def gen_updated_position( + positions, shaper_name, shaper_freq, shaper_damping_ratio +): for s in shaper_defs.INPUT_SHAPERS: if s.name == shaper_name.lower(): A, T = s.init_func(shaper_freq, shaper_damping_ratio) @@ -316,35 +377,47 @@ def gen_updated_position(positions, shaper_name, smoother = C, t_sm, t_offs, s.name.upper() return calc_smoother(smoother, positions) -def gen_extr_is_positions(positions, shaper_name, - shaper_freq, shaper_damping_ratio): + +def gen_extr_is_positions( + positions, shaper_name, shaper_freq, shaper_damping_ratio +): for s in shaper_defs.INPUT_SHAPERS: if s.name == shaper_name.lower(): A, T = s.init_func(shaper_freq, shaper_damping_ratio) t_sm = T[-1] - T[0] - t_offs = shaper_defs.get_shaper_offset(A, T) - .5 * t_sm + t_offs = shaper_defs.get_shaper_offset(A, T) - 0.5 * t_sm for s in shaper_defs.INPUT_SMOOTHERS: if s.name == shaper_name.lower(): C, t_sm = s.init_func(shaper_freq) t_offs = shaper_defs.get_smoother_offset(C, t_sm) - C_e, _ = extruder_smoother.get_extruder_smoother(shaper_name, t_sm, - shaper_damping_ratio) + C_e, _ = extruder_smoother.get_extruder_smoother( + shaper_name, t_sm, shaper_damping_ratio + ) smoother = C_e, t_sm, t_offs, shaper_name return calc_smoother(smoother, positions) + ###################################################################### # Plotting and startup ###################################################################### -def plot_motion(shaper_name, shaper_freq, shaper_damping_ratio, - freq, damping_ratio, smooth_time): + +def plot_motion( + shaper_name, + shaper_freq, + shaper_damping_ratio, + freq, + damping_ratio, + smooth_time, +): # Nominal motion positions = gen_positions() velocities = gen_deriv(positions) accels = gen_deriv(velocities) # Updated motion - upd_positions = gen_updated_position(positions, shaper_name, - shaper_freq, shaper_damping_ratio) + upd_positions = gen_updated_position( + positions, shaper_name, shaper_freq, shaper_damping_ratio + ) upd_velocities = gen_deriv(upd_positions) upd_accels = gen_deriv(upd_velocities) # Estimated position with model of belt as spring @@ -357,40 +430,58 @@ def plot_motion(shaper_name, shaper_freq, shaper_damping_ratio, # Motion with pressure advance extruder_positions = [p * EXTRUDE_R for p in positions] extruder_velocities = [v * EXTRUDE_R for v in velocities] - nom_flow = gen_deriv(calc_nozzle_flow(extruder_positions, - SYSTEM_PRESSURE_ADVANCE)) + nom_flow = gen_deriv( + calc_nozzle_flow(extruder_positions, SYSTEM_PRESSURE_ADVANCE) + ) pa_positions = calc_pa_raw(extruder_positions) pa_velocities = gen_deriv(pa_positions) pa_accels = gen_deriv(pa_velocities) - pa_flow = gen_deriv(calc_nozzle_flow(pa_positions, - SYSTEM_PRESSURE_ADVANCE)) + pa_flow = gen_deriv(calc_nozzle_flow(pa_positions, SYSTEM_PRESSURE_ADVANCE)) # Smoothed PA motion sm_pa_positions = calc_pa(extruder_positions, smooth_time) sm_pa_velocities = gen_deriv(sm_pa_positions) sm_pa_accels = gen_deriv(sm_pa_velocities) - sm_pa_flow = gen_deriv(calc_nozzle_flow(sm_pa_positions, - SYSTEM_PRESSURE_ADVANCE)) + sm_pa_flow = gen_deriv( + calc_nozzle_flow(sm_pa_positions, SYSTEM_PRESSURE_ADVANCE) + ) # Extruder synchronization with IS - extr_is_pos = gen_extr_is_positions(extruder_positions, shaper_name, - shaper_freq, shaper_damping_ratio) + extr_is_pos = gen_extr_is_positions( + extruder_positions, shaper_name, shaper_freq, shaper_damping_ratio + ) extr_is_vel = gen_deriv(extr_is_pos) extr_is_pa_pos = calc_pa_raw(extr_is_pos) extr_is_pa_vel = gen_deriv(extr_is_pa_pos) extr_is_pa_accel = gen_deriv(extr_is_pa_vel) - extr_is_pa_flow = gen_deriv(calc_nozzle_flow(extr_is_pa_pos, - SYSTEM_PRESSURE_ADVANCE)) + extr_is_pa_flow = gen_deriv( + calc_nozzle_flow(extr_is_pa_pos, SYSTEM_PRESSURE_ADVANCE) + ) # Build plot times = [SEG_TIME * i for i in range(len(positions))] - trim_lists(times, velocities, accels, - positions, spring_upd, - upd_velocities, upd_velocities, upd_accels, - head_velocities, head_upd_velocities, - head_accels, head_upd_accels, - extruder_positions, extruder_velocities, - pa_positions, pa_velocities, pa_flow, - sm_pa_velocities, sm_pa_flow, - extr_is_vel, extr_is_pa_vel, extr_is_pa_flow) + trim_lists( + times, + velocities, + accels, + positions, + spring_upd, + upd_velocities, + upd_velocities, + upd_accels, + head_velocities, + head_upd_velocities, + head_accels, + head_upd_accels, + extruder_positions, + extruder_velocities, + pa_positions, + pa_velocities, + pa_flow, + sm_pa_velocities, + sm_pa_flow, + extr_is_vel, + extr_is_pa_vel, + extr_is_pa_flow, + ) # Extrusion width th_index = calc_toolhead_positions(positions) ext_nom = calc_extruded(th_index, positions, extruder_velocities) @@ -398,96 +489,148 @@ def plot_motion(shaper_name, shaper_freq, shaper_damping_ratio, ext_smooth_pa_is = calc_extruded(th_index, spring_upd, sm_pa_flow) ext_is_pa = calc_extruded(th_index, spring_upd, extr_is_pa_flow) - fig, axs = matplotlib.pyplot.subplot_mosaic([ - ['Extruder position', 'Extrusion width'], - ['Extruder velocity', 'Extrusion width'], - ['Extruder acceleration', 'Extrusion width']]) + fig, axs = matplotlib.pyplot.subplot_mosaic( + [ + ["Extruder position", "Extrusion width"], + ["Extruder velocity", "Extrusion width"], + ["Extruder acceleration", "Extrusion width"], + ] + ) ((_, ax1), (_, ax4), (_, ax2), (_, ax3)) = axs.items() - ax1.set_title("Simulation: resonance freq=%.1f Hz, damping_ratio=%.3f,\n" - "shaper = %s, configured freq=%.1f Hz" - % (freq, damping_ratio, shaper_name, shaper_freq)) - ax1.set_ylabel('Velocity (mm/s)') - ax1.plot(times, velocities, 'g', label='Nominal Velocity', alpha=0.8) - ax1.plot(times, upd_velocities, 'r', label='New Velocity', alpha=0.8) - ax1.plot(times, head_velocities, 'orange', label='Head Velocity', alpha=0.4) - ax1.plot(times, head_upd_velocities, 'blue', label='New Head Velocity', - alpha=0.4) + ax1.set_title( + "Simulation: resonance freq=%.1f Hz, damping_ratio=%.3f,\n" + "shaper = %s, configured freq=%.1f Hz" + % (freq, damping_ratio, shaper_name, shaper_freq) + ) + ax1.set_ylabel("Velocity (mm/s)") + ax1.plot(times, velocities, "g", label="Nominal Velocity", alpha=0.8) + ax1.plot(times, upd_velocities, "r", label="New Velocity", alpha=0.8) + ax1.plot(times, head_velocities, "orange", label="Head Velocity", alpha=0.4) + ax1.plot( + times, head_upd_velocities, "blue", label="New Head Velocity", alpha=0.4 + ) fontP = matplotlib.font_manager.FontProperties() - fontP.set_size('x-small') - ax1.legend(loc='best', prop=fontP) + fontP.set_size("x-small") + ax1.legend(loc="best", prop=fontP) ax1.grid(True) - ax2.set_ylabel('Acceleration (mm/s^2)') - #ax2.plot(times, accels, 'g', label='Nominal Accel', alpha=0.8) - ax2.plot(times, upd_accels, 'r', label='New Accel', alpha=0.8) - ax2.plot(times, head_accels, 'orange', label='Head Accel', alpha=0.4) - ax2.plot(times, head_upd_accels, 'blue', label='New Head Accel', alpha=0.4) - ax2.set_ylim([-5. * ACCEL, 5. * ACCEL]) - ax2.legend(loc='best', prop=fontP) + ax2.set_ylabel("Acceleration (mm/s^2)") + # ax2.plot(times, accels, 'g', label='Nominal Accel', alpha=0.8) + ax2.plot(times, upd_accels, "r", label="New Accel", alpha=0.8) + ax2.plot(times, head_accels, "orange", label="Head Accel", alpha=0.4) + ax2.plot(times, head_upd_accels, "blue", label="New Head Accel", alpha=0.4) + ax2.set_ylim([-5.0 * ACCEL, 5.0 * ACCEL]) + ax2.legend(loc="best", prop=fontP) ax2.grid(True) - ax3.set_ylabel('Extruder velocity (mm/s)') - ax3.plot(times, extruder_velocities, 'black', label='Nominal') - ax3.plot(times, sm_pa_velocities, 'g', label='Smooth PA', alpha=0.9) - ax3.plot(times, extr_is_vel, 'orange', label='Extr IS', alpha=0.5) - ax3.plot(times, extr_is_pa_vel, 'blue', label='Extr IS PA', alpha=0.5) - ax3.plot(times, pa_flow, label='PA flow') - ax3.plot(times, sm_pa_flow, label='Smooth PA flow') + ax3.set_ylabel("Extruder velocity (mm/s)") + ax3.plot(times, extruder_velocities, "black", label="Nominal") + ax3.plot(times, sm_pa_velocities, "g", label="Smooth PA", alpha=0.9) + ax3.plot(times, extr_is_vel, "orange", label="Extr IS", alpha=0.5) + ax3.plot(times, extr_is_pa_vel, "blue", label="Extr IS PA", alpha=0.5) + ax3.plot(times, pa_flow, label="PA flow") + ax3.plot(times, sm_pa_flow, label="Smooth PA flow") ax3.grid(True) - ax3.legend(loc='best', prop=fontP) - ax3.set_xlabel('Time (s)') - - ax4.set_title('Extruion width') - ax4.set_xlabel('Time (s)') - ax4.set_ylabel('Filament extruded (mm)') - ax4.plot(th_index, ext_nom, 'black', label='Nominal') - ax4.plot(th_index, ext_smooth_pa_ideal, - 'r', label='Smooth PA with ideal TH motion', alpha=0.5) - ax4.plot(th_index, ext_smooth_pa_is, - 'g', label='Smooth PA with IS', alpha=0.7) - ax4.plot(th_index, ext_is_pa, - 'blue', label='Extr IS PA', alpha=0.5) - ax4.legend(loc='best', prop=fontP) - ax4.set_xlabel('Toolhead Position (mm)') + ax3.legend(loc="best", prop=fontP) + ax3.set_xlabel("Time (s)") + + ax4.set_title("Extruion width") + ax4.set_xlabel("Time (s)") + ax4.set_ylabel("Filament extruded (mm)") + ax4.plot(th_index, ext_nom, "black", label="Nominal") + ax4.plot( + th_index, + ext_smooth_pa_ideal, + "r", + label="Smooth PA with ideal TH motion", + alpha=0.5, + ) + ax4.plot( + th_index, ext_smooth_pa_is, "g", label="Smooth PA with IS", alpha=0.7 + ) + ax4.plot(th_index, ext_is_pa, "blue", label="Extr IS PA", alpha=0.5) + ax4.legend(loc="best", prop=fontP) + ax4.set_xlabel("Toolhead Position (mm)") ax4.grid(True) return fig + def setup_matplotlib(output_to_file): global matplotlib if output_to_file: - matplotlib.use('Agg') + matplotlib.use("Agg") import matplotlib.pyplot, matplotlib.dates, matplotlib.font_manager import matplotlib.ticker + def main(): # Parse command-line arguments usage = "%prog [options]" opts = optparse.OptionParser(usage) - opts.add_option("-o", "--output", type="string", dest="output", - default=None, help="filename of output graph") - opts.add_option("-s", "--shaper", type="string", dest="shaper", - default="ei", help="name of the shaper to plot") - opts.add_option("-f", "--freq", type="float", dest="freq", - default=SPRING_FREQ, - help="the frequency of the system") - opts.add_option("--damping_ratio", type="float", dest="damping_ratio", - default=DAMPING_RATIO, - help="the damping ratio of the system") - opts.add_option("--shaper_freq", type="float", dest="shaper_freq", - default=SHAPER_FREQ, - help="the frequency of the shaper") - opts.add_option("--shaper_damping_ratio", type="float", - dest="shaper_damping_ratio", default=SHAPER_DAMPING_RATIO, - help="the damping ratio of the shaper") - opts.add_option("--smooth_time", type="float", dest="smooth_time", - default=SMOOTH_TIME, help="extruder smooth time") + opts.add_option( + "-o", + "--output", + type="string", + dest="output", + default=None, + help="filename of output graph", + ) + opts.add_option( + "-s", + "--shaper", + type="string", + dest="shaper", + default="ei", + help="name of the shaper to plot", + ) + opts.add_option( + "-f", + "--freq", + type="float", + dest="freq", + default=SPRING_FREQ, + help="the frequency of the system", + ) + opts.add_option( + "--damping_ratio", + type="float", + dest="damping_ratio", + default=DAMPING_RATIO, + help="the damping ratio of the system", + ) + opts.add_option( + "--shaper_freq", + type="float", + dest="shaper_freq", + default=SHAPER_FREQ, + help="the frequency of the shaper", + ) + opts.add_option( + "--shaper_damping_ratio", + type="float", + dest="shaper_damping_ratio", + default=SHAPER_DAMPING_RATIO, + help="the damping ratio of the shaper", + ) + opts.add_option( + "--smooth_time", + type="float", + dest="smooth_time", + default=SMOOTH_TIME, + help="extruder smooth time", + ) options, args = opts.parse_args() if len(args) != 0: opts.error("Incorrect number of arguments") # Draw graph setup_matplotlib(options.output is not None) - fig = plot_motion(options.shaper, - options.shaper_freq, options.shaper_damping_ratio, - options.freq, options.damping_ratio, options.smooth_time) + fig = plot_motion( + options.shaper, + options.shaper_freq, + options.shaper_damping_ratio, + options.freq, + options.damping_ratio, + options.smooth_time, + ) # Show graph if options.output is None: @@ -496,5 +639,6 @@ def main(): fig.set_size_inches(8, 6) fig.savefig(options.output) -if __name__ == '__main__': + +if __name__ == "__main__": main() diff --git a/scripts/klippy-requirements.txt b/scripts/klippy-requirements.txt index cd1ef0c40..e59d932ef 100644 --- a/scripts/klippy-requirements.txt +++ b/scripts/klippy-requirements.txt @@ -9,4 +9,4 @@ greenlet==3.0.3 ; python_version >= '3.12' Jinja2==3.1.4 python-can==3.3.4 markupsafe==2.1.5 -numpy==1.25.2 +numpy==1.26.4 diff --git a/scripts/motan/data_logger.py b/scripts/motan/data_logger.py index d94703b5a..6eb54a39a 100644 --- a/scripts/motan/data_logger.py +++ b/scripts/motan/data_logger.py @@ -189,6 +189,7 @@ def handle_subscribe(self, msg, raw_msg): lname = "%s:%s" % (st, aname) qcmd = "%s/dump_%s" % (st, st) self.send_subscribe(lname, qcmd, {"sensor": aname}) + def handle_dump(self, msg, raw_msg): msg_id = msg["id"] if "result" not in msg: