max_gcode_per_second added

allow a better control than min_length
This commit is contained in:
supermerill 2021-08-23 00:38:28 +02:00
parent 688121b104
commit 55fdc665ca
7 changed files with 131 additions and 99 deletions

View File

@ -19,6 +19,10 @@ group:silent_mode_event:Firmware
setting:gcode_precision_xyz setting:gcode_precision_xyz
setting:gcode_precision_e setting:gcode_precision_e
end_line end_line
line:Processing limit
setting:max_gcode_per_second
setting:min_length
end_line
group:Cooling fan group:Cooling fan
line:Speedup line:Speedup
setting:label$Speedup time:fan_speedup_time setting:label$Speedup time:fan_speedup_time
@ -40,7 +44,6 @@ group:Advanced
setting:use_relative_e_distances setting:use_relative_e_distances
setting:use_firmware_retraction setting:use_firmware_retraction
setting:use_volumetric_e setting:use_volumetric_e
setting:min_length
setting:variable_layer_height setting:variable_layer_height
page:Custom G-code:cog page:Custom G-code:cog

View File

@ -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; ExtrusionPath simplifed_path = path;
const double scaled_min_length = scale_(this->config().min_length.value); 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())); //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 //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()); //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.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()); 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(); 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. // 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. // 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. // 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 //else simplifed_path.simplify(SCALED_RESOLUTION); //should already be simplified
if (scaled_min_length > 0 && simplifed_path.length() < scaled_min_length) { 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 ""; 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) { if (m_wipe.enable) {
m_wipe.path = std::move(simplifed_path.polyline); m_wipe.path = std::move(simplifed_path.polyline);
@ -3737,81 +3742,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string &descri
return gcode; return gcode;
} }
std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string &description_in, double speed) { double_t GCode::_compute_speed_mm_per_sec(const ExtrusionPath& path, double speed) {
std::string gcode;
std::string description{ description_in };
// adjust acceleration, inside the travel to set the deceleration
double acceleration = get_default_acceleration(m_config);
double travel_acceleration = m_writer.get_acceleration();
{
if (this->on_first_layer() && m_config.first_layer_acceleration.value > 0) {
acceleration = m_config.first_layer_acceleration.get_abs_value(acceleration);
} else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) {
acceleration = m_config.perimeter_acceleration.get_abs_value(acceleration);
} else if (m_config.bridge_acceleration.value > 0 && is_bridge(path.role())
&& path.role() != erOverhangPerimeter) {
acceleration = m_config.bridge_acceleration.get_abs_value(acceleration);
} else if (m_config.infill_acceleration.value > 0 && is_infill(path.role())) {
acceleration = m_config.infill_acceleration.get_abs_value(acceleration);
}
if (m_config.travel_acceleration.value > 0)
travel_acceleration = m_config.travel_acceleration.get_abs_value(acceleration);
}
if (travel_acceleration == acceleration) {
m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5));
// go to first point of extrusion path (stop at midpoint to let us set the decel speed)
if (!m_last_pos_defined || m_last_pos != path.first_point()) {
Polyline polyline = this->travel_to(gcode, path.first_point(), path.role());
this->write_travel_to(gcode, polyline, "move to first " + description + " point (" + std::to_string(acceleration) +" == "+ std::to_string(travel_acceleration)+")");
}
} else {
// go to midpoint to let us set the decel speed)
if (!m_last_pos_defined || m_last_pos != path.first_point()) {
Polyline poly_start = this->travel_to(gcode, path.first_point(), path.role());
coordf_t length = poly_start.length();
if (length > SCALED_EPSILON) {
Polyline poly_end;
coordf_t min_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0.5)) * 20;
if (poly_start.size() > 2 && length > min_length * 3) {
//if complex travel, try to deccelerate only at the end, unless it's less than ~ 20 nozzle
if (poly_start.lines().back().length() < min_length) {
poly_end = poly_start;
poly_start.clip_end(min_length);
poly_end.clip_start(length - min_length);
} else {
poly_end.points.push_back(poly_start.points.back());
poly_start.points.pop_back();
poly_end.points.push_back(poly_start.points.back());
poly_end.reverse();
}
} else {
poly_end = poly_start;
poly_start.clip_end(length / 2);
poly_end.clip_start(length / 2);
}
m_writer.set_acceleration((uint32_t)floor(travel_acceleration + 0.5));
this->write_travel_to(gcode, poly_start, "move to first " + description + " point (acceleration)");
//travel acceleration should be already set at startup via special gcode, and so it's automatically used by G0.
m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5));
this->write_travel_to(gcode, poly_end, "move to first " + description + " point (deceleration)");
} else {
m_writer.set_acceleration((uint32_t)floor(travel_acceleration + 0.5));
this->write_travel_to(gcode, poly_start, "move to first " + description + " point (acceleration)");
}
} else {
m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5));
}
}
//if needed, write the gcode_label_objects_end then gcode_label_objects_start
//should be already done by travel_to, but just in case
_add_object_change_labels(gcode);
// compensate retraction
gcode += this->unretract();
// set speed // set speed
if (speed < 0) { if (speed < 0) {
@ -3903,6 +3834,87 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
if (filament_max_speed > 0) { if (filament_max_speed > 0) {
speed = std::min(filament_max_speed, speed); 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 };
// adjust acceleration, inside the travel to set the deceleration
double acceleration = get_default_acceleration(m_config);
double travel_acceleration = m_writer.get_acceleration();
{
if (this->on_first_layer() && m_config.first_layer_acceleration.value > 0) {
acceleration = m_config.first_layer_acceleration.get_abs_value(acceleration);
} else if (m_config.perimeter_acceleration.value > 0 && is_perimeter(path.role())) {
acceleration = m_config.perimeter_acceleration.get_abs_value(acceleration);
} else if (m_config.bridge_acceleration.value > 0 && is_bridge(path.role())
&& path.role() != erOverhangPerimeter) {
acceleration = m_config.bridge_acceleration.get_abs_value(acceleration);
} else if (m_config.infill_acceleration.value > 0 && is_infill(path.role())) {
acceleration = m_config.infill_acceleration.get_abs_value(acceleration);
}
if (m_config.travel_acceleration.value > 0)
travel_acceleration = m_config.travel_acceleration.get_abs_value(acceleration);
}
if (travel_acceleration == acceleration) {
m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5));
// go to first point of extrusion path (stop at midpoint to let us set the decel speed)
if (!m_last_pos_defined || m_last_pos != path.first_point()) {
Polyline polyline = this->travel_to(gcode, path.first_point(), path.role());
this->write_travel_to(gcode, polyline, "move to first " + description + " point (" + std::to_string(acceleration) +" == "+ std::to_string(travel_acceleration)+")");
}
} else {
// go to midpoint to let us set the decel speed)
if (!m_last_pos_defined || m_last_pos != path.first_point()) {
Polyline poly_start = this->travel_to(gcode, path.first_point(), path.role());
coordf_t length = poly_start.length();
if (length > SCALED_EPSILON) {
Polyline poly_end;
coordf_t min_length = scale_(EXTRUDER_CONFIG_WITH_DEFAULT(nozzle_diameter, 0.5)) * 20;
if (poly_start.size() > 2 && length > min_length * 3) {
//if complex travel, try to deccelerate only at the end, unless it's less than ~ 20 nozzle
if (poly_start.lines().back().length() < min_length) {
poly_end = poly_start;
poly_start.clip_end(min_length);
poly_end.clip_start(length - min_length);
} else {
poly_end.points.push_back(poly_start.points.back());
poly_start.points.pop_back();
poly_end.points.push_back(poly_start.points.back());
poly_end.reverse();
}
} else {
poly_end = poly_start;
poly_start.clip_end(length / 2);
poly_end.clip_start(length / 2);
}
m_writer.set_acceleration((uint32_t)floor(travel_acceleration + 0.5));
this->write_travel_to(gcode, poly_start, "move to first " + description + " point (acceleration)");
//travel acceleration should be already set at startup via special gcode, and so it's automatically used by G0.
m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5));
this->write_travel_to(gcode, poly_end, "move to first " + description + " point (deceleration)");
} else {
m_writer.set_acceleration((uint32_t)floor(travel_acceleration + 0.5));
this->write_travel_to(gcode, poly_start, "move to first " + description + " point (acceleration)");
}
} else {
m_writer.set_acceleration((uint32_t)floor(acceleration + 0.5));
}
}
//if needed, write the gcode_label_objects_end then gcode_label_objects_start
//should be already done by travel_to, but just in case
_add_object_change_labels(gcode);
// compensate retraction
gcode += this->unretract();
speed = _compute_speed_mm_per_sec(path, speed);
double F = speed * 60; // convert mm/sec to mm/min double F = speed * 60; // convert mm/sec to mm/min
// extrude arc or line // extrude arc or line

