The last priming area is shortened and the excess wipe is moved

into the wipe tower if there is enough space inside the wipe tower.
This commit is contained in:
bubnikv 2017-09-12 15:55:38 +02:00
parent 6d4ec5c989
commit b08d6f1969
8 changed files with 115 additions and 39 deletions

View File

@ -125,15 +125,17 @@ template void BoundingBoxBase<Pointf>::merge(const Pointfs &points);
template <class PointClass> void template <class PointClass> void
BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb) BoundingBoxBase<PointClass>::merge(const BoundingBoxBase<PointClass> &bb)
{ {
if (this->defined) { if (bb.defined) {
this->min.x = std::min(bb.min.x, this->min.x); if (this->defined) {
this->min.y = std::min(bb.min.y, this->min.y); this->min.x = std::min(bb.min.x, this->min.x);
this->max.x = std::max(bb.max.x, this->max.x); this->min.y = std::min(bb.min.y, this->min.y);
this->max.y = std::max(bb.max.y, this->max.y); this->max.x = std::max(bb.max.x, this->max.x);
} else { this->max.y = std::max(bb.max.y, this->max.y);
this->min = bb.min; } else {
this->max = bb.max; this->min = bb.min;
this->defined = true; this->max = bb.max;
this->defined = true;
}
} }
} }
template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb); template void BoundingBoxBase<Point>::merge(const BoundingBoxBase<Point> &bb);
@ -160,11 +162,13 @@ template void BoundingBox3Base<Pointf3>::merge(const Pointf3s &points);
template <class PointClass> void template <class PointClass> void
BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb) BoundingBox3Base<PointClass>::merge(const BoundingBox3Base<PointClass> &bb)
{ {
if (this->defined) { if (bb.defined) {
this->min.z = std::min(bb.min.z, this->min.z); if (this->defined) {
this->max.z = std::max(bb.max.z, this->max.z); this->min.z = std::min(bb.min.z, this->min.z);
this->max.z = std::max(bb.max.z, this->max.z);
}
BoundingBoxBase<PointClass>::merge(bb);
} }
BoundingBoxBase<PointClass>::merge(bb);
} }
template void BoundingBox3Base<Pointf3>::merge(const BoundingBox3Base<Pointf3> &bb); template void BoundingBox3Base<Pointf3>::merge(const BoundingBox3Base<Pointf3> &bb);

View File

@ -700,15 +700,17 @@ bool GCode::_do_export(Print &print, FILE *file)
BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print)); BoundingBoxf bbox_prime(get_wipe_tower_priming_extrusions_extents(print));
bbox_prime.offset(0.5f); bbox_prime.offset(0.5f);
// Beep for 500ms, tone 800Hz. Yet better, play some Morse. // Beep for 500ms, tone 800Hz. Yet better, play some Morse.
write(file, this->retract());
fprintf(file, "M300 S800 P500\n"); fprintf(file, "M300 S800 P500\n");
if (bbox_prime.overlap(bbox_print)) { if (bbox_prime.overlap(bbox_print)) {
// Wait for the user to remove the priming extrusions, otherwise they would // Wait for the user to remove the priming extrusions, otherwise they would
// get covered by the print. // get covered by the print.
fprintf(file, "M1 Remove priming towers and click button.\n"); fprintf(file, "M1 Remove priming towers and click button.\nM117 Printing\n");
} else { } else {
// Just wait for a bit to let the user check, that the priming succeeded. // Just wait for a bit to let the user check, that the priming succeeded.
fprintf(file, "M0 S10\n"); fprintf(file, "M117 Verify extruder priming\nM0 S10\nM117 Printing\n");
} }
write(file, this->unretract());
} else } else
write(file, WipeTowerIntegration::prime_single_color_print(print, initial_extruder_id, *this)); write(file, WipeTowerIntegration::prime_single_color_print(print, initial_extruder_id, *this));
} }

View File

