diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 4345f2d07..8e0862cf2 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -412,45 +412,54 @@ void GCode::_do_export(Print &print, FILE *file, GCodePreviewData *preview_data) // resets time estimators m_normal_time_estimator.reset(); m_normal_time_estimator.set_dialect(print.config.gcode_flavor); - m_normal_time_estimator.set_acceleration(print.config.machine_max_acceleration_extruding.values[0]); - m_normal_time_estimator.set_retract_acceleration(print.config.machine_max_acceleration_retracting.values[0]); - m_normal_time_estimator.set_minimum_feedrate(print.config.machine_min_extruding_rate.values[0]); - m_normal_time_estimator.set_minimum_travel_feedrate(print.config.machine_min_travel_rate.values[0]); - m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, print.config.machine_max_acceleration_x.values[0]); - m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, print.config.machine_max_acceleration_y.values[0]); - m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, print.config.machine_max_acceleration_z.values[0]); - m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, print.config.machine_max_acceleration_e.values[0]); - m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, print.config.machine_max_feedrate_x.values[0]); - m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, print.config.machine_max_feedrate_y.values[0]); - m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, print.config.machine_max_feedrate_z.values[0]); - m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, print.config.machine_max_feedrate_e.values[0]); - m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, print.config.machine_max_jerk_x.values[0]); - m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, print.config.machine_max_jerk_y.values[0]); - m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, print.config.machine_max_jerk_z.values[0]); - m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, print.config.machine_max_jerk_e.values[0]); + m_silent_time_estimator_enabled = (print.config.gcode_flavor == gcfMarlin) && print.config.silent_mode; - m_silent_time_estimator_enabled = (print.config.gcode_flavor == gcfMarlin) && print.config.silent_mode && boost::starts_with(print.config.printer_model.value, "MK3"); - if (m_silent_time_estimator_enabled) - { - m_silent_time_estimator.reset(); - m_silent_time_estimator.set_dialect(print.config.gcode_flavor); - m_silent_time_estimator.set_acceleration(print.config.machine_max_acceleration_extruding.values[1]); - m_silent_time_estimator.set_retract_acceleration(print.config.machine_max_acceleration_retracting.values[1]); - m_silent_time_estimator.set_minimum_feedrate(print.config.machine_min_extruding_rate.values[1]); - m_silent_time_estimator.set_minimum_travel_feedrate(print.config.machine_min_travel_rate.values[1]); - m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, print.config.machine_max_acceleration_x.values[1]); - m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, print.config.machine_max_acceleration_y.values[1]); - m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, print.config.machine_max_acceleration_z.values[1]); - m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, print.config.machine_max_acceleration_e.values[1]); - m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, print.config.machine_max_feedrate_x.values[1]); - m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, print.config.machine_max_feedrate_y.values[1]); - m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, print.config.machine_max_feedrate_z.values[1]); - m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, print.config.machine_max_feedrate_e.values[1]); - m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, print.config.machine_max_jerk_x.values[1]); - m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, print.config.machine_max_jerk_y.values[1]); - m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, print.config.machine_max_jerk_z.values[1]); - m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, print.config.machine_max_jerk_e.values[1]); + // Until we have a UI support for the other firmwares than the Marlin, use the hardcoded default values + // and let the user to enter the G-code limits into the start G-code. + // If the following block is enabled for other firmwares than the Marlin, then the function + // this->print_machine_envelope(file, print); + // shall be adjusted as well to produce a G-code block compatible with the particular firmware flavor. + if (print.config.gcode_flavor.value == gcfMarlin) { + m_normal_time_estimator.set_max_acceleration(print.config.machine_max_acceleration_extruding.values[0]); + m_normal_time_estimator.set_retract_acceleration(print.config.machine_max_acceleration_retracting.values[0]); + m_normal_time_estimator.set_minimum_feedrate(print.config.machine_min_extruding_rate.values[0]); + m_normal_time_estimator.set_minimum_travel_feedrate(print.config.machine_min_travel_rate.values[0]); + m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, print.config.machine_max_acceleration_x.values[0]); + m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, print.config.machine_max_acceleration_y.values[0]); + m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, print.config.machine_max_acceleration_z.values[0]); + m_normal_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, print.config.machine_max_acceleration_e.values[0]); + m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, print.config.machine_max_feedrate_x.values[0]); + m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, print.config.machine_max_feedrate_y.values[0]); + m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, print.config.machine_max_feedrate_z.values[0]); + m_normal_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, print.config.machine_max_feedrate_e.values[0]); + m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, print.config.machine_max_jerk_x.values[0]); + m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, print.config.machine_max_jerk_y.values[0]); + m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, print.config.machine_max_jerk_z.values[0]); + m_normal_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, print.config.machine_max_jerk_e.values[0]); + + if (m_silent_time_estimator_enabled) + { + m_silent_time_estimator.reset(); + m_silent_time_estimator.set_dialect(print.config.gcode_flavor); + m_silent_time_estimator.set_max_acceleration(print.config.machine_max_acceleration_extruding.values[1]); + m_silent_time_estimator.set_retract_acceleration(print.config.machine_max_acceleration_retracting.values[1]); + m_silent_time_estimator.set_minimum_feedrate(print.config.machine_min_extruding_rate.values[1]); + m_silent_time_estimator.set_minimum_travel_feedrate(print.config.machine_min_travel_rate.values[1]); + m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::X, print.config.machine_max_acceleration_x.values[1]); + m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Y, print.config.machine_max_acceleration_y.values[1]); + m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::Z, print.config.machine_max_acceleration_z.values[1]); + m_silent_time_estimator.set_axis_max_acceleration(GCodeTimeEstimator::E, print.config.machine_max_acceleration_e.values[1]); + m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::X, print.config.machine_max_feedrate_x.values[1]); + m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Y, print.config.machine_max_feedrate_y.values[1]); + m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::Z, print.config.machine_max_feedrate_z.values[1]); + m_silent_time_estimator.set_axis_max_feedrate(GCodeTimeEstimator::E, print.config.machine_max_feedrate_e.values[1]); + m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::X, print.config.machine_max_jerk_x.values[1]); + m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Y, print.config.machine_max_jerk_y.values[1]); + m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::Z, print.config.machine_max_jerk_z.values[1]); + m_silent_time_estimator.set_axis_max_jerk(GCodeTimeEstimator::E, print.config.machine_max_jerk_e.values[1]); + } } + // resets analyzer m_analyzer.reset(); m_enable_analyzer = preview_data != nullptr; diff --git a/xs/src/libslic3r/GCode/ToolOrdering.cpp b/xs/src/libslic3r/GCode/ToolOrdering.cpp index 2a85319aa..9b3f2694f 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.cpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.cpp @@ -442,13 +442,13 @@ bool WipingExtrusions::is_overriddable(const ExtrusionEntityCollection& eec, con // Following function iterates through all extrusions on the layer, remembers those that could be used for wiping after toolchange // and returns volume that is left to be wiped on the wipe tower. -float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int new_extruder, float volume_to_wipe) +float WipingExtrusions::mark_wiping_extrusions(const Print& print, unsigned int old_extruder, unsigned int new_extruder, float volume_to_wipe) { const LayerTools& lt = *m_layer_tools; const float min_infill_volume = 0.f; // ignore infill with smaller volume than this - if (print.config.filament_soluble.get_at(new_extruder)) - return volume_to_wipe; // Soluble filament cannot be wiped in a random infill + if (print.config.filament_soluble.get_at(old_extruder) || print.config.filament_soluble.get_at(new_extruder)) + return volume_to_wipe; // Soluble filament cannot be wiped in a random infill, neither the filament after it // we will sort objects so that dedicated for wiping are at the beginning: PrintObjectPtrs object_list = print.objects; diff --git a/xs/src/libslic3r/GCode/ToolOrdering.hpp b/xs/src/libslic3r/GCode/ToolOrdering.hpp index 13e0212f1..a7263abda 100644 --- a/xs/src/libslic3r/GCode/ToolOrdering.hpp +++ b/xs/src/libslic3r/GCode/ToolOrdering.hpp @@ -28,7 +28,7 @@ public: // This function goes through all infill entities, decides which ones will be used for wiping and // marks them by the extruder id. Returns volume that remains to be wiped on the wipe tower: - float mark_wiping_extrusions(const Print& print, unsigned int new_extruder, float volume_to_wipe); + float mark_wiping_extrusions(const Print& print, unsigned int old_extruder, unsigned int new_extruder, float volume_to_wipe); void ensure_perimeters_infills_order(const Print& print); diff --git a/xs/src/libslic3r/GCodeTimeEstimator.cpp b/xs/src/libslic3r/GCodeTimeEstimator.cpp index 285ed37bd..7c8540e66 100644 --- a/xs/src/libslic3r/GCodeTimeEstimator.cpp +++ b/xs/src/libslic3r/GCodeTimeEstimator.cpp @@ -414,7 +414,10 @@ namespace Slic3r { void GCodeTimeEstimator::set_acceleration(float acceleration_mm_sec2) { - _state.acceleration = acceleration_mm_sec2; + _state.acceleration = (_state.max_acceleration == 0) ? + acceleration_mm_sec2 : + // Clamp the acceleration with the maximum. + std::min(_state.max_acceleration, acceleration_mm_sec2); } float GCodeTimeEstimator::get_acceleration() const @@ -422,6 +425,18 @@ namespace Slic3r { return _state.acceleration; } + void GCodeTimeEstimator::set_max_acceleration(float acceleration_mm_sec2) + { + _state.max_acceleration = acceleration_mm_sec2; + if (acceleration_mm_sec2 > 0) + _state.acceleration = acceleration_mm_sec2; + } + + float GCodeTimeEstimator::get_max_acceleration() const + { + return _state.max_acceleration; + } + void GCodeTimeEstimator::set_retract_acceleration(float acceleration_mm_sec2) { _state.retract_acceleration = acceleration_mm_sec2; @@ -540,6 +555,9 @@ namespace Slic3r { set_e_local_positioning_type(Absolute); set_feedrate(DEFAULT_FEEDRATE); + // Setting the maximum acceleration to zero means that the there is no limit and the G-code + // is allowed to set excessive values. + set_max_acceleration(0); set_acceleration(DEFAULT_ACCELERATION); set_retract_acceleration(DEFAULT_RETRACT_ACCELERATION); set_minimum_feedrate(DEFAULT_MINIMUM_FEEDRATE); diff --git a/xs/src/libslic3r/GCodeTimeEstimator.hpp b/xs/src/libslic3r/GCodeTimeEstimator.hpp index 9b1a38985..fe678884a 100644 --- a/xs/src/libslic3r/GCodeTimeEstimator.hpp +++ b/xs/src/libslic3r/GCodeTimeEstimator.hpp @@ -72,6 +72,8 @@ namespace Slic3r { Axis axis[Num_Axis]; float feedrate; // mm/s float acceleration; // mm/s^2 + // hard limit for the acceleration, to which the firmware will clamp. + float max_acceleration; // mm/s^2 float retract_acceleration; // mm/s^2 float additional_time; // s float minimum_feedrate; // mm/s @@ -263,6 +265,10 @@ namespace Slic3r { void set_acceleration(float acceleration_mm_sec2); float get_acceleration() const; + // Maximum acceleration for the machine. The firmware simulator will clamp the M204 Sxxx to this maximum. + void set_max_acceleration(float acceleration_mm_sec2); + float get_max_acceleration() const; + void set_retract_acceleration(float acceleration_mm_sec2); float get_retract_acceleration() const; diff --git a/xs/src/libslic3r/GCodeWriter.cpp b/xs/src/libslic3r/GCodeWriter.cpp index cbe94f317..34e6b7ec3 100644 --- a/xs/src/libslic3r/GCodeWriter.cpp +++ b/xs/src/libslic3r/GCodeWriter.cpp @@ -18,7 +18,9 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config) { this->config.apply(print_config, true); m_extrusion_axis = this->config.get_extrusion_axis(); - this->m_single_extruder_multi_material = print_config.single_extruder_multi_material.value; + m_single_extruder_multi_material = print_config.single_extruder_multi_material.value; + m_max_acceleration = (print_config.gcode_flavor.value == gcfMarlin) ? + print_config.machine_max_acceleration_extruding.values.front() : 0; } void GCodeWriter::set_extruders(const std::vector &extruder_ids) @@ -85,7 +87,7 @@ std::string GCodeWriter::set_temperature(unsigned int temperature, bool wait, in } gcode << temperature; if (tool != -1 && - ( (this->multiple_extruders && ! this->m_single_extruder_multi_material) || + ( (this->multiple_extruders && ! m_single_extruder_multi_material) || FLAVOR_IS(gcfMakerWare) || FLAVOR_IS(gcfSailfish)) ) { gcode << " T" << tool; } @@ -170,6 +172,10 @@ std::string GCodeWriter::set_fan(unsigned int speed, bool dont_save) std::string GCodeWriter::set_acceleration(unsigned int acceleration) { + // Clamp the acceleration to the allowed maximum. + if (m_max_acceleration > 0 && acceleration > m_max_acceleration) + acceleration = m_max_acceleration; + if (acceleration == 0 || acceleration == m_last_acceleration) return std::string(); diff --git a/xs/src/libslic3r/GCodeWriter.hpp b/xs/src/libslic3r/GCodeWriter.hpp index 78e9c9323..f706b8768 100644 --- a/xs/src/libslic3r/GCodeWriter.hpp +++ b/xs/src/libslic3r/GCodeWriter.hpp @@ -18,7 +18,7 @@ public: GCodeWriter() : multiple_extruders(false), m_extrusion_axis("E"), m_extruder(nullptr), m_single_extruder_multi_material(false), - m_last_acceleration(0), m_last_fan_speed(0), + m_last_acceleration(0), m_max_acceleration(0), m_last_fan_speed(0), m_last_bed_temperature(0), m_last_bed_temperature_reached(true), m_lifted(0) {} @@ -74,6 +74,9 @@ private: bool m_single_extruder_multi_material; Extruder* m_extruder; unsigned int m_last_acceleration; + // Limit for setting the acceleration, to respect the machine limits set for the Marlin firmware. + // If set to zero, the limit is not in action. + unsigned int m_max_acceleration; unsigned int m_last_fan_speed; unsigned int m_last_bed_temperature; bool m_last_bed_temperature_reached; diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 9c9f7f5bb..0b0730d85 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -1147,7 +1147,7 @@ void Print::_make_wipe_tower() float volume_to_wipe = wipe_volumes[current_extruder_id][extruder_id]; // total volume to wipe after this toolchange // try to assign some infills/objects for the wiping: - volume_to_wipe = layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, extruder_id, wipe_volumes[current_extruder_id][extruder_id]); + volume_to_wipe = layer_tools.wiping_extrusions().mark_wiping_extrusions(*this, current_extruder_id, extruder_id, wipe_volumes[current_extruder_id][extruder_id]); wipe_tower.plan_toolchange(layer_tools.print_z, layer_tools.wipe_tower_layer_height, current_extruder_id, extruder_id, first_layer && extruder_id == m_tool_ordering.all_extruders().back(), volume_to_wipe); current_extruder_id = extruder_id;