mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-22 06:41:01 +00:00
Belt: drive the first-layer fan band from the generator, not from parsed moves
The cooling buffer's band pass rebuilt positions from the layer's G-code and tested them against the first-layer plane. The G-code is in machine coordinates and the plane is in slicing coordinates, so on the shipped profiles the nearest move was over 100 mm from a 0.2 mm band and the pass never changed the fan. GCode::_extrude() already knows each path's height above the belt, so it now tags the band changes and the buffer applies and strips the tags. The pass also took the S of every M106 as the part fan, whatever its P index, and stored that 0..255 value where a percentage was expected (an auxiliary fan line came back as M106 S651); it now uses FanMover's parser, which ignores other fans, and converts to percent. It no longer overwrites the layer's intended speed, only the fan's actual state. Raised in Hanif Koh's review of #14394.
This commit is contained in:
1 parent
646fe6384c
commit
556569c0e3
6 files changed
+141
-174
No files matched your search
@@ -596,3 +596,58 @@ TEST_CASE("Belt printers refuse an object taller than the gantry clearance", "[P
|
||||
CHECK_FALSE(print.validate().string.empty());
|
||||
}
|
||||
}
|
||||
|
||||
// On a belt every tilted layer starts on the belt, so "first layer" cooling is a band along
|
||||
// the belt, not the first slicing layers: the part fan goes off for the paths that start
|
||||
// within a layer height of the belt and back on above it, on every layer. The G-code is in
|
||||
// machine coordinates, so the generator tags the band changes and the cooling buffer
|
||||
// applies them; before that the buffer compared machine-frame moves with a slicing-frame
|
||||
// plane and never switched the fan at all.
|
||||
TEST_CASE("Belt printers switch the part fan by height above the belt", "[Print][belt][Cooling]")
|
||||
{
|
||||
DynamicPrintConfig config = DynamicPrintConfig::full_print_config();
|
||||
config.set_deserialize_strict({
|
||||
{ "belt_printer", 1 },
|
||||
{ "belt_slice_rotation", "x" },
|
||||
{ "belt_slice_rotation_angle", 45 },
|
||||
{ "belt_slice_rotation_global", 1 },
|
||||
{ "gcode_remap_x", "rev_x" },
|
||||
{ "gcode_remap_y", "pos_z" },
|
||||
{ "gcode_remap_z", "pos_y" },
|
||||
{ "layer_height", 0.2 },
|
||||
{ "initial_layer_print_height", 0.2 },
|
||||
{ "skirt_loops", 0 },
|
||||
{ "z_hop", 0 },
|
||||
{ "close_fan_the_first_x_layers", 1 },
|
||||
{ "full_fan_speed_layer", 0 },
|
||||
{ "fan_min_speed", 100 },
|
||||
{ "fan_max_speed", 100 },
|
||||
{ "slow_down_layer_time", 1000 },
|
||||
{ "fan_cooling_layer_time", 1001 },
|
||||
{ "reduce_fan_stop_start_freq", 0 },
|
||||
{ "machine_start_gcode", "T[initial_tool]\n" },
|
||||
{ "layer_change_gcode", "G92 E0\n" },
|
||||
});
|
||||
const std::string gcode = slice({ cube(20) }, config);
|
||||
REQUIRE(! gcode.empty());
|
||||
|
||||
// The tags are consumed by the cooling buffer and never reach the file.
|
||||
CHECK(gcode.find(";_BELT_BAND") == std::string::npos);
|
||||
|
||||
size_t fan_off = 0, fan_on = 0;
|
||||
GCodeReader parser;
|
||||
parser.parse_buffer(gcode, [&](GCodeReader &, const GCodeReader::GCodeLine &line) {
|
||||
if (line.cmd_is("M107"))
|
||||
++ fan_off;
|
||||
else if (line.cmd_is("M106")) {
|
||||
float s = 0.f;
|
||||
if (line.has_value('S', s) && s <= 0.f)
|
||||
++ fan_off;
|
||||
else
|
||||
++ fan_on;
|
||||
}
|
||||
});
|
||||
// A flat-bed print turns the fan on once. Here it cycles with the layers.
|
||||
CHECK(fan_off > 10);
|
||||
CHECK(fan_on > 10);
|
||||
}
|
||||
Reference in new issue
Block a user