mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-11 01:41:03 +00:00
fix(imex): name the physical head in M104/M109 tool indices
M104/M109 address a heater, but every caller of the instance GCodeWriter::set_temperature overload addresses filaments by logical id, so on a printer whose physical_extruder_map is not the identity the emitted T named the wrong head -- or, where the logical id exceeds the head count, no head at all. With a map of 0,0,0,0,1,2,3 a toolchange to filament 5 emitted "M109 S265 T4" and "M104 S190 T4 ;cooldown" while the head it meant was T1. Upstream already treats these commands as physical: the preheat it injects in GCodeProcessor maps through the same map before emitting, and BBS's own wipe tower does likewise. Emitting logical is the half that never got the memo. That mismatch also disabled the cooldown suppression beside the preheat, which compares the line's T against pem[tool_number] and so never matched a logical one -- 171 cooldowns survived in a two-head print where none should have. Worse, it could match the wrong line: a cooldown for filament 1 emitted T1, and a toolchange to filament 5 gives pem[4] == 1, so a legitimate cooldown for head 0 was deleted because the incoming head happened to be numbered 1. Translate once, in the instance overload every logical-space caller passes through. The static overload is already physical-in and is left alone. Gated on is_imex. physical_extruder_map carries two readings in this tree: the BBS paths index it by extruder id, the IMEX paths by filament id, and the two coincide only when the filament and nozzle counts match. Mapping unconditionally would impose the IMEX reading on profiles that mean the other one -- fdm_bbl_3dp_002_common ships a non-identity [1,0], spared today only because single_extruder_multi_material suppresses the T qualifier entirely. The wipe tower's interface-temperature pass has to move with it. It strips the M109 that post_toolchange emits by searching for that filament's tool index, so it now searches for the mapped one; left alone it would have stopped matching, and the surviving blocking M109 would have silently defeated the interface temperature. Its sibling pass reads WipeTower2 output, which emits no T at all, and is deliberately unchanged. The bare T<n> toolchange stays logical -- it selects an AFC lane, not a heater. Test slices two objects across a head boundary, the only case that reaches this emission: the same-physical short-circuit in set_extruder suppresses the cooldown entirely for lane swaps within one head. It scans every M104/M109 rather than matching fixed strings, so it catches any unmapped emission and not just the two sites changed here. With the mapping neutered it reports 101 offending lines; with it in place, none. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f0778ef5fa
commit
2e883df7d9
+11
-2
@@ -1617,7 +1617,16 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
: gcodegen.config().nozzle_temperature.get_at(new_fi);
|
||||
if (std::abs(tcr.print_z) < EPSILON)
|
||||
base_temp = gcodegen.config().nozzle_temperature_initial_layer.get_at(new_fi);
|
||||
const std::string t_token = " T" + std::to_string(new_extruder_id);
|
||||
// This pass strips the M109 that OozePrevention::post_toolchange just emitted into
|
||||
// toolchange_gcode_str, so it must look for the tool index that emission actually
|
||||
// wrote -- physical, translated by GCodeWriter::set_temperature -- not the logical
|
||||
// id the temperature lookups above use. Matching on the logical id would leave the
|
||||
// blocking M109 in place and silently defeat the tower interface temperature.
|
||||
// (The sibling scan further down reads WipeTower2 output, whose set_extruder_temp
|
||||
// emits no T at all, so it is deliberately left alone.)
|
||||
const int heater_id = imex_physical_heater_for(
|
||||
gcodegen.config().is_imex.value, gcodegen.config().physical_extruder_map, new_extruder_id);
|
||||
const std::string t_token = " T" + std::to_string(heater_id);
|
||||
std::string out;
|
||||
out.reserve(toolchange_gcode_str.size());
|
||||
size_t pos = 0;
|
||||
@@ -1638,7 +1647,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
const std::string t_val = trimmed.substr(t_pos + 1, t_end == std::string::npos ? std::string::npos : t_end - (t_pos + 1));
|
||||
if (!t_val.empty()) {
|
||||
try {
|
||||
matches_extruder = std::stoi(t_val) == new_extruder_id;
|
||||
matches_extruder = std::stoi(t_val) == heater_id;
|
||||
} catch (...) {
|
||||
matches_extruder = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user