diff --git a/README.md b/README.md index 653e40246..70ec89d1d 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,7 @@ The author of the Silk icon set is Mark James. default: reprap) --use-relative-e-distances Enable this to get relative E values (default: no) --use-firmware-retraction Enable firmware-controlled retraction using G10/G11 (default: no) + --use-volumetric-e Express E in cubic millimeters and prepend M200 (default: no) --gcode-arcs Use G2/G3 commands for native arcs (experimental, not supported by all firmwares) --gcode-comments Make G-code verbose by adding comments (default: no) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index d3e7ccd35..7a21b3fc0 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -927,6 +927,7 @@ sub build { gcode_flavor use_relative_e_distances octoprint_host octoprint_apikey use_firmware_retraction pressure_advance vibration_limit + use_volumetric_e start_gcode end_gcode layer_gcode toolchange_gcode nozzle_diameter extruder_offset retract_length retract_lift retract_speed retract_restart_extra retract_before_travel retract_layer_change wipe @@ -1036,11 +1037,12 @@ sub build { { my $optgroup = $page->new_optgroup('Firmware'); $optgroup->append_single_option_line('gcode_flavor'); - $optgroup->append_single_option_line('use_relative_e_distances'); } { my $optgroup = $page->new_optgroup('Advanced'); + $optgroup->append_single_option_line('use_relative_e_distances'); $optgroup->append_single_option_line('use_firmware_retraction'); + $optgroup->append_single_option_line('use_volumetric_e'); $optgroup->append_single_option_line('pressure_advance'); $optgroup->append_single_option_line('vibration_limit'); } diff --git a/slic3r.pl b/slic3r.pl index debc5ff79..bea11ce1b 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -286,6 +286,7 @@ $j default: $config->{gcode_flavor}) --use-relative-e-distances Enable this to get relative E values (default: no) --use-firmware-retraction Enable firmware-controlled retraction using G10/G11 (default: no) + --use-volumetric-e Express E in cubic millimeters and prepend M200 (default: no) --gcode-arcs Use G2/G3 commands for native arcs (experimental, not supported by all firmwares) --gcode-comments Make G-code verbose by adding comments (default: no) diff --git a/xs/src/libslic3r/Extruder.cpp b/xs/src/libslic3r/Extruder.cpp index d0934851e..8cbd00b73 100644 --- a/xs/src/libslic3r/Extruder.cpp +++ b/xs/src/libslic3r/Extruder.cpp @@ -9,8 +9,12 @@ Extruder::Extruder(int id, GCodeConfig *config) reset(); // cache values that are going to be called often - this->e_per_mm3 = this->extrusion_multiplier() - * (4 / ((this->filament_diameter() * this->filament_diameter()) * PI)); + if (config->use_volumetric_e) { + this->e_per_mm3 = this->extrusion_multiplier(); + } else { + this->e_per_mm3 = this->extrusion_multiplier() + * (4 / ((this->filament_diameter() * this->filament_diameter()) * PI)); + } this->retract_speed_mm_min = this->retract_speed() * 60; } @@ -80,12 +84,22 @@ Extruder::e_per_mm(double mm3_per_mm) const double Extruder::extruded_volume() const { + if (this->config->use_volumetric_e) { + // Any current amount of retraction should not affect used filament, since + // it represents empty volume in the nozzle. We add it back to E. + return this->absolute_E + this->retracted; + } + return this->used_filament() * (this->filament_diameter() * this->filament_diameter()) * PI/4; } double Extruder::used_filament() const { + if (this->config->use_volumetric_e) { + return this->extruded_volume() / (this->filament_diameter() * this->filament_diameter() * PI/4); + } + // Any current amount of retraction should not affect used filament, since // it represents empty volume in the nozzle. We add it back to E. return this->absolute_E + this->retracted; diff --git a/xs/src/libslic3r/GCodeWriter.cpp b/xs/src/libslic3r/GCodeWriter.cpp index bb8035ac3..0fe15809e 100644 --- a/xs/src/libslic3r/GCodeWriter.cpp +++ b/xs/src/libslic3r/GCodeWriter.cpp @@ -48,22 +48,32 @@ GCodeWriter::set_extruders(const std::vector &extruder_ids) std::string GCodeWriter::preamble() { - std::string gcode; + std::ostringstream gcode; if (FLAVOR_IS_NOT(gcfMakerWare)) { - gcode += "G21 ; set units to millimeters\n"; - gcode += "G90 ; use absolute coordinates\n"; + gcode << "G21 ; set units to millimeters\n"; + gcode << "G90 ; use absolute coordinates\n"; } if (FLAVOR_IS(gcfRepRap) || FLAVOR_IS(gcfTeacup)) { if (this->config.use_relative_e_distances) { - gcode += "M83 ; use relative distances for extrusion\n"; + gcode << "M83 ; use relative distances for extrusion\n"; } else { - gcode += "M82 ; use absolute distances for extrusion\n"; + gcode << "M82 ; use absolute distances for extrusion\n"; } - gcode += this->reset_e(true); + if (this->config.use_volumetric_e && this->config.start_gcode.value.find("M200") == std::string::npos) { + for (std::map::const_iterator it = this->extruders.begin(); it != this->extruders.end(); ++it) { + unsigned int extruder_id = it->first; + gcode << "M200 D" << E_NUM(this->config.filament_diameter.get_at(extruder_id)); + if (this->multiple_extruders || extruder_id != 0) { + gcode << " T" << extruder_id; + } + gcode << " ; set filament diameter\n"; + } + } + gcode << this->reset_e(true); } - return gcode; + return gcode.str(); } std::string @@ -423,6 +433,14 @@ GCodeWriter::_retract(double length, double restart_extra, const std::string &co might be 0, in which case the retraction logic gets skipped. */ if (this->config.use_firmware_retraction) length = 1; + // If we use volumetric E values we turn lengths into volumes */ + if (this->config.use_volumetric_e) { + double d = this->_extruder->filament_diameter(); + double area = d * d * PI/4; + length = length * area; + restart_extra = restart_extra * area; + } + double dE = this->_extruder->retract(length, restart_extra); if (dE != 0) { if (this->config.use_firmware_retraction) { diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index e4847a570..e18179cd1 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -945,6 +945,11 @@ PrintConfigDef::build_def() { Options["use_relative_e_distances"].tooltip = "If your firmware requires relative E values, check this, otherwise leave it unchecked. Most firmwares use absolute values."; Options["use_relative_e_distances"].cli = "use-relative-e-distances!"; + Options["use_volumetric_e"].type = coBool; + Options["use_volumetric_e"].label = "Use volumetric E"; + Options["use_volumetric_e"].tooltip = "This experimental setting uses outputs the E values in cubic millimeters instead of linear millimeters. The M200 command is prepended to the generated G-code, unless it is found in the configured start G-code. This is only supported in recent Marlin."; + Options["use_volumetric_e"].cli = "use-volumetric-e!"; + Options["vibration_limit"].type = coFloat; Options["vibration_limit"].label = "Vibration limit (deprecated)"; Options["vibration_limit"].tooltip = "This experimental option will slow down those moves hitting the configured frequency limit. The purpose of limiting vibrations is to avoid mechanical resonance. Set zero to disable."; diff --git a/xs/src/libslic3r/PrintConfig.hpp b/xs/src/libslic3r/PrintConfig.hpp index b647acfb8..500babb88 100644 --- a/xs/src/libslic3r/PrintConfig.hpp +++ b/xs/src/libslic3r/PrintConfig.hpp @@ -321,11 +321,13 @@ class PrintRegionConfig : public virtual StaticPrintConfig class GCodeConfig : public virtual StaticPrintConfig { public: + ConfigOptionString end_gcode; ConfigOptionString extrusion_axis; ConfigOptionFloats extrusion_multiplier; ConfigOptionFloats filament_diameter; ConfigOptionBool gcode_comments; ConfigOptionEnum gcode_flavor; + ConfigOptionString layer_gcode; ConfigOptionFloat pressure_advance; ConfigOptionFloats retract_length; ConfigOptionFloats retract_length_toolchange; @@ -333,11 +335,15 @@ class GCodeConfig : public virtual StaticPrintConfig ConfigOptionFloats retract_restart_extra; ConfigOptionFloats retract_restart_extra_toolchange; ConfigOptionInts retract_speed; + ConfigOptionString start_gcode; + ConfigOptionString toolchange_gcode; ConfigOptionFloat travel_speed; ConfigOptionBool use_firmware_retraction; ConfigOptionBool use_relative_e_distances; + ConfigOptionBool use_volumetric_e; GCodeConfig() : StaticPrintConfig() { + this->end_gcode.value = "M104 S0 ; turn off temperature\nG28 X0 ; home X axis\nM84 ; disable motors\n"; this->extrusion_axis.value = "E"; this->extrusion_multiplier.values.resize(1); this->extrusion_multiplier.values[0] = 1; @@ -345,6 +351,7 @@ class GCodeConfig : public virtual StaticPrintConfig this->filament_diameter.values[0] = 3; this->gcode_comments.value = false; this->gcode_flavor.value = gcfRepRap; + this->layer_gcode.value = ""; this->pressure_advance.value = 0; this->retract_length.values.resize(1); this->retract_length.values[0] = 1; @@ -358,17 +365,22 @@ class GCodeConfig : public virtual StaticPrintConfig this->retract_restart_extra_toolchange.values[0] = 0; this->retract_speed.values.resize(1); this->retract_speed.values[0] = 30; + this->start_gcode.value = "G28 ; home all axes\nG1 Z5 F5000 ; lift nozzle\n"; + this->toolchange_gcode.value = ""; this->travel_speed.value = 130; this->use_firmware_retraction.value = false; this->use_relative_e_distances.value = false; + this->use_volumetric_e.value = false; }; ConfigOption* option(const t_config_option_key opt_key, bool create = false) { + if (opt_key == "end_gcode") return &this->end_gcode; if (opt_key == "extrusion_axis") return &this->extrusion_axis; if (opt_key == "extrusion_multiplier") return &this->extrusion_multiplier; if (opt_key == "filament_diameter") return &this->filament_diameter; if (opt_key == "gcode_comments") return &this->gcode_comments; if (opt_key == "gcode_flavor") return &this->gcode_flavor; + if (opt_key == "layer_gcode") return &this->layer_gcode; if (opt_key == "pressure_advance") return &this->pressure_advance; if (opt_key == "retract_length") return &this->retract_length; if (opt_key == "retract_length_toolchange") return &this->retract_length_toolchange; @@ -376,9 +388,12 @@ class GCodeConfig : public virtual StaticPrintConfig if (opt_key == "retract_restart_extra") return &this->retract_restart_extra; if (opt_key == "retract_restart_extra_toolchange") return &this->retract_restart_extra_toolchange; if (opt_key == "retract_speed") return &this->retract_speed; + if (opt_key == "start_gcode") return &this->start_gcode; + if (opt_key == "toolchange_gcode") return &this->toolchange_gcode; if (opt_key == "travel_speed") return &this->travel_speed; if (opt_key == "use_firmware_retraction") return &this->use_firmware_retraction; if (opt_key == "use_relative_e_distances") return &this->use_relative_e_distances; + if (opt_key == "use_volumetric_e") return &this->use_volumetric_e; return NULL; }; @@ -409,7 +424,6 @@ class PrintConfig : public GCodeConfig ConfigOptionFloat default_acceleration; ConfigOptionInt disable_fan_first_layers; ConfigOptionFloat duplicate_distance; - ConfigOptionString end_gcode; ConfigOptionFloat extruder_clearance_height; ConfigOptionFloat extruder_clearance_radius; ConfigOptionPoints extruder_offset; @@ -423,7 +437,6 @@ class PrintConfig : public GCodeConfig ConfigOptionBool gcode_arcs; ConfigOptionFloat infill_acceleration; ConfigOptionBool infill_first; - ConfigOptionString layer_gcode; ConfigOptionInt max_fan_speed; ConfigOptionInt min_fan_speed; ConfigOptionInt min_print_speed; @@ -444,10 +457,8 @@ class PrintConfig : public GCodeConfig ConfigOptionInt slowdown_below_layer_time; ConfigOptionBool spiral_vase; ConfigOptionInt standby_temperature_delta; - ConfigOptionString start_gcode; ConfigOptionInts temperature; ConfigOptionInt threads; - ConfigOptionString toolchange_gcode; ConfigOptionFloat vibration_limit; ConfigOptionBools wipe; ConfigOptionFloat z_offset; @@ -467,7 +478,6 @@ class PrintConfig : public GCodeConfig this->default_acceleration.value = 0; this->disable_fan_first_layers.value = 1; this->duplicate_distance.value = 6; - this->end_gcode.value = "M104 S0 ; turn off temperature\nG28 X0 ; home X axis\nM84 ; disable motors\n"; this->extruder_clearance_height.value = 20; this->extruder_clearance_radius.value = 20; this->extruder_offset.values.resize(1); @@ -485,7 +495,6 @@ class PrintConfig : public GCodeConfig this->gcode_arcs.value = false; this->infill_acceleration.value = 0; this->infill_first.value = false; - this->layer_gcode.value = ""; this->max_fan_speed.value = 100; this->min_fan_speed.value = 35; this->min_print_speed.value = 10; @@ -508,11 +517,9 @@ class PrintConfig : public GCodeConfig this->slowdown_below_layer_time.value = 30; this->spiral_vase.value = false; this->standby_temperature_delta.value = -5; - this->start_gcode.value = "G28 ; home all axes\nG1 Z5 F5000 ; lift nozzle\n"; this->temperature.values.resize(1); this->temperature.values[0] = 200; this->threads.value = 2; - this->toolchange_gcode.value = ""; this->vibration_limit.value = 0; this->wipe.values.resize(1); this->wipe.values[0] = false; @@ -531,7 +538,6 @@ class PrintConfig : public GCodeConfig if (opt_key == "default_acceleration") return &this->default_acceleration; if (opt_key == "disable_fan_first_layers") return &this->disable_fan_first_layers; if (opt_key == "duplicate_distance") return &this->duplicate_distance; - if (opt_key == "end_gcode") return &this->end_gcode; if (opt_key == "extruder_clearance_height") return &this->extruder_clearance_height; if (opt_key == "extruder_clearance_radius") return &this->extruder_clearance_radius; if (opt_key == "extruder_offset") return &this->extruder_offset; @@ -545,7 +551,6 @@ class PrintConfig : public GCodeConfig if (opt_key == "gcode_arcs") return &this->gcode_arcs; if (opt_key == "infill_acceleration") return &this->infill_acceleration; if (opt_key == "infill_first") return &this->infill_first; - if (opt_key == "layer_gcode") return &this->layer_gcode; if (opt_key == "max_fan_speed") return &this->max_fan_speed; if (opt_key == "min_fan_speed") return &this->min_fan_speed; if (opt_key == "min_print_speed") return &this->min_print_speed; @@ -566,10 +571,8 @@ class PrintConfig : public GCodeConfig if (opt_key == "slowdown_below_layer_time") return &this->slowdown_below_layer_time; if (opt_key == "spiral_vase") return &this->spiral_vase; if (opt_key == "standby_temperature_delta") return &this->standby_temperature_delta; - if (opt_key == "start_gcode") return &this->start_gcode; if (opt_key == "temperature") return &this->temperature; if (opt_key == "threads") return &this->threads; - if (opt_key == "toolchange_gcode") return &this->toolchange_gcode; if (opt_key == "vibration_limit") return &this->vibration_limit; if (opt_key == "wipe") return &this->wipe; if (opt_key == "z_offset") return &this->z_offset;