2017-05-16 11:45:28 +00:00
# ifndef WipeTowerPrusaMM_hpp_
# define WipeTowerPrusaMM_hpp_
2017-05-16 14:02:52 +00:00
# include <cmath>
2017-05-16 11:45:28 +00:00
# include <string>
2018-02-28 15:04:56 +00:00
# include <sstream>
2017-05-16 11:45:28 +00:00
# include <utility>
2018-05-31 14:21:10 +00:00
# include <algorithm>
2017-05-16 11:45:28 +00:00
# include "WipeTower.hpp"
2018-02-28 15:04:56 +00:00
2017-05-16 11:45:28 +00:00
namespace Slic3r
{
namespace PrusaMultiMaterial {
class Writer ;
} ;
2018-02-28 15:04:56 +00:00
2017-05-16 11:45:28 +00:00
class WipeTowerPrusaMM : public WipeTower
{
public :
enum material_type
{
INVALID = - 1 ,
PLA = 0 , // E:210C B:55C
ABS = 1 , // E:255C B:100C
PET = 2 , // E:240C B:90C
HIPS = 3 , // E:220C B:100C
FLEX = 4 , // E:245C B:80C
SCAFF = 5 , // E:215C B:55C
EDGE = 6 , // E:240C B:80C
NGEN = 7 , // E:230C B:80C
PVA = 8 // E:210C B:80C
} ;
// Parse material name into material_type.
static material_type parse_material ( const char * name ) ;
2019-01-29 17:28:52 +00:00
static std : : string to_string ( material_type material ) ;
2017-05-16 11:45:28 +00:00
// x -- x coordinates of wipe tower in mm ( left bottom corner )
// y -- y coordinates of wipe tower in mm ( left bottom corner )
// width -- width of wipe tower in mm ( default 60 mm - leave as it is )
// wipe_area -- space available for one toolchange in mm
2018-03-22 12:37:01 +00:00
WipeTowerPrusaMM ( float x , float y , float width , float rotation_angle , float cooling_tube_retraction ,
2018-12-14 19:09:10 +00:00
float cooling_tube_length , float parking_pos_retraction , float extra_loading_move ,
float bridging , bool set_extruder_trimpot ,
2018-05-24 15:24:37 +00:00
const std : : vector < std : : vector < float > > & wiping_matrix , unsigned int initial_tool ) :
2018-09-17 13:12:13 +00:00
m_wipe_tower_pos ( x , y ) ,
2017-05-16 11:45:28 +00:00
m_wipe_tower_width ( width ) ,
2017-11-30 11:08:22 +00:00
m_wipe_tower_rotation_angle ( rotation_angle ) ,
2018-02-21 12:07:32 +00:00
m_y_shift ( 0.f ) ,
2017-05-25 20:27:53 +00:00
m_z_pos ( 0.f ) ,
2018-02-21 12:07:32 +00:00
m_is_first_layer ( false ) ,
2018-03-02 12:26:16 +00:00
m_cooling_tube_retraction ( cooling_tube_retraction ) ,
m_cooling_tube_length ( cooling_tube_length ) ,
m_parking_pos_retraction ( parking_pos_retraction ) ,
2018-04-16 12:26:57 +00:00
m_extra_loading_move ( extra_loading_move ) ,
2018-03-20 14:45:11 +00:00
m_bridging ( bridging ) ,
2018-12-14 19:09:10 +00:00
m_set_extruder_trimpot ( set_extruder_trimpot ) ,
2018-05-24 15:24:37 +00:00
m_current_tool ( initial_tool ) ,
wipe_volumes ( wiping_matrix )
{ }
2017-05-25 20:27:53 +00:00
2017-05-16 11:45:28 +00:00
virtual ~ WipeTowerPrusaMM ( ) { }
2017-12-21 12:28:26 +00:00
2017-05-16 11:45:28 +00:00
// Set the extruder properties.
2018-08-21 12:36:24 +00:00
void set_extruder ( size_t idx , material_type material , int temp , int first_layer_temp , float loading_speed , float loading_speed_start ,
2018-08-14 14:23:23 +00:00
float unloading_speed , float unloading_speed_start , float delay , int cooling_moves ,
float cooling_initial_speed , float cooling_final_speed , std : : string ramming_parameters , float nozzle_diameter )
2017-05-16 11:45:28 +00:00
{
2018-03-21 14:57:17 +00:00
//while (m_filpar.size() < idx+1) // makes sure the required element is in the vector
m_filpar . push_back ( FilamentParameters ( ) ) ;
2018-03-05 09:45:35 +00:00
m_filpar [ idx ] . material = material ;
2018-12-17 09:30:20 +00:00
if ( material = = FLEX | | material = = SCAFF | | material = = PVA ) {
// MMU2 lowers the print speed using the speed override (M220) for printing of soluble PVA/BVOH and flex materials.
// Therefore it does not make sense to use the new M220 B and M220 R (backup / restore).
m_retain_speed_override = false ;
}
2018-03-05 09:45:35 +00:00
m_filpar [ idx ] . temperature = temp ;
m_filpar [ idx ] . first_layer_temperature = first_layer_temp ;
m_filpar [ idx ] . loading_speed = loading_speed ;
2018-08-21 12:36:24 +00:00
m_filpar [ idx ] . loading_speed_start = loading_speed_start ;
2018-03-05 09:45:35 +00:00
m_filpar [ idx ] . unloading_speed = unloading_speed ;
2018-08-14 14:23:23 +00:00
m_filpar [ idx ] . unloading_speed_start = unloading_speed_start ;
2018-03-05 09:45:35 +00:00
m_filpar [ idx ] . delay = delay ;
2018-04-24 11:02:08 +00:00
m_filpar [ idx ] . cooling_moves = cooling_moves ;
m_filpar [ idx ] . cooling_initial_speed = cooling_initial_speed ;
m_filpar [ idx ] . cooling_final_speed = cooling_final_speed ;
2018-03-29 13:32:09 +00:00
m_filpar [ idx ] . nozzle_diameter = nozzle_diameter ; // to be used in future with (non-single) multiextruder MM
m_perimeter_width = nozzle_diameter * Width_To_Nozzle_Ratio ; // all extruders are now assumed to have the same diameter
2018-03-21 14:57:17 +00:00
2018-03-15 13:04:12 +00:00
std : : stringstream stream { ramming_parameters } ;
float speed = 0.f ;
stream > > m_filpar [ idx ] . ramming_line_width_multiplicator > > m_filpar [ idx ] . ramming_step_multiplicator ;
m_filpar [ idx ] . ramming_line_width_multiplicator / = 100 ;
m_filpar [ idx ] . ramming_step_multiplicator / = 100 ;
while ( stream > > speed )
m_filpar [ idx ] . ramming_speed . push_back ( speed ) ;
2018-09-17 13:12:13 +00:00
m_used_filament_length . resize ( std : : max ( m_used_filament_length . size ( ) , idx + 1 ) ) ; // makes sure that the vector is big enough so we don't have to check later
2017-05-16 11:45:28 +00:00
}
2017-12-21 12:28:26 +00:00
2018-03-21 14:57:17 +00:00
// Appends into internal structure m_plan containing info about the future wipe tower
2017-12-21 12:28:26 +00:00
// to be used before building begins. The entries must be added ordered in z.
2018-05-30 09:56:30 +00:00
void plan_toolchange ( float z_par , float layer_height_par , unsigned int old_tool , unsigned int new_tool , bool brim , float wipe_volume = 0.f ) ;
2017-12-21 12:28:26 +00:00
2018-02-22 10:03:29 +00:00
// Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result"
2017-12-21 12:28:26 +00:00
void generate ( std : : vector < std : : vector < WipeTower : : ToolChangeResult > > & result ) ;
2018-07-27 13:56:27 +00:00
float get_depth ( ) const { return m_wipe_tower_depth ; }
2018-02-21 12:07:32 +00:00
2018-03-06 18:14:12 +00:00
2017-05-16 11:45:28 +00:00
// Switch to a next layer.
virtual void set_layer (
// Print height of this layer.
2017-12-21 12:28:26 +00:00
float print_z ,
// Layer height, used to calculate extrusion the rate.
float layer_height ,
2017-05-16 11:45:28 +00:00
// Maximum number of tool changes on this layer or the layers below.
2017-12-21 12:28:26 +00:00
size_t max_tool_changes ,
2017-05-16 11:45:28 +00:00
// Is this the first layer of the print? In that case print the brim first.
2017-12-21 12:28:26 +00:00
bool is_first_layer ,
2017-05-16 11:45:28 +00:00
// Is this the last layer of the waste tower?
2017-12-21 12:28:26 +00:00
bool is_last_layer )
2017-05-16 11:45:28 +00:00
{
m_z_pos = print_z ;
2017-05-25 20:27:53 +00:00
m_layer_height = layer_height ;
2017-05-16 11:45:28 +00:00
m_is_first_layer = is_first_layer ;
2017-12-21 12:28:26 +00:00
m_print_brim = is_first_layer ;
2018-03-21 14:57:17 +00:00
m_depth_traversed = 0.f ;
2017-05-17 14:45:37 +00:00
m_current_shape = ( ! is_first_layer & & m_current_shape = = SHAPE_NORMAL ) ? SHAPE_REVERSED : SHAPE_NORMAL ;
2018-04-06 10:02:52 +00:00
if ( is_first_layer ) {
this - > m_num_layer_changes = 0 ;
this - > m_num_tool_changes = 0 ;
}
else
+ + m_num_layer_changes ;
2017-12-07 10:59:14 +00:00
2018-03-21 14:57:17 +00:00
// Calculate extrusion flow from desired line width, nozzle diameter, filament diameter and layer_height:
2017-12-21 12:28:26 +00:00
m_extrusion_flow = extrusion_flow ( layer_height ) ;
2018-03-21 14:57:17 +00:00
// Advance m_layer_info iterator, making sure we got it right
while ( ! m_plan . empty ( ) & & m_layer_info - > z < print_z - WT_EPSILON & & m_layer_info + 1 ! = m_plan . end ( ) )
2018-02-22 10:03:29 +00:00
+ + m_layer_info ;
2017-05-16 11:45:28 +00:00
}
// Return the wipe tower position.
2017-05-25 20:27:53 +00:00
virtual const xy & position ( ) const { return m_wipe_tower_pos ; }
2017-05-19 17:24:21 +00:00
// Return the wipe tower width.
2017-05-25 20:27:53 +00:00
virtual float width ( ) const { return m_wipe_tower_width ; }
2017-05-16 11:45:28 +00:00
// The wipe tower is finished, there should be no more tool changes or wipe tower prints.
2017-05-25 20:27:53 +00:00
virtual bool finished ( ) const { return m_max_color_changes = = 0 ; }
2017-05-16 11:45:28 +00:00
2017-09-01 15:30:18 +00:00
// Returns gcode to prime the nozzles at the front edge of the print bed.
2017-09-12 13:55:38 +00:00
virtual ToolChangeResult prime (
// print_z of the first layer.
float first_layer_height ,
// Extruder indices, in the order to be primed. The last extruder will later print the wipe tower brim, print brim and the object.
2017-12-03 08:43:00 +00:00
const std : : vector < unsigned int > & tools ,
2017-09-12 13:55:38 +00:00
// If true, the last priming are will be the same as the other priming areas, and the rest of the wipe will be performed inside the wipe tower.
// If false, the last priming are will be large enough to wipe the last extruder sufficiently.
2018-03-08 15:44:52 +00:00
bool last_wipe_inside_wipe_tower ) ;
2017-09-01 15:30:18 +00:00
2017-05-17 08:42:39 +00:00
// Returns gcode for a toolchange and a final print head position.
// On the first layer, extrude a brim around the future wipe tower first.
2018-03-08 15:44:52 +00:00
virtual ToolChangeResult tool_change ( unsigned int new_tool , bool last_in_layer ) ;
2017-05-16 11:45:28 +00:00
2018-03-21 14:57:17 +00:00
// Fill the unfilled space with a sparse infill.
2017-05-17 14:45:37 +00:00
// Call this method only if layer_finished() is false.
2018-03-08 15:44:52 +00:00
virtual ToolChangeResult finish_layer ( ) ;
2017-05-17 14:45:37 +00:00
2018-02-22 10:03:29 +00:00
// Is the current layer finished?
2017-12-21 12:28:26 +00:00
virtual bool layer_finished ( ) const {
2018-02-21 12:07:32 +00:00
return ( ( m_is_first_layer ? m_wipe_tower_depth - m_perimeter_width : m_layer_info - > depth ) - WT_EPSILON < m_depth_traversed ) ;
2017-12-21 12:28:26 +00:00
}
2018-09-17 13:12:13 +00:00
virtual std : : vector < float > get_used_filament ( ) const override { return m_used_filament_length ; }
virtual int get_number_of_toolchanges ( ) const override { return m_num_tool_changes ; }
2017-05-16 11:45:28 +00:00
private :
WipeTowerPrusaMM ( ) ;
2018-03-21 14:57:17 +00:00
enum wipe_shape // A fill-in direction
2017-05-16 11:45:28 +00:00
{
2018-02-21 12:07:32 +00:00
SHAPE_NORMAL = 1 ,
2017-05-16 11:45:28 +00:00
SHAPE_REVERSED = - 1
} ;
2018-03-21 14:57:17 +00:00
const bool m_peters_wipe_tower = false ; // sparse wipe tower inspired by Peter's post processor - not finished yet
2018-03-29 13:32:09 +00:00
const float Filament_Area = M_PI * 1.75f * 1.75f / 4.f ; // filament area in mm^2
2018-03-21 14:57:17 +00:00
const float Width_To_Nozzle_Ratio = 1.25f ; // desired line width (oval) in multiples of nozzle diameter - may not be actually neccessary to adjust
const float WT_EPSILON = 1e-3 f ;
2018-02-21 12:07:32 +00:00
xy m_wipe_tower_pos ; // Left front corner of the wipe tower in mm.
float m_wipe_tower_width ; // Width of the wipe tower.
float m_wipe_tower_depth = 0.f ; // Depth of the wipe tower
2018-03-21 14:57:17 +00:00
float m_wipe_tower_rotation_angle = 0.f ; // Wipe tower rotation angle in degrees (with respect to x axis)
2018-07-27 13:56:27 +00:00
float m_internal_rotation = 0.f ;
2018-02-21 12:07:32 +00:00
float m_y_shift = 0.f ; // y shift passed to writer
float m_z_pos = 0.f ; // Current Z position.
float m_layer_height = 0.f ; // Current layer height.
size_t m_max_color_changes = 0 ; // Maximum number of color changes per layer.
bool m_is_first_layer = false ; // Is this the 1st layer of the print? If so, print the brim around the waste tower.
2018-05-11 15:35:42 +00:00
int m_old_temperature = - 1 ; // To keep track of what was the last temp that we set (so we don't issue the command when not neccessary)
2017-05-16 11:45:28 +00:00
// G-code generator parameters.
2018-03-01 15:15:00 +00:00
float m_cooling_tube_retraction = 0.f ;
float m_cooling_tube_length = 0.f ;
float m_parking_pos_retraction = 0.f ;
2018-04-16 12:26:57 +00:00
float m_extra_loading_move = 0.f ;
2018-03-12 14:41:25 +00:00
float m_bridging = 0.f ;
2018-12-14 19:09:10 +00:00
bool m_set_extruder_trimpot = false ;
2018-12-17 09:30:20 +00:00
bool m_retain_speed_override = true ;
2018-03-12 14:41:25 +00:00
bool m_adhesion = true ;
2018-03-05 09:45:35 +00:00
2018-03-29 13:32:09 +00:00
float m_perimeter_width = 0.4 * Width_To_Nozzle_Ratio ; // Width of an extrusion line, also a perimeter spacing for 100% infill.
2018-02-21 12:07:32 +00:00
float m_extrusion_flow = 0.038 ; //0.029f;// Extrusion flow is derived from m_perimeter_width, layer height and filament diameter.
2017-05-16 11:45:28 +00:00
2018-03-05 09:45:35 +00:00
struct FilamentParameters {
2018-03-20 14:45:11 +00:00
material_type material = PLA ;
int temperature = 0 ;
int first_layer_temperature = 0 ;
float loading_speed = 0.f ;
2018-08-21 12:36:24 +00:00
float loading_speed_start = 0.f ;
2018-03-20 14:45:11 +00:00
float unloading_speed = 0.f ;
2018-08-14 14:23:23 +00:00
float unloading_speed_start = 0.f ;
2018-03-20 14:45:11 +00:00
float delay = 0.f ;
2018-04-24 11:02:08 +00:00
int cooling_moves = 0 ;
float cooling_initial_speed = 0.f ;
float cooling_final_speed = 0.f ;
2018-03-20 14:45:11 +00:00
float ramming_line_width_multiplicator = 0.f ;
float ramming_step_multiplicator = 0.f ;
2018-03-15 13:04:12 +00:00
std : : vector < float > ramming_speed ;
2018-03-29 13:32:09 +00:00
float nozzle_diameter ;
2018-03-05 09:45:35 +00:00
} ;
2017-05-16 11:45:28 +00:00
// Extruder specific parameters.
2018-03-20 14:45:11 +00:00
std : : vector < FilamentParameters > m_filpar ;
2018-03-05 09:45:35 +00:00
2017-05-16 11:45:28 +00:00
2018-03-21 14:57:17 +00:00
// State of the wipe tower generator.
2018-02-21 12:07:32 +00:00
unsigned int m_num_layer_changes = 0 ; // Layer change counter for the output statistics.
unsigned int m_num_tool_changes = 0 ; // Tool change change counter for the output statistics.
///unsigned int m_idx_tool_change_in_layer = 0; // Layer change counter in this layer. Counting up to m_max_color_changes.
2017-12-21 12:28:26 +00:00
bool m_print_brim = true ;
2017-05-17 08:42:39 +00:00
// A fill-in direction (positive Y, negative Y) alternates with each layer.
2017-05-16 11:45:28 +00:00
wipe_shape m_current_shape = SHAPE_NORMAL ;
2017-05-25 20:27:53 +00:00
unsigned int m_current_tool = 0 ;
2018-05-24 15:24:37 +00:00
const std : : vector < std : : vector < float > > wipe_volumes ;
2018-02-21 12:07:32 +00:00
2018-03-21 14:57:17 +00:00
float m_depth_traversed = 0.f ; // Current y position at the wipe tower.
bool m_left_to_right = true ;
float m_extra_spacing = 1.f ;
2018-02-22 10:03:29 +00:00
// Calculates extrusion flow needed to produce required line width for given layer height
float extrusion_flow ( float layer_height = - 1.f ) const // negative layer_height - return current m_extrusion_flow
2017-12-21 12:28:26 +00:00
{
if ( layer_height < 0 )
return m_extrusion_flow ;
2018-03-29 13:32:09 +00:00
return layer_height * ( m_perimeter_width - layer_height * ( 1 - M_PI / 4.f ) ) / Filament_Area ;
2017-12-21 12:28:26 +00:00
}
2018-02-22 10:03:29 +00:00
// Calculates length of extrusion line to extrude given volume
2018-02-21 12:07:32 +00:00
float volume_to_length ( float volume , float line_width , float layer_height ) const {
2018-05-24 15:24:37 +00:00
return std : : max ( 0. , volume / ( layer_height * ( line_width - layer_height * ( 1. - M_PI / 4. ) ) ) ) ;
2018-02-21 12:07:32 +00:00
}
2018-03-21 14:57:17 +00:00
// Calculates depth for all layers and propagates them downwards
void plan_tower ( ) ;
// Goes through m_plan and recalculates depths and width of the WT to make it exactly square - experimental
void make_wipe_tower_square ( ) ;
// Goes through m_plan, calculates border and finish_layer extrusions and subtracts them from last wipe
void save_on_last_wipe ( ) ;
2018-02-21 12:07:32 +00:00
2017-05-16 11:45:28 +00:00
struct box_coordinates
{
box_coordinates ( float left , float bottom , float width , float height ) :
ld ( left , bottom ) ,
lu ( left , bottom + height ) ,
rd ( left + width , bottom ) ,
ru ( left + width , bottom + height ) { }
box_coordinates ( const xy & pos , float width , float height ) : box_coordinates ( pos . x , pos . y , width , height ) { }
2017-05-17 14:45:37 +00:00
void translate ( const xy & shift ) {
ld + = shift ; lu + = shift ;
rd + = shift ; ru + = shift ;
}
void translate ( const float dx , const float dy ) { translate ( xy ( dx , dy ) ) ; }
2017-05-16 11:45:28 +00:00
void expand ( const float offset ) {
ld + = xy ( - offset , - offset ) ;
lu + = xy ( - offset , offset ) ;
rd + = xy ( offset , - offset ) ;
ru + = xy ( offset , offset ) ;
}
2017-05-17 14:45:37 +00:00
void expand ( const float offset_x , const float offset_y ) {
ld + = xy ( - offset_x , - offset_y ) ;
lu + = xy ( - offset_x , offset_y ) ;
rd + = xy ( offset_x , - offset_y ) ;
ru + = xy ( offset_x , offset_y ) ;
}
2017-05-16 11:45:28 +00:00
xy ld ; // left down
xy lu ; // left upper
xy rd ; // right lower
2018-02-21 12:07:32 +00:00
xy ru ; // right upper
2017-05-16 11:45:28 +00:00
} ;
2017-12-21 12:28:26 +00:00
// to store information about tool changes for a given layer
struct WipeTowerInfo {
struct ToolChange {
unsigned int old_tool ;
unsigned int new_tool ;
float required_depth ;
2018-03-06 18:14:12 +00:00
float ramming_depth ;
float first_wipe_line ;
2018-05-24 15:24:37 +00:00
float wipe_volume ;
ToolChange ( unsigned int old , unsigned int newtool , float depth = 0.f , float ramming_depth = 0.f , float fwl = 0.f , float wv = 0.f )
: old_tool { old } , new_tool { newtool } , required_depth { depth } , ramming_depth { ramming_depth } , first_wipe_line { fwl } , wipe_volume { wv } { }
2017-12-21 12:28:26 +00:00
} ;
float z ; // z position of the layer
float height ; // layer height
float depth ; // depth of the layer based on all layers above
2018-02-21 12:07:32 +00:00
float extra_spacing ;
2017-12-21 12:28:26 +00:00
float toolchanges_depth ( ) const { float sum = 0.f ; for ( const auto & a : tool_changes ) sum + = a . required_depth ; return sum ; }
std : : vector < ToolChange > tool_changes ;
WipeTowerInfo ( float z_par , float layer_height_par )
2018-02-21 12:07:32 +00:00
: z { z_par } , height { layer_height_par } , depth { 0 } , extra_spacing { 1.f } { }
2017-12-21 12:28:26 +00:00
} ;
2018-02-22 10:03:29 +00:00
std : : vector < WipeTowerInfo > m_plan ; // Stores information about all layers and toolchanges for the future wipe tower (filled by plan_toolchange(...))
2018-03-07 10:44:47 +00:00
std : : vector < WipeTowerInfo > : : iterator m_layer_info = m_plan . end ( ) ;
2017-12-21 12:28:26 +00:00
2018-09-17 13:12:13 +00:00
// Stores information about used filament length per extruder:
std : : vector < float > m_used_filament_length ;
2017-12-21 12:28:26 +00:00
2017-05-16 11:45:28 +00:00
// Returns gcode for wipe tower brim
2017-12-21 12:28:26 +00:00
// sideOnly -- set to false -- experimental, draw brim on sides of wipe tower
2017-05-16 11:45:28 +00:00
// offset -- set to 0 -- experimental, offset to replace brim in front / rear of wipe tower
2018-03-08 15:44:52 +00:00
ToolChangeResult toolchange_Brim ( bool sideOnly = false , float y_offset = 0.f ) ;
2017-05-16 11:45:28 +00:00
void toolchange_Unload (
PrusaMultiMaterial : : Writer & writer ,
const box_coordinates & cleaning_box ,
2017-05-17 14:45:37 +00:00
const material_type current_material ,
const int new_temperature ) ;
2017-05-16 11:45:28 +00:00
void toolchange_Change (
PrusaMultiMaterial : : Writer & writer ,
2017-09-01 15:30:18 +00:00
const unsigned int new_tool ,
2017-05-16 11:45:28 +00:00
material_type new_material ) ;
void toolchange_Load (
PrusaMultiMaterial : : Writer & writer ,
const box_coordinates & cleaning_box ) ;
void toolchange_Wipe (
PrusaMultiMaterial : : Writer & writer ,
2017-09-12 13:55:38 +00:00
const box_coordinates & cleaning_box ,
2018-03-09 11:40:39 +00:00
float wipe_volume ) ;
2017-05-16 11:45:28 +00:00
} ;
2018-02-28 15:04:56 +00:00
2017-05-16 11:45:28 +00:00
} ; // namespace Slic3r
# endif /* WipeTowerPrusaMM_hpp_ */