Skip to content

Commit

Permalink
refinements to selector homing, don't allow tool to be selected and n…
Browse files Browse the repository at this point in the history
…ot homed, simplification of mmu toolhead homing, added GATES as parameter option to MMU_CHECK_GATE
  • Loading branch information
moggieuk committed Oct 26, 2023
1 parent 3ae303c commit 0ab1eb0
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 35 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Happy Hare has a built in help system to aid remembering the command set. It can
Happy Hare MMU commands: (use MMU_HELP MACROS=1 TESTING=1 for full command set)
MMU : Enable/Disable functionality and reset state
MMU_CHANGE_TOOL : Perform a tool swap
MMU_CHECK_GATES : Automatically inspects gate(s), parks filament and marks availability
MMU_CHECK_GATE : Automatically inspects gate(s), parks filament and marks availability
MMU_STATS : Dump (and optionally reset) the MMU statistics
MMU_EJECT : Eject filament and park it in the MMU or optionally unloads just the extruder (EXTRUDER_ONLY=1)
MMU_ENCODER : Display encoder position or temporarily enable/disable detection logic in encoder
Expand Down Expand Up @@ -497,7 +497,7 @@ Needless to say, other operations can update specific state<br>
Couple of miscellaneous notes:

<ul>
<li>Closely relevant to the usefulness of this functionality is the `MMU_CHECK_GATES` command that will examine all or selection of gates for presence of filament</li>
<li>Closely relevant to the usefulness of this functionality is the `MMU_CHECK_GATE` command that will examine all or selection of gates for presence of filament</li>
<li>In the graphic depictions of filament state the `*` indicates presence ('B' and 'S' represent whether the filament is buffered or pulling straight from the spool), '?' unknown and ' ' or '.' the lack of filament</li>
<li>With tool-to-gate mapping it is entirely possible to have multiple tools mapped to the same gate (for example to force a multi-color print to be monotone) and therefore some gates can be made inaccessable until map is reset</li>
<li>The default value for `gate_status`, `tool_to_gate_map` and `endless_spool_groups` can be set in `mmu_parameters.cfg`. If not set the default will be, Tx maps to Gate#x, the status of each gate is unknown and each tool is in its own endless spool group (i.e. not part of a group)</li>
Expand Down Expand Up @@ -804,17 +804,17 @@ Finally, you can unload just the extruder using the usual eject:
### 11. Useful pre-print functionality
There are a couple of commands (`MMU_PRELOAD` and `MMU_CHECK_GATES`) that are useful to ensure MMU readiness prior to printing.
There are a couple of commands (`MMU_PRELOAD` and `MMU_CHECK_GATE`) that are useful to ensure MMU readiness prior to printing.
<details>
<summary><sub>🔹 Read more on pre-print readiness...</sub></summary><br>
The `MMU_PRELOAD` is an aid to loading filament into the MMU. The command works a bit like the Prusa's functionality and spins gear with servo depressed until filament is fed in. It then parks the filament nicely. This is the recommended way to load filament into your MMU and ensures that filament is not under/over inserted potentially preventing pickup or blocking the gate.<br>
Similarly the `MMU_CHECK_GATES` command will run through all the gates (or the one specified), checks that filament is loaded, correctly parks and updates the "gate status" map so the MMU knows which gates have filament available.<br>
Similarly the `MMU_CHECK_GATE` command will run through all the gates (or the one specified), checks that filament is loaded, correctly parks and updates the "gate status" map so the MMU knows which gates have filament available.<br>
> [!NOTE]
> The `MMU_CHECK_GATES` command has a special option that is designed to be called from your `PRINT_START` macro. When called as in this example: `MMU_CHECK_GATES TOOLS=0,3,5`. Happy Hare will validate that tools 0, 3 & 5 are ready to go else generate an error prior to starting the print. This is a really useful pre-print check! See [Gcode Preprocessing](./doc/gcode_preprocessing.md) for more details.
> The `MMU_CHECK_GATE` command has a special option that is designed to be called from your `PRINT_START` macro. When called as in this example: `MMU_CHECK_GATE TOOLS=0,3,5`. Happy Hare will validate that tools 0, 3 & 5 are ready to go else generate an error prior to starting the print. This is a really useful pre-print check! See [Gcode Preprocessing](./doc/gcode_preprocessing.md) for more details.
</details>
Expand Down
21 changes: 14 additions & 7 deletions config/base/mmu_software.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,25 @@ gcode:
{% set GATE = params.GATE|default(0)|int %}
MMU_PRELOAD GATE={GATE}

