Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# top-most EditorConfig file
root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.{py,sh}]
indent_style = space
indent_size = 4
7 changes: 7 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"recommendations": [
"yzhang.markdown-all-in-one",
"EditorConfig.EditorConfig",
"dannymcgee.klipper"
]
}
6 changes: 4 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"editor.rulers": [
70, 80, 120
]
}
],
"markdown.extension.toc.levels": "2..6",
"markdown.extension.toc.updateOnSave": true
}
134 changes: 58 additions & 76 deletions Kalico/klippy_module/trad_rack.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,11 @@ def __init__(self, config):
self.cmd_TR_PRINT_TOOL_GROUPS,
desc=self.cmd_TR_PRINT_TOOL_GROUPS_help,
)
self.gcode.register_command(
"TR_QUERY_LANE_ENTRY_SENSORS",
self.cmd_TR_QUERY_LANE_ENTRY_SENSORS,
desc=self.cmd_TR_QUERY_LANE_ENTRY_SENSORS_help,
)
if register_toolchange_commands:
for i in range(self.lane_count):
self.gcode.register_command(
Expand Down Expand Up @@ -1134,6 +1139,19 @@ def cmd_TR_PRINT_TOOL_GROUPS(self, gcmd):
msg += "\n"
gcmd.respond_info(msg)

cmd_TR_QUERY_LANE_ENTRY_SENSORS_help = "Query the status of the lane entry sensors"

def cmd_TR_QUERY_LANE_ENTRY_SENSORS(self, gcmd):
triggered_sensors = self._get_lane_entry_sensors_active()
msg = ""
for lane, triggered in enumerate(triggered_sensors):
if triggered is None:
msg += "Lane {}: UNAVAILABLE".format(lane)
else:
msg += "Lane {}: {}".format(lane, "TRIGGERED" if triggered[0] else "UNTRIGGERED")
msg += "\n"
gcmd.respond_info(msg)

# helper functions
def _lower_servo(self, toolhead_dwell=False):
self.tr_toolhead.wait_moves()
Expand Down Expand Up @@ -2335,6 +2353,19 @@ def _set_lane_entry_sensors_active(self, sensors_active):
trigger_active, untrigger_active = sensors_active[lane]
sensor.set_trigger_active(trigger_active)
sensor.set_untrigger_active(untrigger_active)
def _get_lane_entry_sensors_state(self, gcmd):
sensors_state = [None] * self.lane_count
# return the last raw state reported by each sensor (or None)
msg = "trad_rack: Lane entry sensors state:\n"
for lane in range(self.lane_count):
sensor = self.lane_entry_sensors[lane]
if sensor is not None:
msg += "Lane {}: {}\n".format(lane, "OPEN" if 0 in sensor.state else "CLOSED")
sensors_state[lane] = sensor.state
else:
sensors_state[lane] = "UNAVAILABLE"
msg += "\n"
gcmd.respond_info(msg)

# resume callbacks
def _resume_load_toolhead(self):
Expand Down Expand Up @@ -2430,6 +2461,7 @@ def get_status(self, eventtime):
"next_tool": self.next_tool,
"tool_map": self.tool_map,
"selector_homed": self._is_selector_homed(),
"lane_entry_sensors": self._get_lane_entry_sensors_state(),
}


