Reserve WipeTower2 toolchange depth to match the printed purge

The planner reserved ramming rows gated only on enable_filament_ramming and
sized them with the SEMM 0.25s time step, while toolchange_Unload rams on
(semm && enable_filament_ramming) || filament_multitool_ramming with the
multitool time step. Disabling multitool ramming therefore left ~3 unprinted
rows per toolchange as blank bands in the tower. Without ramming the first
wipe line also needs reserved depth of its own (it no longer rides the last
ramming row), plus the y_step/2 offset the wipe start inherits from the
ramming start position - otherwise the tightened boxes truncate the ordered
purge at the box edge.
This commit is contained in:
SoftFever
2026-07-29 13:23:29 +08:00
parent bef47b2c70
commit 9292db2f9f
2 changed files with 27 additions and 6 deletions

View File

@@ -2346,15 +2346,29 @@ void WipeTower2::plan_toolchange(float z_par, float layer_height_par, unsigned i
m_plan.back().tool_changes.push_back(set_toolchange(old_tool, new_tool, layer_height_par, wipe_volume, first_layer_plan)); m_plan.back().tool_changes.push_back(set_toolchange(old_tool, new_tool, layer_height_par, wipe_volume, first_layer_plan));
} }
float WipeTower2::wipe_start_depth_offset(size_t old_tool) const
{
const bool do_ramming = (m_semm && m_enable_filament_ramming) || m_filpar[old_tool].multitool_ramming;
if (do_ramming)
return 0.f;
return 0.5f * m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator * m_filpar[old_tool].ramming_step_multiplicator * m_extra_spacing_ramming;
}
WipeTower2::WipeTowerInfo::ToolChange WipeTower2::set_toolchange(size_t old_tool, size_t new_tool, float layer_height, float wipe_volume, bool first_layer_plan) WipeTower2::WipeTowerInfo::ToolChange WipeTower2::set_toolchange(size_t old_tool, size_t new_tool, float layer_height, float wipe_volume, bool first_layer_plan)
{ {
float width = m_wipe_tower_width - 3*m_perimeter_width; float width = m_wipe_tower_width - 3*m_perimeter_width;
float length_to_extrude = volume_to_length(0.25f * std::accumulate(m_filpar[old_tool].ramming_speed.begin(), m_filpar[old_tool].ramming_speed.end(), 0.f), float length_to_extrude = volume_to_length((m_semm ? 0.25f : m_filpar[old_tool].multitool_ramming_time) * std::accumulate(m_filpar[old_tool].ramming_speed.begin(), m_filpar[old_tool].ramming_speed.end(), 0.f),
m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator, m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator,
layer_height); layer_height);
// Orca: Set ramming depth to 0 if ramming is disabled. // Orca: Reserve ramming depth only when toolchange_Unload() will actually ram
float ramming_depth = m_enable_filament_ramming ? ((int(length_to_extrude / width) + 1) * (m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator * m_filpar[old_tool].ramming_step_multiplicator) * m_extra_spacing_ramming) : 0; // (same condition as its do_ramming), otherwise the unprinted reservation
float first_wipe_line = - (width*((length_to_extrude / width)-int(length_to_extrude / width)) - width); // leaves blank bands between the purge boxes.
const bool do_ramming = (m_semm && m_enable_filament_ramming) || m_filpar[old_tool].multitool_ramming;
float ramming_depth = do_ramming ? ((int(length_to_extrude / width) + 1) * (m_perimeter_width * m_filpar[old_tool].ramming_line_width_multiplicator * m_filpar[old_tool].ramming_step_multiplicator) * m_extra_spacing_ramming) : 0;
// first_wipe_line rides for free on the last (partially used) ramming row, which
// is already covered by ramming_depth. Without ramming that row does not exist,
// so the whole wipe volume needs reserved wiping depth.
float first_wipe_line = do_ramming ? - (width*((length_to_extrude / width)-int(length_to_extrude / width)) - width) : 0.f;
float first_wipe_volume = length_to_volume(first_wipe_line, m_perimeter_width * m_extra_flow, layer_height); float first_wipe_volume = length_to_volume(first_wipe_line, m_perimeter_width * m_extra_flow, layer_height);
@@ -2367,7 +2381,8 @@ WipeTower2::WipeTowerInfo::ToolChange WipeTower2::set_toolchange(size_t old_tool
// ORCA: and first-layer purge segments do not leave visible gaps. // ORCA: and first-layer purge segments do not leave visible gaps.
const float planning_spacing = first_layer_plan ? m_extra_flow : m_extra_spacing_wipe; const float planning_spacing = first_layer_plan ? m_extra_flow : m_extra_spacing_wipe;
float wiping_depth = get_wipe_depth(wipe_volume - first_wipe_volume, layer_height, m_perimeter_width, m_extra_flow, planning_spacing, width); float wiping_depth = get_wipe_depth(wipe_volume - first_wipe_volume, layer_height, m_perimeter_width, m_extra_flow, planning_spacing, width)
+ wipe_start_depth_offset(old_tool);
return WipeTowerInfo::ToolChange(old_tool, new_tool, ramming_depth + wiping_depth, ramming_depth, first_wipe_line, wipe_volume); return WipeTowerInfo::ToolChange(old_tool, new_tool, ramming_depth + wiping_depth, ramming_depth, first_wipe_line, wipe_volume);
} }
@@ -2429,7 +2444,8 @@ void WipeTower2::save_on_last_wipe()
const bool first_layer_plan = size_t(m_layer_info - m_plan.begin()) == m_first_layer_idx; const bool first_layer_plan = size_t(m_layer_info - m_plan.begin()) == m_first_layer_idx;
const float planning_spacing = first_layer_plan ? m_extra_flow : m_extra_spacing_wipe; const float planning_spacing = first_layer_plan ? m_extra_flow : m_extra_spacing_wipe;
float depth_to_wipe = get_wipe_depth(volume_we_need_depth_for, m_layer_info->height, m_perimeter_width, m_extra_flow, planning_spacing, width); float depth_to_wipe = get_wipe_depth(volume_we_need_depth_for, m_layer_info->height, m_perimeter_width, m_extra_flow, planning_spacing, width)
+ wipe_start_depth_offset(toolchange.old_tool);
toolchange.required_depth = toolchange.ramming_depth + depth_to_wipe; toolchange.required_depth = toolchange.ramming_depth + depth_to_wipe;
toolchange.wipe_volume = volume_left_to_wipe; toolchange.wipe_volume = volume_left_to_wipe;

View File

@@ -387,6 +387,11 @@ private:
// Computes the depth reserved for a toolchange (shared by plan_toolchange() and the // Computes the depth reserved for a toolchange (shared by plan_toolchange() and the
// rib-wall square-tower replanning in generate()). // rib-wall square-tower replanning in generate()).
WipeTowerInfo::ToolChange set_toolchange(size_t old_tool, size_t new_tool, float layer_height, float wipe_volume, bool first_layer_plan); WipeTowerInfo::ToolChange set_toolchange(size_t old_tool, size_t new_tool, float layer_height, float wipe_volume, bool first_layer_plan);
// Depth consumed before the first wipe row when no ramming is printed (the wipe
// still starts y_step/2 into the box, see toolchange_Unload()); 0 with ramming,
// whose planned rows already carry the slack for it.
float wipe_start_depth_offset(size_t old_tool) const;
}; };