From e8968e9ce9cbfff02e90a1fb2621858ccebb102c Mon Sep 17 00:00:00 2001 From: Morton Jonuschat Date: Fri, 27 Dec 2024 17:10:17 -0800 Subject: [PATCH] [FEATURE] Enable pre-heating of toolheads for all toolchangers --- src/libslic3r/GCode/GCodeProcessor.cpp | 37 ++++++++++++++++---------- src/libslic3r/GCode/GCodeProcessor.hpp | 4 +-- src/libslic3r/GCode/GCodeWriter.cpp | 35 +++++++++++++++--------- src/libslic3r/GCode/GCodeWriter.hpp | 1 + src/libslic3r/Preset.cpp | 3 +++ src/libslic3r/Print.cpp | 2 ++ src/libslic3r/PrintConfig.cpp | 19 +++++++++++++ src/libslic3r/PrintConfig.hpp | 2 ++ src/slic3r/GUI/ConfigManipulation.cpp | 2 ++ src/slic3r/GUI/Tab.cpp | 2 ++ 10 files changed, 78 insertions(+), 29 deletions(-) diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 96a7243f41a..2e29e91611e 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -627,11 +627,14 @@ void GCodeProcessor::apply_config(const PrintConfig& config) m_producer = EProducer::PrusaSlicer; m_flavor = config.gcode_flavor; - m_result.backtrace_enabled = is_XL_printer(config); - size_t extruders_count = config.nozzle_diameter.values.size(); m_result.extruders_count = extruders_count; + m_is_XL_printer = is_XL_printer(config); + m_single_extruder_multi_material = config.single_extruder_multi_material; + m_preheat_time = config.preheat_time; + m_preheat_steps = std::max(config.preheat_steps, 1); + m_extruder_offsets.resize(extruders_count); m_extruder_colors.resize(extruders_count); m_result.filament_diameters.resize(extruders_count); @@ -640,7 +643,8 @@ void GCodeProcessor::apply_config(const PrintConfig& config) m_extruder_temps.resize(extruders_count); m_extruder_temps_config.resize(extruders_count); m_extruder_temps_first_layer_config.resize(extruders_count); - m_is_XL_printer = is_XL_printer(config); + + m_result.backtrace_enabled = m_preheat_time > 0 && (m_is_XL_printer || (!m_single_extruder_multi_material && extruders_count > 1)); for (size_t i = 0; i < extruders_count; ++ i) { m_extruder_offsets[i] = to_3d(config.extruder_offset.get_at(i).cast().eval(), 0.f); @@ -682,8 +686,6 @@ void GCodeProcessor::apply_config(const PrintConfig& config) m_time_processor.filament_unload_times[i] = static_cast(config.filament_unload_time.values[i]); } - m_single_extruder_multi_material = config.single_extruder_multi_material; - // With MM setups like Prusa MMU2, the filaments may be expected to be parked at the beginning. // Remember the parking position so the initial load is not included in filament estimate. if (m_single_extruder_multi_material && extruders_count > 1 && config.wipe_tower) { @@ -1075,6 +1077,8 @@ void GCodeProcessor::reset() m_kissslicer_toolchange_time_correction = 0.0f; m_single_extruder_multi_material = false; + m_preheat_time = 0.f; + m_preheat_steps = 1; } static inline const char* skip_whitespaces(const char *begin, const char *end) { @@ -4315,13 +4319,19 @@ void GCodeProcessor::post_process() // line inserter [tool_number, this](unsigned int id, const std::vector& time_diffs) { const int temperature = int(m_layer_id != 1 ? m_extruder_temps_config[tool_number] : m_extruder_temps_first_layer_config[tool_number]); - std::string out = "M104.1 T" + std::to_string(tool_number); - if (time_diffs.size() > 0) - out += " P" + std::to_string(int(std::round(time_diffs[0]))); - if (time_diffs.size() > 1) - out += " Q" + std::to_string(int(std::round(time_diffs[1]))); - out += " S" + std::to_string(temperature) + "\n"; - return out; + if (m_is_XL_printer) { + std::string out = "M104.1 T" + std::to_string(tool_number); + if (time_diffs.size() > 0) + out += " P" + std::to_string(int(std::round(time_diffs[0]))); + if (time_diffs.size() > 1) + out += " Q" + std::to_string(int(std::round(time_diffs[1]))); + out += " S" + std::to_string(temperature) + "\n"; + return out; + } else { + std::string comment = "preheat T" + std::to_string(tool_number) + + " time: " + std::to_string((int) std::round(time_diffs[0])) + "s"; + return GCodeWriter::set_temperature(temperature, m_flavor, false, tool_number, comment); + } }, // line replacer [this, tool_number](const std::string& line) { @@ -4346,7 +4356,7 @@ void GCodeProcessor::post_process() unsigned int line_id = 0; // Backtrace data for Tx gcode lines - static const ExportLines::Backtrace backtrace_T = { 120.0f, 10 }; + static const ExportLines::Backtrace backtrace_T = { m_preheat_time, static_cast(m_preheat_steps) }; // In case there are multiple sources of backtracing, keeps track of the longest backtrack time needed // to flush the backtrace cache accordingly float max_backtrace_time = 120.0f; @@ -4766,4 +4776,3 @@ double GCodeProcessor::extract_absolute_position_on_axis(Axis axis, const GCodeR } } /* namespace Slic3r */ - diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index b218c95dc05..e06298ed5e9 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -539,6 +539,8 @@ namespace Slic3r { size_t m_last_default_color_id; float m_kissslicer_toolchange_time_correction; bool m_single_extruder_multi_material; + float m_preheat_time; + int m_preheat_steps; enum class EProducer { @@ -784,5 +786,3 @@ namespace Slic3r { } /* namespace Slic3r */ #endif /* slic3r_GCodeProcessor_hpp_ */ - - diff --git a/src/libslic3r/GCode/GCodeWriter.cpp b/src/libslic3r/GCode/GCodeWriter.cpp index c002b9d36ff..6c177463883 100644 --- a/src/libslic3r/GCode/GCodeWriter.cpp +++ b/src/libslic3r/GCode/GCodeWriter.cpp @@ -107,35 +107,36 @@ std::string GCodeWriter::postamble() const return gcode.str(); } -std::string GCodeWriter::set_temperature(unsigned int temperature, bool wait, int tool) const +std::string GCodeWriter::set_temperature(unsigned int temperature, GCodeFlavor flavor, bool wait, int tool, std::string comment) { - if (wait && (FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish))) + if (wait && (flavor == gcfMakerWare || flavor == gcfSailfish)) return {}; - std::string_view code, comment; - if (wait && FLAVOR_IS_NOT(gcfTeacup) && FLAVOR_IS_NOT(gcfRepRapFirmware)) { + std::string_view code; + if (wait && flavor != gcfTeacup && flavor != gcfRepRapFirmware) { code = "M109"sv; - comment = "set temperature and wait for it to be reached"sv; + if(comment.empty()) + comment = "set temperature and wait for it to be reached"sv; } else { - if (FLAVOR_IS(gcfRepRapFirmware)) { // M104 is deprecated on RepRapFirmware + if (flavor == gcfRepRapFirmware) { // M104 is deprecated on RepRapFirmware code = "G10"sv; } else { code = "M104"sv; } - comment = "set temperature"sv; + if(comment.empty()) + comment = "set temperature"sv; } std::ostringstream gcode; gcode << code << " "; - if (FLAVOR_IS(gcfMach3) || FLAVOR_IS(gcfMachinekit)) { + if (flavor == gcfMach3 || flavor == gcfMachinekit) { gcode << "P"; } else { gcode << "S"; } gcode << temperature; - bool multiple_tools = this->multiple_extruders && ! m_single_extruder_multi_material; - if (tool != -1 && (multiple_tools || FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish) || FLAVOR_IS(gcfRepRapFirmware)) ) { - if (FLAVOR_IS(gcfRepRapFirmware)) { + if (tool != -1) { + if (flavor == gcfRepRapFirmware) { gcode << " P" << tool; } else { gcode << " T" << tool; @@ -143,12 +144,20 @@ std::string GCodeWriter::set_temperature(unsigned int temperature, bool wait, in } gcode << " ; " << comment << "\n"; - if ((FLAVOR_IS(gcfTeacup) || FLAVOR_IS(gcfRepRapFirmware)) && wait) + if ((flavor == gcfTeacup || flavor == gcfRepRapFirmware) && wait) gcode << "M116 ; wait for temperature to be reached\n"; - + return gcode.str(); } +std::string GCodeWriter::set_temperature(unsigned int temperature, bool wait, int tool) const +{ + // set tool to -1 to make sure we won't emit T parameter for single extruder or SEMM + if (!this->multiple_extruders || m_single_extruder_multi_material) + tool = -1; + return set_temperature(temperature, this->config.gcode_flavor, wait, tool); +} + std::string GCodeWriter::set_bed_temperature(unsigned int temperature, bool wait) { if (temperature == m_last_bed_temperature && (! wait || m_last_bed_temperature_reached)) diff --git a/src/libslic3r/GCode/GCodeWriter.hpp b/src/libslic3r/GCode/GCodeWriter.hpp index ace44344967..0d533fceaae 100644 --- a/src/libslic3r/GCode/GCodeWriter.hpp +++ b/src/libslic3r/GCode/GCodeWriter.hpp @@ -57,6 +57,7 @@ class GCodeWriter { } std::string preamble(); std::string postamble() const; + static std::string set_temperature(unsigned int temperature, GCodeFlavor flavor, bool wait = false, int tool = -1, std::string comment = std::string()); std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1) const; std::string set_bed_temperature(unsigned int temperature, bool wait = false); std::string set_chamber_temperature(unsigned int temperature, bool wait, bool accurate) const; diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index 88ee7c0c6cc..48643fe5bd9 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -572,6 +572,9 @@ static std::vector s_Preset_print_options { "top_layer_flow_ratio", "print_extrusion_multiplier", + + "preheat_time", + "preheat_steps", }; static std::vector s_Preset_filament_options { diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index 5e275f46165..3ad1c6fbc60 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -183,6 +183,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n "solid_infill_minimum_cruise_ratio", "solid_infill_jerk", "standby_temperature_delta", + "preheat_time", + "preheat_steps", "start_gcode", "start_filament_gcode", "toolchange_gcode", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 3c0403eab41..5759fc6dec8 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3422,6 +3422,25 @@ void PrintConfigDef::init_fff_params() def->mode = comExpert; def->set_default_value(new ConfigOptionBool(true)); + def = this->add("preheat_time", coFloat); + def->label = L("Preheat time"); + def->tooltip = L("To reduce the waiting time after tool change, the next tool can be preheated while the current " + "tool is still in use. This setting specifies the time in seconds to preheat the next tool. A M104 " + "command to preheat the tool in advance will be inserted into the G-Code."); + def->sidetext = "s"; + def->min = 0; + def->max = 120; + def->mode = comExpert; + def->set_default_value(new ConfigOptionFloat(120.0)); + + def = this->add("preheat_steps", coInt); + def->label = L("Preheat steps"); + def->tooltip = L("Insert multiple preheat commands (e.g. M104.1). Only useful for Prusa XL. For other printers, please set it to 1."); + def->min = 1; + def->max = 10; + def->mode = comExpert; + def->set_default_value(new ConfigOptionInt(1)); + def = this->add("start_gcode", coString); def->label = L("Start G-code"); def->tooltip = L("This start procedure is inserted at the beginning, possibly prepended by " diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 4de78c66059..1b9d3c8096f 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -1051,6 +1051,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE( ((ConfigOptionBool, wiping_volumes_use_custom_matrix)) ((ConfigOptionFloat, z_offset)) ((ConfigOptionFloat, init_z_rotate)) + ((ConfigOptionFloat, preheat_time)) + ((ConfigOptionInt, preheat_steps)) ) PRINT_CONFIG_CLASS_DERIVED_DEFINE0( diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index afb2899c1af..1c2538208b0 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -455,6 +455,8 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) bool have_ooze_prevention = config->opt_bool("ooze_prevention"); toggle_field("standby_temperature_delta", have_ooze_prevention); + toggle_field("preheat_time", have_ooze_prevention); + toggle_field("preheat_steps", have_ooze_prevention); bool have_wipe_tower = config->opt_bool("wipe_tower"); for (auto el : { "wipe_tower_width", "wipe_tower_brim_width", "wipe_tower_cone_angle", diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 45ddd6b2417..c34615360e1 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1755,6 +1755,8 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Ooze prevention")); optgroup->append_single_option_line("ooze_prevention"); optgroup->append_single_option_line("standby_temperature_delta"); + optgroup->append_single_option_line("preheat_time"); + optgroup->append_single_option_line("preheat_steps"); optgroup = page->new_optgroup(L("Wipe tower")); optgroup->append_single_option_line("wipe_tower");