View File

@ -430,6 +430,7 @@ private:
std::string _extrude(const ExtrusionPath &path, const std::string &description, double speed = -1); 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); 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); std::string _after_extrude(const ExtrusionPath &path);
void print_machine_envelope(FILE *file, Print &print); 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); void _print_first_layer_bed_temperature(FILE *file, Print &print, const std::string &gcode, uint16_t first_printing_extruder_id, bool wait);

View File

@ -730,6 +730,7 @@ const std::vector<std::string>& Preset::printer_options()
"use_relative_e_distances", "use_relative_e_distances",
"use_firmware_retraction", "use_volumetric_e", "variable_layer_height", "use_firmware_retraction", "use_volumetric_e", "variable_layer_height",
"min_length", "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. //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", "host_type", "print_host", "printhost_apikey", "printhost_cafile", "printhost_port",
"single_extruder_multi_material", "single_extruder_multi_material",

View File

@ -128,6 +128,7 @@ bool Print::invalidate_state_by_config_options(const std::vector<t_config_option
"infill_acceleration", "infill_acceleration",
"layer_gcode", "layer_gcode",
"max_fan_speed", "max_fan_speed",
"max_gcode_per_second",
"max_print_height", "max_print_height",
"max_print_speed", "max_print_speed",
"max_volumetric_speed", "max_volumetric_speed",

View File

@ -2586,6 +2586,17 @@ void PrintConfigDef::init_fff_params()
def->mode = comAdvanced; def->mode = comAdvanced;
def->set_default_value(new ConfigOptionFloats{ 1500., 1250. }); 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 = this->add("max_fan_speed", coInts);
def->label = L("Max"); def->label = L("Max");
def->full_label = L("Max fan speed"); def->full_label = L("Max fan speed");
@ -2700,7 +2711,8 @@ void PrintConfigDef::init_fff_params()
def = this->add("min_length", coFloat); def = this->add("min_length", coFloat);
def->label = L("Minimum extrusion length"); def->label = L("Minimum extrusion length");
def->category = OptionCategory::speed; 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." 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."); "\nSet zero to disable.");
def->sidetext = L("mm"); def->sidetext = L("mm");
def->min = 0; def->min = 0;

View File

@ -1096,6 +1096,7 @@ public:
ConfigOptionInts gcode_precision_e; ConfigOptionInts gcode_precision_e;
ConfigOptionString layer_gcode; ConfigOptionString layer_gcode;
ConfigOptionString feature_gcode; ConfigOptionString feature_gcode;
ConfigOptionFloat max_gcode_per_second;
ConfigOptionFloat max_print_speed; ConfigOptionFloat max_print_speed;
ConfigOptionFloat max_volumetric_speed; ConfigOptionFloat max_volumetric_speed;
#ifdef HAS_PRESSURE_EQUALIZER #ifdef HAS_PRESSURE_EQUALIZER
@ -1209,6 +1210,7 @@ protected:
OPT_PTR(gcode_precision_e); OPT_PTR(gcode_precision_e);
OPT_PTR(layer_gcode); OPT_PTR(layer_gcode);
OPT_PTR(feature_gcode); OPT_PTR(feature_gcode);
OPT_PTR(max_gcode_per_second);
OPT_PTR(max_print_speed); OPT_PTR(max_print_speed);
OPT_PTR(max_volumetric_speed); OPT_PTR(max_volumetric_speed);
OPT_PTR(milling_z_lift); OPT_PTR(milling_z_lift);