Wait for the toolchange temperature on the wipe tower

Adds a printer option that picks up the new tool without a blocking temperature
wait, travels to the wipe tower, and waits there right before purging, parked
beside the tower so the ooze from the heat-up lands next to it rather than on the
model. The incoming filament's target is raised ahead of the tool change, so the
heat-up overlaps both the change itself and the travel to the tower.

Off by default, and only offered for multi-extruder printers using a Type 2 wipe
tower; the generic toolchanger profile enables it.
This commit is contained in:
SoftFever
2026-08-06 12:24:00 +08:00
parent b97ca3c0ac
commit 408db4b3b0
13 changed files with 895 additions and 16 deletions
+26 -5
View File
@@ -1554,7 +1554,8 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
interface_temp = gcodegen.config().nozzle_temperature_range_high.get_at(new_extruder_id);
toolchange_temp_override = interface_temp;
}
toolchange_gcode_str = gcodegen.set_extruder(new_extruder_id, tcr.print_z, false, toolchange_temp_override); // TODO: toolchange_z vs print_z
toolchange_gcode_str = gcodegen.set_extruder(new_extruder_id, tcr.print_z, false, toolchange_temp_override,
WipeTower2::wait_for_temp_enabled(gcodegen.m_config)); // TODO: toolchange_z vs print_z
if (!travel_to_tower_now && !tcr.priming && WipeTower2::use_gap_wall(gcodegen.m_config)) {
// The tool changed in place (multi-tool printer without ramming), so the
// tower entry is the tcr's own positioning move — a straight line across
@@ -1705,7 +1706,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
std::string trimmed = line;
trimmed.erase(0, trimmed.find_first_not_of(" \t"));
bool skip_line = false;
if (boost::starts_with(trimmed, "M109")) {
if (boost::starts_with(trimmed, "M109") && trimmed.find(WipeTower2::wait_for_temp_tag()) == std::string::npos) {
bool matches_extruder = true;
if (trimmed.find('T') != std::string::npos)
matches_extruder = trimmed.find(t_token) != std::string::npos;
@@ -8939,7 +8940,7 @@ void GCode::update_placeholder_parser_with_variant_params()
}
}
std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bool by_object, int toolchange_temp_override)
std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bool by_object, int toolchange_temp_override, bool defer_temp_wait)
{
int new_extruder_id = get_extruder_id(new_filament_id);
if (!m_writer.need_toolchange(new_filament_id))
@@ -9046,6 +9047,24 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
if (toolchange_temp_override > 0)
new_filament_temp = toolchange_temp_override;
// With wait_for_temp_on_wipe_tower the blocking M109 is deferred to the wipe tower, so raise
// the incoming filament's target here — ahead of the tool change rather than after it — and
// let the heat-up overlap the change itself as well as the travel to the tower. The command
// always carries an explicit tool index (the option is off for single extruder MM, so the
// writer emits one), leaving the outgoing filament that pre_toolchange just dropped to its
// standby temperature alone. nozzle_temperature == 0 means "use the first layer temperature".
if (defer_temp_wait) {
// Target what the tower will wait on. It waits on the first layer temperature not only on
// the first layer but also while priming, which runs before any layer is set: there
// on_first_layer() is false and print_z is the initial layer height, so neither test above
// catches it. nozzle_temperature == 0 means "use the first layer temperature" as well.
int preheat_temp = new_filament_temp;
if (toolchange_temp_override <= 0 && (m_layer == nullptr || preheat_temp <= 0))
preheat_temp = m_config.nozzle_temperature_initial_layer.get_at(new_fi);
if (preheat_temp > 0)
gcode += m_writer.set_temperature(preheat_temp, false, new_filament_id);
}
Vec3d nozzle_pos = m_writer.get_position();
float old_retract_length, old_retract_length_toolchange, wipe_volume;
int old_filament_temp, old_filament_e_feedrate;
@@ -9349,8 +9368,10 @@ std::string GCode::set_extruder(unsigned int new_filament_id, double print_z, bo
}
check_add_eol(gcode);
}
// Set the new extruder to the operating temperature.
if (m_ooze_prevention.enable)
// Set the new extruder to the operating temperature. With defer_temp_wait the target was
// already raised before the tool change and the blocking wait belongs to the wipe tower
// generator, so there is nothing left to restore here.
if (m_ooze_prevention.enable && !defer_temp_wait)
gcode += m_ooze_prevention.post_toolchange(*this);
if (m_config.enable_pressure_advance.get_at(new_filament_id)) {