Added Prusa MultiMaterial Wipe Tower. Now it is time to integrate it
into the G-code generator.
This commit is contained in:
parent
2f57ee60d1
commit
146039f402
3 changed files with 980 additions and 0 deletions
|
@ -430,6 +430,8 @@ src/libslic3r/TriangleMesh.cpp
|
|||
src/libslic3r/TriangleMesh.hpp
|
||||
src/libslic3r/utils.cpp
|
||||
src/libslic3r/Utils.hpp
|
||||
src/libslic3r/WipeTower.cpp
|
||||
src/libslic3r/WipeTower.hpp
|
||||
src/perlglue.cpp
|
||||
src/poly2tri/common/shapes.cc
|
||||
src/poly2tri/common/shapes.h
|
||||
|
|
809
xs/src/libslic3r/WipeTower.cpp
Normal file
809
xs/src/libslic3r/WipeTower.cpp
Normal file
|
@ -0,0 +1,809 @@
|
|||
#include "WipeTower.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define strcasecmp _stricmp
|
||||
#endif
|
||||
|
||||
namespace PrusaSingleExtruderMM
|
||||
{
|
||||
|
||||
static inline std::string line_XY(float x, float y)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "G1 X%.3f Y%.3f\n", x, y);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline std::string line_XYE(float x, float y, float e)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "G1 X%.3f Y%.3f E%.4f\n", x, y, e);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline std::string line_XYF(float x, float y, float f)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "G1 X%.3f Y%.3f F%.0f\n", x, y, f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline std::string line_ZF(float z, float f)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "G1 Z%.3f F%.0f\n", z, f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline std::string line_F(float f)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "G1 F%.0f\n", f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline std::string line_XEF(float x, float e, float f)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "G1 X%.3f E%.4f F%.0f\n", x, e, f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static inline std::string line_EF(float e, float f)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "G1 E%.4f F%.0f\n", e, f);
|
||||
return buf;
|
||||
}
|
||||
|
||||
// Set extruder temperature, don't wait.
|
||||
static inline std::string line_M104(int temperature)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "M104 S%d\n", temperature);
|
||||
return buf;
|
||||
};
|
||||
|
||||
// Set extruder temperature and wait.
|
||||
static inline std::string line_M109(int temperature)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "M109 S%d\n", temperature);
|
||||
buf;
|
||||
};
|
||||
|
||||
// Set maximum feedrate
|
||||
static inline std::string line_M203(int feedrate)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "M203 E%d\n", feedrate);
|
||||
return buf;
|
||||
};
|
||||
|
||||
// Set speed factor override percentage
|
||||
static inline std::string line_M220(int speed)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "M220 S%d\n", speed);
|
||||
return buf;
|
||||
};
|
||||
|
||||
// Set digital trimpot motor
|
||||
static inline std::string line_M907(int current)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "M907 E%d\n", current);
|
||||
return buf;
|
||||
};
|
||||
|
||||
// Dwell for seconds. If delay == 0, this just flushes planner queue.
|
||||
static inline std::string line_G4(int delay)
|
||||
{
|
||||
char buf[128];
|
||||
sprintf(buf, "G4 S%d\n", delay);
|
||||
return buf;
|
||||
};
|
||||
|
||||
// Reset internal extruder counter.
|
||||
static inline std::string line_ResetE()
|
||||
{
|
||||
return "G92 E0.0\n";
|
||||
};
|
||||
|
||||
static inline std::string line_CommentValue(const char *comment, int value)
|
||||
{
|
||||
char strvalue[15];
|
||||
sprintf(strvalue, "%d", value);
|
||||
return std::string(";") + comment + strvalue + "\n";
|
||||
};
|
||||
|
||||
static inline std::string line_CommentMaterial(WipeTower::material_type material)
|
||||
{
|
||||
std::string ret("; material : ");
|
||||
|
||||
switch (material)
|
||||
{
|
||||
case WipeTower::PVA:
|
||||
ret += "#8 (PVA)";
|
||||
break;
|
||||
case WipeTower::SCAFF:
|
||||
ret += "#5 (Scaffold)";
|
||||
break;
|
||||
case WipeTower::FLEX:
|
||||
ret += "#4 (Flex)";
|
||||
break;
|
||||
default:
|
||||
ret += "DEFAULT (PLA)";
|
||||
break;
|
||||
}
|
||||
|
||||
return ret + "\n";
|
||||
};
|
||||
|
||||
static inline int randi(int lo, int hi)
|
||||
{
|
||||
int n = hi - lo + 1;
|
||||
int i = rand() % n;
|
||||
if (i < 0) i = -i;
|
||||
return lo + i;
|
||||
}
|
||||
|
||||
WipeTower::material_type WipeTower::parse_material(const char *name)
|
||||
{
|
||||
if (strcasecmp(name, "PLA") == 0)
|
||||
return PLA;
|
||||
if (strcasecmp(name, "ABS") == 0)
|
||||
return ABS;
|
||||
if (strcasecmp(name, "PET") == 0)
|
||||
return PET;
|
||||
if (strcasecmp(name, "HIPS") == 0)
|
||||
return HIPS;
|
||||
if (strcasecmp(name, "FLEX") == 0)
|
||||
return FLEX;
|
||||
if (strcasecmp(name, "SCAFF") == 0)
|
||||
return SCAFF;
|
||||
if (strcasecmp(name, "EDGE") == 0)
|
||||
return EDGE;
|
||||
if (strcasecmp(name, "NGEN") == 0)
|
||||
return NGEN;
|
||||
if (strcasecmp(name, "PVA") == 0)
|
||||
return PVA;
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
std::string WipeTower::FirstLayer(bool sideOnly, float offset)
|
||||
{
|
||||
float _ext = extrusion_flow + ((extrusion_flow / 100) * 10);
|
||||
|
||||
box_coordinates wipeTower_box(m_wipe_tower_pos, m_wipe_tower_width, m_wipe_area * float(m_color_changes) - perimeterWidth / 2);
|
||||
|
||||
std::string gcode =
|
||||
";-------------------------------------\n"
|
||||
"; CP WIPE TOWER FIRST LAYER BRIM START\n";
|
||||
|
||||
gcode += line_ZF(m_z_pos + zHop, 7200);
|
||||
|
||||
gcode += line_F(6000);
|
||||
gcode += line_XY( wipeTower_box.lu.x - (perimeterWidth * 10), wipeTower_box.lu.y );
|
||||
gcode += line_ZF(m_z_pos, 7200);
|
||||
|
||||
gcode += line_F(2400);
|
||||
gcode += line_XYE(wipeTower_box.ld.x - (perimeterWidth * 10), wipeTower_box.ld.y, retract);
|
||||
|
||||
float _offset = 0;
|
||||
gcode += line_F(2100);
|
||||
int _per = 0;
|
||||
|
||||
if (sideOnly)
|
||||
{
|
||||
do
|
||||
{
|
||||
_offset = _offset + perimeterWidth;
|
||||
gcode += line_XY(wipeTower_box.ld.x - _offset, wipeTower_box.ld.y + offset);
|
||||
gcode += line_XYE(wipeTower_box.lu.x - _offset, wipeTower_box.lu.y - offset, (wipeTower_box.lu.y - wipeTower_box.ld.y) * _ext);
|
||||
_per++;
|
||||
} while (_per < 4);
|
||||
gcode += line_F(7000);
|
||||
gcode += line_XY(wipeTower_box.rd.x + _offset, wipeTower_box.ld.y + offset);
|
||||
gcode += line_F(2100);
|
||||
_per = 0;
|
||||
_offset = 0;
|
||||
do
|
||||
{
|
||||
_offset = _offset + perimeterWidth;
|
||||
gcode += line_XY(wipeTower_box.rd.x + _offset, wipeTower_box.ld.y + offset);
|
||||
gcode += line_XYE(wipeTower_box.ru.x + _offset, wipeTower_box.lu.y - offset, (wipeTower_box.lu.y - wipeTower_box.ld.y) * _ext);
|
||||
_per++;
|
||||
} while (_per < 4);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
_offset = _offset + perimeterWidth;
|
||||
float _ext_X = ((wipeTower_box.rd.x + _offset) - (wipeTower_box.ld.x - _offset))* _ext;
|
||||
float _ext_Y = ((wipeTower_box.lu.y + _offset) - (wipeTower_box.ld.y - _offset))* _ext;
|
||||
|
||||
float __x0 = wipeTower_box.ld.x - _offset + (perimeterWidth / 2);
|
||||
float __y0 = wipeTower_box.ld.y - _offset + perimeterWidth;
|
||||
gcode += line_XY(__x0, __y0);
|
||||
|
||||
float __x1 = wipeTower_box.lu.x - _offset + (perimeterWidth / 2);
|
||||
float __y1 = wipeTower_box.lu.y + _offset;
|
||||
gcode += line_XYE(__x1, __y1, _ext_Y);
|
||||
|
||||
float __x2 = wipeTower_box.ru.x + _offset - (perimeterWidth / 2);
|
||||
float __y2 = wipeTower_box.ru.y + _offset;
|
||||
gcode += line_XYE(__x2, __y2, _ext_X);
|
||||
|
||||
float __x3 = wipeTower_box.rd.x + _offset - (perimeterWidth / 2);
|
||||
float __y3 = wipeTower_box.rd.y - _offset + perimeterWidth;
|
||||
gcode += line_XYE(__x3, __y3, _ext_Y);
|
||||
|
||||
float __x4 = wipeTower_box.ld.x - _offset + (perimeterWidth / 2);
|
||||
float __y4 = wipeTower_box.ld.y - _offset + perimeterWidth;
|
||||
gcode += line_XYE(__x4, __y4, _ext_X);
|
||||
_per++;
|
||||
|
||||
} while (_per < 4);
|
||||
|
||||
|
||||
}
|
||||
|
||||
gcode += line_F(7000);
|
||||
gcode += line_XY(wipeTower_box.ld.x, wipeTower_box.ld.y);
|
||||
gcode += line_XY(wipeTower_box.rd.x, wipeTower_box.ld.y);
|
||||
gcode += line_XY(wipeTower_box.ld.x, wipeTower_box.ld.y);
|
||||
|
||||
gcode += "; CP WIPE TOWER FIRST LAYER BRIM END\n";
|
||||
gcode += ";-----------------------------------\n";
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::pair<std::string, WipeTower::xy> WipeTower::Toolchange(int tool, material_type current_material, material_type new_material, int temperature, wipe_shape shape, int count, float spaceAvailable, float wipeStartY, bool lastInFile, bool colorInit)
|
||||
{
|
||||
box_coordinates cleaning_box(
|
||||
m_wipe_tower_pos.x,
|
||||
m_wipe_tower_pos.y + wipeStartY, //(order * _wipe_area); //wipeStartY;
|
||||
m_wipe_tower_width,
|
||||
spaceAvailable - perimeterWidth / 2); //space_available //wipe_area
|
||||
|
||||
std::string gcode;
|
||||
gcode += ";--------------------\n";
|
||||
gcode += "; CP TOOLCHANGE START\n";
|
||||
gcode += line_CommentValue(" toolchange #", count);
|
||||
gcode += line_CommentMaterial(current_material);
|
||||
gcode += ";--------------------\n";
|
||||
|
||||
gcode += line_M220(100);
|
||||
gcode += line_ZF(m_z_pos + zHop, 7200);
|
||||
|
||||
gcode += line_EF((retract/2)*-1, 3600); // additional retract on move to tower
|
||||
gcode += line_XYF(cleaning_box.ld.x + perimeterWidth, cleaning_box.ld.y + shape * perimeterWidth, 7200);
|
||||
gcode += line_ZF(m_z_pos, 7200);
|
||||
gcode += line_EF((retract / 2), 3600); // additional retract on move to tower
|
||||
gcode += line_EF((retract), 1500);
|
||||
|
||||
m_y_position = (shape == NORMAL) ? cleaning_box.ld.y : cleaning_box.lu.y;
|
||||
|
||||
gcode += line_M907(750);
|
||||
gcode += line_G4(0);
|
||||
|
||||
gcode += toolchange_Unload(cleaning_box, current_material, shape, temperature);
|
||||
|
||||
if (!lastInFile)
|
||||
{
|
||||
gcode += toolchange_Change(tool, current_material, new_material);
|
||||
gcode += toolchange_Load(cleaning_box, current_material, shape, colorInit);
|
||||
gcode += toolchange_Wipe(cleaning_box, current_material, shape);
|
||||
gcode += toolchange_Done(cleaning_box, current_material, shape);
|
||||
}
|
||||
|
||||
gcode += line_M907(550);
|
||||
gcode += line_G4(0);
|
||||
gcode += line_ResetE();
|
||||
|
||||
gcode += "; CP TOOLCHANGE END\n"
|
||||
";------------------\n"
|
||||
"\n\n";
|
||||
return std::pair<std::string, xy>(gcode, (shape == NORMAL) ? cleaning_box.lu : cleaning_box.ld);
|
||||
}
|
||||
|
||||
std::string WipeTower::toolchange_Unload(const box_coordinates &cleaning_box, material_type material, wipe_shape shape, int temperature)
|
||||
{
|
||||
float __xl = 0;
|
||||
float __xr = 0;
|
||||
__xl = cleaning_box.ld.x + (perimeterWidth / 2);
|
||||
__xr = cleaning_box.rd.x - (perimeterWidth / 2);
|
||||
|
||||
std::string gcode = "; CP TOOLCHANGE UNLOAD";
|
||||
|
||||
switch (material)
|
||||
{
|
||||
case PVA:
|
||||
|
||||
gcode += line_F(4000);
|
||||
m_y_position += shape * perimeterWidth * 1.2f;
|
||||
gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0);
|
||||
gcode += line_XYE(__xr - perimeterWidth, m_y_position, 3);
|
||||
|
||||
gcode += line_F(4500);
|
||||
m_y_position += shape * perimeterWidth * 1.5f;
|
||||
gcode += line_XYE(__xr - perimeterWidth, m_y_position, 0);
|
||||
gcode += line_XYE(__xl + perimeterWidth, m_y_position, 3);
|
||||
|
||||
gcode += line_F(4800);
|
||||
m_y_position += shape * perimeterWidth * 1.5f;
|
||||
gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0);
|
||||
gcode += line_XYE(__xr - (perimeterWidth * 2), m_y_position, 3);
|
||||
|
||||
gcode += line_F(5000);
|
||||
m_y_position += shape * perimeterWidth * 1.5f;
|
||||
gcode += line_XYE(__xr - perimeterWidth, m_y_position, 0);
|
||||
gcode += line_XYE(__xl + perimeterWidth, m_y_position, 3);
|
||||
|
||||
gcode += line_EF(-15, 5000);
|
||||
gcode += line_EF(-50, 5400);
|
||||
gcode += line_EF(-15, 3000);
|
||||
gcode += line_EF(-12, 2000);
|
||||
|
||||
|
||||
if (temperature != 0)
|
||||
{
|
||||
gcode += line_M104(temperature);
|
||||
}
|
||||
|
||||
// cooling moves
|
||||
m_y_position += shape * perimeterWidth * 0.8f;
|
||||
|
||||
gcode += line_F(1600);
|
||||
gcode += line_XYE(__xl, m_y_position, 3);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2000);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2200);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2400);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2400);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2400);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -3);
|
||||
|
||||
gcode += line_G4(0);
|
||||
|
||||
break; // end of SCAFF
|
||||
|
||||
|
||||
case SCAFF:
|
||||
|
||||
gcode += line_F(4000);
|
||||
m_y_position += shape * perimeterWidth * 3.f;
|
||||
gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0);
|
||||
gcode += line_XYE(__xr - perimeterWidth, m_y_position, 3);
|
||||
|
||||
gcode += line_F(4600);
|
||||
m_y_position += shape * perimeterWidth * 3.f;
|
||||
gcode += line_XYE(__xr - perimeterWidth, m_y_position, 0);
|
||||
gcode += line_XYE(__xl + perimeterWidth, m_y_position, 4);
|
||||
|
||||
gcode += line_F(5200);
|
||||
m_y_position += shape * perimeterWidth * 3.f;
|
||||
gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0);
|
||||
gcode += line_XYE(__xr - (perimeterWidth * 2), m_y_position, 4.5);
|
||||
|
||||
gcode += line_EF(-15, 5000);
|
||||
gcode += line_EF(-50, 5400);
|
||||
gcode += line_EF(-15, 3000);
|
||||
gcode += line_EF(-12, 2000);
|
||||
|
||||
|
||||
if (temperature != 0)
|
||||
{
|
||||
gcode += line_M104(temperature);
|
||||
}
|
||||
|
||||
// cooling moves
|
||||
m_y_position += shape * perimeterWidth * 0.8f;
|
||||
|
||||
gcode += line_F(1600);
|
||||
gcode += line_XYE(__xl, m_y_position, 3);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2000);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2200);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2200);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2400);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -3);
|
||||
|
||||
gcode += line_G4(0);
|
||||
|
||||
break; // end of SCAFF
|
||||
|
||||
|
||||
default:
|
||||
|
||||
gcode += line_F(4000);
|
||||
m_y_position += shape * perimeterWidth * 1.2f;
|
||||
gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, 0);
|
||||
gcode += line_XYE(__xr - perimeterWidth, m_y_position, (__xr - __xl) * (extrusion_flow*(float)1.6));
|
||||
|
||||
gcode += line_F(4600);
|
||||
m_y_position += shape * perimeterWidth * 1.2f;
|
||||
gcode += line_XYE(__xr - perimeterWidth, m_y_position, perimeterWidth*extrusion_flow);
|
||||
gcode += line_XYE(__xl + perimeterWidth, m_y_position, (__xr - __xl) * (extrusion_flow*(float)1.65));
|
||||
|
||||
gcode += line_F(5200);
|
||||
m_y_position += shape * perimeterWidth * 1.2f; //1.4f
|
||||
gcode += line_XYE(__xl + (perimeterWidth * 2), m_y_position, perimeterWidth*extrusion_flow);
|
||||
gcode += line_XYE(__xr - (perimeterWidth * 2), m_y_position, (__xr - __xl) * (extrusion_flow*(float)1.74));
|
||||
|
||||
gcode += line_EF(-15, 5000);
|
||||
gcode += line_EF(-50, 5400);
|
||||
gcode += line_EF(-15, 3000);
|
||||
gcode += line_EF(-12, 2000);
|
||||
|
||||
|
||||
if (temperature != 0)
|
||||
{
|
||||
gcode += line_M104(temperature);
|
||||
}
|
||||
|
||||
// cooling moves
|
||||
m_y_position += shape * perimeterWidth * 0.8f;
|
||||
|
||||
gcode += line_F(1600);
|
||||
gcode += line_XYE(__xl, m_y_position, 3);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2000);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2400);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -5);
|
||||
|
||||
gcode += line_F(2400);
|
||||
gcode += line_XYE(__xl, m_y_position, 5);
|
||||
gcode += line_XYE(__xr, m_y_position, -3);
|
||||
|
||||
gcode += line_G4(0);
|
||||
|
||||
break; // end of default material
|
||||
}
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string WipeTower::toolchange_Load(const box_coordinates &cleaning_box, material_type material, wipe_shape shape, bool colorInit)
|
||||
{
|
||||
float __xl = 0;
|
||||
float __xr = 0;
|
||||
|
||||
std::string gcode = "; CP TOOLCHANGE LOAD\n";
|
||||
|
||||
switch (material)
|
||||
{
|
||||
default:
|
||||
|
||||
__xl = cleaning_box.ld.x + (perimeterWidth * 1);
|
||||
__xr = cleaning_box.rd.x - (perimeterWidth * 1);
|
||||
float _extrusion = (__xr - __xl) * extrusion_flow;
|
||||
|
||||
gcode += line_XEF(__xr, 20, 1400);
|
||||
gcode += line_XEF(__xl, 40, 3000);
|
||||
gcode += line_XEF(__xr, 20, 1600);
|
||||
gcode += line_XEF(__xl, 10, 1000);
|
||||
|
||||
gcode += line_F(1600);
|
||||
gcode += line_XYE(__xr, m_y_position, _extrusion);
|
||||
|
||||
gcode += line_F(2200);
|
||||
|
||||
int _pass = 2;
|
||||
if (colorInit) _pass = 1;
|
||||
|
||||
for (int _i = 0; _i < _pass; _i++)
|
||||
{
|
||||
m_y_position += shape * perimeterWidth * 0.85f;
|
||||
gcode += line_XY(__xr, m_y_position);
|
||||
gcode += line_XYE(__xl, m_y_position, _extrusion);
|
||||
|
||||
m_y_position += shape * perimeterWidth * 0.85f;
|
||||
gcode += line_XY(__xl, m_y_position);
|
||||
gcode += line_XYE(__xr, m_y_position, _extrusion);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
gcode += line_M907(550);
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string WipeTower::toolchange_Wipe(const box_coordinates &cleaning_box, material_type material, wipe_shape shape)
|
||||
{
|
||||
// wipe new filament until end of wipe area
|
||||
float __xl = 0;
|
||||
float __xr = 0;
|
||||
int __p = 0;
|
||||
float _wipespeed = 4200;
|
||||
float _extr = extrusion_flow;
|
||||
float _wipekoef = 1;
|
||||
|
||||
std::string gcode = "; CP TOOLCHANGE WIPE\n";
|
||||
|
||||
// increase flow on first layer, slow down print
|
||||
if (int(m_z_pos * 100) < 21)
|
||||
{
|
||||
_extr = extrusion_flow + ((extrusion_flow / 100) * 18);
|
||||
_wipekoef = (float)0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
_extr = extrusion_flow;
|
||||
_wipekoef = (float)1;
|
||||
}
|
||||
|
||||
switch (material)
|
||||
{
|
||||
|
||||
default:
|
||||
|
||||
__xl = cleaning_box.ld.x + (perimeterWidth*2);
|
||||
__xr = cleaning_box.rd.x - (perimeterWidth*2);
|
||||
|
||||
switch (shape)
|
||||
{
|
||||
case NORMAL:
|
||||
do
|
||||
{
|
||||
__p++;
|
||||
_wipespeed = _wipespeed + 50;
|
||||
if (_wipespeed > 4800) { _wipespeed = 4800; }
|
||||
gcode += line_F(_wipespeed * _wipekoef);
|
||||
m_y_position += shape * perimeterWidth * 0.7f;
|
||||
if (__p < 2)
|
||||
{
|
||||
gcode += line_XYE(__xl - (perimeterWidth/2), m_y_position, perimeterWidth * _extr);
|
||||
gcode += line_XYE(__xr + (perimeterWidth), m_y_position, (__xr - __xl) * _extr);
|
||||
}
|
||||
else
|
||||
{
|
||||
gcode += line_XYE(__xl-(perimeterWidth), m_y_position, perimeterWidth * _extr);
|
||||
gcode += line_XYE(__xr+(perimeterWidth*2), m_y_position, (__xr - __xl) * _extr);
|
||||
__p = 0;
|
||||
}
|
||||
_wipespeed = _wipespeed + 50;
|
||||
if (_wipespeed > 4800) { _wipespeed = 4800; }
|
||||
gcode += line_F(_wipespeed * _wipekoef);
|
||||
m_y_position += shape * perimeterWidth * 0.7f;
|
||||
gcode += line_XYE(__xr + (perimeterWidth), m_y_position, perimeterWidth * _extr);
|
||||
gcode += line_XYE(__xl - (perimeterWidth), m_y_position, (__xr - __xl) * _extr);
|
||||
|
||||
} while (m_y_position <= cleaning_box.lu.y - (perimeterWidth*1));
|
||||
break;
|
||||
|
||||
case REVERSED:
|
||||
do
|
||||
{
|
||||
__p++;
|
||||
_wipespeed = _wipespeed + 50;
|
||||
if (_wipespeed > 4900) { _wipespeed = 4900; }
|
||||
gcode += line_F(_wipespeed * _wipekoef);
|
||||
m_y_position += shape * perimeterWidth * 0.7f;
|
||||
if (__p < 2)
|
||||
{
|
||||
gcode += line_XYE(__xl - (perimeterWidth/2), m_y_position, perimeterWidth * _extr);
|
||||
gcode += line_XYE(__xr + (perimeterWidth), m_y_position, (__xr - __xl) * _extr);
|
||||
}
|
||||
else
|
||||
{
|
||||
gcode += line_XYE(__xl - (perimeterWidth), m_y_position, perimeterWidth * _extr);
|
||||
gcode += line_XYE(__xr + (perimeterWidth *2), m_y_position, (__xr - __xl) * _extr);
|
||||
__p = 0;
|
||||
|
||||
}
|
||||
_wipespeed = _wipespeed + 50;
|
||||
if (_wipespeed > 4900) { _wipespeed = 4900; }
|
||||
gcode += line_F(_wipespeed * _wipekoef);
|
||||
m_y_position += shape * perimeterWidth * 0.7f;
|
||||
gcode += line_XYE(__xr + (perimeterWidth), m_y_position, perimeterWidth * _extr);
|
||||
gcode += line_XYE(__xl - (perimeterWidth), m_y_position, (__xr - __xl) * _extr);
|
||||
|
||||
} while (m_y_position >= cleaning_box.ld.y + (perimeterWidth*1 ));
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string WipeTower::toolchange_Done(const box_coordinates &cleaning_box, material_type /* material */, wipe_shape shape)
|
||||
{
|
||||
std::string gcode;
|
||||
|
||||
switch (shape)
|
||||
{
|
||||
case NORMAL:
|
||||
gcode += line_F(7000);
|
||||
gcode += line_XY(cleaning_box.lu.x, cleaning_box.lu.y);
|
||||
gcode += line_F(3200);
|
||||
gcode += line_XYE(cleaning_box.ld.x, cleaning_box.ld.y, (cleaning_box.lu.y - cleaning_box.ld.y)*(extrusion_flow ));
|
||||
gcode += line_XYE(cleaning_box.rd.x, cleaning_box.rd.y, (cleaning_box.rd.x - cleaning_box.ld.x)*(extrusion_flow ));
|
||||
gcode += line_XYE(cleaning_box.ru.x, cleaning_box.lu.y, (cleaning_box.lu.y - cleaning_box.ld.y)*(extrusion_flow ));
|
||||
gcode += line_XYE(cleaning_box.lu.x, cleaning_box.lu.y, (cleaning_box.rd.x - cleaning_box.ld.x)*(extrusion_flow ));
|
||||
|
||||
gcode += line_F(7200);
|
||||
gcode += line_XY(cleaning_box.ru.x, cleaning_box.lu.y);
|
||||
gcode += line_XY(cleaning_box.lu.x, cleaning_box.lu.y);
|
||||
|
||||
|
||||
gcode += line_F(6000);
|
||||
break;
|
||||
|
||||
case REVERSED:
|
||||
gcode += line_F(7000);
|
||||
gcode += line_XY(cleaning_box.ld.x , cleaning_box.ld.y );
|
||||
gcode += line_F(3200);
|
||||
gcode += line_XYE(cleaning_box.rd.x , cleaning_box.rd.y, (cleaning_box.rd.x - cleaning_box.ld.x)*(extrusion_flow ));
|
||||
gcode += line_XYE(cleaning_box.ru.x , cleaning_box.ru.y, (cleaning_box.ru.y - cleaning_box.rd.y)*(extrusion_flow ));
|
||||
gcode += line_XYE(cleaning_box.lu.x , cleaning_box.lu.y, (cleaning_box.ru.x - cleaning_box.lu.x)*(extrusion_flow ));
|
||||
gcode += line_XYE(cleaning_box.ld.x, cleaning_box.ld.y, (cleaning_box.lu.y - cleaning_box.ld.y)*(extrusion_flow ));
|
||||
|
||||
gcode += line_F(7200);
|
||||
gcode += line_XY(cleaning_box.rd.x, cleaning_box.ld.y);
|
||||
gcode += line_XY(cleaning_box.ld.x, cleaning_box.ld.y);
|
||||
|
||||
gcode += line_F(6000);
|
||||
break;
|
||||
}
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string WipeTower::toolchange_Change(int tool, material_type /* current_material */, material_type new_material)
|
||||
{
|
||||
assert(tool >= 0 && tool < 4);
|
||||
std::string gcode("T0\n");
|
||||
gcode[1] += char(tool);
|
||||
|
||||
switch (new_material)
|
||||
{
|
||||
case PVA:
|
||||
gcode += line_M220(80);
|
||||
gcode += line_G4(0);
|
||||
break;
|
||||
case SCAFF:
|
||||
gcode += line_M220(35);
|
||||
gcode += line_G4(0);
|
||||
break;
|
||||
case FLEX:
|
||||
gcode += line_M220(35);
|
||||
gcode += line_G4(0);
|
||||
break;
|
||||
default:
|
||||
gcode += line_M220(100);
|
||||
gcode += line_G4(0);
|
||||
break;
|
||||
}
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
std::string WipeTower::Perimeter(int order, int total, int Layer, bool afterToolchange, int firstLayerOffset)
|
||||
{
|
||||
float _speed = 1.f;
|
||||
|
||||
std::string gcode =
|
||||
";--------------------\n"
|
||||
"; CP EMPTY GRID START\n";
|
||||
gcode += line_CommentValue(" layer #", Layer);
|
||||
|
||||
if (Layer == 20)
|
||||
_speed = 2.f;
|
||||
|
||||
box_coordinates _p = _boxForColor(order);
|
||||
box_coordinates _to = _boxForColor(total);
|
||||
_p.ld.y += firstLayerOffset;
|
||||
_p.rd.y += firstLayerOffset;
|
||||
|
||||
_p.lu = _to.lu; _p.ru = _to.ru;
|
||||
|
||||
|
||||
if (!afterToolchange)
|
||||
{
|
||||
gcode += line_EF(retract*(float)-1.5, 3600);
|
||||
gcode += line_ZF(m_z_pos + zHop, 7200);
|
||||
gcode += line_XYF(_p.ld.x + randi(5, 20), _p.ld.y, 7000);
|
||||
gcode += line_ZF(m_z_pos, 7200);
|
||||
gcode += line_XEF(_p.ld.x, retract*(float)1.5, 3600);
|
||||
}
|
||||
|
||||
gcode += line_F(2400 / _speed);
|
||||
gcode += line_XYE(_p.lu.x, _p.ru.y, (_p.ru.y - _p.ld.y) * extrusion_flow);
|
||||
gcode += line_XYE(_p.ru.x, _p.ru.y, (_p.ru.x - _p.lu.x) * extrusion_flow);
|
||||
gcode += line_XYE(_p.rd.x, _p.rd.y, (_p.ru.y - _p.ld.y) * extrusion_flow);
|
||||
gcode += line_XYE(_p.ld.x + (perimeterWidth / 2), _p.ld.y, (_p.ru.x - _p.lu.x) * extrusion_flow);
|
||||
|
||||
gcode += line_F(3200 / _speed);
|
||||
gcode += line_XYE(_p.lu.x + (perimeterWidth / 2), _p.lu.y - (perimeterWidth / 2), (_p.ru.y - _p.ld.y) * extrusion_flow);
|
||||
gcode += line_XYE(_p.ru.x - (perimeterWidth / 2), _p.ru.y - (perimeterWidth / 2), (_p.ru.x - _p.lu.x) * extrusion_flow);
|
||||
gcode += line_XYE(_p.rd.x - (perimeterWidth / 2), _p.rd.y + (perimeterWidth / 2), (_p.ru.y - _p.ld.y) * extrusion_flow);
|
||||
gcode += line_XYE(_p.ld.x + perimeterWidth, _p.ld.y + (perimeterWidth / 2), (_p.ru.x - _p.lu.x) * extrusion_flow);
|
||||
gcode += line_XYE(_p.ld.x + perimeterWidth, _p.ld.y + perimeterWidth, perimeterWidth * extrusion_flow);
|
||||
|
||||
gcode += line_F(2900 / _speed);
|
||||
gcode += line_XYE(_p.ld.x + (perimeterWidth * 3), _p.ld.y + perimeterWidth, (perimeterWidth * 3) * extrusion_flow);
|
||||
gcode += line_XYE(_p.lu.x + (perimeterWidth * 3), _p.lu.y - perimeterWidth, (_p.ru.y - _p.ld.y) * extrusion_flow);
|
||||
gcode += line_XYE(_p.lu.x + (perimeterWidth * 6), _p.lu.y - perimeterWidth, (perimeterWidth * 3) * extrusion_flow);
|
||||
gcode += line_XYE(_p.ld.x + (perimeterWidth * 6), _p.ld.y + perimeterWidth, (_p.ru.y - _p.ld.y) * extrusion_flow);
|
||||
|
||||
if (_p.lu.y - _p.ld.y > 4)
|
||||
{
|
||||
gcode += line_F(3200 / _speed);
|
||||
float _step = (m_wipe_tower_width - (perimeterWidth * 12)) / 3;
|
||||
float _sx = 0;
|
||||
for (int _s = 0; _s < 3; _s++)
|
||||
{
|
||||
float _ext = ((_p.ru.y - _p.ld.y) / 3)*(extrusion_flow*(float)1.5);
|
||||
_sx = _sx + (_step / 2);
|
||||
gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + (_step / 4) + (_step * _s), _p.ld.y + (perimeterWidth * 8), _ext);
|
||||
gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + (_step / 4) + (_step * _s), _p.lu.y - (perimeterWidth * 8), _ext);
|
||||
gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + ((_step / 4) * 2) + (_step * _s), _p.lu.y - perimeterWidth, _ext);
|
||||
gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + ((_step / 4) * 3) + (_step * _s), _p.lu.y - (perimeterWidth * 8), _ext);
|
||||
gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + ((_step / 4) * 3) + (_step * _s), _p.ld.y + (perimeterWidth * 8), _ext);
|
||||
gcode += line_XYE(_p.ld.x + (perimeterWidth * 6) + (_step)+(_step * _s), _p.ld.y + perimeterWidth, _ext);
|
||||
}
|
||||
}
|
||||
|
||||
gcode += line_F(2900 / _speed);
|
||||
gcode += line_XYE(_p.ru.x - (perimeterWidth * 6), _p.ru.y - perimeterWidth, (_p.ru.y - _p.ld.y) * extrusion_flow);
|
||||
gcode += line_XYE(_p.ru.x - (perimeterWidth * 3), _p.ru.y - perimeterWidth, (perimeterWidth * 3) * extrusion_flow);
|
||||
gcode += line_XYE(_p.rd.x - (perimeterWidth * 3), _p.rd.y + perimeterWidth, (_p.ru.y - _p.ld.y) * extrusion_flow);
|
||||
gcode += line_XYE(_p.rd.x - perimeterWidth, _p.rd.y + perimeterWidth, perimeterWidth * extrusion_flow);
|
||||
|
||||
gcode += line_F(7200);
|
||||
gcode += line_XY(_p.ld.x + perimeterWidth, _p.rd.y + (perimeterWidth / 2));
|
||||
gcode += line_XY(_p.rd.x - perimeterWidth, _p.ld.y + (perimeterWidth / 2));
|
||||
|
||||
gcode += "; CP EMPTY GRID END\n"
|
||||
";------------------\n\n\n\n\n\n\n";
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
WipeTower::box_coordinates WipeTower::_boxForColor(int order) const
|
||||
{
|
||||
return box_coordinates(m_wipe_tower_pos.x, m_wipe_tower_pos.y + m_wipe_area * order - perimeterWidth / 2, m_wipe_tower_width, perimeterWidth);
|
||||
}
|
||||
|
||||
}; // namespace PrusaSingleExtruderMM
|
169
xs/src/libslic3r/WipeTower.hpp
Normal file
169
xs/src/libslic3r/WipeTower.hpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
#ifndef PrusaSingleExtruderMM_WipeTower_hpp_
|
||||
#define PrusaSingleExtruderMM_WipeTower_hpp_
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
namespace PrusaSingleExtruderMM
|
||||
{
|
||||
|
||||
class 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
|
||||
};
|
||||
|
||||
enum wipe_shape
|
||||
{
|
||||
NORMAL = 1,
|
||||
REVERSED = -1
|
||||
};
|
||||
|
||||
struct xy
|
||||
{
|
||||
xy(float x = 0.f, float y = 0.f) : x(x), y(y) {}
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
// Parse material name into material_type.
|
||||
static material_type parse_material(const char *name);
|
||||
|
||||
// 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
|
||||
// colors -- maximum colors for object
|
||||
WipeTower(float x, float y, float width, float wipe_area, int color_changes) :
|
||||
m_wipe_tower_pos(x, y),
|
||||
m_wipe_tower_width(width),
|
||||
m_wipe_area(wipe_area),
|
||||
m_color_changes(color_changes),
|
||||
m_z_pos(0.f) {}
|
||||
|
||||
// colors -- maximum color changes for layer
|
||||
void setColors(int colors) { m_color_changes = colors; }
|
||||
|
||||
// Z height -- mm
|
||||
void setZ(float z) { m_z_pos = z; }
|
||||
|
||||
// _retract - retract value in mm
|
||||
void setRetract(float _retract) { retract = _retract; }
|
||||
|
||||
// _zHop - z hop value in mm
|
||||
void setZHop(float _zhop) { zHop = _zhop; }
|
||||
|
||||
void setExtrusion(int layerHeight)
|
||||
{
|
||||
// set extrusion coefficient for layer height
|
||||
// layerHeight -- mm * 100
|
||||
|
||||
switch (layerHeight)
|
||||
{
|
||||
case 15:
|
||||
extrusion_flow = (float)0.024;
|
||||
break;
|
||||
case 20:
|
||||
extrusion_flow = (float)0.029;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Returns gcode for wipe tower brim
|
||||
|
||||
sideOnly -- set to false -- experimental, draw brim on sides of wipe tower
|
||||
offset -- set to 0 -- experimental, offset to replace brim in front / rear of wipe tower
|
||||
*/
|
||||
std::string FirstLayer(bool sideOnly, float offset);
|
||||
|
||||
/*
|
||||
Returns gcode for toolchange
|
||||
|
||||
tool -- extruder # 0 - 3
|
||||
current_material -- filament type currently used to print and loaded in nozzle -- see enum material_type
|
||||
new_material -- filament type that will be loaded in to the nozzle -- see enum material_type
|
||||
temperature -- temperature in Celsius for new filament that will be loaded into the nozzle
|
||||
shape -- orientation of purge / wipe shape -- 0 = normal, 1 = reversed -- enum wipe_shape
|
||||
count -- total toolchanges done counter ( comment in header of toolchange only )
|
||||
spaceAvailable -- space available for toolchange ( purge / load / wipe ) - in mm
|
||||
wipeStartY -- experimental, don't use, set to 0
|
||||
lastInFile -- for last toolchange in object set to true to unload filament into cooling tube, for all other set to false
|
||||
colorInit -- experimental, set to 0
|
||||
*/
|
||||
std::pair<std::string, WipeTower::xy> Toolchange(
|
||||
int tool, material_type current_material, material_type new_material, int temperature, wipe_shape shape,
|
||||
int count, float spaceAvailable, float wipeStartY, bool lastInFile, bool colorInit);
|
||||
|
||||
/*
|
||||
Returns gcode to draw empty pattern in place of a toolchange -> in case there are less toolchanges atm then what is required later
|
||||
|
||||
order -- total toolchanges done for current layer
|
||||
total -- total colors in current z layer including empty ones
|
||||
layer -- Z height in mm * 100 ( slows down print for first layer )
|
||||
afterToolchange -- true - ignore some not neccesary moves | false - do whole move from object to wipe tower
|
||||
firstLayerOffset -- experimental , set to 0
|
||||
*/
|
||||
std::string Perimeter(int order, int total, int layer, bool afterToolchange, int firstLayerOffset);
|
||||
|
||||
private:
|
||||
WipeTower();
|
||||
|
||||
// Left front corner of the wipe tower in mm.
|
||||
xy m_wipe_tower_pos;
|
||||
// Width of the wipe tower.
|
||||
float m_wipe_tower_width;
|
||||
// Per color Y span.
|
||||
float m_wipe_area;
|
||||
// Current Z position.
|
||||
float m_z_pos;
|
||||
// Maximum number of color changes per layer.
|
||||
int m_color_changes;
|
||||
// Current y position at the wipe tower.
|
||||
float m_y_position;
|
||||
|
||||
float zHop = 0.5f;
|
||||
float retract = 4.f;
|
||||
float perimeterWidth = 0.5f;
|
||||
float extrusion_flow = 0.029f;
|
||||
|
||||
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) {}
|
||||
xy ld; // left down
|
||||
xy lu; // left upper
|
||||
xy ru; // right upper
|
||||
xy rd; // right lower
|
||||
};
|
||||
|
||||
std::string toolchange_Unload(const box_coordinates &cleaning_box, material_type material, wipe_shape shape, int temperature);
|
||||
std::string toolchange_Change(int tool, material_type current_material, material_type new_material);
|
||||
std::string toolchange_Load(const box_coordinates &cleaning_box, material_type material, wipe_shape shape, bool colorInit);
|
||||
std::string toolchange_Wipe(const box_coordinates &cleaning_box, material_type material, wipe_shape shape);
|
||||
std::string toolchange_Done(const box_coordinates &cleaning_box, material_type material, wipe_shape shape);
|
||||
|
||||
box_coordinates _boxForColor(int order) const;
|
||||
};
|
||||
|
||||
}; // namespace PrusaSingleExtruderMM
|
||||
|
||||
#endif /* PrusaSingleExtruderMM_WipeTower_hpp_ */
|
Loading…
Reference in a new issue