mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-16 17:05:55 +08:00
max_gcode_per_second added
allow a better control than min_length
This commit is contained in:
parent
688121b104
commit
55fdc665ca
@ -19,6 +19,10 @@ group:silent_mode_event:Firmware
|
||||
setting:gcode_precision_xyz
|
||||
setting:gcode_precision_e
|
||||
end_line
|
||||
line:Processing limit
|
||||
setting:max_gcode_per_second
|
||||
setting:min_length
|
||||
end_line
|
||||
group:Cooling fan
|
||||
line:Speedup
|
||||
setting:label$Speedup time:fan_speedup_time
|
||||
@ -40,7 +44,6 @@ group:Advanced
|
||||
setting:use_relative_e_distances
|
||||
setting:use_firmware_retraction
|
||||
setting:use_volumetric_e
|
||||
setting:min_length
|
||||
setting:variable_layer_height
|
||||
|
||||
page:Custom G-code:cog
|
||||
|
@ -3366,14 +3366,19 @@ void GCode::use(const ExtrusionEntityCollection &collection) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string GCode::extrude_path(const ExtrusionPath &path, const std::string &description, double speed) {
|
||||
std::string GCode::extrude_path(const ExtrusionPath &path, const std::string &description, double speed_mm_per_sec) {
|
||||
|
||||
ExtrusionPath simplifed_path = path;
|
||||
const double scaled_min_length = scale_(this->config().min_length.value);
|
||||
if (scaled_min_length > 0 && !m_last_too_small.empty()) {
|
||||
const double max_gcode_per_second = this->config().max_gcode_per_second.value;
|
||||
double current_scaled_min_length = scaled_min_length;
|
||||
if (max_gcode_per_second > 0) {
|
||||
current_scaled_min_length = std::max(current_scaled_min_length, scale_(_compute_speed_mm_per_sec(path, speed_mm_per_sec)) / max_gcode_per_second);
|
||||
}
|
||||
if (current_scaled_min_length > 0 && !m_last_too_small.empty()) {
|
||||
//descr += " trys fusion " + std::to_string(unscaled(m_last_too_small.last_point().x())) + " , " + std::to_string(unscaled(path.first_point().x()));
|
||||
//ensure that it's a continous thing
|
||||
if (m_last_too_small.last_point().distance_to_square(path.first_point()) < scaled_min_length*scaled_min_length /*&& m_last_too_small.first_point().distance_to_square(path.first_point()) > EPSILON*/) {
|
||||
if (m_last_too_small.last_point().distance_to_square(path.first_point()) < current_scaled_min_length * current_scaled_min_length /*&& m_last_too_small.first_point().distance_to_square(path.first_point()) > EPSILON*/) {
|
||||
//descr += " ! fusion " + std::to_string(simplifed_path.polyline.points.size());
|
||||
simplifed_path.height = (m_last_too_small.height * m_last_too_small.length() + simplifed_path.height * simplifed_path.length()) / (m_last_too_small.length() + simplifed_path.length());
|
||||
simplifed_path.mm3_per_mm = (m_last_too_small.mm3_per_mm * m_last_too_small.length() + simplifed_path.mm3_per_mm * simplifed_path.length()) / (m_last_too_small.length() + simplifed_path.length());
|
||||
@ -3383,11 +3388,11 @@ std::string GCode::extrude_path(const ExtrusionPath &path, const std::string &de
|
||||
}
|
||||
m_last_too_small.polyline.points.clear();
|
||||
}
|
||||
if (scaled_min_length > 0) {
|
||||
if (current_scaled_min_length > 0) {
|
||||
// it's an alternative to simplifed_path.simplify(scale_(this->config().min_length)); with more enphasis ont he segment length that on the feature detail.
|
||||
// because tolerance = min_length /10, douglas_peucker will erase more points if angles are shallower than 6° and then the '_plus' will kick in to keep a bit more.
|
||||
// if angles are all bigger than 6°, then the douglas_peucker will do all the work.
|
||||
simplifed_path.polyline.points = MultiPoint::_douglas_peucker_plus(simplifed_path.polyline.points, scaled_min_length / 10, scaled_min_length);
|
||||
simplifed_path.polyline.points = MultiPoint::_douglas_peucker_plus(simplifed_path.polyline.points, current_scaled_min_length / 10, current_scaled_min_length);
|
||||
}
|
||||
//else simplifed_path.simplify(SCALED_RESOLUTION); //should already be simplified
|
||||
if (scaled_min_length > 0 && simplifed_path.length() < scaled_min_length) {
|
||||
@ -3395,7 +3400,7 @@ std::string GCode::extrude_path(const ExtrusionPath &path, const std::string &de
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string gcode = this->_extrude(simplifed_path, description, speed);
|
||||
std::string gcode = this->_extrude(simplifed_path, description, speed_mm_per_sec);
|
||||
|
||||
if (m_wipe.enable) {
|
||||
m_wipe.path = std::move(simplifed_path.polyline);
|
||||
@ -3737,6 +3742,102 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string &descri
|
||||
return gcode;
|
||||
}
|
||||
|
||||
double_t GCode::_compute_speed_mm_per_sec(const ExtrusionPath& path, double speed) {
|
||||
|
||||
// set speed
|
||||
if (speed < 0) {
|
||||
//if speed == -1, then it's means "choose yourself, but if it's -1 < speed <0 , then it's a scaling from small_periemter.
|
||||
//it's a bit hacky, so if you want to rework it, help yourself.
|
||||
float factor = (-speed);
|
||||
if (path.role() == erPerimeter) {
|
||||
speed = m_config.get_abs_value("perimeter_speed");
|
||||
} else if (path.role() == erExternalPerimeter) {
|
||||
speed = m_config.get_abs_value("external_perimeter_speed");
|
||||
} else if (path.role() == erBridgeInfill) {
|
||||
speed = m_config.get_abs_value("bridge_speed");
|
||||
} else if (path.role() == erInternalBridgeInfill) {
|
||||
speed = m_config.get_abs_value("bridge_speed_internal");
|
||||
} else if (path.role() == erOverhangPerimeter) {
|
||||
speed = m_config.get_abs_value("overhangs_speed");
|
||||
} else if (path.role() == erInternalInfill) {
|
||||
speed = m_config.get_abs_value("infill_speed");
|
||||
} else if (path.role() == erSolidInfill) {
|
||||
speed = m_config.get_abs_value("solid_infill_speed");
|
||||
} else if (path.role() == erTopSolidInfill) {
|
||||
speed = m_config.get_abs_value("top_solid_infill_speed");
|
||||
} else if (path.role() == erThinWall) {
|
||||
speed = m_config.get_abs_value("thin_walls_speed");
|
||||
} else if (path.role() == erGapFill) {
|
||||
speed = m_config.get_abs_value("gap_fill_speed");
|
||||
} else if (path.role() == erIroning) {
|
||||
speed = m_config.get_abs_value("ironing_speed");
|
||||
} else if (path.role() == erNone) {
|
||||
speed = m_config.get_abs_value("travel_speed");
|
||||
} else if (path.role() == erMilling) {
|
||||
speed = m_config.get_abs_value("milling_speed");
|
||||
} else {
|
||||
throw Slic3r::InvalidArgument("Invalid speed");
|
||||
}
|
||||
//don't modify bridge speed
|
||||
if (factor < 1 && !(is_bridge(path.role()))) {
|
||||
float small_speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
|
||||
//apply factor between feature speed and small speed
|
||||
speed = (speed * factor) + double((1.f - factor) * small_speed);
|
||||
}
|
||||
}
|
||||
if (m_volumetric_speed != 0. && speed == 0) {
|
||||
//if m_volumetric_speed, use the max size for thinwall & gapfill, to avoid variations
|
||||
double vol_speed = m_volumetric_speed / path.mm3_per_mm;
|
||||
if (vol_speed > m_config.max_print_speed.value)
|
||||
vol_speed = m_config.max_print_speed.value;
|
||||
// if using a % of an auto speed, use the % over the volumetric speed.
|
||||
if (path.role() == erExternalPerimeter) {
|
||||
speed = m_config.external_perimeter_speed.get_abs_value(vol_speed);
|
||||
} else if (path.role() == erInternalBridgeInfill) {
|
||||
speed = m_config.bridge_speed_internal.get_abs_value(vol_speed);
|
||||
} else if (path.role() == erOverhangPerimeter) {
|
||||
speed = m_config.overhangs_speed.get_abs_value(vol_speed);
|
||||
} else if (path.role() == erSolidInfill) {
|
||||
speed = m_config.solid_infill_speed.get_abs_value(vol_speed);
|
||||
} else if (path.role() == erTopSolidInfill) {
|
||||
speed = m_config.top_solid_infill_speed.get_abs_value(vol_speed);
|
||||
}
|
||||
if (speed == 0) {
|
||||
speed = vol_speed;
|
||||
}
|
||||
}
|
||||
if (speed == 0) // this code shouldn't trigger as if it's 0, you have to get a m_volumetric_speed
|
||||
speed = m_config.max_print_speed.value;
|
||||
if (this->on_first_layer()) {
|
||||
const double base_speed = speed;
|
||||
if (path.role() == erInternalInfill || path.role() == erSolidInfill) {
|
||||
double first_layer_infill_speed = m_config.first_layer_infill_speed.get_abs_value(base_speed);
|
||||
if (first_layer_infill_speed > 0)
|
||||
speed = std::min(first_layer_infill_speed, speed);
|
||||
} else {
|
||||
double first_layer_speed = m_config.first_layer_speed.get_abs_value(base_speed);
|
||||
if (first_layer_speed > 0)
|
||||
speed = std::min(first_layer_speed, speed);
|
||||
}
|
||||
double first_layer_min_speed = m_config.first_layer_min_speed.get_abs_value(base_speed);
|
||||
speed = std::max(first_layer_min_speed, speed);
|
||||
}
|
||||
// cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
|
||||
if (m_config.max_volumetric_speed.value > 0 && path.mm3_per_mm > 0) {
|
||||
speed = std::min(m_config.max_volumetric_speed.value / path.mm3_per_mm, speed);
|
||||
}
|
||||
double filament_max_volumetric_speed = EXTRUDER_CONFIG_WITH_DEFAULT(filament_max_volumetric_speed, 0);
|
||||
if (filament_max_volumetric_speed > 0) {
|
||||
speed = std::min(filament_max_volumetric_speed / path.mm3_per_mm, speed);
|
||||
}
|
||||
double filament_max_speed = EXTRUDER_CONFIG_WITH_DEFAULT(filament_max_speed, 0);
|
||||
if (filament_max_speed > 0) {
|
||||
speed = std::min(filament_max_speed, speed);
|
||||
}
|
||||
|
||||
return speed;
|
||||
}
|
||||
|
||||
std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string &description_in, double speed) {
|
||||
std::string gcode;
|
||||
std::string description{ description_in };
|
||||
@ -3813,96 +3914,7 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
|
||||
// compensate retraction
|
||||
gcode += this->unretract();
|
||||
|
||||
// set speed
|
||||
if (speed < 0) {
|
||||
//if speed == -1, then it's means "choose yourself, but if it's -1 < speed <0 , then it's a scaling from small_periemter.
|
||||
//it's a bit hacky, so if you want to rework it, help yourself.
|
||||
float factor = (-speed);
|
||||
if (path.role() == erPerimeter) {
|
||||
speed = m_config.get_abs_value("perimeter_speed");
|
||||
} else if (path.role() == erExternalPerimeter) {
|
||||
speed = m_config.get_abs_value("external_perimeter_speed");
|
||||
} else if (path.role() == erBridgeInfill) {
|
||||
speed = m_config.get_abs_value("bridge_speed");
|
||||
} else if (path.role() == erInternalBridgeInfill) {
|
||||
speed = m_config.get_abs_value("bridge_speed_internal");
|
||||
} else if (path.role() == erOverhangPerimeter) {
|
||||
speed = m_config.get_abs_value("overhangs_speed");
|
||||
} else if (path.role() == erInternalInfill) {
|
||||
speed = m_config.get_abs_value("infill_speed");
|
||||
} else if (path.role() == erSolidInfill) {
|
||||
speed = m_config.get_abs_value("solid_infill_speed");
|
||||
} else if (path.role() == erTopSolidInfill) {
|
||||
speed = m_config.get_abs_value("top_solid_infill_speed");
|
||||
} else if (path.role() == erThinWall) {
|
||||
speed = m_config.get_abs_value("thin_walls_speed");
|
||||
} else if (path.role() == erGapFill) {
|
||||
speed = m_config.get_abs_value("gap_fill_speed");
|
||||
} else if (path.role() == erIroning) {
|
||||
speed = m_config.get_abs_value("ironing_speed");
|
||||
} else if (path.role() == erNone) {
|
||||
speed = m_config.get_abs_value("travel_speed");
|
||||
} else if (path.role() == erMilling) {
|
||||
speed = m_config.get_abs_value("milling_speed");
|
||||
} else {
|
||||
throw Slic3r::InvalidArgument("Invalid speed");
|
||||
}
|
||||
//don't modify bridge speed
|
||||
if (factor < 1 && !(is_bridge(path.role()))) {
|
||||
float small_speed = m_config.small_perimeter_speed.get_abs_value(m_config.perimeter_speed);
|
||||
//apply factor between feature speed and small speed
|
||||
speed = (speed * factor) + double((1.f - factor) * small_speed);
|
||||
}
|
||||
}
|
||||
if (m_volumetric_speed != 0. && speed == 0) {
|
||||
//if m_volumetric_speed, use the max size for thinwall & gapfill, to avoid variations
|
||||
double vol_speed = m_volumetric_speed / path.mm3_per_mm;
|
||||
if (vol_speed > m_config.max_print_speed.value)
|
||||
vol_speed = m_config.max_print_speed.value;
|
||||
// if using a % of an auto speed, use the % over the volumetric speed.
|
||||
if (path.role() == erExternalPerimeter) {
|
||||
speed = m_config.external_perimeter_speed.get_abs_value(vol_speed);
|
||||
} else if (path.role() == erInternalBridgeInfill) {
|
||||
speed = m_config.bridge_speed_internal.get_abs_value(vol_speed);
|
||||
} else if (path.role() == erOverhangPerimeter) {
|
||||
speed = m_config.overhangs_speed.get_abs_value(vol_speed);
|
||||
} else if (path.role() == erSolidInfill) {
|
||||
speed = m_config.solid_infill_speed.get_abs_value(vol_speed);
|
||||
} else if (path.role() == erTopSolidInfill) {
|
||||
speed = m_config.top_solid_infill_speed.get_abs_value(vol_speed);
|
||||
}
|
||||
if(speed == 0){
|
||||
speed = vol_speed;
|
||||
}
|
||||
}
|
||||
if (speed == 0) // this code shouldn't trigger as if it's 0, you have to get a m_volumetric_speed
|
||||
speed = m_config.max_print_speed.value;
|
||||
if (this->on_first_layer()) {
|
||||
const double base_speed = speed;
|
||||
if (path.role() == erInternalInfill || path.role() == erSolidInfill) {
|
||||
double first_layer_infill_speed = m_config.first_layer_infill_speed.get_abs_value(base_speed);
|
||||
if (first_layer_infill_speed > 0)
|
||||
speed = std::min(first_layer_infill_speed, speed);
|
||||
} else {
|
||||
double first_layer_speed = m_config.first_layer_speed.get_abs_value(base_speed);
|
||||
if (first_layer_speed > 0)
|
||||
speed = std::min(first_layer_speed, speed);
|
||||
}
|
||||
double first_layer_min_speed = m_config.first_layer_min_speed.get_abs_value(base_speed);
|
||||
speed = std::max(first_layer_min_speed, speed);
|
||||
}
|
||||
// cap speed with max_volumetric_speed anyway (even if user is not using autospeed)
|
||||
if (m_config.max_volumetric_speed.value > 0 && path.mm3_per_mm > 0) {
|
||||
speed = std::min(m_config.max_volumetric_speed.value / path.mm3_per_mm, speed);
|
||||
}
|
||||
double filament_max_volumetric_speed = EXTRUDER_CONFIG_WITH_DEFAULT(filament_max_volumetric_speed, 0);
|
||||
if (filament_max_volumetric_speed > 0) {
|
||||
speed = std::min(filament_max_volumetric_speed / path.mm3_per_mm, speed);
|
||||
}
|
||||
double filament_max_speed = EXTRUDER_CONFIG_WITH_DEFAULT(filament_max_speed, 0);
|
||||
if (filament_max_speed > 0) {
|
||||
speed = std::min(filament_max_speed, speed);
|
||||
}
|
||||
speed = _compute_speed_mm_per_sec(path, speed);
|
||||
double F = speed * 60; // convert mm/sec to mm/min
|
||||
|
||||
// extrude arc or line
|
||||
|
@ -430,6 +430,7 @@ private:
|
||||
|
||||
std::string _extrude(const ExtrusionPath &path, const std::string &description, double speed = -1);
|
||||
std::string _before_extrude(const ExtrusionPath &path, const std::string &description, double speed = -1);
|
||||
double_t _compute_speed_mm_per_sec(const ExtrusionPath& path, double speed = -1);
|
||||
std::string _after_extrude(const ExtrusionPath &path);
|
||||
void print_machine_envelope(FILE *file, Print &print);
|
||||
void _print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait);
|
||||
|
@ -730,6 +730,7 @@ const std::vector<std::string>& Preset::printer_options()
|
||||
"use_relative_e_distances",
|
||||
"use_firmware_retraction", "use_volumetric_e", "variable_layer_height",
|
||||
"min_length",
|
||||
"max_gcode_per_second",
|
||||
//FIXME the print host keys are left here just for conversion from the Printer preset to Physical Printer preset.
|
||||
"host_type", "print_host", "printhost_apikey", "printhost_cafile", "printhost_port",
|
||||
"single_extruder_multi_material",
|
||||
|
@ -128,6 +128,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
|
||||
"infill_acceleration",
|
||||
"layer_gcode",
|
||||
"max_fan_speed",
|
||||
"max_gcode_per_second",
|
||||
"max_print_height",
|
||||
"max_print_speed",
|
||||
"max_volumetric_speed",
|
||||
|
@ -2586,6 +2586,17 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats{ 1500., 1250. });
|
||||
|
||||
def = this->add("max_gcode_per_second", coFloat);
|
||||
def->label = L("Maximum G1 per second");
|
||||
def->category = OptionCategory::speed;
|
||||
def->tooltip = L("If your firmware stops while printing, it may have its gcode queue full."
|
||||
" Set this parameter to merge extrusions into bigger ones to reduce the number of gcode commands the printer has to process each second."
|
||||
"\nNote that reducing your printing speed (at least for the external extrusions) will reduce the number of time this will triggger and so increase quality."
|
||||
"\nSet zero to disable.");
|
||||
def->min = 0;
|
||||
def->mode = comExpert;
|
||||
def->set_default_value(new ConfigOptionFloat(1500));
|
||||
|
||||
def = this->add("max_fan_speed", coInts);
|
||||
def->label = L("Max");
|
||||
def->full_label = L("Max fan speed");
|
||||
@ -2700,8 +2711,9 @@ void PrintConfigDef::init_fff_params()
|
||||
def = this->add("min_length", coFloat);
|
||||
def->label = L("Minimum extrusion length");
|
||||
def->category = OptionCategory::speed;
|
||||
def->tooltip = L("Too many too small commands may overload the firmware / connection. Put a higher value here if you see strange slowdown."
|
||||
"\nSet zero to disable.");
|
||||
def->tooltip = L("[Deprecated] Prefer using max_gcode_per_second instead, as it's much better when you have very different speeds for features."
|
||||
"\nToo many too small commands may overload the firmware / connection. Put a higher value here if you see strange slowdown."
|
||||
"\nSet zero to disable.");
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->precision = 8;
|
||||
|
@ -1096,6 +1096,7 @@ public:
|
||||
ConfigOptionInts gcode_precision_e;
|
||||
ConfigOptionString layer_gcode;
|
||||
ConfigOptionString feature_gcode;
|
||||
ConfigOptionFloat max_gcode_per_second;
|
||||
ConfigOptionFloat max_print_speed;
|
||||
ConfigOptionFloat max_volumetric_speed;
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
@ -1209,6 +1210,7 @@ protected:
|
||||
OPT_PTR(gcode_precision_e);
|
||||
OPT_PTR(layer_gcode);
|
||||
OPT_PTR(feature_gcode);
|
||||
OPT_PTR(max_gcode_per_second);
|
||||
OPT_PTR(max_print_speed);
|
||||
OPT_PTR(max_volumetric_speed);
|
||||
OPT_PTR(milling_z_lift);
|
||||
|
Loading…
x
Reference in New Issue
Block a user