Expand All @@ -2441,16 +2473,9 @@ def __init__(self, config, buffer_pull_speed, is_extruder_synced):
except config.error:
pass
self.reactor = self.printer.get_reactor()
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.lookahead.set_flush_time(toolhead.BUFFER_TIME_HIGH)
else:
self.move_queue = toolhead.MoveQueue(self)
self.move_queue.set_flush_time(toolhead.BUFFER_TIME_HIGH)
self.mcu = self.printer.lookup_object("mcu")
self.lookahead = toolhead.LookAheadQueue()
self.lookahead.set_flush_time(toolhead.BUFFER_TIME_HIGH)
self.commanded_pos = [0.0, 0.0, 0.0, 0.0]
# Velocity and acceleration control
tr_config = config.getsection("trad_rack")
Expand All @@ -2466,24 +2491,13 @@ def __init__(self, config, buffer_pull_speed, is_extruder_synced):
"filament_max_accel", default=1500.0, above=0.0
)
self.max_accel = max(self.sel_max_accel, self.fil_max_accel)
self.min_cruise_ratio = config.getfloat(
"minimum_cruise_ratio", None, below=1.0, minval=0.0
)
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
)
if req_accel_to_decel is not None:
config.deprecate("max_accel_to_decel")
self.min_cruise_ratio = 1.0 - min(
1.0, (req_accel_to_decel / self.max_accel)
)
self.requested_accel_to_decel = self.min_cruise_ratio * self.max_accel
self.square_corner_velocity = config.getfloat(
"square_corner_velocity", 5.0, minval=0.0
self.min_cruise_ratio = tr_config.getfloat(
"minimum_cruise_ratio", 0.0, below=1.0, minval=0.0
)
self.square_corner_velocity = tr_config.getfloat(
"square_corner_velocity", 0.0, minval=0.0
)
self.junction_deviation = self.max_accel_to_decel = 0.0
self.junction_deviation = self.mcr_pseudo_accel = 0.0
self._calc_junction_deviation()
# Input stall detection
self.check_stall_time = 0.0
Expand All @@ -2497,26 +2511,13 @@ def __init__(self, config, buffer_pull_speed, is_extruder_synced):
self.print_time = 0.0
self.special_queuing_state = "NeedPrime"
self.priming_timer = None
# 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
)
# Kinematic step generation scan window time tracking
self.kin_flush_delay = toolhead.SDS_CHECK_TIME
self.kin_flush_times = []
# Setup iterative solver
ffi_main, ffi_lib = chelper.get_ffi()
self.trapq = ffi_main.gc(ffi_lib.trapq_alloc(), ffi_lib.trapq_free)
self.trapq_append = ffi_lib.trapq_append
self.trapq_finalize_moves = ffi_lib.trapq_finalize_moves
# Motion flushing
self.step_generators = []
self.flush_trapqs = [self.trapq]
# Setup for generating moves
self.motion_queuing = self.printer.load_object(config, "motion_queuing")
self.motion_queuing.register_flush_callback(
self._handle_step_flush, can_add_trapq=True
)
self.trapq = self.motion_queuing.allocate_trapq()
self.trapq_append = self.motion_queuing.lookup_trapq_append()
# Create kinematic class
gcode = self.printer.lookup_object("gcode")
self.Coord = gcode.Coord
Expand Down Expand Up @@ -2561,11 +2562,6 @@ def __init__(self, toolhead, config, is_extruder_synced):
rail.setup_itersolve("cartesian_stepper_alloc", axis.encode())
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
)

