FIX: cooling the unused extruder if only using one

1.Always add extruder usage block in filament change and end gcode
2.Modify the heating rate

jira:NONE

Signed-off-by: xun.zhang <xun.zhang@bambulab.com>
Change-Id: I099b306ea6e4c6296ac1dc15bc6a67ed15a29b0f
This commit is contained in:
xun.zhang 2025-01-11 14:20:30 +08:00 committed by lane.wei
parent eaeac42b19
commit dd3e3fe750
3 changed files with 82 additions and 110 deletions

View File

@ -19,6 +19,7 @@
"2" "2"
], ],
"enable_pre_heating": "1", "enable_pre_heating": "1",
"hotend_heating_rate": "3.6",
"extruder_clearance_height_to_lid": "201", "extruder_clearance_height_to_lid": "201",
"extruder_clearance_height_to_rod": "47.4", "extruder_clearance_height_to_rod": "47.4",
"extruder_clearance_max_radius": "96", "extruder_clearance_max_radius": "96",

View File

@ -2292,6 +2292,8 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
//BBS: gcode writer doesn't know where the real position of extruder is after inserting custom gcode //BBS: gcode writer doesn't know where the real position of extruder is after inserting custom gcode
m_writer.set_current_position_clear(false); m_writer.set_current_position_clear(false);
m_start_gcode_filament = GCodeProcessor::get_gcode_last_filament(machine_start_gcode); m_start_gcode_filament = GCodeProcessor::get_gcode_last_filament(machine_start_gcode);
// mark the first filament used in print
file.write_format(";VT%d\n",initial_extruder_id);
// Process filament-specific gcode. // Process filament-specific gcode.
/* if (has_wipe_tower) { /* if (has_wipe_tower) {

View File

@ -825,7 +825,19 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
size_t g1_lines_counter = 0; size_t g1_lines_counter = 0;
lines_ends.clear(); lines_ends.clear();
ExtruderUsageBlcok temp_construct_block; // the temperarily constructed block, will be pushed into container after initializing ExtruderUsageBlcok temp_construct_block; // the temperarily constructed block, will be pushed into container after initializing
auto gcode_time_handler = [&temp_construct_block,&filament_blocks, &extruder_blocks, &offsets, &handle_nozzle_change_line , & process_placeholders, &is_temporary_decoration, & process_line_move, & g1_lines_counter, & machine_start_gcode_end_line_id, & machine_end_gcode_start_line_id](std::string& gcode_line, std::string& gcode_buffer, int& line_id) {
auto handle_filament_change = [&filament_blocks,&machine_start_gcode_end_line_id,&machine_end_gcode_start_line_id](int filament_id,int line_id){
// skip the filaments change in machine start/end gcode
if (machine_start_gcode_end_line_id == (unsigned int)(-1) && (unsigned int)(line_id)<machine_start_gcode_end_line_id ||
machine_end_gcode_start_line_id != (unsigned int)(-1) && (unsigned int)(line_id)>machine_end_gcode_start_line_id)
return;
if (!filament_blocks.empty())
filament_blocks.back().upper_gcode_id = line_id;
filament_blocks.emplace_back(filament_id, line_id, -1);
};
auto gcode_time_handler = [&temp_construct_block,&filament_blocks, &extruder_blocks, &offsets, &handle_nozzle_change_line , & process_placeholders, &is_temporary_decoration, & process_line_move, & g1_lines_counter, & machine_start_gcode_end_line_id, & machine_end_gcode_start_line_id,handle_filament_change](std::string& gcode_line, std::string& gcode_buffer, int& line_id) {
auto [processed, lines_added_count] = process_placeholders(gcode_line,line_id); auto [processed, lines_added_count] = process_placeholders(gcode_line,line_id);
if (processed && lines_added_count > 0) if (processed && lines_added_count > 0)
offsets.push_back({ line_id, lines_added_count }); offsets.push_back({ line_id, lines_added_count });
@ -848,14 +860,16 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
std::istringstream str(gcode_line.substr(skips + 1)); // skip white spaces and T std::istringstream str(gcode_line.substr(skips + 1)); // skip white spaces and T
str >> fid; str >> fid;
if (!str.fail() && 0 <= fid && fid < 255) { if (!str.fail() && 0 <= fid && fid < 255) {
// skip the filaments change in machine start/end gcode handle_filament_change(fid, line_id);
if (machine_start_gcode_end_line_id == (unsigned int)(-1) && line_id<machine_start_gcode_end_line_id || }
machine_end_gcode_start_line_id != (unsigned int)(-1) && line_id>machine_end_gcode_start_line_id) }
return; else if (GCodeReader::GCodeLine::cmd_start_with(gcode_line, ";VT")) {
int fid;
if (!filament_blocks.empty()) int skips = GCodeReader::skip_whitespaces(gcode_line.data()) - gcode_line.data();
filament_blocks.back().upper_gcode_id = line_id; std::istringstream str(gcode_line.substr(skips + 3)); // skip white spaces and ;VT
filament_blocks.emplace_back(fid, line_id, -1); str >> fid;
if (!str.fail() && 0 <= fid && fid < 255) {
handle_filament_change(fid, line_id);
} }
} }
else if (GCodeReader::GCodeLine::cmd_start_with(gcode_line, "M1020")) { else if (GCodeReader::GCodeLine::cmd_start_with(gcode_line, "M1020")) {
@ -865,14 +879,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
int fid; int fid;
str >> fid; str >> fid;
if (!str.fail() && 0 <= fid && fid < 255) { if (!str.fail() && 0 <= fid && fid < 255) {
// skip the filaments change in machine start/end gcode handle_filament_change(fid, line_id);
if (machine_start_gcode_end_line_id == (unsigned int)(-1) && line_id<machine_start_gcode_end_line_id ||
machine_end_gcode_start_line_id != (unsigned int)(-1) && line_id>machine_end_gcode_start_line_id)
return;
if (!filament_blocks.empty())
filament_blocks.back().upper_gcode_id = line_id;
filament_blocks.emplace_back(fid, line_id, -1);
} }
} }
} }
@ -958,24 +965,13 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename, st
// After traversing the G-code, the first and last extruder blocks still have uncompleted initialization steps // After traversing the G-code, the first and last extruder blocks still have uncompleted initialization steps
if (!extruder_blocks.empty()) { if (!extruder_blocks.empty()) {
int first_filament = -1; int first_filament = 0;
int last_filament = -1; int last_filament = 0;
if (!filament_blocks.empty()) { if (!filament_blocks.empty()) {
first_filament = filament_blocks.front().filament_id; first_filament = filament_blocks.front().filament_id;
last_filament = filament_blocks.back().filament_id; last_filament = filament_blocks.back().filament_id;
} }
else {
if (extruder_blocks.size() == 1) {
// only with a dummy extruder block, we can't find any available filament
first_filament = 0;
last_filament = 0;
}
else {
first_filament = extruder_blocks.front().end_filament;
last_filament = extruder_blocks.back().start_filament;
}
}
extruder_blocks.front().initialize_step_1(context.filament_maps[first_filament], machine_start_gcode_end_line_id, first_filament); extruder_blocks.front().initialize_step_1(context.filament_maps[first_filament], machine_start_gcode_end_line_id, first_filament);
extruder_blocks.back().initialize_step_2(machine_end_gcode_start_line_id); extruder_blocks.back().initialize_step_2(machine_end_gcode_start_line_id);
extruder_blocks.back().initialize_step_3(machine_end_gcode_start_line_id,last_filament,machine_end_gcode_start_line_id); extruder_blocks.back().initialize_step_3(machine_end_gcode_start_line_id,last_filament,machine_end_gcode_start_line_id);
@ -5819,6 +5815,12 @@ int GCodeProcessor::get_extruder_id(bool force_initialize)const
void GCodeProcessor::PreCoolingInjector::process_pre_cooling_and_heating(TimeProcessor::InsertedLinesMap& inserted_operation_lines) void GCodeProcessor::PreCoolingInjector::process_pre_cooling_and_heating(TimeProcessor::InsertedLinesMap& inserted_operation_lines)
{ {
auto get_nozzle_temp = [this](int filament_id,bool from_or_to) {
if (filament_id == -1)
return from_or_to ? 140 : 0; // default temp
return filament_nozzle_temps[filament_id];
};
std::map<int, std::vector<ExtruderFreeBlock>> per_extruder_free_blocks; std::map<int, std::vector<ExtruderFreeBlock>> per_extruder_free_blocks;
for (auto& block : m_extruder_free_blocks) for (auto& block : m_extruder_free_blocks)
@ -5830,9 +5832,9 @@ void GCodeProcessor::PreCoolingInjector::process_pre_cooling_and_heating(TimePro
for (auto iter = extruder_free_blcoks.begin(); iter != extruder_free_blcoks.end(); ++iter) { for (auto iter = extruder_free_blcoks.begin(); iter != extruder_free_blcoks.end(); ++iter) {
bool is_end = std::next(iter) == extruder_free_blcoks.end(); bool is_end = std::next(iter) == extruder_free_blcoks.end();
bool apply_pre_cooling = true; bool apply_pre_cooling = true;
bool apply_pre_heating = !is_end; bool apply_pre_heating = is_end ? false : true;
float curr_temp = (float)(filament_nozzle_temps[iter->last_filament_id]); float curr_temp = get_nozzle_temp(iter->last_filament_id,true);
float target_temp = (float)(is_end ? 0 : filament_nozzle_temps[iter->next_filament_id]); float target_temp = get_nozzle_temp(iter->next_filament_id, false);
inject_cooling_heating_command(inserted_operation_lines, *iter, curr_temp, target_temp, apply_pre_cooling, apply_pre_heating); inject_cooling_heating_command(inserted_operation_lines, *iter, curr_temp, target_temp, apply_pre_cooling, apply_pre_heating);
} }
} }
@ -5860,6 +5862,8 @@ void GCodeProcessor::PreCoolingInjector::inject_cooling_heating_command(TimeProc
}; };
auto is_tpu_filament = [&filament_types = this->filament_types](int idx) { auto is_tpu_filament = [&filament_types = this->filament_types](int idx) {
if (idx == -1)
return false;
return filament_types[idx] == "TPU"; return filament_types[idx] == "TPU";
}; };
@ -5901,20 +5905,20 @@ void GCodeProcessor::PreCoolingInjector::inject_cooling_heating_command(TimeProc
if (partial_free_move_lower < partial_free_move_upper) { if (partial_free_move_lower < partial_free_move_upper) {
float max_cooling_temp = std::min(curr_temp, std::min(partial_free_cooling_thres, partial_free_time_gap * cooling_rate)); float max_cooling_temp = std::min(curr_temp, std::min(partial_free_cooling_thres, partial_free_time_gap * cooling_rate));
curr_temp -= max_cooling_temp; // set the temperature after doing cooling when post-extruding curr_temp -= max_cooling_temp; // set the temperature after doing cooling when post-extruding
inserted_operation_lines[partial_free_move_lower->gcode_id].emplace_back(format_line_M104(curr_temp, block.extruder_id, "Multi extruder pre cooling"), TimeProcessor::InsertLineType::PreCooling); inserted_operation_lines[partial_free_move_lower->gcode_id].emplace_back(format_line_M104(curr_temp, block.extruder_id, "Multi extruder pre cooling in post extrusion"), TimeProcessor::InsertLineType::PreCooling);
} }
} }
if (pre_cooling && !pre_heating) { if (pre_cooling && !pre_heating) {
// only perform cooling // only perform cooling
if (target_temp > curr_temp) if (target_temp >= curr_temp)
return; return;
inserted_operation_lines[block.free_lower_gcode_id].emplace_back(format_line_M104(target_temp, block.extruder_id, "Multi extruder pre cooling"), TimeProcessor::InsertLineType::PreCooling); inserted_operation_lines[block.free_lower_gcode_id].emplace_back(format_line_M104(target_temp, block.extruder_id, "Multi extruder pre cooling"), TimeProcessor::InsertLineType::PreCooling);
return; return;
} }
if (!pre_cooling && pre_heating) { if (!pre_cooling && pre_heating) {
// only perform heating // only perform heating
if (target_temp < curr_temp) if (target_temp <= curr_temp)
return; return;
float heating_start_time = move_iter_upper->time[valid_machine_id] - (target_temp - curr_temp) / heating_rate; float heating_start_time = move_iter_upper->time[valid_machine_id] - (target_temp - curr_temp) / heating_rate;
auto heating_move_iter = std::upper_bound(move_iter_lower, move_iter_upper + 1, heating_start_time, [valid_machine_id = this->valid_machine_id](float time, const GCodeProcessorResult::MoveVertex& a) {return time < a.time[valid_machine_id]; }); auto heating_move_iter = std::upper_bound(move_iter_lower, move_iter_upper + 1, heating_start_time, [valid_machine_id = this->valid_machine_id](float time, const GCodeProcessorResult::MoveVertex& a) {return time < a.time[valid_machine_id]; });
@ -5939,6 +5943,8 @@ void GCodeProcessor::PreCoolingInjector::inject_cooling_heating_command(TimeProc
// get the insert pos of heat cmd and recalculate time gap and delta temp // get the insert pos of heat cmd and recalculate time gap and delta temp
float real_cooling_time = heating_move_iter->time[valid_machine_id] - move_iter_lower->time[valid_machine_id]; float real_cooling_time = heating_move_iter->time[valid_machine_id] - move_iter_lower->time[valid_machine_id];
int real_delta_temp = std::min((int)(real_cooling_time * cooling_rate), (int)curr_temp); int real_delta_temp = std::min((int)(real_cooling_time * cooling_rate), (int)curr_temp);
if (real_delta_temp == 0)
return;
inserted_operation_lines[block.free_lower_gcode_id].emplace_back(format_line_M104(curr_temp - real_delta_temp, block.extruder_id, "Multi extruder pre cooling"), TimeProcessor::InsertLineType::PreCooling); inserted_operation_lines[block.free_lower_gcode_id].emplace_back(format_line_M104(curr_temp - real_delta_temp, block.extruder_id, "Multi extruder pre cooling"), TimeProcessor::InsertLineType::PreCooling);
inserted_operation_lines[heating_move_iter->gcode_id].emplace_back(format_line_M104(target_temp, block.extruder_id, "Multi extruder pre heating"), TimeProcessor::InsertLineType::PreHeating); inserted_operation_lines[heating_move_iter->gcode_id].emplace_back(format_line_M104(target_temp, block.extruder_id, "Multi extruder pre heating"), TimeProcessor::InsertLineType::PreHeating);
} }
@ -5946,50 +5952,30 @@ void GCodeProcessor::PreCoolingInjector::inject_cooling_heating_command(TimeProc
void GCodeProcessor::PreCoolingInjector::build_by_filament_blocks(const std::vector<ExtruderPreHeating::FilamentUsageBlock>& filament_usage_blocks_) void GCodeProcessor::PreCoolingInjector::build_by_filament_blocks(const std::vector<ExtruderPreHeating::FilamentUsageBlock>& filament_usage_blocks_)
{ {
m_extruder_free_blocks.clear(); m_extruder_free_blocks.clear();
std::map<int, std::vector<ExtruderPreHeating::FilamentUsageBlock>> per_extruder_usage_blocks; std::vector<std::vector<ExtruderPreHeating::FilamentUsageBlock>> per_extruder_usage_blocks(2);
for (auto& block : filament_usage_blocks_) for (auto& block : filament_usage_blocks_)
per_extruder_usage_blocks[filament_maps[block.filament_id]].emplace_back(block); per_extruder_usage_blocks[filament_maps[block.filament_id]].emplace_back(block);
for (auto& extruder_usages : per_extruder_usage_blocks) { ExtruderPreHeating::FilamentUsageBlock start_filament_block(-1, 0, machine_start_gcode_end_id);
int extruder_id = extruder_usages.first; ExtruderPreHeating::FilamentUsageBlock end_filament_block(-1, machine_end_gcode_start_id, std::numeric_limits<unsigned int>::max());
const auto& filament_blocks = extruder_usages.second;
auto iter_lower = filament_blocks.begin(); for (auto& blocks : per_extruder_usage_blocks) {
auto iter_upper = filament_blocks.end(); blocks.insert(blocks.begin(), start_filament_block);
blocks.emplace_back(end_filament_block);
}
while (iter_lower != filament_blocks.end() && iter_lower->lower_gcode_id < machine_start_gcode_end_id) for(size_t extruder_id =0 ;extruder_id<per_extruder_usage_blocks.size();++extruder_id){
++iter_lower; const auto& filament_blocks = per_extruder_usage_blocks[extruder_id];
while (iter_upper != filament_blocks.begin() && std::prev(iter_upper)->upper_gcode_id > machine_end_gcode_start_id)
--iter_upper;
if (iter_lower >= iter_upper) for (auto iter = filament_blocks.begin(); iter < filament_blocks.end(); ++iter) {
continue;
{
ExtruderFreeBlock block;
block.free_lower_gcode_id = machine_start_gcode_end_id;
block.free_upper_gcode_id = std::min(machine_end_gcode_start_id, iter_lower->lower_gcode_id);
block.last_filament_id = iter_lower->filament_id;
block.next_filament_id = iter_lower->filament_id;
block.extruder_id = extruder_id;
block.partial_free_lower_id = block.free_lower_gcode_id;
block.partial_free_upper_id = block.free_lower_gcode_id;
m_extruder_free_blocks.emplace_back(block);
}
for (auto iter = iter_lower; iter < iter_upper; ++iter) {
auto niter = std::next(iter); auto niter = std::next(iter);
if (niter == filament_blocks.end())
break;
ExtruderFreeBlock block; ExtruderFreeBlock block;
block.free_lower_gcode_id = std::max(iter->upper_gcode_id, machine_start_gcode_end_id); block.free_lower_gcode_id = iter->upper_gcode_id;
block.last_filament_id = iter->filament_id; block.last_filament_id = iter->filament_id;
if (niter != iter_upper) { block.free_upper_gcode_id = niter->lower_gcode_id;
block.free_upper_gcode_id = std::min(niter->lower_gcode_id, machine_end_gcode_start_id); block.next_filament_id = niter->filament_id;
block.next_filament_id = niter->filament_id;
}
else {
block.free_upper_gcode_id = machine_end_gcode_start_id;
block.next_filament_id = iter->filament_id;
}
block.extruder_id = extruder_id; block.extruder_id = extruder_id;
block.partial_free_lower_id = block.free_lower_gcode_id; block.partial_free_lower_id = block.free_lower_gcode_id;
block.partial_free_upper_id = block.free_lower_gcode_id; block.partial_free_upper_id = block.free_lower_gcode_id;
@ -6005,54 +5991,37 @@ void GCodeProcessor::PreCoolingInjector::build_by_filament_blocks(const std::vec
void GCodeProcessor::PreCoolingInjector::build_by_extruder_blocks(const std::vector<ExtruderPreHeating::ExtruderUsageBlcok>& extruder_usage_blocks_) void GCodeProcessor::PreCoolingInjector::build_by_extruder_blocks(const std::vector<ExtruderPreHeating::ExtruderUsageBlcok>& extruder_usage_blocks_)
{ {
m_extruder_free_blocks.clear(); m_extruder_free_blocks.clear();
std::map<int, std::vector<ExtruderPreHeating::ExtruderUsageBlcok>> per_extruder_usage_blocks; std::vector<std::vector<ExtruderPreHeating::ExtruderUsageBlcok>> per_extruder_usage_blocks(2);
for (auto& block : extruder_usage_blocks_) for (auto& block : extruder_usage_blocks_)
per_extruder_usage_blocks[block.extruder_id].emplace_back(block); per_extruder_usage_blocks[block.extruder_id].emplace_back(block);
for (auto& extruder_usages : per_extruder_usage_blocks) { for(size_t extruder_id =0;extruder_id<per_extruder_usage_blocks.size();++extruder_id){
int extruder_id = extruder_usages.first; auto& blocks = per_extruder_usage_blocks[extruder_id];
const auto& extruder_usage_blocks = extruder_usages.second; ExtruderPreHeating::ExtruderUsageBlcok start_filament_block;
if (extruder_usage_blocks.empty()) start_filament_block.initialize_step_1(extruder_id, 0, -1);
continue; start_filament_block.initialize_step_2(machine_start_gcode_end_id);
start_filament_block.initialize_step_3(machine_start_gcode_end_id, -1, machine_start_gcode_end_id);
auto iter_lower = extruder_usage_blocks.begin(); ExtruderPreHeating::ExtruderUsageBlcok end_filament_block;
auto iter_upper = extruder_usage_blocks.end(); end_filament_block.initialize_step_1(extruder_id, machine_end_gcode_start_id, -1);
while (iter_lower != extruder_usage_blocks.end() && iter_lower->start_id < machine_start_gcode_end_id) end_filament_block.initialize_step_2(std::numeric_limits<int>::max());
++iter_lower; end_filament_block.initialize_step_3(std::numeric_limits<int>::max(), -1, std::numeric_limits<int>::max());
while (iter_upper != extruder_usage_blocks.begin() && std::prev(iter_upper)->end_id > machine_end_gcode_start_id)
--iter_upper;
if (iter_lower >= iter_upper) blocks.insert(blocks.begin(), start_filament_block);
continue; blocks.emplace_back(end_filament_block);
}
{ for (size_t extruder_id = 0; extruder_id < per_extruder_usage_blocks.size(); ++extruder_id) {
ExtruderFreeBlock block; const auto& extruder_usage_blocks = per_extruder_usage_blocks[extruder_id];
block.free_lower_gcode_id = machine_start_gcode_end_id; for (auto iter = extruder_usage_blocks.begin(); iter != extruder_usage_blocks.end(); ++iter) {
block.free_upper_gcode_id = std::min(iter_lower->start_id, machine_end_gcode_start_id);
block.extruder_id = extruder_id;
block.last_filament_id = iter_lower->start_filament;
block.next_filament_id = iter_lower->start_filament;
block.partial_free_lower_id = machine_start_gcode_end_id;
block.partial_free_upper_id = machine_start_gcode_end_id; // invalid
m_extruder_free_blocks.emplace_back(block);
}
for (auto iter = iter_lower; iter != iter_upper; ++iter) {
auto niter = std::next(iter); auto niter = std::next(iter);
if (niter == extruder_usage_blocks.end())
break;
ExtruderFreeBlock block; ExtruderFreeBlock block;
block.free_lower_gcode_id = std::max(iter->end_id, machine_start_gcode_end_id); block.free_lower_gcode_id = iter->end_id;
block.last_filament_id = iter->end_filament; block.last_filament_id = iter->end_filament;
if (niter != iter_upper) { block.free_upper_gcode_id = niter->start_id;
block.free_upper_gcode_id = std::min(niter->start_id, machine_end_gcode_start_id); block.next_filament_id = niter->start_filament;
block.next_filament_id = niter->start_filament;
}
else {
block.free_upper_gcode_id = machine_end_gcode_start_id;
block.next_filament_id = iter->end_filament;
}
block.extruder_id = extruder_id; block.extruder_id = extruder_id;
block.partial_free_lower_id = iter->post_extrusion_start_id; block.partial_free_lower_id = iter->post_extrusion_start_id;
block.partial_free_upper_id = iter->post_extrusion_end_id; block.partial_free_upper_id = iter->post_extrusion_end_id;