mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-17 21:35: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_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
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user