# Setup boundary checks
self.sel_max_velocity, self.sel_max_accel = (
toolhead.get_sel_max_velocity()
Expand All @@ -2585,8 +2581,7 @@ def __init__(self, toolhead, config, is_extruder_synced):
self.is_extruder_synced = is_extruder_synced

def get_steppers(self):
rails = self.rails
return [s for rail in rails for s in rail.get_steppers()]
return [s for rail in self.rails for s in rail.get_steppers()]

def calc_position(self, stepper_positions):
return [stepper_positions[rail.get_name()] for rail in self.rails]
Expand All @@ -2597,11 +2592,7 @@ def set_position(self, newpos, homing_axes):
if i in homing_axes:
self.limits[i] = rail.get_range()

def note_z_not_homed(self):
# Helper for Safe Z Home
pass

def _home_axis(self, homing_state, axis, rail):
def home_axis(self, homing_state, axis, rail):
# Determine movement
position_min, position_max = rail.get_range()
hi = rail.get_homing_info()
Expand All @@ -2618,10 +2609,7 @@ def _home_axis(self, homing_state, axis, rail):
def home(self, homing_state):
# Each axis is homed independently and in order
for axis in homing_state.get_axes():
self._home_axis(homing_state, axis, self.rails[axis])

def _motor_off(self, print_time):
self.limits = [(1.0, -1.0)] * self.stepper_count
self.home_axis(homing_state, axis, self.rails[axis])

def _check_endstops(self, move):
end_pos = move.end_pos
Expand Down Expand Up @@ -2873,8 +2861,6 @@ def _sync(self, sync_type):
self._prev_trapq = steppers[0].get_trapq()
external_trapq = self.tr_toolhead.get_trapq()
stepper_alloc = ffi_lib.cartesian_stepper_alloc(b"y")
prev_toolhead = self.toolhead
external_toolhead = self.tr_toolhead
self.reset_fil_driver()
new_pos = [0.0, 0.0, 0.0]
elif sync_type == FIL_DRIVER_TO_EXTRUDER:
Expand All @@ -2883,8 +2869,6 @@ def _sync(self, sync_type):
extruder = self.toolhead.get_extruder()
external_trapq = extruder.get_trapq()
stepper_alloc = ffi_lib.extruder_stepper_alloc()
prev_toolhead = self.tr_toolhead
external_toolhead = self.toolhead
new_pos = extruder.last_position
if not isinstance(new_pos, list):
new_pos = [new_pos, 0.0, 0.0]
Expand All @@ -2901,8 +2885,6 @@ def _sync(self, sync_type):
)
stepper.set_trapq(external_trapq)
stepper.set_position(new_pos)
prev_toolhead.step_generators.remove(stepper.generate_steps)
external_toolhead.register_step_generator(stepper.generate_steps)
self.sync_state = sync_type

def sync_extruder_to_fil_driver(self):
Expand All @@ -2921,20 +2903,14 @@ def unsync(self):

if self.sync_state == EXTRUDER_TO_FIL_DRIVER:
steppers = self._get_extruder_mcu_steppers()
prev_toolhead = self.toolhead
external_toolhead = self.tr_toolhead
elif self.sync_state == FIL_DRIVER_TO_EXTRUDER:
self.printer.send_event("trad_rack:unsyncing_from_extruder")
steppers = self.fil_driver_rail.get_steppers()
prev_toolhead = self.tr_toolhead
external_toolhead = self.toolhead
else:
raise Exception("Invalid sync_state: %d" % self.sync_state)

for i in range(len(steppers)):
stepper = steppers[i]
external_toolhead.step_generators.remove(stepper.generate_steps)
prev_toolhead.register_step_generator(stepper.generate_steps)
stepper.set_trapq(self._prev_trapq)
stepper.set_stepper_kinematics(self._prev_sks[i])
stepper.set_rotation_distance(self._prev_rotation_dists[i])
Expand Down Expand Up @@ -3024,7 +3000,6 @@ def __init__(
untrigger_only_when_printing,
trigger_only_when_printing,
]

