PressureRegulator.pm 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package Slic3r::GCode::PressureRegulator;
  2. use Moo;
  3. has 'config' => (is => 'ro', required => 1);
  4. has 'enable' => (is => 'rw', default => sub { 0 });
  5. has 'reader' => (is => 'ro', default => sub { Slic3r::GCode::Reader->new });
  6. has '_extrusion_axis' => (is => 'rw', default => sub { "E" });
  7. has '_tool' => (is => 'rw', default => sub { 0 });
  8. has '_advance' => (is => 'rw', default => sub { 0 }); # extra E injected
  9. use Slic3r::Geometry qw(epsilon);
  10. # Acknowledgements:
  11. # The advance algorithm was proposed by Matthew Roberts.
  12. # The initial work on this Slic3r feature was done by Luís Andrade (lluis)
  13. sub BUILD {
  14. my ($self) = @_;
  15. $self->reader->apply_print_config($self->config);
  16. $self->_extrusion_axis($self->config->get_extrusion_axis);
  17. }
  18. sub process {
  19. my $self = shift;
  20. my ($gcode) = @_;
  21. my $new_gcode = "";
  22. $self->reader->parse($gcode, sub {
  23. my ($reader, $cmd, $args, $info) = @_;
  24. if ($cmd =~ /^T(\d+)/) {
  25. $self->_tool($1);
  26. } elsif ($info->{extruding} && $info->{dist_XY} > 0) {
  27. # This is a print move.
  28. if (exists $args->{F}) {
  29. # We are setting a (potentially) new speed, so we calculate the new advance amount.
  30. # First calculate relative flow rate (mm of filament over mm of travel)
  31. my $rel_flow_rate = $info->{dist_E} / $info->{dist_XY};
  32. # Then calculate absolute flow rate (mm/sec of feedstock)
  33. my $flow_rate = $rel_flow_rate * $args->{F} / 60;
  34. # And finally calculate advance by using the user-configured K factor.
  35. my $new_advance = $self->config->pressure_advance * ($flow_rate**2);
  36. if (abs($new_advance - $self->_advance) > 1E-5) {
  37. my $new_E = ($self->config->use_relative_e_distances ? 0 : $reader->E) + ($new_advance - $self->_advance);
  38. $new_gcode .= sprintf "G1 %s%.5f F%.3f ; pressure advance\n",
  39. $self->_extrusion_axis, $new_E, $self->unretract_speed;
  40. $new_gcode .= sprintf "G92 %s%.5f ; restore E\n", $self->_extrusion_axis, $reader->E
  41. if !$self->config->use_relative_e_distances;
  42. $self->_advance($new_advance);
  43. }
  44. }
  45. } elsif (($info->{retracting} || $cmd eq 'G10') && $self->_advance != 0) {
  46. # We need to bring pressure to zero when retracting.
  47. my $new_E = ($self->config->use_relative_e_distances ? 0 : $reader->E) - $self->_advance;
  48. $new_gcode .= sprintf "G1 %s%.5f F%.3f ; pressure discharge\n",
  49. $self->_extrusion_axis, $new_E, $args->{F} // $self->unretract_speed;
  50. $new_gcode .= sprintf "G92 %s%.5f ; restore E\n", $self->_extrusion_axis, $reader->E
  51. if !$self->config->use_relative_e_distances;
  52. }
  53. $new_gcode .= "$info->{raw}\n";
  54. });
  55. return $new_gcode;
  56. }
  57. sub unretract_speed {
  58. my ($self) = @_;
  59. return $self->config->get_at('retract_speed', $self->_tool) * 60;
  60. }
  61. 1;