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_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

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;
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,81 +3742,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string &descri
return gcode;
}
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();
double_t GCode::_compute_speed_mm_per_sec(const ExtrusionPath& path, double speed) {
// set speed
if (speed < 0) {
@ -3903,6 +3834,87 @@ std::string GCode::_before_extrude(const ExtrusionPath &path, const std::string
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 };
// 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
// 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 _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);

View File

@ -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",

View File

@ -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",

View File

@ -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,7 +2711,8 @@ 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."
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;

View File

@ -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);