Browse Source

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

Alessandro Ranellucci 10 years ago
parent
commit
ff9b53260d

+ 2 - 0
README.md

@@ -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)

+ 1 - 0
lib/Slic3r.pm

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

+ 13 - 0
lib/Slic3r/GCode/Layer.pm

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

+ 78 - 0
lib/Slic3r/GCode/PressureRegulator.pm

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

+ 2 - 1
lib/Slic3r/GUI/Tab.pm

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

+ 1 - 1
lib/Slic3r/Print.pm

@@ -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%

+ 2 - 0
slic3r.pl

@@ -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])

+ 6 - 0
xs/src/libslic3r/PrintConfig.cpp

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

+ 3 - 0
xs/src/libslic3r/PrintConfig.hpp

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