From 0f7933c4f9e29ada1b468956b16894fdfe9cfefc Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Tue, 6 Jan 2015 00:35:39 +0100 Subject: [PATCH] Bugfix: pressure regulation accumulated too much retraction and didn't discharge at the end of print. Includes regression test. #2470 --- lib/Slic3r/GCode/PressureRegulator.pm | 29 +++++++++++++++++++-------- lib/Slic3r/Print/GCode.pm | 21 ++++++++++--------- t/pressure.t | 15 ++++++-------- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/lib/Slic3r/GCode/PressureRegulator.pm b/lib/Slic3r/GCode/PressureRegulator.pm index 6acbf0e09..8d1cd6525 100644 --- a/lib/Slic3r/GCode/PressureRegulator.pm +++ b/lib/Slic3r/GCode/PressureRegulator.pm @@ -24,7 +24,7 @@ sub BUILD { sub process { my $self = shift; - my ($gcode) = @_; + my ($gcode, $flush) = @_; my $new_gcode = ""; @@ -51,7 +51,7 @@ sub process { 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; + $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); @@ -61,20 +61,33 @@ sub process { } } 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 .= $self->_discharge($args->{F}); } $new_gcode .= "$info->{raw}\n"; }); + if ($flush) { + $new_gcode .= $self->_discharge; + } + return $new_gcode; } -sub unretract_speed { +sub _discharge { + my ($self, $F) = @_; + + my $new_E = ($self->config->use_relative_e_distances ? 0 : $self->reader->E) - $self->_advance; + my $gcode = sprintf "G1 %s%.5f F%.3f ; pressure discharge\n", + $self->_extrusion_axis, $new_E, $F // $self->_unretract_speed; + $gcode .= sprintf "G92 %s%.5f ; restore E\n", $self->_extrusion_axis, $self->reader->E + if !$self->config->use_relative_e_distances; + $self->_advance(0); + + return $gcode; +} + +sub _unretract_speed { my ($self) = @_; return $self->config->get_at('retract_speed', $self->_tool) * 60; } diff --git a/lib/Slic3r/Print/GCode.pm b/lib/Slic3r/Print/GCode.pm index a40a64e28..762978655 100644 --- a/lib/Slic3r/Print/GCode.pm +++ b/lib/Slic3r/Print/GCode.pm @@ -54,7 +54,7 @@ sub BUILD { if $self->config->spiral_vase; $self->_vibration_limit(Slic3r::GCode::VibrationLimit->new(config => $self->config)) - if $self->config->vibration_limit > 0; + if $self->config->vibration_limit != 0; $self->_arc_fitting(Slic3r::GCode::ArcFitting->new(config => $self->config)) if $self->config->gcode_arcs; @@ -208,7 +208,7 @@ sub export { } $self->process_layer($layer, [$copy]); } - $self->flush_cooling_buffer; + $self->flush_filters; $finished_objects++; } } @@ -234,7 +234,7 @@ sub export { } } } - $self->flush_cooling_buffer; + $self->flush_filters; } # write end commands to file @@ -529,28 +529,29 @@ sub _extrude_infill { return $gcode; } -sub flush_cooling_buffer { +sub flush_filters { my ($self) = @_; - print {$self->fh} $self->filter($self->_cooling_buffer->flush); + + print {$self->fh} $self->filter($self->_cooling_buffer->flush, 1); } sub filter { - my ($self, $gcode) = @_; + my ($self, $gcode, $flush) = @_; # apply vibration limit if enabled; # this injects pauses according to time (thus depends on actual speeds) $gcode = $self->_vibration_limit->process($gcode) - if $self->print->config->vibration_limit != 0; + if defined $self->_vibration_limit; # apply pressure regulation if enabled; # this depends on actual speeds - $gcode = $self->_pressure_regulator->process($gcode) - if $self->print->config->pressure_advance > 0; + $gcode = $self->_pressure_regulator->process($gcode, $flush) + if defined $self->_pressure_regulator; # apply arc fitting if enabled; # this does not depend on speeds but changes G1 XY commands into G2/G2 IJ $gcode = $self->_arc_fitting->process($gcode) - if $self->print->config->gcode_arcs; + if defined $self->_arc_fitting; return $gcode; } diff --git a/t/pressure.t b/t/pressure.t index fe4f05fb7..fd9045c82 100644 --- a/t/pressure.t +++ b/t/pressure.t @@ -9,7 +9,7 @@ BEGIN { use List::Util qw(); use Slic3r; -use Slic3r::Geometry qw(); +use Slic3r::Geometry qw(epsilon); use Slic3r::Test; { @@ -18,21 +18,18 @@ use Slic3r::Test; $config->set('retract_length', [1]); my $print = Slic3r::Test::init_print('20mm_cube', config => $config, duplicate => 2); - my $retracted = 0; - my $extruding_before_full_unretract = 0; + my $retracted = $config->retract_length->[0]; Slic3r::GCode::Reader->new->parse(Slic3r::Test::gcode($print), sub { my ($self, $cmd, $args, $info) = @_; - if ($info->{extruding} && $info->{dist_XY}) { - $extruding_before_full_unretract if $retracted != 0; - } elsif ($info->{extruding}) { - $retracted += -$info->{dist_E}; + if ($info->{extruding} && !$info->{dist_XY}) { + $retracted += $info->{dist_E}; } elsif ($info->{retracting}) { - $retracted += -$info->{dist_E}; + $retracted += $info->{dist_E}; } }); - ok !$extruding_before_full_unretract, 'not extruding before complete unretract'; + ok abs($retracted) < epsilon, 'all retractions are compensated'; }