Merge branch 'lm_acceleration'

This commit is contained in:
Lukas Matena 2023-03-24 09:30:08 +01:00
commit 5d4f11ac24
13 changed files with 229 additions and 85 deletions

View file

@ -1147,10 +1147,6 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
// Emit machine envelope limits for the Marlin firmware.
this->print_machine_envelope(file, print);
// Disable fan.
if (! print.config().cooling.get_at(initial_extruder_id) || print.config().disable_fan_first_layers.get_at(initial_extruder_id))
file.write(m_writer.set_fan(0));
// Let the start-up script prime the 1st printing tool.
m_placeholder_parser.set("initial_tool", initial_extruder_id);
m_placeholder_parser.set("initial_extruder", initial_extruder_id);
@ -1667,23 +1663,25 @@ void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print)
int(print.config().machine_max_feedrate_e.values.front() * factor + 0.5),
factor == 60 ? "mm / min" : "mm / sec");
// Now M204 - acceleration. This one is quite hairy thanks to how Marlin guys care about
// backwards compatibility: https://github.com/prusa3d/PrusaSlicer/issues/1089
// Legacy Marlin should export travel acceleration the same as printing acceleration.
// MarlinFirmware has the two separated.
int travel_acc = flavor == gcfMarlinLegacy
? int(print.config().machine_max_acceleration_extruding.values.front() + 0.5)
: int(print.config().machine_max_acceleration_travel.values.front() + 0.5);
// Retract acceleration not accepted in M204 in RRF
// Now M204 - acceleration. This one is quite hairy...
if (flavor == gcfRepRapFirmware)
// Uses M204 P[print] T[travel]
file.write_format("M204 P%d T%d ; sets acceleration (P, T), mm/sec^2\n",
int(print.config().machine_max_acceleration_extruding.values.front() + 0.5),
travel_acc);
else
file.write_format("M204 P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n",
int(print.config().machine_max_acceleration_travel.values.front() + 0.5));
else if (flavor == gcfMarlinLegacy)
// Legacy Marlin uses M204 S[print] T[retract]
file.write_format("M204 " + "S%d T%d ; sets acceleration (S) and retract acceleration (R), mm/sec^2\n",
int(print.config().machine_max_acceleration_extruding.values.front() + 0.5),
int(print.config().machine_max_acceleration_retracting.values.front() + 0.5));
else if (flavor == gcfMarlinFirmware)
// New Marlin uses M204 P[print] R[retract] T[travel]
file.write_format("M204 " + "P%d R%d T%d ; sets acceleration (P, T) and retract acceleration (R), mm/sec^2\n",
int(print.config().machine_max_acceleration_extruding.values.front() + 0.5),
int(print.config().machine_max_acceleration_retracting.values.front() + 0.5),
travel_acc);
int(print.config().machine_max_acceleration_travel.values.front() + 0.5));
else
assert(false);
assert(is_decimal_separator_point());
file.write_format(flavor == gcfRepRapFirmware
@ -1710,17 +1708,18 @@ void GCode::print_machine_envelope(GCodeOutputStream &file, Print &print)
// M190 - Set Extruder Temperature and Wait
void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait)
{
bool autoemit = print.config().autoemit_temperature_commands;
// Initial bed temperature based on the first extruder.
int temp = print.config().first_layer_bed_temperature.get_at(first_printing_extruder_id);
// Is the bed temperature set by the provided custom G-code?
int temp_by_gcode = -1;
bool temp_set_by_gcode = custom_gcode_sets_temperature(gcode, 140, 190, false, temp_by_gcode);
if (temp_set_by_gcode && temp_by_gcode >= 0 && temp_by_gcode < 1000)
if (autoemit && temp_set_by_gcode && temp_by_gcode >= 0 && temp_by_gcode < 1000)
temp = temp_by_gcode;
// Always call m_writer.set_bed_temperature() so it will set the internal "current" state of the bed temp as if
// the custom start G-code emited these.
std::string set_temp_gcode = m_writer.set_bed_temperature(temp, wait);
if (! temp_set_by_gcode)
if (autoemit && ! temp_set_by_gcode)
file.write(set_temp_gcode);
}
@ -1731,13 +1730,14 @@ void GCode::_print_first_layer_bed_temperature(GCodeOutputStream &file, Print &p
// RepRapFirmware: G10 Sxx
void GCode::_print_first_layer_extruder_temperatures(GCodeOutputStream &file, Print &print, const std::string &gcode, unsigned int first_printing_extruder_id, bool wait)
{
bool autoemit = print.config().autoemit_temperature_commands;
// Is the bed temperature set by the provided custom G-code?
int temp_by_gcode = -1;
bool include_g10 = print.config().gcode_flavor == gcfRepRapFirmware;
if (custom_gcode_sets_temperature(gcode, 104, 109, include_g10, temp_by_gcode)) {
if (! autoemit || custom_gcode_sets_temperature(gcode, 104, 109, include_g10, temp_by_gcode)) {
// Set the extruder temperature at m_writer, but throw away the generated G-code as it will be written with the custom G-code.
int temp = print.config().first_layer_temperature.get_at(first_printing_extruder_id);
if (temp_by_gcode >= 0 && temp_by_gcode < 1000)
if (autoemit && temp_by_gcode >= 0 && temp_by_gcode < 1000)
temp = temp_by_gcode;
m_writer.set_temperature(temp, wait, first_printing_extruder_id);
} else {
@ -2547,7 +2547,7 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, const std::string_view descr
}
// reset acceleration
gcode += m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5));
gcode += m_writer.set_print_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5));
if (m_wipe.enable) {
m_wipe.path = paths.front().polyline;
@ -2633,7 +2633,7 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, const std::s
}
}
// reset acceleration
gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
return gcode;
}
@ -2659,7 +2659,7 @@ std::string GCode::extrude_path(ExtrusionPath path, std::string_view description
m_wipe.path.reverse();
}
// reset acceleration
gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
gcode += m_writer.set_print_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
return gcode;
}
@ -2802,7 +2802,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, const std::string_view de
} else {
acceleration = m_config.default_acceleration.value;
}
gcode += m_writer.set_acceleration((unsigned int)floor(acceleration + 0.5));
gcode += m_writer.set_print_acceleration((unsigned int)floor(acceleration + 0.5));
}
// calculate extrusion length per distance unit
@ -3071,8 +3071,18 @@ std::string GCode::travel_to(const Point &point, ExtrusionRole role, std::string
// use G1 because we rely on paths being straight (G0 may make round paths)
if (travel.size() >= 2) {
gcode += m_writer.set_travel_acceleration((unsigned int)(m_config.travel_acceleration.value + 0.5));
for (size_t i = 1; i < travel.size(); ++ i)
gcode += m_writer.travel_to_xy(this->point_to_gcode(travel.points[i]), comment);
if (! GCodeWriter::supports_separate_travel_acceleration(config().gcode_flavor)) {
// In case that this flavor does not support separate print and travel acceleration,
// reset acceleration to default.
gcode += m_writer.set_travel_acceleration((unsigned int)(m_config.travel_acceleration.value + 0.5));
}
this->set_last_pos(travel.points.back());
}
return gcode;

View file

@ -3,6 +3,7 @@
#include "libslic3r/Print.hpp"
#include "libslic3r/LocalesUtils.hpp"
#include "libslic3r/format.hpp"
#include "libslic3r/GCodeWriter.hpp"
#include "GCodeProcessor.hpp"
#include <boost/algorithm/string/case_conv.hpp>
@ -568,10 +569,11 @@ void GCodeProcessor::apply_config(const PrintConfig& config)
m_result.filament_cost[i] = static_cast<float>(config.filament_cost.get_at(i));
}
if ((m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfRepRapFirmware) && config.machine_limits_usage.value != MachineLimitsUsage::Ignore) {
if ((m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfRepRapFirmware || m_flavor == gcfKlipper)
&& config.machine_limits_usage.value != MachineLimitsUsage::Ignore) {
m_time_processor.machine_limits = reinterpret_cast<const MachineEnvelopeConfig&>(config);
if (m_flavor == gcfMarlinLegacy) {
// Legacy Marlin does not have separate travel acceleration, it uses the 'extruding' value instead.
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfKlipper) {
// Legacy Marlin and Klipper don't have separate travel acceleration, they use the 'extruding' value instead.
m_time_processor.machine_limits.machine_max_acceleration_travel = m_time_processor.machine_limits.machine_max_acceleration_extruding;
}
if (m_flavor == gcfRepRapFirmware) {
@ -609,7 +611,12 @@ for (size_t i = 0; i < static_cast<size_t>(PrintEstimatedStatistics::ETimeMode::
float max_retract_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_retracting, i);
m_time_processor.machines[i].max_retract_acceleration = max_retract_acceleration;
m_time_processor.machines[i].retract_acceleration = (max_retract_acceleration > 0.0f) ? max_retract_acceleration : DEFAULT_RETRACT_ACCELERATION;
float max_travel_acceleration = get_option_value(m_time_processor.machine_limits.machine_max_acceleration_travel, i);
if ( ! GCodeWriter::supports_separate_travel_acceleration(config.gcode_flavor.value) || config.machine_limits_usage.value != MachineLimitsUsage::EmitToGCode) {
// Only clamp travel acceleration when it is accessible in machine limits.
max_travel_acceleration = 0;
}
m_time_processor.machines[i].max_travel_acceleration = max_travel_acceleration;
m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
}
@ -788,7 +795,7 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
if (machine_limits_usage != nullptr)
use_machine_limits = machine_limits_usage->value != MachineLimitsUsage::Ignore;
if (use_machine_limits && (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfRepRapFirmware)) {
if (use_machine_limits && (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware || m_flavor == gcfRepRapFirmware || m_flavor == gcfKlipper)) {
const ConfigOptionFloats* machine_max_acceleration_x = config.option<ConfigOptionFloats>("machine_max_acceleration_x");
if (machine_max_acceleration_x != nullptr)
m_time_processor.machine_limits.machine_max_acceleration_x.values = machine_max_acceleration_x->values;
@ -846,8 +853,8 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
m_time_processor.machine_limits.machine_max_acceleration_retracting.values = machine_max_acceleration_retracting->values;
// Legacy Marlin does not have separate travel acceleration, it uses the 'extruding' value instead.
const ConfigOptionFloats* machine_max_acceleration_travel = config.option<ConfigOptionFloats>(m_flavor == gcfMarlinLegacy
// Legacy Marlin and Klipper don't have separate travel acceleration, they use the 'extruding' value instead.
const ConfigOptionFloats* machine_max_acceleration_travel = config.option<ConfigOptionFloats>((m_flavor == gcfMarlinLegacy || m_flavor == gcfKlipper)
? "machine_max_acceleration_extruding"
: "machine_max_acceleration_travel");
if (machine_max_acceleration_travel != nullptr)
@ -885,7 +892,7 @@ void GCodeProcessor::apply_config(const DynamicPrintConfig& config)
m_time_processor.machines[i].travel_acceleration = (max_travel_acceleration > 0.0f) ? max_travel_acceleration : DEFAULT_TRAVEL_ACCELERATION;
}
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) {
if (m_flavor == gcfMarlinLegacy || m_flavor == gcfMarlinFirmware) { // No Klipper here, it does not support silent mode.
const ConfigOptionBool* silent_mode = config.option<ConfigOptionBool>("silent_mode");
if (silent_mode != nullptr) {
if (silent_mode->value && m_time_processor.machine_limits.machine_max_acceleration_x.values.size() > 1)
@ -3244,7 +3251,7 @@ void GCodeProcessor::process_M205(const GCodeReader::GCodeLine& line)
void GCodeProcessor::process_M220(const GCodeReader::GCodeLine& line)
{
if (m_flavor != gcfMarlinLegacy && m_flavor != gcfMarlinFirmware)
if (m_flavor != gcfMarlinLegacy && m_flavor != gcfMarlinFirmware && m_flavor != gcfKlipper)
return;
if (line.has('B'))

View file

@ -93,9 +93,12 @@ public:
}
WipeTowerWriter& disable_linear_advance() {
m_gcode += (m_gcode_flavor == gcfRepRapSprinter || m_gcode_flavor == gcfRepRapFirmware
? (std::string("M572 D") + std::to_string(m_current_tool) + " S0\n")
: std::string("M900 K0\n"));
if (m_gcode_flavor == gcfRepRapSprinter || m_gcode_flavor == gcfRepRapFirmware)
m_gcode += (std::string("M572 D") + std::to_string(m_current_tool) + " S0\n");
else if (m_gcode_flavor == gcfKlipper)
m_gcode += "SET_PRESSURE_ADVANCE ADVANCE=0\n";
else
m_gcode += "M900 K0\n";
return *this;
}
@ -363,6 +366,8 @@ public:
// Set digital trimpot motor
WipeTowerWriter& set_extruder_trimpot(int current)
{
if (m_gcode_flavor == gcfKlipper)
return *this;
if (m_gcode_flavor == gcfRepRapSprinter || m_gcode_flavor == gcfRepRapFirmware)
m_gcode += "M906 E";
else

View file

@ -15,6 +15,12 @@
namespace Slic3r {
// static
bool GCodeWriter::supports_separate_travel_acceleration(GCodeFlavor flavor)
{
return (flavor == gcfRepetier || flavor == gcfMarlinFirmware || flavor == gcfRepRapFirmware);
}
void GCodeWriter::apply_print_config(const PrintConfig &print_config)
{
this->config.apply(print_config, true);
@ -25,6 +31,8 @@ void GCodeWriter::apply_print_config(const PrintConfig &print_config)
|| print_config.gcode_flavor.value == gcfRepRapFirmware;
m_max_acceleration = static_cast<unsigned int>(std::round((use_mach_limits && print_config.machine_limits_usage.value == MachineLimitsUsage::EmitToGCode) ?
print_config.machine_max_acceleration_extruding.values.front() : 0));
m_max_travel_acceleration = static_cast<unsigned int>(std::round((use_mach_limits && print_config.machine_limits_usage.value == MachineLimitsUsage::EmitToGCode && supports_separate_travel_acceleration(print_config.gcode_flavor.value)) ?
print_config.machine_max_acceleration_travel.values.front() : 0));
}
void GCodeWriter::set_extruders(std::vector<unsigned int> extruder_ids)
@ -53,6 +61,7 @@ std::string GCodeWriter::preamble()
FLAVOR_IS(gcfRepRapFirmware) ||
FLAVOR_IS(gcfMarlinLegacy) ||
FLAVOR_IS(gcfMarlinFirmware) ||
FLAVOR_IS(gcfKlipper) ||
FLAVOR_IS(gcfTeacup) ||
FLAVOR_IS(gcfRepetier) ||
FLAVOR_IS(gcfSmoothie))
@ -154,36 +163,31 @@ std::string GCodeWriter::set_bed_temperature(unsigned int temperature, bool wait
return gcode.str();
}
std::string GCodeWriter::set_acceleration(unsigned int acceleration)
std::string GCodeWriter::set_acceleration_internal(Acceleration type, unsigned int acceleration)
{
// Clamp the acceleration to the allowed maximum.
if (m_max_acceleration > 0 && acceleration > m_max_acceleration)
if (type == Acceleration::Print && m_max_acceleration > 0 && acceleration > m_max_acceleration)
acceleration = m_max_acceleration;
if (type == Acceleration::Travel && m_max_travel_acceleration > 0 && acceleration > m_max_travel_acceleration)
acceleration = m_max_travel_acceleration;
if (acceleration == 0 || acceleration == m_last_acceleration)
// Are we setting travel acceleration for a flavour that supports separate travel and print acc?
bool separate_travel = (type == Acceleration::Travel && supports_separate_travel_acceleration(this->config.gcode_flavor));
auto& last_value = separate_travel ? m_last_travel_acceleration : m_last_acceleration ;
if (acceleration == 0 || acceleration == last_value)
return std::string();
m_last_acceleration = acceleration;
last_value = acceleration;
std::ostringstream gcode;
if (FLAVOR_IS(gcfRepetier)) {
// M201: Set max printing acceleration
gcode << "M201 X" << acceleration << " Y" << acceleration;
if (this->config.gcode_comments) gcode << " ; adjust acceleration";
gcode << "\n";
// M202: Set max travel acceleration
gcode << "M202 X" << acceleration << " Y" << acceleration;
} else if (FLAVOR_IS(gcfRepRapFirmware)) {
// M204: Set default acceleration
gcode << "M204 P" << acceleration;
} else if (FLAVOR_IS(gcfMarlinFirmware)) {
// This is new MarlinFirmware with separated print/retraction/travel acceleration.
// Use M204 P, we don't want to override travel acc by M204 S (which is deprecated anyway).
gcode << "M204 P" << acceleration;
} else {
// M204: Set default acceleration
if (FLAVOR_IS(gcfRepetier))
gcode << (separate_travel ? "M202 X" : "M201 X") << acceleration << " Y" << acceleration;
else if (FLAVOR_IS(gcfRepRapFirmware) || FLAVOR_IS(gcfMarlinFirmware))
gcode << (separate_travel ? "M204 T" : "M204 P") << acceleration;
else
gcode << "M204 S" << acceleration;
}
if (this->config.gcode_comments) gcode << " ; adjust acceleration";
gcode << "\n";

View file

@ -43,7 +43,8 @@ public:
std::string postamble() const;
std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1) const;
std::string set_bed_temperature(unsigned int temperature, bool wait = false);
std::string set_acceleration(unsigned int acceleration);
std::string set_print_acceleration(unsigned int acceleration) { return set_acceleration_internal(Acceleration::Print, acceleration); }
std::string set_travel_acceleration(unsigned int acceleration) { return set_acceleration_internal(Acceleration::Travel, acceleration); }
std::string reset_e(bool force = false);
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
// return false if this extruder was already selected
@ -69,6 +70,9 @@ public:
std::string unlift();
Vec3d get_position() const { return m_pos; }
// Returns whether this flavor supports separate print and travel acceleration.
static bool supports_separate_travel_acceleration(GCodeFlavor flavor);
// To be called by the CoolingBuffer from another thread.
static std::string set_fan(const GCodeFlavor gcode_flavor, bool gcode_comments, unsigned int speed);
// To be called by the main thread. It always emits the G-code, it does not remember the previous state.
@ -81,17 +85,26 @@ private:
std::string m_extrusion_axis;
bool m_single_extruder_multi_material;
Extruder* m_extruder;
unsigned int m_last_acceleration;
unsigned int m_last_acceleration = (unsigned int)(-1);
unsigned int m_last_travel_acceleration = (unsigned int)(-1); // only used for flavors supporting separate print/travel acc
// 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_max_travel_acceleration;
unsigned int m_last_bed_temperature;
bool m_last_bed_temperature_reached;
double m_lifted;
Vec3d m_pos = Vec3d::Zero();
enum class Acceleration {
Travel,
Print
};
std::string _travel_to_z(double z, const std::string &comment);
std::string _retract(double length, double restart_extra, const std::string &comment);
std::string set_acceleration_internal(Acceleration type, unsigned int acceleration);
};
class GCodeFormatter {

View file

@ -434,7 +434,7 @@ static std::vector<std::string> s_Preset_print_options {
"enable_dynamic_overhang_speeds", "overhang_speed_0", "overhang_speed_1", "overhang_speed_2", "overhang_speed_3",
"top_solid_infill_speed", "support_material_speed", "support_material_xy_spacing", "support_material_interface_speed",
"bridge_speed", "gap_fill_speed", "gap_fill_enabled", "travel_speed", "travel_speed_z", "first_layer_speed", "first_layer_speed_over_raft", "perimeter_acceleration", "infill_acceleration",
"external_perimeter_acceleration", "top_solid_infill_acceleration", "solid_infill_acceleration",
"external_perimeter_acceleration", "top_solid_infill_acceleration", "solid_infill_acceleration", "travel_acceleration",
"bridge_acceleration", "first_layer_acceleration", "first_layer_acceleration_over_raft", "default_acceleration", "skirts", "skirt_distance", "skirt_height", "draft_shield",
"min_skirt_length", "brim_width", "brim_separation", "brim_type", "support_material", "support_material_auto", "support_material_threshold", "support_material_enforce_layers",
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
@ -482,7 +482,7 @@ static std::vector<std::string> s_Preset_machine_limits_options {
};
static std::vector<std::string> s_Preset_printer_options {
"printer_technology",
"printer_technology", "autoemit_temperature_commands",
"bed_shape", "bed_custom_texture", "bed_custom_model", "z_offset", "gcode_flavor", "use_relative_e_distances",
"use_firmware_retraction", "use_volumetric_e", "variable_layer_height",
//FIXME the print host keys are left here just for conversion from the Printer preset to Physical Printer preset.

View file

@ -58,6 +58,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
// Cache the plenty of parameters, which influence the G-code generator only,
// or they are only notes not influencing the generated G-code.
static std::unordered_set<std::string> steps_gcode = {
"autoemit_temperature_commands",
"avoid_crossing_perimeters",
"avoid_crossing_perimeters_max_detour",
"bed_shape",
@ -137,6 +138,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
"start_filament_gcode",
"toolchange_gcode",
"top_solid_infill_acceleration",
"travel_acceleration",
"thumbnails",
"thumbnails_format",
"use_firmware_retraction",
@ -501,6 +503,10 @@ std::string Print::validate(std::string* warning) const
return _u8L("The Spiral Vase option can only be used when printing single material objects.");
}
if (m_config.machine_limits_usage == MachineLimitsUsage::EmitToGCode && m_config.gcode_flavor == gcfKlipper)
return L("Machine limits cannot be emitted to G-Code when Klipper firmware flavor is used. "
"Change the value of machine_limits_usage.");
// Cache of layer height profiles for checking:
// 1) Whether all layers are synchronized if printing with wipe tower and / or unsynchronized supports.
// 2) Whether layer height is constant for Organic supports.
@ -557,8 +563,9 @@ std::string Print::validate(std::string* warning) const
}
if (m_config.gcode_flavor != gcfRepRapSprinter && m_config.gcode_flavor != gcfRepRapFirmware &&
m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlinLegacy && m_config.gcode_flavor != gcfMarlinFirmware)
return _u8L("The Wipe Tower is currently only supported for the Marlin, RepRap/Sprinter, RepRapFirmware and Repetier G-code flavors.");
m_config.gcode_flavor != gcfRepetier && m_config.gcode_flavor != gcfMarlinLegacy &&
m_config.gcode_flavor != gcfMarlinFirmware && m_config.gcode_flavor != gcfKlipper)
return _u8L("The Wipe Tower is currently only supported for the Marlin, Klipper, RepRap/Sprinter, RepRapFirmware and Repetier G-code flavors.");
if (! m_config.use_relative_e_distances)
return _u8L("The Wipe Tower is currently only supported with the relative extruder addressing (use_relative_e_distances=1).");
if (m_config.ooze_prevention && m_config.single_extruder_multi_material)

View file

@ -48,6 +48,7 @@ static const t_config_enum_values s_keys_map_GCodeFlavor {
{ "makerware", gcfMakerWare },
{ "marlin", gcfMarlinLegacy },
{ "marlin2", gcfMarlinFirmware },
{ "klipper", gcfKlipper },
{ "sailfish", gcfSailfish },
{ "smoothie", gcfSmoothie },
{ "mach3", gcfMach3 },
@ -67,6 +68,7 @@ static const t_config_enum_values s_keys_map_PrintHostType {
{ "prusalink", htPrusaLink },
{ "prusaconnect", htPrusaConnect },
{ "octoprint", htOctoPrint },
{ "mainsail", htMainSail },
{ "duet", htDuet },
{ "flashair", htFlashAir },
{ "astrobox", htAstroBox },
@ -1406,6 +1408,7 @@ void PrintConfigDef::init_fff_params()
{ "makerware", "MakerWare (MakerBot)" },
{ "marlin", "Marlin (legacy)" },
{ "marlin2", "Marlin 2" },
{ "klipper", "Klipper" },
{ "sailfish", "Sailfish (MakerBot)" },
{ "mach3", "Mach3/LinuxCNC" },
{ "machinekit", "Machinekit" },
@ -1463,7 +1466,15 @@ void PrintConfigDef::init_fff_params()
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0));
def = this->add("travel_acceleration", coFloat);
def->label = L("Travel");
def->tooltip = L("This is the acceleration your printer will use for travel moves. Set zero to disable "
"acceleration control for travel.");
def->sidetext = L("mm/s²");
def->min = 0;
def->mode = comExpert;
def->set_default_value(new ConfigOptionFloat(0));
def = this->add("infill_every_layers", coInt);
def->label = L("Combine infill every");
@ -1792,9 +1803,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("machine_max_acceleration_extruding", coFloats);
def->full_label = L("Maximum acceleration when extruding");
def->category = L("Machine limits");
def->tooltip = L("Maximum acceleration when extruding (M204 P)\n\n"
"Marlin (legacy) firmware flavor will use this also "
"as travel acceleration (M204 T).");
def->tooltip = L("Maximum acceleration when extruding");
def->sidetext = L("mm/s²");
def->min = 0;
def->mode = comAdvanced;
@ -1805,7 +1814,8 @@ void PrintConfigDef::init_fff_params()
def = this->add("machine_max_acceleration_retracting", coFloats);
def->full_label = L("Maximum acceleration when retracting");
def->category = L("Machine limits");
def->tooltip = L("Maximum acceleration when retracting (M204 R)");
def->tooltip = L("Maximum acceleration when retracting.\n\n"
"Not used for RepRapFirmware, which does not support it.");
def->sidetext = L("mm/s²");
def->min = 0;
def->mode = comAdvanced;
@ -1815,7 +1825,7 @@ void PrintConfigDef::init_fff_params()
def = this->add("machine_max_acceleration_travel", coFloats);
def->full_label = L("Maximum acceleration for travel moves");
def->category = L("Machine limits");
def->tooltip = L("Maximum acceleration for travel moves (M204 T)");
def->tooltip = L("Maximum acceleration for travel moves.");
def->sidetext = L("mm/s²");
def->min = 0;
def->mode = comAdvanced;
@ -1944,6 +1954,7 @@ void PrintConfigDef::init_fff_params()
{ "prusalink", "PrusaLink" },
{ "prusaconnect", "PrusaConnect" },
{ "octoprint", "OctoPrint" },
{ "mainsail", "Mainsail/Fluidd" },
{ "duet", "Duet" },
{ "flashair", "FlashAir" },
{ "astrobox", "AstroBox" },
@ -2478,15 +2489,25 @@ void PrintConfigDef::init_fff_params()
def->mode = comExpert;
def->set_default_value(new ConfigOptionInt(-5));
def = this->add("autoemit_temperature_commands", coBool);
def->label = L("Emit temperature commands automatically");
def->tooltip = L("When enabled, PrusaSlicer will check whether your Custom Start G-Code contains M104 or M190. "
"If so, the temperatures will not be emitted automatically so you're free to customize "
"the order of heating commands and other custom actions. Note that you can use "
"placeholder variables for all PrusaSlicer settings, so you can put "
"a \"M109 S[first_layer_temperature]\" command wherever you want.\n"
"If your Custom Start G-Code does NOT contain M104 or M190, "
"PrusaSlicer will execute the Start G-Code after bed reached its target temperature "
"and extruder just started heating.\n\n"
"When disabled, PrusaSlicer will NOT emit commands to heat up extruder and bed, "
"leaving both to Custom Start G-Code.");
def->mode = comExpert;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("start_gcode", coString);
def->label = L("Start G-code");
def->tooltip = L("This start procedure is inserted at the beginning, after bed has reached "
"the target temperature and extruder just started heating, and before extruder "
"has finished heating. If PrusaSlicer detects M104 or M190 in your custom codes, "
"such commands will not be prepended automatically so you're free to customize "
"the order of heating commands and other custom actions. Note that you can use "
"placeholder variables for all PrusaSlicer settings, so you can put "
"a \"M109 S[first_layer_temperature]\" command wherever you want.");
def->tooltip = L("This start procedure is inserted at the beginning, possibly prepended by "
"temperature-changing commands. See 'autoemit_temperature_commands'.");
def->multiline = true;
def->full_width = true;
def->height = 12;
@ -4413,8 +4434,9 @@ std::string validate(const FullPrintConfig &cfg)
cfg.gcode_flavor.value != gcfMarlinLegacy &&
cfg.gcode_flavor.value != gcfMarlinFirmware &&
cfg.gcode_flavor.value != gcfMachinekit &&
cfg.gcode_flavor.value != gcfRepetier)
return "--use-firmware-retraction is only supported by Marlin, Smoothie, RepRapFirmware, Repetier and Machinekit firmware";
cfg.gcode_flavor.value != gcfRepetier &&
cfg.gcode_flavor.value != gcfKlipper)
return "--use-firmware-retraction is only supported by Marlin, Klipper, Smoothie, RepRapFirmware, Repetier and Machinekit firmware";
if (cfg.use_firmware_retraction.value)
for (unsigned char wipe : cfg.wipe.values)

View file

@ -32,7 +32,7 @@
namespace Slic3r {
enum GCodeFlavor : unsigned char {
gcfRepRapSprinter, gcfRepRapFirmware, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinLegacy, gcfMarlinFirmware, gcfSailfish, gcfMach3, gcfMachinekit,
gcfRepRapSprinter, gcfRepRapFirmware, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinLegacy, gcfMarlinFirmware, gcfKlipper, gcfSailfish, gcfMach3, gcfMachinekit,
gcfSmoothie, gcfNoExtrusion,
};
@ -44,7 +44,7 @@ enum class MachineLimitsUsage {
};
enum PrintHostType {
htPrusaLink, htPrusaConnect, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier, htMKS
htPrusaLink, htPrusaConnect, htOctoPrint, htDuet, htFlashAir, htAstroBox, htRepetier, htMKS, htMainSail
};
enum AuthorizationType {
@ -661,6 +661,7 @@ PRINT_CONFIG_CLASS_DEFINE(
PRINT_CONFIG_CLASS_DEFINE(
GCodeConfig,
((ConfigOptionBool, autoemit_temperature_commands))
((ConfigOptionString, before_layer_gcode))
((ConfigOptionString, between_objects_gcode))
((ConfigOptionFloats, deretract_speed))
@ -815,6 +816,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionPoints, thumbnails))
((ConfigOptionEnum<GCodeThumbnailsFormat>, thumbnails_format))
((ConfigOptionFloat, top_solid_infill_acceleration))
((ConfigOptionFloat, travel_acceleration))
((ConfigOptionBools, wipe))
((ConfigOptionBool, wipe_tower))
((ConfigOptionFloat, wipe_tower_x))

View file

@ -256,7 +256,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
bool have_default_acceleration = config->opt_float("default_acceleration") > 0;
for (auto el : { "perimeter_acceleration", "infill_acceleration", "top_solid_infill_acceleration",
"solid_infill_acceleration", "external_perimeter_acceleration"
"solid_infill_acceleration", "external_perimeter_acceleration",
"bridge_acceleration", "first_layer_acceleration" })
toggle_field(el, have_default_acceleration);

View file

@ -7,6 +7,7 @@
#include "libslic3r/Utils.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/GCode/GCodeProcessor.hpp"
#include "libslic3r/GCodeWriter.hpp"
#include "slic3r/Utils/Http.hpp"
#include "slic3r/Utils/PrintHost.hpp"
@ -1573,6 +1574,7 @@ void TabPrint::build()
optgroup->append_single_option_line("bridge_acceleration");
optgroup->append_single_option_line("first_layer_acceleration");
optgroup->append_single_option_line("first_layer_acceleration_over_raft");
optgroup->append_single_option_line("travel_acceleration");
optgroup->append_single_option_line("default_acceleration");
optgroup = page->new_optgroup(L("Autospeed (advanced)"));
@ -2259,6 +2261,12 @@ void TabPrinter::build_print_host_upload_group(Page* page)
optgroup->append_line(line);
}
static wxString get_info_klipper_string()
{
return _L("Emitting machine limits to G-code is not supported with Klipper G-code flavor.\n"
"The option was switched to \"Use for time estimate\".");
}
void TabPrinter::build_fff()
{
if (!m_pages.empty())
@ -2376,14 +2384,42 @@ void TabPrinter::build_fff()
}
}
if (opt_key == "gcode_flavor") {
const int flavor = boost::any_cast<int>(value);
bool supports_travel_acceleration = (flavor == int(gcfMarlinFirmware) || flavor == int(gcfRepRapFirmware));
bool supports_min_feedrates = (flavor == int(gcfMarlinFirmware) || flavor == int(gcfMarlinLegacy));
const GCodeFlavor flavor = static_cast<GCodeFlavor>(boost::any_cast<int>(value));
bool supports_travel_acceleration = GCodeWriter::supports_separate_travel_acceleration(flavor);
bool supports_min_feedrates = (flavor == gcfMarlinFirmware || flavor == gcfMarlinLegacy);
if (supports_travel_acceleration != m_supports_travel_acceleration || supports_min_feedrates != m_supports_min_feedrates) {
m_rebuild_kinematics_page = true;
m_supports_travel_acceleration = supports_travel_acceleration;
m_supports_min_feedrates = supports_min_feedrates;
}
const bool is_emit_to_gcode = m_config->option("machine_limits_usage")->getInt() == static_cast<int>(MachineLimitsUsage::EmitToGCode);
if ((flavor == gcfKlipper && is_emit_to_gcode) || (!m_supports_min_feedrates && m_use_silent_mode)) {
DynamicPrintConfig new_conf = *m_config;
wxString msg;
if (flavor == gcfKlipper && is_emit_to_gcode) {
msg = get_info_klipper_string();
auto machine_limits_usage = static_cast<ConfigOptionEnum<MachineLimitsUsage>*>(m_config->option("machine_limits_usage")->clone());
machine_limits_usage->value = MachineLimitsUsage::TimeEstimateOnly;
new_conf.set_key_value("machine_limits_usage", machine_limits_usage);
}
if (!m_supports_min_feedrates && m_use_silent_mode) {
if (!msg.IsEmpty())
msg += "\n\n";
msg += _L("Stealth mode for machine limits to G-code is not supported with selected G-code flavor.\n"
"The Stealth mode was suppressed.");
auto silent_mode = static_cast<ConfigOptionBool*>(m_config->option("silent_mode")->clone());
silent_mode->value = false;
new_conf.set_key_value("silent_mode", silent_mode);
}
InfoDialog(parent(), _L("G-code flavor is switched"), msg).ShowModal();
load_config(new_conf);
}
}
build_unregular_pages();
update_dirty();
@ -2410,6 +2446,9 @@ void TabPrinter::build_fff()
option.opt.height = 3 * gcode_field_height;//150;
optgroup->append_single_option_line(option);
optgroup = page->new_optgroup(L("Start G-Code options"));
optgroup->append_single_option_line("autoemit_temperature_commands");
optgroup = page->new_optgroup(L("End G-code"), 0);
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
@ -2629,6 +2668,27 @@ PageShp TabPrinter::build_kinematics_page()
optgroup->append_line(line);
}
optgroup->m_on_change = [this](const t_config_option_key& opt_key, boost::any value)
{
if (opt_key == "machine_limits_usage" &&
static_cast<MachineLimitsUsage>(boost::any_cast<int>(value)) == MachineLimitsUsage::EmitToGCode &&
static_cast<GCodeFlavor>(m_config->option("gcode_flavor")->getInt()) == gcfKlipper)
{
DynamicPrintConfig new_conf = *m_config;
auto machine_limits_usage = static_cast<ConfigOptionEnum<MachineLimitsUsage>*>(m_config->option("machine_limits_usage")->clone());
machine_limits_usage->value = MachineLimitsUsage::TimeEstimateOnly;
new_conf.set_key_value("machine_limits_usage", machine_limits_usage);
InfoDialog(parent(), wxEmptyString, get_info_klipper_string()).ShowModal();
load_config(new_conf);
}
update_dirty();
update();
};
if (m_use_silent_mode) {
// Legend for OptionsGroups
auto optgroup = page->new_optgroup("");
@ -2865,7 +2925,7 @@ void TabPrinter::build_unregular_pages(bool from_initial_build/* = false*/)
{
size_t n_before_extruders = 2; // Count of pages before Extruder pages
auto flavor = m_config->option<ConfigOptionEnum<GCodeFlavor>>("gcode_flavor")->value;
bool show_mach_limits = (flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware || flavor == gcfRepRapFirmware);
bool show_mach_limits = (flavor == gcfMarlinLegacy || flavor == gcfMarlinFirmware || flavor == gcfRepRapFirmware || flavor == gcfKlipper);
/* ! Freeze/Thaw in this function is needed to avoid call OnPaint() for erased pages
* and be cause of application crash, when try to change Preset in moment,
@ -3101,7 +3161,8 @@ void TabPrinter::toggle_options()
if (m_active_page->title() == "Machine limits" && m_machine_limits_description_line) {
assert(flavor == gcfMarlinLegacy
|| flavor == gcfMarlinFirmware
|| flavor == gcfRepRapFirmware);
|| flavor == gcfRepRapFirmware
|| flavor == gcfKlipper);
const auto *machine_limits_usage = m_config->option<ConfigOptionEnum<MachineLimitsUsage>>("machine_limits_usage");
bool enabled = machine_limits_usage->value != MachineLimitsUsage::Ignore;
bool silent_mode = m_config->opt_bool("silent_mode");
@ -4510,6 +4571,8 @@ bool Tab::validate_custom_gcodes()
if (!opt_group->is_activated())
break;
std::string key = opt_group->opt_map().begin()->first;
if (key == "autoemit_temperature_commands")
continue;
valid &= validate_custom_gcode(opt_group->title, boost::any_cast<std::string>(opt_group->get_value(key)));
if (!valid)
break;

View file

@ -139,6 +139,16 @@ protected:
void set_http_post_header_args(Http& http, PrintHostPostUploadAction post_action) const override;
};
class Mainsail : public OctoPrint
{
public:
Mainsail(DynamicPrintConfig* config) : OctoPrint(config) {}
~Mainsail() override = default;
const char* get_name() const override { return "Mainsail/Fluidd"; }
};
}
#endif

View file

@ -54,6 +54,7 @@ PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config)
case htPrusaLink: return new PrusaLink(config);
case htPrusaConnect: return new PrusaConnect(config);
case htMKS: return new MKS(config);
case htMainSail: return new Mainsail(config);
default: return nullptr;
}
} else {