From 7de8b20bc4edca6d9be7202564e380e45e297012 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 17 Mar 2013 02:22:50 +0100 Subject: [PATCH 1/3] New wipe feature --- README.markdown | 1 + lib/Slic3r/Config.pm | 11 ++++++++++- lib/Slic3r/Extruder.pm | 10 ++++++++-- lib/Slic3r/GCode.pm | 26 ++++++++++++++++++++++++-- lib/Slic3r/Polyline.pm | 25 +++++++++++++++++++++++++ lib/Slic3r/Print.pm | 3 ++- slic3r.pl | 1 + 7 files changed, 71 insertions(+), 6 deletions(-) diff --git a/README.markdown b/README.markdown index 95c565c98..dabd97a88 100644 --- a/README.markdown +++ b/README.markdown @@ -239,6 +239,7 @@ The author of the Silk icon set is Mark James. --retract-lift Lift Z by the given distance in mm when retracting (default: 0) --retract-layer-change Enforce a retraction before each Z move (default: yes) + --wipe Wipe the nozzle while doing a retraction (default: no) Retraction options for multi-extruder setups: --retract-length-toolchange diff --git a/lib/Slic3r/Config.pm b/lib/Slic3r/Config.pm index 3e147a440..dc0763be3 100644 --- a/lib/Slic3r/Config.pm +++ b/lib/Slic3r/Config.pm @@ -794,6 +794,15 @@ END deserialize => $deserialize_comma, default => [1], }, + 'wipe' => { + label => 'Wipe before retract', + tooltip => 'This flag will move the nozzle while retracting to minimize the possible blob on leaky extruders.', + cli => 'wipe!', + type => 'bool', + serialize => $serialize_comma, + deserialize => $deserialize_comma, + default => [0], + }, 'retract_length_toolchange' => { label => 'Length', tooltip => 'When retraction is triggered before changing tool, filament is pulled back by the specified amount (the length is measured on raw filament, before it enters the extruder).', @@ -1065,7 +1074,7 @@ sub new_from_cli { } $args{$_} = $Options->{$_}{deserialize}->($args{$_}) - for grep exists $args{$_}, qw(print_center bed_size duplicate_grid extruder_offset retract_layer_change); + for grep exists $args{$_}, qw(print_center bed_size duplicate_grid extruder_offset retract_layer_change wipe); return $class->new(%args); } diff --git a/lib/Slic3r/Extruder.pm b/lib/Slic3r/Extruder.pm index bc124dad2..526ac5048 100644 --- a/lib/Slic3r/Extruder.pm +++ b/lib/Slic3r/Extruder.pm @@ -1,13 +1,13 @@ package Slic3r::Extruder; use Moo; -use Slic3r::Geometry qw(PI); +use Slic3r::Geometry qw(PI scale); use constant OPTIONS => [qw( extruder_offset nozzle_diameter filament_diameter extrusion_multiplier temperature first_layer_temperature retract_length retract_lift retract_speed retract_restart_extra retract_before_travel - retract_layer_change retract_length_toolchange retract_restart_extra_toolchange + retract_layer_change retract_length_toolchange retract_restart_extra_toolchange wipe )]; has 'id' => (is => 'rw', required => 1); @@ -18,6 +18,7 @@ has 'retracted' => (is => 'rw', default => sub {0} ); has 'restart_extra' => (is => 'rw', default => sub {0} ); has 'e_per_mm3' => (is => 'lazy'); has 'retract_speed_mm_min' => (is => 'lazy'); +has 'scaled_wipe_distance' => (is => 'lazy'); # scaled mm has '_mm3_per_mm_cache' => (is => 'ro', default => sub {{}}); sub _build_bridge_flow { @@ -35,6 +36,11 @@ sub _build_retract_speed_mm_min { return $self->retract_speed * 60; } +sub _build_scaled_wipe_distance { + my $self = shift; + return scale $self->retract_length / $self->retract_speed * $Slic3r::Config->travel_speed; +} + sub make_flow { my $self = shift; return Slic3r::Flow->new(nozzle_diameter => $self->nozzle_diameter, @_); diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 52efe6b39..247ad9fa5 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -28,6 +28,7 @@ has 'last_pos' => (is => 'rw', default => sub { Slic3r::Point->new(0,0 has 'last_speed' => (is => 'rw', default => sub {""}); has 'last_f' => (is => 'rw', default => sub {""}); has 'last_fan_speed' => (is => 'rw', default => sub {0}); +has 'wipe_path' => (is => 'rw'); has 'dec' => (is => 'ro', default => sub { 3 } ); # used for vibration limit: @@ -150,6 +151,7 @@ sub extrude_loop { # extrude along the path my $gcode = $self->extrude_path($extrusion_path, $description); + $self->wipe_path($extrusion_path->polyline); # make a little move inwards before leaving loop if ($loop->role == EXTR_ROLE_EXTERNAL_PERIMETER) { @@ -236,12 +238,15 @@ sub extrude_path { $path_length = unscale $path->length; $gcode .= $self->G2_G3($path->points->[-1], $path->orientation, $path->center, $e * unscale $path_length, $description); + $self->wipe_path(undef); } else { foreach my $line ($path->lines) { my $line_length = unscale $line->length; $path_length += $line_length; $gcode .= $self->G1($line->[B], undef, $e * $line_length, $description); } + $self->wipe_path([ reverse @{$path->points}[0..$#{$path->points}] ]) + if $Slic3r::Config->wipe; } if ($Slic3r::Config->cooling) { @@ -347,6 +352,14 @@ sub retract { # if we already retracted, reduce the required amount of retraction $length -= $self->extruder->retracted; return "" unless $length > 0; + my $gcode = ""; + + # wipe + my $wipe_path = (); + if ($Slic3r::Config->wipe && $self->wipe_path) { + $wipe_path = Slic3r::Polyline->new([ $self->last_pos, @{$self->wipe_path} ]) + ->clip_start($self->extruder->scaled_wipe_distance); + } # prepare moves $self->speed('retract'); @@ -355,7 +368,6 @@ sub retract { ? undef : [undef, $self->z + $self->extruder->retract_lift, 0, 'lift plate during travel']; - my $gcode = ""; if (($Slic3r::Config->g0 || $Slic3r::Config->gcode_flavor eq 'mach3') && $params{travel_to}) { if ($lift) { # combine lift and retract @@ -371,7 +383,17 @@ sub retract { my $travel = [undef, $params{move_z}, $retract->[2], "change layer and $comment"]; $gcode .= $self->G0(@$travel); } else { - $gcode .= $self->G1(@$retract); + if ($wipe_path) { + $self->speed('travel'); + # subdivide the retraction + my $total_wipe_length = $wipe_path->length; + for (1 .. $#$wipe_path) { + my $segment_length = $wipe_path->[$_-1]->distance_to($wipe_path->[$_]); + $gcode .= $self->G1($wipe_path->[$_], undef, $retract->[2] * ($segment_length / $total_wipe_length), $retract->[3] . ";_WIPE"); + } + } else { + $gcode .= $self->G1(@$retract); + } if (!$self->lifted) { if (defined $params{move_z} && $self->extruder->retract_lift > 0) { my $travel = [undef, $params{move_z} + $self->extruder->retract_lift, 0, 'move to next layer (' . $self->layer->id . ') and lift']; diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 2578e505d..8d5c9c133 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -164,6 +164,7 @@ sub scale { return $self; } +# removes the given distance from the end of the polyline sub clip_end { my $self = shift; my ($distance) = @_; @@ -184,6 +185,30 @@ sub clip_end { } } +# only keeps the given distance at the beginning of the polyline +sub clip_start { + my $self = shift; + my ($distance) = @_; + + my $points = []; + + for (my $i = 1; $distance > 0 && $i <= $#$self; $i++) { + my $point = $self->[$i]; + my $segment_length = $point->distance_to($self->[$i-1]); + if ($segment_length <= $distance) { + $distance -= $segment_length; + push @$points, $point; + next; + } + + my $new_point = Slic3r::Geometry::point_along_segment($self->[$i-1], $point, $distance); + push @$points, Slic3r::Point->new($new_point); + $distance = 0; + } + + return (ref $self)->new($points); +} + package Slic3r::Polyline::Collection; use Moo; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index e374a6cfa..7c664861f 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -957,7 +957,7 @@ sub write_gcode { Slic3r::debugf " fan = %d%%, speed = %d%%\n", $fan_speed, $speed_factor * 100; if ($speed_factor < 1) { - $gcode =~ s/^(?=.*? [XY])(?=.*? E)(?set_fan($Slic3r::Config->bridge_fan_speed, 1) /gmex; $gcode =~ s/^;_BRIDGE_FAN_END\n/ $gcodegen->set_fan($fan_speed, 1) /gmex; } + $gcode =~ s/;_WIPE//g; return $gcode; }; diff --git a/slic3r.pl b/slic3r.pl index 5c5c80b16..9850a9916 100755 --- a/slic3r.pl +++ b/slic3r.pl @@ -292,6 +292,7 @@ $j --retract-lift Lift Z by the given distance in mm when retracting (default: $config->{retract_lift}[0]) --retract-layer-change Enforce a retraction before each Z move (default: yes) + --wipe Wipe the nozzle while doing a retraction (default: no) Retraction options for multi-extruder setups: --retract-length-toolchange From ec5f0635f7cc0411f54d36f0b9ff935bf60d5422 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 18 Mar 2013 21:20:32 +0100 Subject: [PATCH 2/3] Add wipe in GUI --- lib/Slic3r/GUI/Tab.pm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 8fdacf6f6..f83f2aa5e 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -686,7 +686,7 @@ sub build { $self->_build_extruder_pages; } -sub _extruder_options { qw(nozzle_diameter extruder_offset retract_length retract_lift retract_speed retract_restart_extra retract_before_travel +sub _extruder_options { qw(nozzle_diameter extruder_offset retract_length retract_lift retract_speed retract_restart_extra retract_before_travel wipe retract_layer_change retract_length_toolchange retract_restart_extra_toolchange) } sub config { @@ -720,7 +720,7 @@ sub _build_extruder_pages { title => 'Retraction', options => [ map "${_}#${extruder_idx}", - qw(retract_length retract_lift retract_speed retract_restart_extra retract_before_travel retract_layer_change) + qw(retract_length retract_lift retract_speed retract_restart_extra retract_before_travel retract_layer_change wipe) ], }, { From 843a700e960d7745de002c5dbdfe7113b2c0ecd7 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Mon, 25 Mar 2013 23:06:18 +0100 Subject: [PATCH 3/3] Fixes for wipe --- lib/Slic3r/GCode.pm | 11 +++++++---- lib/Slic3r/Polyline.pm | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 247ad9fa5..92190cf7d 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -65,10 +65,12 @@ sub set_shift { my @shift = @_; # if shift increases (goes towards right), last_pos decreases because it goes towards left - $self->last_pos->translate( + my @translate = ( scale ($self->shift_x - $shift[X]), scale ($self->shift_y - $shift[Y]), ); + $self->last_pos->translate(@translate); + $self->wipe_path->translate(@translate) if $self->wipe_path; $self->shift_x($shift[X]); $self->shift_y($shift[Y]); @@ -245,7 +247,7 @@ sub extrude_path { $path_length += $line_length; $gcode .= $self->G1($line->[B], undef, $e * $line_length, $description); } - $self->wipe_path([ reverse @{$path->points}[0..$#{$path->points}] ]) + $self->wipe_path(Slic3r::Polyline->new([ reverse @{$path->points} ])) if $Slic3r::Config->wipe; } @@ -355,9 +357,9 @@ sub retract { my $gcode = ""; # wipe - my $wipe_path = (); + my $wipe_path; if ($Slic3r::Config->wipe && $self->wipe_path) { - $wipe_path = Slic3r::Polyline->new([ $self->last_pos, @{$self->wipe_path} ]) + $wipe_path = Slic3r::Polyline->new([ $self->last_pos, @{$self->wipe_path}[1..$#{$self->wipe_path}] ]) ->clip_start($self->extruder->scaled_wipe_distance); } @@ -387,6 +389,7 @@ sub retract { $self->speed('travel'); # subdivide the retraction my $total_wipe_length = $wipe_path->length; + for (1 .. $#$wipe_path) { my $segment_length = $wipe_path->[$_-1]->distance_to($wipe_path->[$_]); $gcode .= $self->G1($wipe_path->[$_], undef, $retract->[2] * ($segment_length / $total_wipe_length), $retract->[3] . ";_WIPE"); diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 8d5c9c133..16a72886b 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -190,7 +190,7 @@ sub clip_start { my $self = shift; my ($distance) = @_; - my $points = []; + my $points = [ $self->[0] ]; for (my $i = 1; $distance > 0 && $i <= $#$self; $i++) { my $point = $self->[$i];