@ -101,7 +101,7 @@ BoundingBoxf get_print_extrusions_extents(const Print &print)
return bbox; return bbox;
} }
BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coord_t max_print_z) BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coordf_t max_print_z)
{ {
BoundingBoxf bbox; BoundingBoxf bbox;
for (const Layer *layer : print_object.layers) { for (const Layer *layer : print_object.layers) {
@ -129,7 +129,7 @@ BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object
// Returns a bounding box of a projection of the wipe tower for the layers <= max_print_z. // Returns a bounding box of a projection of the wipe tower for the layers <= max_print_z.
// The projection does not contain the priming regions. // The projection does not contain the priming regions.
BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coord_t max_print_z) BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_t max_print_z)
{ {
BoundingBoxf bbox; BoundingBoxf bbox;
for (const std::vector<WipeTower::ToolChangeResult> &tool_changes : print.m_wipe_tower_tool_changes) { for (const std::vector<WipeTower::ToolChangeResult> &tool_changes : print.m_wipe_tower_tool_changes) {

View File

@ -16,11 +16,11 @@ class BoundingBoxf;
BoundingBoxf get_print_extrusions_extents(const Print &print); BoundingBoxf get_print_extrusions_extents(const Print &print);
// Returns a bounding box of a projection of the object extrusions at z <= max_print_z. // Returns a bounding box of a projection of the object extrusions at z <= max_print_z.
BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coord_t max_print_z); BoundingBoxf get_print_object_extrusions_extents(const PrintObject &print_object, const coordf_t max_print_z);
// Returns a bounding box of a projection of the wipe tower for the layers <= max_print_z. // Returns a bounding box of a projection of the wipe tower for the layers <= max_print_z.
// The projection does not contain the priming regions. // The projection does not contain the priming regions.
BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coord_t max_print_z); BoundingBoxf get_wipe_tower_extrusions_extents(const Print &print, const coordf_t max_print_z);
// Returns a bounding box of the wipe tower priming extrusions. // Returns a bounding box of the wipe tower priming extrusions.
BoundingBoxf get_wipe_tower_priming_extrusions_extents(const Print &print); BoundingBoxf get_wipe_tower_priming_extrusions_extents(const Print &print);

View File

@ -105,7 +105,16 @@ public:
}; };
// Returns gcode to prime the nozzles at the front edge of the print bed. // Returns gcode to prime the nozzles at the front edge of the print bed.
virtual ToolChangeResult prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0; 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.
std::vector<unsigned int> tools,
// 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.
bool last_wipe_inside_wipe_tower,
// May be used by a stand alone post processor.
Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) = 0;
// Returns gcode for toolchange and the end position. // Returns gcode for toolchange and the end position.
// if new_tool == -1, just unload the current filament over the wipe tower. // if new_tool == -1, just unload the current filament over the wipe tower.

View File

@ -364,7 +364,16 @@ WipeTowerPrusaMM::material_type WipeTowerPrusaMM::parse_material(const char *nam
} }
// Returns gcode to prime the nozzles at the front edge of the print bed. // Returns gcode to prime the nozzles at the front edge of the print bed.
WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose) WipeTower::ToolChangeResult WipeTowerPrusaMM::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.
std::vector<unsigned int> tools,
// 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.
bool last_wipe_inside_wipe_tower,
// May be used by a stand alone post processor.
Purpose purpose)
{ {
this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false); this->set_layer(first_layer_height, first_layer_height, tools.size(), true, false);
@ -411,6 +420,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(float first_layer_height, st
.set_extruder_trimpot(750); .set_extruder_trimpot(750);
if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) { if (purpose == PURPOSE_EXTRUDE || purpose == PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE) {
float y_end = 0.f;
for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) { for (size_t idx_tool = 0; idx_tool < tools.size(); ++ idx_tool) {
unsigned int tool = tools[idx_tool]; unsigned int tool = tools[idx_tool];
// Select the tool, set a speed override for soluble and flex materials. // Select the tool, set a speed override for soluble and flex materials.
@ -419,10 +429,20 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::prime(float first_layer_height, st
toolchange_Load(writer, cleaning_box); toolchange_Load(writer, cleaning_box);
if (idx_tool + 1 == tools.size()) { if (idx_tool + 1 == tools.size()) {
// Last tool should not be unloaded, but it should be wiped enough to become of a pure color. // Last tool should not be unloaded, but it should be wiped enough to become of a pure color.
toolchange_Wipe(writer, cleaning_box); if (last_wipe_inside_wipe_tower) {
// Shrink the last wipe area to the area of the other purge areas,
// remember the last initial wipe width to be purged into the 1st layer of the wipe tower.
this->m_initial_extra_wipe = std::max(0.f, wipe_area - (y_end + 0.5f * 0.85f * m_perimeter_width - cleaning_box.ld.y));
cleaning_box.lu.y -= this->m_initial_extra_wipe;
cleaning_box.ru.y -= this->m_initial_extra_wipe;
}
toolchange_Wipe(writer, cleaning_box, false);
} else { } else {
// Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool. // Ram the hot material out of the melt zone, retract the filament into the cooling tubes and let it cool.
writer.travel(writer.x(), writer.y() + m_perimeter_width, 7200);
toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], m_first_layer_temperature[tool]); toolchange_Unload(writer, cleaning_box, m_material[m_current_tool], m_first_layer_temperature[tool]);
// Save the y end of the non-last priming area.
y_end = writer.y();
cleaning_box.translate(m_wipe_tower_width, 0.f); cleaning_box.translate(m_wipe_tower_width, 0.f);
writer.travel(cleaning_box.ld, 7200); writer.travel(cleaning_box.ld, 7200);
} }
@ -546,7 +566,7 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::tool_change(unsigned int tool, boo
toolchange_Change(writer, tool, m_material[tool]); toolchange_Change(writer, tool, m_material[tool]);
toolchange_Load(writer, cleaning_box); toolchange_Load(writer, cleaning_box);
// Wipe the newly loaded filament until the end of the assigned wipe area. // Wipe the newly loaded filament until the end of the assigned wipe area.
toolchange_Wipe(writer, cleaning_box); toolchange_Wipe(writer, cleaning_box, false);
// Draw a perimeter around cleaning_box and wipe. // Draw a perimeter around cleaning_box and wipe.
box_coordinates box = cleaning_box; box_coordinates box = cleaning_box;
if (m_current_shape == SHAPE_REVERSED) { if (m_current_shape == SHAPE_REVERSED) {
@ -647,6 +667,21 @@ WipeTower::ToolChangeResult WipeTowerPrusaMM::toolchange_Brim(Purpose purpose, b
} }
} }
if (m_initial_extra_wipe > m_perimeter_width * 1.9f) {
box_coordinates cleaning_box(
m_wipe_tower_pos + xy(0.f, 0.5f * m_perimeter_width),
m_wipe_tower_width,
m_initial_extra_wipe - m_perimeter_width);
writer.travel(cleaning_box.ld + xy(m_perimeter_width, 0.5f * m_perimeter_width), 6000);
// Wipe the newly loaded filament until the end of the assigned wipe area.
toolchange_Wipe(writer, cleaning_box, true);
// Draw a perimeter around cleaning_box.
writer.travel(cleaning_box.lu, 7000)
.extrude(cleaning_box.ld, 3200).extrude(cleaning_box.rd)
.extrude(cleaning_box.ru).extrude(cleaning_box.lu);
m_current_wipe_start_y = m_initial_extra_wipe;
}
// Move to the front left corner. // Move to the front left corner.
writer.travel(wipeTower_box.ld, 7000); writer.travel(wipeTower_box.ld, 7000);
@ -786,6 +821,9 @@ void WipeTowerPrusaMM::toolchange_Load(
{ {
float xl = cleaning_box.ld.x + m_perimeter_width; float xl = cleaning_box.ld.x + m_perimeter_width;
float xr = cleaning_box.rd.x - m_perimeter_width; float xr = cleaning_box.rd.x - m_perimeter_width;
//FIXME flipping left / right side, so that the following toolchange_Wipe will start
// where toolchange_Load ends.
std::swap(xl, xr);
writer.append("; CP TOOLCHANGE LOAD\n") writer.append("; CP TOOLCHANGE LOAD\n")
// Load the filament while moving left / right, // Load the filament while moving left / right,
@ -819,7 +857,8 @@ void WipeTowerPrusaMM::toolchange_Load(
// Wipe the newly loaded filament until the end of the assigned wipe area. // Wipe the newly loaded filament until the end of the assigned wipe area.
void WipeTowerPrusaMM::toolchange_Wipe( void WipeTowerPrusaMM::toolchange_Wipe(
PrusaMultiMaterial::Writer &writer, PrusaMultiMaterial::Writer &writer,
const box_coordinates &cleaning_box) const box_coordinates &cleaning_box,
bool skip_initial_y_move)
{ {
// Increase flow on first layer, slow down print. // Increase flow on first layer, slow down print.
writer.set_extrusion_flow(m_extrusion_flow * (m_is_first_layer ? 1.18f : 1.f)) writer.set_extrusion_flow(m_extrusion_flow * (m_is_first_layer ? 1.18f : 1.f))
@ -833,23 +872,27 @@ void WipeTowerPrusaMM::toolchange_Wipe(
float wipe_speed_max = 4800.f; float wipe_speed_max = 4800.f;
// Y increment per wipe line. // Y increment per wipe line.
float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width * 0.8f; float dy = ((m_current_shape == SHAPE_NORMAL) ? 1.f : -1.f) * m_perimeter_width * 0.8f;
for (bool p = true; ; p = ! p) { for (bool p = true;
// Next wipe line fits the cleaning box.
((m_current_shape == SHAPE_NORMAL) ?
(writer.y() <= cleaning_box.lu.y - m_perimeter_width) :
(writer.y() >= cleaning_box.ld.y + m_perimeter_width));
p = ! p)
{
wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc); wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc);
if (p) { if (skip_initial_y_move)
writer.extrude(xl - m_perimeter_width / 2, writer.y() + dy, wipe_speed * wipe_coeff); skip_initial_y_move = false;
writer.extrude(xr + m_perimeter_width, writer.y()); else
} else { writer.extrude(xl - (p ? m_perimeter_width / 2 : m_perimeter_width), writer.y() + dy, wipe_speed * wipe_coeff);
writer.extrude(xl - m_perimeter_width, writer.y() + dy, wipe_speed * wipe_coeff); writer.extrude(xr + (p ? m_perimeter_width : m_perimeter_width * 2), writer.y(), wipe_speed * wipe_coeff);
writer.extrude(xr + m_perimeter_width * 2, writer.y()); // Next wipe line fits the cleaning box.
}
wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc);
writer.extrude(xr + m_perimeter_width, writer.y() + dy, wipe_speed * wipe_coeff);
writer.extrude(xl - m_perimeter_width, writer.y());
if ((m_current_shape == SHAPE_NORMAL) ? if ((m_current_shape == SHAPE_NORMAL) ?
(writer.y() > cleaning_box.lu.y - m_perimeter_width) : (writer.y() > cleaning_box.lu.y - m_perimeter_width) :
(writer.y() < cleaning_box.ld.y + m_perimeter_width)) (writer.y() < cleaning_box.ld.y + m_perimeter_width))
// Next wipe line does not fit the cleaning box.
break; break;
wipe_speed = std::min(wipe_speed_max, wipe_speed + wipe_speed_inc);
writer.extrude(xr + m_perimeter_width, writer.y() + dy, wipe_speed * wipe_coeff);
writer.extrude(xl - m_perimeter_width, writer.y());
} }
// Reset the extrusion flow. // Reset the extrusion flow.
writer.set_extrusion_flow(m_extrusion_flow); writer.set_extrusion_flow(m_extrusion_flow);

View File

@ -108,7 +108,16 @@ public:
virtual bool finished() const { return m_max_color_changes == 0; } virtual bool finished() const { return m_max_color_changes == 0; }
// Returns gcode to prime the nozzles at the front edge of the print bed. // Returns gcode to prime the nozzles at the front edge of the print bed.
virtual ToolChangeResult prime(float first_layer_height, std::vector<unsigned int> tools, Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE); 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.
std::vector<unsigned int> tools,
// 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.
bool last_wipe_inside_wipe_tower,
// May be used by a stand alone post processor.
Purpose purpose = PURPOSE_MOVE_TO_TOWER_AND_EXTRUDE);
// Returns gcode for a toolchange and a final print head position. // Returns gcode for a toolchange and a final print head position.
// On the first layer, extrude a brim around the future wipe tower first. // On the first layer, extrude a brim around the future wipe tower first.
@ -176,6 +185,9 @@ private:
unsigned int m_current_tool = 0; unsigned int m_current_tool = 0;
// Current y position at the wipe tower. // Current y position at the wipe tower.
float m_current_wipe_start_y = 0.f; float m_current_wipe_start_y = 0.f;
// How much to wipe the 1st extruder over the wipe tower at the 1st layer
// after the wipe tower brim has been extruded?
float m_initial_extra_wipe = 0.f;
struct box_coordinates struct box_coordinates
{ {
@ -230,7 +242,8 @@ private:
void toolchange_Wipe( void toolchange_Wipe(
PrusaMultiMaterial::Writer &writer, PrusaMultiMaterial::Writer &writer,
const box_coordinates &cleaning_box); const box_coordinates &cleaning_box,
bool skip_initial_y_move);
void toolchange_Perimeter(); void toolchange_Perimeter();
}; };

View File

@ -992,8 +992,13 @@ void Print::_make_wipe_tower()
this->config.temperature.get_at(i), this->config.temperature.get_at(i),
this->config.first_layer_temperature.get_at(i)); this->config.first_layer_temperature.get_at(i));
// When printing the first layer's wipe tower, the first extruder is expected to be active and primed.
// Therefore the number of wipe sections at the wipe tower will be (m_tool_ordering.front().extruders-1) at the 1st layer.
// The following variable is true if the last priming section cannot be squeezed inside the wipe tower.
bool last_priming_wipe_full = m_tool_ordering.front().extruders.size() > m_tool_ordering.front().wipe_tower_partitions;
m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>( m_wipe_tower_priming = Slic3r::make_unique<WipeTower::ToolChangeResult>(
wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), WipeTower::PURPOSE_EXTRUDE)); wipe_tower.prime(this->skirt_first_layer_height(), m_tool_ordering.all_extruders(), ! last_priming_wipe_full, WipeTower::PURPOSE_EXTRUDE));
// Generate the wipe tower layers. // Generate the wipe tower layers.
m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size()); m_wipe_tower_tool_changes.reserve(m_tool_ordering.layer_tools().size());