[gcode_macro MMU__CHECK_GATES]
[gcode_macro MMU__CHECK_GATE]
gcode:
{% set GATE = params.GATE|default(0)|int %}
MMU_CHECK_GATES GATE={GATE}
{% set GATE = params.GATE|default(-1)|int %}
{% set TOOL = params.GATE|default(-1)|int %}
{% set GATES = params.GATE|default('!')|string %}
{% set TOOLS = params.GATE|default('!')|string %}
MMU_CHECK_GATE GATE={GATE} TOOL={TOOL} GATES={GATES} TOOLS={TOOLS}

# Useful convenience commands...
# Aliases (for backward compatibility)...

[gcode_macro MMU_CHANGE_TOOL_STANDALONE]
description: Convenience macro for inclusion in print_start for initial tool load (defined in mmu_software.cfg)
description: Convenience macro for inclusion in print_start for initial tool load
gcode:
{% set TOOL = params.TOOL|default(0)|int %}
MMU_CHANGE_TOOL TOOL={TOOL} STANDALONE=1
MMU_CHANGE_TOOL {rawparams} STANDALONE=1

[gcode_macro MMU_CHECK_GATES]
description: Alias for updated macro name of MMU_CHECK_GATE
gcode:
MMU_CHECK_GATE {rawparams}