if allow_duplicate_pins:
# disable config checks for duplicate pins
pin_desc = pin
Expand All @@ -3040,7 +3015,11 @@ def __init__(
buttons.register_buttons([pin], self.sensor_callback)

self.printer.register_event_handler("klippy:ready", self.handle_ready)
# last raw state reported by the button callback (None if unknown)
# state values come from the buttons framework (usually 0/1)
self.state = None

# active flags control whether trigger/untrigger callbacks will run
self.active = [False, False]

def handle_ready(self):
Expand All @@ -3049,6 +3028,9 @@ def handle_ready(self):
self.active[state] = True

def sensor_callback(self, eventtime, state):
# always record the last raw sensor state so callers can query it
# even when callbacks/auto-reset logic prevents triggering handlers
self.state = state
idle_timeout = self.printer.lookup_object("idle_timeout")
printing = idle_timeout.get_status(eventtime)["state"] == "Printing"
if (
Expand Down
38 changes: 25 additions & 13 deletions docs/kalico/Config_Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,45 @@ This document is modeled after Kalico's
but only contains items pertaining to Trad Rack.

**Table of Contents**

- [Main configuration](#main-configuration)
- [\[trad\_rack\]](#trad_rack)
- [\[trad_rack\]](#trad_rack)
- [Additional sections](#additional-sections)
- [\[stepper\_tr\_selector\]](#stepper_tr_selector)
- [\[stepper\_tr\_fil\_driver\]](#stepper_tr_fil_driver)
- [\[tmc2209 stepper\_tr\_selector\]](#tmc2209-stepper_tr_selector)
- [\[tmc2209 stepper\_tr\_fil\_driver\]](#tmc2209-stepper_tr_fil_driver)
- [\[servo tr\_servo\]](#servo-tr_servo)
- [\[stepper_tr_selector\]](#stepper_tr_selector)
- [\[stepper_tr_fil_driver\]](#stepper_tr_fil_driver)
- [\[tmc2209 stepper_tr_selector\]](#tmc2209-stepper_tr_selector)
- [\[tmc2209 stepper_tr_fil_driver\]](#tmc2209-stepper_tr_fil_driver)
- [\[servo tr_servo\]](#servo-tr_servo)

## Main configuration

### [trad_rack]

Main configuration section for Trad Rack. Some config options
reference [Tuning.md](/docs/Tuning.md) for more details.

```
[trad_rack]
selector_max_velocity:
# Maximum velocity (in mm/s) of the selector.
# Maximum velocity (in mm/s) of the selector.
# This parameter must be specified.
selector_max_accel:
# Maximum acceleration (in mm/s^2) of the selector.
# Maximum acceleration (in mm/s^2) of the selector.
# This parameter must be specified.
#filament_max_velocity:
# Maximum velocity (in mm/s) for filament movement.
# Maximum velocity (in mm/s) for filament movement.
# Defaults to buffer_pull_speed.
#filament_max_accel: 1500.0
# Maximum acceleration (in mm/s^2) for filament movement.
# The default is 1500.0.
toolhead_fil_sensor_pin:
# The pin on which the toolhead filament sensor is connected.
# If a pin is not specified, no toolhead filament sensor will
# If a pin is not specified, no toolhead filament sensor will
# be used.
lane_count:
# The number of filament lanes. This parameter must be specified.
lane_spacing:
# Spacing (in mm) between filament lanes.
# Spacing (in mm) between filament lanes.
# This parameter must be specified.
#lane_offset_<lane index>:
# Options with a "lane_offset_" prefix may be specified for any of
Expand Down Expand Up @@ -135,7 +137,7 @@ toolhead_unload_length:
# segment into the lane module.
#spool_pull_speed: 100.0
# Speed (in mm/s) to move filament through the bowden tube when
# loading from a spool. See Tuning.md for details.
# loading from a spool. See Tuning.md for details.
# The default is 100.0.
#buffer_pull_speed:
# Speed (in mm/s) to move filament through the bowden tube when
Expand All @@ -157,7 +159,7 @@ toolhead_unload_length:
#load_with_toolhead_sensor: True
# Whether to use the toolhead sensor when loading the toolhead.
# See Tuning.md for details. Defaults to True but is ignored if
# toolhead_fil_sensor_pin is not specified.
# toolhead_fil_sensor_pin is not specified.
#unload_with_toolhead_sensor: True
# Whether to use the toolhead sensor when unloading the toolhead.
# See Tuning.md for details. Defaults to True but is ignored if
Expand Down Expand Up @@ -235,6 +237,16 @@ toolhead_unload_length:
# entry sensor so that the corresponding lane can be loaded. If set
# to False, the lane will not be automatically loaded unless the
# selector is already homed. The default is True.
#minimum_cruise_ratio: 0.0
# See the "printer" section of Kalico's Config Reference document
# for a description of this parameter. This parameter affects
# selector moves and filament moves made by Trad Rack. The default
# is 0.0.
#square_corner_velocity: 0.0
# See the "printer" section of Kalico's Config Reference document
# for a description of this parameter. This parameter can affect
# selector moves and filament moves made by Trad Rack. The default
# is 0.0.
#log_bowden_lengths: False
# Whether to log bowden load length data and bowden unload length
# data (to ~/bowden_load_lengths.csv and ~/bowden_unload_lengths.csv
Expand Down
Loading