mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-19 17:02:08 +00:00
Improve filament change time estimation for CC & CC2 printers and add purge length statistics. (#14663)
* Improve filament change time estimation for CC & CC2 printers and add purge length statistics. * fix(gcode): route elegoo M6211 handling
This commit is contained in:
@@ -221,6 +221,7 @@ set(lisbslic3r_sources
|
||||
GCode/FanMover.hpp
|
||||
GCode/GCodeProcessor.cpp
|
||||
GCode/GCodeProcessor.hpp
|
||||
GCode/ElegooGCodeProcessorHelper.cpp
|
||||
GCode.hpp
|
||||
GCode/PchipInterpolatorHelper.cpp
|
||||
GCode/PchipInterpolatorHelper.hpp
|
||||
|
||||
190
src/libslic3r/GCode/ElegooGCodeProcessorHelper.cpp
Normal file
190
src/libslic3r/GCode/ElegooGCodeProcessorHelper.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
#include "GCodeProcessor.hpp"
|
||||
|
||||
#include "libslic3r/libslic3r.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <string_view>
|
||||
|
||||
namespace Slic3r {
|
||||
namespace {
|
||||
|
||||
bool equals_case_insensitive(std::string_view lhs, std::string_view rhs)
|
||||
{
|
||||
return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin(), [](unsigned char l, unsigned char r) {
|
||||
return std::tolower(l) == std::tolower(r);
|
||||
});
|
||||
}
|
||||
|
||||
float get_clamped_param(const GCodeReader::GCodeLine& line, char axis, float default_value, float min_value, float max_value)
|
||||
{
|
||||
float value = default_value;
|
||||
line.has_value(axis, value);
|
||||
return std::clamp(value, min_value, max_value);
|
||||
}
|
||||
|
||||
float extrusion_time(float e_length, float feedrate)
|
||||
{
|
||||
return feedrate > 0.0f && e_length > 0.0f ? e_length / feedrate * 60.0f : 0.0f;
|
||||
}
|
||||
|
||||
float retract_time(float e_length)
|
||||
{
|
||||
static constexpr float retract_feedrate = 1800.0f;
|
||||
return extrusion_time(std::max(e_length, 0.0f), retract_feedrate);
|
||||
}
|
||||
|
||||
float s819_time(float e_length, float feedrate)
|
||||
{
|
||||
static constexpr float s819_tail_flush_length = 10.0f;
|
||||
static constexpr float s819_tail_feedrate = 400.0f;
|
||||
|
||||
const float tail_length = std::min(std::max(e_length, 0.0f), s819_tail_flush_length);
|
||||
const float main_length = std::max(e_length - tail_length, 0.0f);
|
||||
return extrusion_time(main_length, feedrate) + extrusion_time(tail_length, s819_tail_feedrate);
|
||||
}
|
||||
|
||||
float estimate_M6211_time_for_centauri_carbon(const GCodeReader::GCodeLine& line, float length, double current_x,
|
||||
double current_y)
|
||||
{
|
||||
static constexpr float max_segment_length = 73.0f;
|
||||
static constexpr float wipe_after_flush_time = 2.8f;
|
||||
static constexpr float main_feedrate = 500.0f;
|
||||
static constexpr float tail_feedrate = 400.0f;
|
||||
static constexpr float travel_feedrate = 5000.0f;
|
||||
static constexpr double parking_x = 256.0;
|
||||
static constexpr double parking_y = 0.0;
|
||||
|
||||
const float flush_length = std::clamp(length, 10.0f, 1000.0f);
|
||||
const float cool_time = get_clamped_param(line, 'P', 5000.0f, 0.0f, 20000.0f) * 0.001f;
|
||||
const float travel_time = static_cast<float>(std::abs(current_y - parking_y) + std::abs(current_x - parking_x)) /
|
||||
travel_feedrate * 60.0f;
|
||||
|
||||
// Initial time, including: material change, heating, etc.
|
||||
float m6211_time = 18.2f + travel_time;
|
||||
|
||||
float remaining_flush_length = std::max(flush_length, 0.0f);
|
||||
while (remaining_flush_length > 0.0f) {
|
||||
const float segment_length = std::min(remaining_flush_length, max_segment_length);
|
||||
remaining_flush_length -= segment_length;
|
||||
if (segment_length >= max_segment_length) {
|
||||
// Full segment: 3-phase extrusion (30+35+10=75mm) + retract
|
||||
m6211_time += extrusion_time(30.0f, main_feedrate) + extrusion_time(35.0f, main_feedrate) +
|
||||
extrusion_time(10.0f, tail_feedrate) + extrusion_time(2.0f, tail_feedrate) + cool_time +
|
||||
wipe_after_flush_time;
|
||||
} else {
|
||||
// Partial last segment: simple extrude at F500 + retract at F400
|
||||
m6211_time += extrusion_time(segment_length, main_feedrate) + extrusion_time(2.0f, tail_feedrate) + cool_time +
|
||||
wipe_after_flush_time;
|
||||
}
|
||||
}
|
||||
|
||||
return m6211_time;
|
||||
}
|
||||
|
||||
float estimate_M6211_time_for_centauri_carbon_2(const GCodeReader::GCodeLine& line, float length, float new_extruder_temp)
|
||||
{
|
||||
const float flush_length = std::clamp(length, 10.0f, 1000.0f);
|
||||
const float flush_length_single = get_clamped_param(line, 'K', 75.0f, 10.0f, 300.0f);
|
||||
const float old_filament_e_feedrate = get_clamped_param(line, 'M', 300.0f, 10.0f, 600.0f);
|
||||
const float new_filament_e_feedrate = get_clamped_param(line, 'N', 300.0f, 10.0f, 600.0f);
|
||||
const float cool_time = get_clamped_param(line, 'P', 3000.0f, 0.0f, 20000.0f) * 0.001f;
|
||||
|
||||
// The flush length of the old material, unit: mm
|
||||
static constexpr float e_flush_dist = 15.0f;
|
||||
// Wipe time after flush, in seconds
|
||||
static constexpr float wipe_after_flush_time = 5.0f;
|
||||
|
||||
const float flush_length_after_start = std::max(flush_length - e_flush_dist, 0.0f);
|
||||
const int flush_times = std::max(1, static_cast<int>(std::ceil(flush_length_after_start / flush_length_single)));
|
||||
const float flush_length_actual = flush_length_single;
|
||||
|
||||
// Initial time, including: material change, heating, moving, etc.
|
||||
float m6211_time = 31.0f;
|
||||
m6211_time += extrusion_time(std::min(e_flush_dist, flush_length), old_filament_e_feedrate);
|
||||
|
||||
const int intermediate_flush_times = flush_times - 1;
|
||||
const float intermediate_flush_time = s819_time(flush_length_actual, new_filament_e_feedrate) + retract_time(6.0f) + cool_time +
|
||||
wipe_after_flush_time;
|
||||
m6211_time += static_cast<float>(intermediate_flush_times) * intermediate_flush_time;
|
||||
m6211_time += s819_time(flush_length_actual, new_filament_e_feedrate * 0.8f) + retract_time(4.0f) + cool_time + wipe_after_flush_time;
|
||||
|
||||
static constexpr float cooling_rate = 1.36f;
|
||||
const float r_temp = get_clamped_param(line, 'R', new_extruder_temp + 20.0f, 185.0f, 350.0f);
|
||||
const float s_temp = get_clamped_param(line, 'S', 250.0f, 185.0f, 350.0f);
|
||||
|
||||
if (s_temp < r_temp)
|
||||
m6211_time += (r_temp - s_temp) / cooling_rate;
|
||||
|
||||
return m6211_time;
|
||||
}
|
||||
|
||||
float estimate_M6211_time(const GCodeReader::GCodeLine& line, std::string_view printer_model, float length, float new_extruder_temp, double current_x, double current_y)
|
||||
{
|
||||
if (equals_case_insensitive(printer_model, "Elegoo Centauri Carbon") || equals_case_insensitive(printer_model, "Elegoo Centauri")) {
|
||||
return estimate_M6211_time_for_centauri_carbon(line, length, current_x, current_y);
|
||||
} else if (equals_case_insensitive(printer_model, "Elegoo Centauri Carbon 2") ||
|
||||
equals_case_insensitive(printer_model, "Elegoo Centauri 2")) {
|
||||
return estimate_M6211_time_for_centauri_carbon_2(line, length, new_extruder_temp);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void GCodeProcessor::process_elegoo_M6211(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
float length = 0.0f;
|
||||
if (!line.has_value('L', length) || length <= 0.0f)
|
||||
return;
|
||||
|
||||
float t = -1.0f;
|
||||
if (!line.has_value('T', t) || t < 0.0f)
|
||||
return;
|
||||
|
||||
const int filament_id = static_cast<int>(std::round(t));
|
||||
if (filament_id < 0 || filament_id >= m_result.filaments_count)
|
||||
return;
|
||||
|
||||
const int extruder_id = m_filament_maps[filament_id];
|
||||
|
||||
float new_extruder_temp = 0.0f;
|
||||
if (line.has_value('S', new_extruder_temp)) {
|
||||
if (extruder_id >= 0 && static_cast<size_t>(extruder_id) < m_extruder_temps.size())
|
||||
m_extruder_temps[static_cast<size_t>(extruder_id)] = new_extruder_temp;
|
||||
}
|
||||
|
||||
const float m6211_time = estimate_M6211_time(line, m_printer_model, length, new_extruder_temp,
|
||||
m_start_position[X], m_start_position[Y]);
|
||||
const int curr_filament_id = get_filament_id(false);
|
||||
const bool is_first_extrusion = (curr_filament_id == -1) || (filament_id == curr_filament_id);
|
||||
|
||||
m_time_processor.filament_unload_times = 0;
|
||||
m_time_processor.filament_load_times = m6211_time;
|
||||
process_filament_change(filament_id);
|
||||
|
||||
if (extruder_id >= 0 && static_cast<size_t>(extruder_id) < m_remaining_volume.size()) {
|
||||
const float remaining_volume = static_cast<size_t>(extruder_id) < m_nozzle_volume.size() ?
|
||||
m_nozzle_volume[extruder_id] :
|
||||
0.0f;
|
||||
const float filament_diameter = static_cast<size_t>(filament_id) < m_result.filament_diameters.size() ?
|
||||
m_result.filament_diameters[filament_id] :
|
||||
m_result.filament_diameters.back();
|
||||
const float area_filament_cross_section = static_cast<float>(M_PI) * sqr(0.5f * filament_diameter);
|
||||
const float volume_flushed_filament = area_filament_cross_section * length;
|
||||
|
||||
if (volume_flushed_filament >= remaining_volume) {
|
||||
if (!is_first_extrusion)
|
||||
m_used_filaments.update_flush_per_filament(curr_filament_id, remaining_volume);
|
||||
|
||||
m_used_filaments.update_flush_per_filament(filament_id, volume_flushed_filament - remaining_volume);
|
||||
m_remaining_volume[extruder_id] = 0.0f;
|
||||
} else {
|
||||
m_used_filaments.update_flush_per_filament(filament_id, volume_flushed_filament);
|
||||
m_remaining_volume[extruder_id] -= volume_flushed_filament;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
@@ -1839,7 +1839,8 @@ void GCodeProcessor::register_commands()
|
||||
{"VM104", [this](const GCodeReader::GCodeLine& line) { process_VM104(line); }},
|
||||
{"VM109", [this](const GCodeReader::GCodeLine& line) { process_VM109(line); }},
|
||||
{"M622", [this](const GCodeReader::GCodeLine& line) { process_M622(line);}},
|
||||
{"M623", [this](const GCodeReader::GCodeLine& line) { process_M623(line);}}
|
||||
{"M623", [this](const GCodeReader::GCodeLine& line) { process_M623(line);}},
|
||||
{"M6211", [this](const GCodeReader::GCodeLine& line) { process_M6211(line); }}
|
||||
};
|
||||
|
||||
std::unordered_set<std::string>early_quit_commands = {
|
||||
@@ -1863,6 +1864,12 @@ void GCodeProcessor::register_commands()
|
||||
}
|
||||
}
|
||||
|
||||
void GCodeProcessor::process_M6211(const GCodeReader::GCodeLine& line)
|
||||
{
|
||||
if (boost::algorithm::istarts_with(m_printer_model, "elegoo"))
|
||||
process_elegoo_M6211(line);
|
||||
}
|
||||
|
||||
bool GCodeProcessor::check_multi_extruder_gcode_valid(const int extruder_size,
|
||||
const Pointfs plate_printable_area,
|
||||
const double plate_printable_height,
|
||||
@@ -2027,6 +2034,7 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
|
||||
m_parser.apply_config(config);
|
||||
|
||||
m_flavor = config.gcode_flavor;
|
||||
m_printer_model = config.printer_model.value;
|
||||
|
||||
m_single_extruder_multi_material = config.single_extruder_multi_material;
|
||||
|
||||
@@ -2213,6 +2221,10 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
|
||||
if (printer_settings_id != nullptr)
|
||||
m_result.settings_ids.printer = printer_settings_id->value;
|
||||
|
||||
const ConfigOptionString* printer_model = config.option<ConfigOptionString>("printer_model");
|
||||
if (printer_model != nullptr)
|
||||
m_printer_model = printer_model->value;
|
||||
|
||||
// BBS
|
||||
m_result.filaments_count = config.option<ConfigOptionFloats>("filament_diameter")->values.size();
|
||||
|
||||
|
||||
@@ -846,6 +846,7 @@ class Print;
|
||||
float m_preheat_time;
|
||||
int m_preheat_steps;
|
||||
bool m_disable_m73;
|
||||
std::string m_printer_model;
|
||||
|
||||
enum class EProducer
|
||||
{
|
||||
@@ -1084,6 +1085,10 @@ class Print;
|
||||
// Unload the current filament into the MK3 MMU2 unit at the end of print.
|
||||
void process_M702(const GCodeReader::GCodeLine& line);
|
||||
|
||||
//Used for Elegoo printer to change tool head
|
||||
void process_M6211(const GCodeReader::GCodeLine& line);
|
||||
void process_elegoo_M6211(const GCodeReader::GCodeLine& line);
|
||||
|
||||
void process_SYNC(const GCodeReader::GCodeLine& line);
|
||||
|
||||
// Processes T line (Select Tool)
|
||||
|
||||
Reference in New Issue
Block a user