########################################################################
Expand Down
4 changes: 2 additions & 2 deletions doc/command_ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Firstly you can get a quick reminder of commands using the `MMU_HELP` command fr
Happy Hare MMU commands: (use MMU_HELP MACROS=1 TESTING=1 for full command set)
MMU : Enable/Disable functionality and reset state
MMU_CHANGE_TOOL : Perform a tool swap
MMU_CHECK_GATES : Automatically inspects gate(s), parks filament and marks availability
MMU_CHECK_GATE : Automatically inspects gate(s), parks filament and marks availability
MMU_STATS : Dump or reset the MMU statistics
MMU_EJECT : Eject filament and park it in the MMU or optionally unloads just the extruder (EXTRUDER_ONLY=1)
MMU_ENCODER : Display encoder position or temporarily enable/disable detection logic in encoder
Expand Down Expand Up @@ -66,7 +66,7 @@ Firstly you can get a quick reminder of commands using the `MMU_HELP` command fr
### Filament specification, Tool to Gate map and Endless spool commands
| Command | Description | &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Parameters&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp |
| ------- | ----------- | ---------- |
| `MMU_CHECK_GATES` | Inspect the gate(s) and mark availability | `GATE=[0..n]` The specific gate to check <br>`TOOL=[0..n]` The specific too to check (same as gate if no TTG mapping in place) <br>`TOOLS={csv}` The list of tools to check. Typically used in print start macro to validate all necessary tools <br>If all parameters are omitted all gates will be checked (the default) <br>`QUIET=[0\|1]` Optional. Supresses dump of gate status at end of checking procedure |
| `MMU_CHECK_GATE` | Inspect the gate(s) and mark availability | `GATE=[0..n]` The specific gate to check <br>`TOOL=[0..n]` The specific too to check (same as gate if no TTG mapping in place) <br>`TOOLS={csv}` The list of tools to check. Typically used in print start macro to validate all necessary tools <br>`GATES={csv}` The lis of gates to check. <br>If all parameters are omitted all gates will be checked (the default) <br>`QUIET=[0\|1]` Optional. Supresses dump of gate status at end of checking procedure |
| `MMU_GATE_MAP` | Without parameters this will display the current gate map. Optionally configure the filament type, color and availabilty. Used in colored UI's and available via printer variables in your print_start macro | `RESET=[0\|1]` If specified the 'gate_materials, 'gate_colors' and 'gate_status' will be reset to that defined in mmu_parameters.cfg <br>The following must be specified together to create a complete entry in the gate map: <br>`GATE=[0..n]` Gate numer <br>`MATERIAL=..` The material type. Short, no spaces. e.g. "PLA+" <br>`COLOR=..` The color of the filament. Can be a string representing one of the [w3c color names](https://www.w3.org/TR/css-color-4/#named-colors) e.g. "violet" or a color string in the hexadeciaml format RRGGBB e.g. "ff0000" for red. NO space or # symbols. Empty string for no color <br>`AVAILABLE=[0\|1\|2]` Optionally marks gate as empty (0) or available from spool (1) or available from buffer (2) <br>`SPOOLID=..` The SpoolMan SpoolID (integer) if SpoolMan support is enabled <br>`QUIET=[0\|1]` Optional. Supresses dump of current gate map to log file |
| `MMU_REMAP_TTG` | Reconfiguration of the Tool - to - Gate (TTG) map. Can also set gates as empty! | `RESET=[0\|1]` If specified the Tool -> Gate mapping will be reset to that defined in mmu_parameters.cfg <br>`TOOL=[0..n]` Tool to set in TTG map <br>`GATE=[0..n]` Maps specified tool to this gate (multiple tools can point to same gate) <br>`AVAILABLE=[0\|1]` Marks gate as available or empty <br>`QUIET=[0\|1]` Optional. Supresses dump of current TTG map to log file <br>`MAP={csv}` List of gates, one for each tool to specify the entire TTG map for bulk updates |
| `MMU_ENDLESS_SPOOL` | With parameters this will display the EndlessSpool groups. It can also modify the defined EndlessSpool groups at runtime | `RESET=[0\|1]` If specified the EndlessSpool groups will be reset to that defined in mmu_parameters.cfg <br>`GROUPS={csv of groups}` The same format as the default groups defined in mmu_parameters.cfg. Must be the same length as the number of MMU gates | `QUIET=[0\|1]` Optional. Supresses dump of current TTG and endless spool map to log file <br>`ENABLE=[0\|1]` Optional. Force the enabling or disabling of endless spool at runtime (not persisted) |
Expand Down
39 changes: 30 additions & 9 deletions extras/mmu.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ def __init__(self, config):
self.gcode.register_command('MMU_REMAP_TTG', self.cmd_MMU_REMAP_TTG, desc = self.cmd_MMU_REMAP_TTG_help)
self.gcode.register_command('MMU_GATE_MAP', self.cmd_MMU_GATE_MAP, desc = self.cmd_MMU_GATE_MAP_help)
self.gcode.register_command('MMU_ENDLESS_SPOOL', self.cmd_MMU_ENDLESS_SPOOL, desc = self.cmd_MMU_ENDLESS_SPOOL_help)
self.gcode.register_command('MMU_CHECK_GATES', self.cmd_MMU_CHECK_GATES, desc = self.cmd_MMU_CHECK_GATES_help)
self.gcode.register_command('MMU_CHECK_GATE', self.cmd_MMU_CHECK_GATE, desc = self.cmd_MMU_CHECK_GATE_help)
self.gcode.register_command('MMU_TOOL_OVERRIDES', self.cmd_MMU_TOOL_OVERRIDES, desc = self.cmd_MMU_TOOL_OVERRIDES_help)

# For use in user controlled load and unload macros
Expand Down Expand Up @@ -833,6 +833,10 @@ def _load_persisted_state(self):
self.tool_selected = self.TOOL_GATE_BYPASS # Sanity check
self._set_selector_pos(self.bypass_offset)
self.is_homed = True
else:
self.tool_selected = self.TOOL_GATE_UNKNOWN
self.gate_selected = self.TOOL_GATE_UNKNOWN
self.is_homed = False
else:
errors.append("Incorrect number of gates specified in %s or %s" % (self.VARS_MMU_TOOL_SELECTED, self.VARS_MMU_GATE_SELECTED))
if gate_selected != self.TOOL_GATE_UNKNOWN and tool_selected != self.TOOL_GATE_UNKNOWN:
Expand Down Expand Up @@ -2520,7 +2524,8 @@ def cmd_MMU_HELP(self, gcmd):
d = self.gcode.gcode_help.get(c, "n/a")
if c.startswith("MMU") and not c.startswith("MMU__"):
if not "_CALIBRATE" in c and not "_TEST" in c and not "_SOAKTEST" in c:
msg += "%s : %s\n" % (c.upper(), d)
if c not in ["MMU_UNLOAD", "MMU_CHANGE_TOOL_STANDALONE", "MMU_CHECK_GATES"]: # Remove aliases
msg += "%s : %s\n" % (c.upper(), d)
else:
tmsg += "%s : %s\n" % (c.upper(), d)
elif c.startswith("_MMU") and not c.startswith("_MMU_STEP"):
Expand Down Expand Up @@ -4216,7 +4221,7 @@ def cmd_MMU_SELECT(self, gcmd):
finally:
self._servo_auto()

cmd_MMU_CHANGE_TOOL_help = "Perform a tool swap"
cmd_MMU_CHANGE_TOOL_help = "Perform a tool swap (called from Tx command)"
def cmd_MMU_CHANGE_TOOL(self, gcmd):
if self._check_is_disabled(): return
if self._check_in_bypass(): return
Expand Down Expand Up @@ -4854,7 +4859,10 @@ def _tool_to_gate_map_to_human_string(self, summary=False):
msg += "|\n"
msg += msg_selct
msg += "|" if self.gate_selected == self.mmu_num_gates - 1 else "-"
msg += " Bypass" if self.gate_selected == self.TOOL_GATE_BYPASS else (" T%d" % self.tool_selected) if self.tool_selected >= 0 else ""
if self.is_homed:
msg += " Bypass" if self.gate_selected == self.TOOL_GATE_BYPASS else (" T%d" % self.tool_selected) if self.tool_selected >= 0 else ""
else:
msg += " NOT HOMED"
return msg

def _gate_map_to_human_string(self, detail=False):
Expand Down Expand Up @@ -5085,8 +5093,8 @@ def cmd_MMU_TOOL_OVERRIDES(self, gcmd):
msg += "|\n"
self._log_always(msg)

cmd_MMU_CHECK_GATES_help = "Automatically inspects gate(s), parks filament and marks availability"
def cmd_MMU_CHECK_GATES(self, gcmd):
cmd_MMU_CHECK_GATE_help = "Automatically inspects gate(s), parks filament and marks availability"
def cmd_MMU_CHECK_GATE(self, gcmd):
if self._check_is_disabled(): return
if self._check_not_homed(): return
if self._check_in_bypass(): return
Expand All @@ -5095,6 +5103,7 @@ def cmd_MMU_CHECK_GATES(self, gcmd):
quiet = gcmd.get_int('QUIET', 0, minval=0, maxval=1)
# These three parameters are mutually exclusive so we only process one
tools = gcmd.get('TOOLS', "!")
gates = gcmd.get('GATES', "!")
tool = gcmd.get_int('TOOL', -1, minval=0, maxval=self.mmu_num_gates - 1)
gate = gcmd.get_int('GATE', -1, minval=0, maxval=self.mmu_num_gates - 1)

Expand All @@ -5108,8 +5117,10 @@ def cmd_MMU_CHECK_GATES(self, gcmd):
# Tools used in print (may be empty list)
try:
for tool in tools.split(','):
gate = int(self.tool_to_gate_map[int(tool)])
gates_tools.append([gate, int(tool)])
tool = int(tool)
if tool >= 0 and tool < self.mmu_num_gates:
gate = self.tool_to_gate_map[tool]
gates_tools.append([gate, tool])
if len(gates_tools) == 0:
self._log_debug("No tools to check, assuming default tool is already loaded")
return
Expand All @@ -5120,6 +5131,16 @@ def cmd_MMU_CHECK_GATES(self, gcmd):
else:
self._log_always(msg)
return
elif gates != "!":
# List of gates
try:
for gate in gates.split(','):
gate = int(gate)
if gate >= 0 and gate < self.mmu_num_gates:
gates_tools.append([gate, -1])
except ValueError as ve:
self._log_always("Invalid GATES parameter: %s" % gates)
return
elif tool >= 0:
# Individual tool
gate = self.tool_to_gate_map[tool]
Expand Down Expand Up @@ -5165,7 +5186,7 @@ def cmd_MMU_CHECK_GATES(self, gcmd):
msg = "Tool T%d on gate #%d marked EMPTY" % (tool, gate)
else:
msg = "Gate #%d marked EMPTY" % gate
if self._is_in_print() and tools != "!":
if self._is_in_print():
# Use case of in-print verification of all tools used in print
self._mmu_pause(msg)
return
Expand Down
16 changes: 4 additions & 12 deletions extras/mmu_toolhead.py
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,8 @@ def get_steppers(self):

def calc_position(self, stepper_positions):
#for r in self.rails:
# logging.info("PAUL: * rail=%s, initial_stepper_name=%s" % (r.get_name, r.steppers[0].get_name()))
#logging.info("PAUL: * stepper_positions=%s" % stepper_positions)
# logging.info("DEBUG: * rail=%s, initial_stepper_name=%s" % (r.get_name, r.steppers[0].get_name()))
#logging.info("DEBUG: * stepper_positions=%s" % stepper_positions)
return [stepper_positions[rail.steppers[0].get_name()] for rail in self.rails] # Note can't assume rail name == stepper name

def set_position(self, newpos, homing_axes):
Expand All @@ -392,22 +392,14 @@ def home(self, homing_state):
forcepos[axis] += 1.5 * (position_max - hi.position_endstop)
homing_state.home_rails([rail], forcepos, homepos) # Perform homing

def _check_endstops(self, move):
end_pos = move.end_pos
for i in range(len(self.rails)):
if (move.axes_d[i] and (end_pos[i] < self.limits[i][0] or end_pos[i] > self.limits[i][1])):
if self.limits[i][0] > self.limits[i][1]:
raise move.move_error("Must home axis first")
raise move.move_error()

def set_accel_limit(self, accel):
self.move_accel = accel

def check_move(self, move):
limits = self.limits
xpos, ypos = move.end_pos[:2]
if xpos < limits[0][0] or xpos > limits[0][1]:
self._check_endstops(move)
if xpos != 0. and (xpos < limits[0][0] or xpos > limits[0][1]):
raise move.move_error()

if move.axes_d[0]: # Selector
move.limit_speed(self.selector_max_velocity, self.selector_max_accel)
Expand Down

0 comments on commit 0ab1eb0

Please sign in to comment.