Bugfix: pressure regulation accumulated too much retraction and didn't discharge at the end of print. Includes regression test. #2470

This commit is contained in:
Alessandro Ranellucci 2015-01-06 00:35:39 +01:00
parent 9fd0637990
commit 0f7933c4f9
3 changed files with 38 additions and 27 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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';
}