Skip to content

Prime tool changes into the purge chute, sized by idle time - #1107

Open
abehrman wants to merge 8 commits into
Snapmaker:mainfrom
abehrman:feature/toolchange-prime-snapmaker
Open

abehrman wants to merge 8 commits into
Snapmaker:mainfrom
abehrman:feature/toolchange-prime-snapmaker

Conversation

@abehrman

@abehrman abehrman commented Oct 27, 2026 •

Copy link
Copy Markdown

Description

Multi-tool printers with a purge chute or bucket, like the Snapmaker U1, can prime each tool there after a tool change instead of on a prime tower. The tool still gets a pressure-normalizing prime, but nothing has to be built on the bed. This adds that as an opt-in feature and sizes each prime by how long the tool was parked.

This replaces my earlier drafts that tried to avoid the prime tower by flushing into infill or skipping the prime for support-only filaments. Those left the nozzle unprimed, and a tool needs a prime to restore pressure after a park.

How it works

  • Tool change prime G-code (printer setting toolchange_prime_gcode) runs after each real tool change when Smart tool change prime (toolchange_prime_enable, off by default) is on. It only runs when the prime tower is off and the printer isn't single-extruder multi-material.
    • Placeholders: prime_length, prime_speed (limited by the filament's max volumetric speed), prime_first_use, retract_restore_length, next_extruder, previous_extruder, new_filament_temp.
  • Restores the retraction in the chute. A parked tool still holds its tool change retraction (10 mm on the U1). The block extrudes it in the chute first, on a line marked ; restore retraction and sized by retract_restore_length. The G-code writer then counts the tool as unretracted, so it doesn't unretract again on the part.
  • Sized by idle time, as a step. The block is tagged, and the G-code processor sizes its prime extrusions by the tool's estimated park time:
    • a park of at least the idle time gets the maximum length: by then the nozzle has cooled on standby;
    • a shorter park gets the minimum length: the nozzle is still hot and only needs its pressure back;
    • below the skip time the prime is commented out, but the retraction is still restored.
    • The tag comment records why, for example (idle 42s, 3.10mm), (first use, …) or (after pause, …).
  • Full prime after planned pauses. A tool parked across a pause or filament change (PAUSE, M600, M0, M1, M25, or the pause and color-change tags) gets the full length, because the slicer can't know how long the pause lasted.
  • Time primes on the printer (toolchange_prime_on_printer, off by default). This covers pauses the slicer can't see: a pause pressed on the printer, a filament runout, a long reheat.
    • The G-code is emitted untagged, and the printer's own macro sizes the prime from real time.
    • The U1 profile calls SMART_TOOLCHANGE_PRIME, which is included in doc/printer_settings/snapmaker-u1-smart-toolchange-prime.cfg and proposed to the firmware in Add SMART_TOOLCHANGE_PRIME to prime a tool by its real park time u1-klipper#21. It times each park with print_stats.total_duration and primes fully after any pause.
  • First use. The starting tool counts as primed by the start G-code. Each later tool's first use is reported as prime_first_use, and the U1 template leaves that to the firmware's SM_PRINT_PREEXTRUDE_FILAMENT.
  • Snapmaker U1 profile: the template ends the same way as the firmware's SM_PRINT_PREEXTRUDE_FILAMENT. Inside SAVE_GCODE_STATE/RESTORE_GCODE_STATE it:
    1. moves to the discard position;
    2. restores the retraction and primes;
    3. retracts 0.5 mm;
    4. cuts, wipes and knocks the blob off (INNER_CUTOFF_BASE_DISCARD, INNER_ROUGHLY_CLEAN_NOZZLE_BASE_DISCARD, INNER_DISCARD_FILAMENT_BASE_DISCARD);
    5. leaves the chute Y first with MOVE_TO_XY_IDLE_POSITION_EXTRUDER.

Recommended defaults (process settings, "Tool change priming"):

Setting Default Why
Minimum prime length 10 mm About 24 mm³ of 1.75 mm filament. The stock U1 prime tower purges 45 mm³ (about 18.7 mm) per tool change at 0.20 mm layers, and 2 mm was too little on a test print
Maximum prime length 20 mm Matches the stock pre-extrusion; purges filament that sat in a cooled nozzle
Idle time for maximum prime 30 s Time for a parked nozzle to cool below the flow temperature: measured on a U1 PETG print (220 °C, standby 70 °C), below 180 °C after 24–30 s and about 135 °C at 60 s
Skip prime below idle time 0 s Always prime unless you raise it

Fixed since the first version

A test print on a U1 lost position on a tool change: the head hit the frame and missed the dock by several inches. The first version had two problems that likely contributed. I can't prove which one caused it.

  • The new tool's 10 mm tool change retraction was unretracted on the part right after the prime, leaving a blob in the same spot on every swap.
  • The head left the chute with a fast diagonal travel instead of the firmware's Y-first move.

This version fixes both, as described above. The prime length is also a step now instead of a linear ramp.

The U1 profile change is now in Snapmaker/snapmaker-profiles#1. #1128 moved the presets into the submodules/Profiles submodule, so fdm_U1.json is no longer in this repo. That PR adds toolchange_prime_gcode to the U1 profile and bumps the profile version to 02.03.04.05. Merge both, then update the submodule pin.

The version bump matters. Without it, the app keeps its cached copy of the U1 profile, so an updated build still slices with the old prime G-code. That happened on a test print: the 2 mm prime ran while the tool was still retracted 10 mm, so nothing came out in the chute, and the 10 mm unretract then left a blob on the part.

No breaking changes: everything is off by default, and nothing changes for printers without tool change prime G-code.

Screenshots/Recordings/Graphs

None. The UI change is six settings in a new "Tool change priming" group on the process "Multimaterial" page, plus the printer's tool change prime G-code field.

Tests

  • New tests/fff_print/test_toolchange_prime.cpp (7 cases): sized as a step by idle time, the retraction restored in the chute with no second unretract on the part, skipped below the skip time, not emitted for single-extruder multi-material printers, off unless enabled, full length after a pause, and left to the printer when timed on the printer.
  • All 7 pass, and so does the full fff_print_tests suite (58 cases), in a Release build on macOS arm64. That run was on my local branch, which has this change plus unrelated work.
  • This branch's changes were cherry-picked cleanly from that local branch and are otherwise unchanged.
  • SMART_TOOLCHANGE_PRIME was checked in a Jinja simulation of two prints, including a pause pressed on the printer. It hasn't been tried on a real U1 yet, and neither has this version of the slicer side.

Supersedes #1021 and #1022.

🤖 Generated with Claude Code

abehrman and others added 2 commits October 27, 2026 10:40
Opt-in (toolchange_prime_enable) when the prime tower is off. The printer's
toolchange_prime_gcode runs after each tool change; the G-code processor
scales its extrusion between a minimum and maximum length by the tool's
estimated idle time, skips it below a skip time, and primes the full length
after any pause or filament change, whose real length is unknown.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add the opt-in toolchange_prime_on_printer setting. The prime G-code is then
emitted untagged and the U1 template calls a Klipper macro,
SMART_TOOLCHANGE_PRIME (doc/printer_settings), which times each tool's park
with print_stats and primes fully after any pause, including ones pressed on
the printer or caused by a filament runout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
abehrman and others added 4 commits October 27, 2026 11:46
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…k way

The prime block now extrudes the new tool's parked retraction in the purge
chute (a line marked "restore retraction", sized by the new
retract_restore_length placeholder), and the writer no longer unretracts it
again on the part. Before, the 10 mm unretract landed on the print right
after the block, leaving a blob in the same spot on every swap.

The prime is now a step instead of a ramp: a tool parked at least
toolchange_prime_idle_time (default 60 s) gets the maximum (default 20 mm),
a shorter park gets the minimum. The skip time drops only the prime, never
the restore.

The U1 template and macro end like the stock pre-extrusion: a 0.5 mm
retraction, the cut and wipe, then MOVE_TO_XY_IDLE_POSITION_EXTRUDER (Y
first) inside SAVE/RESTORE_GCODE_STATE, instead of a diagonal travel out of
the chute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Run INNER_DISCARD_FILAMENT_BASE_DISCARD after the wipe, as
SM_PRINT_PREEXTRUDE_FILAMENT does, so purged blobs are flicked off at a
varying spot instead of piling up where the nozzle leaves the chute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main now keeps the Snapmaker presets in submodules/Profiles and deleted
resources/profiles/Snapmaker/machine/fdm_U1.json. Take the deletion; the
U1 toolchange_prime_gcode has to go to Snapmaker/snapmaker-profiles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
abehrman and others added 2 commits November 1, 2026 22:40
…chute wipe

The stock cutter macro rams the head against the chute six times at
10000 mm/s^2. Run at every tool change it can skip steps; two U1 prints
with priming on failed on a T3 swap. The U1 profile change is in
Snapmaker/snapmaker-profiles#1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address review on the tool change prime:
- A park at least as long as the idle time always gets the full prime, even when
  the skip time is longer, matching the printer macro.
- After the prime block, emit M82 for absolute-extrusion prints, since the
  template is told to use M83.
- Label a reused tool with no recorded park time "park time unknown", not "first use".
- Note that time and filament estimates count primes at full length.
- static_cast for next_extruder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@abehrman

abehrman commented Nov 3, 2026

Copy link
Copy Markdown
Author

Thanks. Addressed in b5b0dad:

  1. Skip vs idle: fixed. A park at least as long as the idle time always gets the full prime, matching the macro. The tooltip says so. New test: idle 0.001 s with skip 36000 s gives the full prime on every block.
  2. Estimates: they come from the first pass, so they count every prime at full length. That overstates by at most the minimum-to-maximum prime per short park, a few seconds and a fraction of a gram. I added a code comment instead of re-running the time model on the rewritten lines.
  3. E mode: for absolute-E prints, an M82 is now emitted after the block, before G92 E0. New test with use_relative_e_distances = false and an M83 template.
  4. Profiles: the profiles now live in the Profiles submodule (after the Snapmaker main merge), so the U1 preset change goes there, not into this PR. Until then the feature stays off by default and is inert.
  5. Label: a reused tool with no recorded park time is now labelled "park time unknown".
  6. Cast: now uses static_cast<int>.

All [ToolchangePrime] tests pass (9 cases).

🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant