New experimental feature for pressure management. Credits to @llluis for the original implementation. #1203 #1677 #2018

This commit is contained in:
Alessandro Ranellucci 2014-11-24 18:22:39 +01:00
parent 5a382f0200
commit ff9b53260d
9 changed files with 108 additions and 2 deletions

View File

@ -139,6 +139,8 @@ The author of the Silk icon set is Mark James.
--gcode-comments Make G-code verbose by adding comments (default: no)
--vibration-limit Limit the frequency of moves on X and Y axes (Hz, set zero to disable;
default: 0)
--pressure-advance Adjust pressure using the experimental advance algorithm (K constant,
set zero to disable; default: 0)
Filament options:
--filament-diameter Diameter in mm of your raw filament (default: 3)

View File

@ -51,6 +51,7 @@ use Slic3r::GCode::CoolingBuffer;
use Slic3r::GCode::Layer;
use Slic3r::GCode::MotionPlanner;
use Slic3r::GCode::PlaceholderParser;
use Slic3r::GCode::PressureRegulator;
use Slic3r::GCode::Reader;
use Slic3r::GCode::SpiralVase;
use Slic3r::GCode::VibrationLimit;

View File

@ -11,6 +11,7 @@ has 'origin' => (is => 'ro', default => sub { Slic3r::Poi
has 'spiralvase' => (is => 'lazy');
has 'vibration_limit' => (is => 'lazy');
has 'arc_fitting' => (is => 'lazy');
has 'pressure_regulator' => (is => 'lazy');
has 'skirt_done' => (is => 'rw', default => sub { {} }); # print_z => 1
has 'brim_done' => (is => 'rw');
has 'second_layer_things_done' => (is => 'rw');
@ -40,6 +41,14 @@ sub _build_arc_fitting {
: undef;
}
sub _build_pressure_regulator {
my $self = shift;
return $self->print->config->pressure_advance > 0
? Slic3r::GCode::PressureRegulator->new(config => $self->print->config)
: undef;
}
sub process_layer {
my $self = shift;
my ($layer, $object_copies) = @_;
@ -197,6 +206,10 @@ sub process_layer {
$gcode = $self->vibration_limit->process($gcode)
if $self->print->config->vibration_limit != 0;
# apply pressure regulation if enabled
$gcode = $self->pressure_regulator->process($gcode)
if $self->print->config->pressure_advance > 0;
# apply arc fitting if enabled
$gcode = $self->arc_fitting->process($gcode)
if $self->print->config->gcode_arcs;

View File

@ -0,0 +1,78 @@
package Slic3r::GCode::PressureRegulator;
use Moo;
has 'config' => (is => 'ro', required => 1);
has 'enable' => (is => 'rw', default => sub { 0 });
has 'reader' => (is => 'ro', default => sub { Slic3r::GCode::Reader->new });
has '_extrusion_axis' => (is => 'rw', default => sub { "E" });
has '_tool' => (is => 'rw', default => sub { 0 });
has '_advance' => (is => 'rw', default => sub { 0 }); # extra E injected
use Slic3r::Geometry qw(epsilon);
# Acknowledgements:
# The advance algorithm was proposed by Matthew Roberts.
# The initial work on this Slic3r feature was done by Luís Andrade (lluis)
sub BUILD {
my ($self) = @_;
$self->reader->apply_print_config($self->config);
$self->_extrusion_axis($self->config->get_extrusion_axis);
}
sub process {
my $self = shift;
my ($gcode) = @_;
my $new_gcode = "";
$self->reader->parse($gcode, sub {
my ($reader, $cmd, $args, $info) = @_;
if ($cmd =~ /^T(\d+)/) {
$self->_tool($1);
} elsif ($info->{extruding} && $info->{dist_XY} > 0) {
# This is a print move.
if (exists $args->{F}) {
# We are setting a (potentially) new speed, so we calculate the new advance amount.
# First calculate relative flow rate (mm of filament over mm of travel)
my $rel_flow_rate = $info->{dist_E} / $info->{dist_XY};
# Then calculate absolute flow rate (mm/sec of feedstock)
my $flow_rate = $rel_flow_rate * $args->{F} / 60;
# And finally calculate advance by using the user-configured K factor.
my $new_advance = $self->config->pressure_advance * ($flow_rate**2);
if (abs($new_advance - $self->_advance) > 1E-5) {
my $new_E = ($self->config->use_relative_e_distances ? 0 : $reader->E) + ($new_advance - $self->_advance);
$new_gcode .= sprintf "G1 %s%.5f F%.3f ; pressure advance\n",
$self->_extrusion_axis, $new_E, $self->unretract_speed;
$new_gcode .= sprintf "G92 %s%.5f ; restore E\n", $self->_extrusion_axis, $reader->E
if !$self->config->use_relative_e_distances;
$self->_advance($new_advance);
}
}
} elsif (($info->{retracting} || $cmd eq 'G10') && $self->_advance != 0) {
# We need to bring pressure to zero when retracting.
my $new_E = ($self->config->use_relative_e_distances ? 0 : $reader->E) - $self->_advance;
$new_gcode .= sprintf "G1 %s%.5f F%.3f ; pressure discharge\n",
$self->_extrusion_axis, $new_E, $args->{F} // $self->unretract_speed;
$new_gcode .= sprintf "G92 %s%.5f ; restore E\n", $self->_extrusion_axis, $reader->E
if !$self->config->use_relative_e_distances;
}
$new_gcode .= "$info->{raw}\n";
});
return $new_gcode;
}
sub unretract_speed {
my ($self) = @_;
return $self->config->get_at('retract_speed', $self->_tool) * 60;
}
1;

View File

@ -894,7 +894,7 @@ sub build {
$self->init_config_options(qw(
bed_shape z_offset
gcode_flavor use_relative_e_distances
use_firmware_retraction vibration_limit
use_firmware_retraction pressure_advance vibration_limit
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
@ -970,6 +970,7 @@ sub build {
{
my $optgroup = $page->new_optgroup('Advanced');
$optgroup->append_single_option_line('use_firmware_retraction');
$optgroup->append_single_option_line('pressure_advance');
$optgroup->append_single_option_line('vibration_limit');
}
}

View File

@ -667,7 +667,7 @@ sub write_gcode {
}
# write end commands to file
print $fh $gcodegen->retract;
print $fh $gcodegen->retract; # TODO: process this retract through PressureRegulator in order to discharge fully
print $fh $gcodegen->writer->set_fan(0);
printf $fh "%s\n", $gcodegen->placeholder_parser->process($self->config->end_gcode);
print $fh $gcodegen->writer->update_progress($gcodegen->layer_count, $gcodegen->layer_count, 1); # 100%

View File

@ -291,6 +291,8 @@ $j
--gcode-comments Make G-code verbose by adding comments (default: no)
--vibration-limit Limit the frequency of moves on X and Y axes (Hz, set zero to disable;
default: $config->{vibration_limit})
--pressure-advance Adjust pressure using the experimental advance algorithm (K constant,
set zero to disable; default: $config->{pressure_advance})
Filament options:
--filament-diameter Diameter in mm of your raw filament (default: $config->{filament_diameter}->[0])

View File

@ -550,6 +550,12 @@ PrintConfigDef::build_def() {
Options["post_process"].full_width = true;
Options["post_process"].height = 60;
Options["pressure_advance"].type = coFloat;
Options["pressure_advance"].label = "Pressure advance";
Options["pressure_advance"].tooltip = "When set to a non-zero value, this experimental option enables pressure regulation. It's the K constant for the advance algorithm that pushes more or less filament upon speed changes. It's useful for Bowden-tube extruders. Reasonable values are in range 0-10.";
Options["pressure_advance"].cli = "pressure-advance=f";
Options["pressure_advance"].min = 0;
Options["raft_layers"].type = coInt;
Options["raft_layers"].label = "Raft layers";
Options["raft_layers"].category = "Support material";

View File

@ -319,6 +319,7 @@ class GCodeConfig : public virtual StaticPrintConfig
ConfigOptionFloats filament_diameter;
ConfigOptionBool gcode_comments;
ConfigOptionEnum<GCodeFlavor> gcode_flavor;
ConfigOptionFloat pressure_advance;
ConfigOptionFloats retract_length;
ConfigOptionFloats retract_length_toolchange;
ConfigOptionFloats retract_lift;
@ -337,6 +338,7 @@ class GCodeConfig : public virtual StaticPrintConfig
this->filament_diameter.values[0] = 3;
this->gcode_comments.value = false;
this->gcode_flavor.value = gcfRepRap;
this->pressure_advance.value = 0;
this->retract_length.values.resize(1);
this->retract_length.values[0] = 1;
this->retract_length_toolchange.values.resize(1);
@ -360,6 +362,7 @@ class GCodeConfig : public virtual StaticPrintConfig
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 == "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;
if (opt_key == "retract_lift") return &this->retract_lift;