ENH: add new calibration
pa calibration for 3rd party printer and retraction calibration Change-Id: Ifeb12807cdce366c9d265a0490b320224dfb23fe (cherry picked from commit 732adceeef43c9c957468ab490f0e3ee20f3173b)
This commit is contained in:
parent
2910014887
commit
11fb7fb89f
15 changed files with 515 additions and 120 deletions
BIN
resources/calib/pressure_advance/pressure_advance_test.stl
Normal file
BIN
resources/calib/pressure_advance/pressure_advance_test.stl
Normal file
Binary file not shown.
BIN
resources/calib/pressure_advance/tower.stl
Normal file
BIN
resources/calib/pressure_advance/tower.stl
Normal file
Binary file not shown.
BIN
resources/calib/pressure_advance/tower_with_seam.stl
Normal file
BIN
resources/calib/pressure_advance/tower_with_seam.stl
Normal file
Binary file not shown.
BIN
resources/calib/retraction/retraction_tower.stl
Normal file
BIN
resources/calib/retraction/retraction_tower.stl
Normal file
Binary file not shown.
|
@ -37,6 +37,7 @@ set(lisbslic3r_sources
|
|||
Brim.hpp
|
||||
BuildVolume.cpp
|
||||
BuildVolume.hpp
|
||||
Calib.cpp
|
||||
Calib.hpp
|
||||
Circle.cpp
|
||||
Circle.hpp
|
||||
|
|
221
src/libslic3r/Calib.cpp
Normal file
221
src/libslic3r/Calib.cpp
Normal file
|
@ -0,0 +1,221 @@
|
|||
#include "Calib.hpp"
|
||||
#include "Point.hpp"
|
||||
#include "PrintConfig.hpp"
|
||||
#include "GCodeWriter.hpp"
|
||||
#include "GCode.hpp"
|
||||
#include <map>
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
calib_pressure_advance::calib_pressure_advance(GCode* gcodegen) :mp_gcodegen(gcodegen), m_length_short(20.0), m_length_long(40.0), m_space_y(3.5), m_line_width(0.6), m_draw_numbers(true) {}
|
||||
|
||||
std::string calib_pressure_advance::generate_test(double start_pa, double step_pa, int count ) {
|
||||
BoundingBoxf bed_ext = get_extents(mp_gcodegen->config().printable_area.values);
|
||||
bool is_delta = false;
|
||||
if (mp_gcodegen->config().printable_area.values.size() > 4) {
|
||||
is_delta = true;
|
||||
bed_ext.scale(1.0f / 1.41421f);
|
||||
}
|
||||
|
||||
auto bed_sizes = mp_gcodegen->config().printable_area.values;
|
||||
const auto &w = bed_ext.size().x();
|
||||
const auto &h = bed_ext.size().y();
|
||||
count = std::min(count, int((h - 10) / m_space_y));
|
||||
|
||||
m_length_long = 40 + std::min(w - 120.0, 0.0);
|
||||
|
||||
auto startx = (w - m_length_short * 2 - m_length_long - 20) / 2;
|
||||
auto starty = (h - count * m_space_y) / 2;
|
||||
if (is_delta) {
|
||||
startx = -startx;
|
||||
starty = -(count * m_space_y) / 2;
|
||||
}
|
||||
|
||||
return print_pa_lines(startx, starty, start_pa, step_pa, count);
|
||||
}
|
||||
|
||||
std::string calib_pressure_advance::move_to(Vec2d pt) {
|
||||
std::stringstream gcode;
|
||||
gcode << mp_gcodegen->retract();
|
||||
gcode << mp_gcodegen->writer().travel_to_xyz(Vec3d(pt.x(), pt.y(), 0.2));
|
||||
gcode << mp_gcodegen->unretract();
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string calib_pressure_advance::print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num) {
|
||||
|
||||
auto& writer = mp_gcodegen->writer();
|
||||
Flow line_flow = Flow(m_line_width, 0.2, mp_gcodegen->config().nozzle_diameter.get_at(0));
|
||||
Flow thin_line_flow = Flow(0.44, 0.2, mp_gcodegen->config().nozzle_diameter.get_at(0));
|
||||
const double e_calib = line_flow.mm3_per_mm() / 2.40528; // filament_mm/extrusion_mm
|
||||
const double e = thin_line_flow.mm3_per_mm() / 2.40528; // filament_mm/extrusion_mm
|
||||
|
||||
|
||||
const double fast = m_fast_speed * 60.0;
|
||||
const double slow = m_slow_speed * 60.0;
|
||||
std::stringstream gcode;
|
||||
gcode << mp_gcodegen->writer().travel_to_z(0.2);
|
||||
double y_pos = start_y;
|
||||
|
||||
// prime line
|
||||
auto prime_x = start_x - 2;
|
||||
gcode << move_to(Vec2d(prime_x, y_pos + (num - 4) * m_space_y));
|
||||
gcode << writer.set_speed(slow);
|
||||
gcode << writer.extrude_to_xy(Vec2d(prime_x, y_pos + 3 * m_space_y), e_calib * m_space_y * num * 1.1);
|
||||
|
||||
for (int i = 0; i < num; ++i) {
|
||||
|
||||
gcode << writer.set_pressure_advance(start_pa + i * step_pa);
|
||||
gcode << move_to(Vec2d(start_x, y_pos + i * m_space_y));
|
||||
gcode << writer.set_speed(slow);
|
||||
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + i * m_space_y), e_calib * m_length_short);
|
||||
gcode << writer.set_speed(fast);
|
||||
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + i * m_space_y), e_calib * m_length_long);
|
||||
gcode << writer.set_speed(slow);
|
||||
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long + m_length_short, y_pos + i * m_space_y), e_calib * m_length_short);
|
||||
|
||||
}
|
||||
gcode << writer.set_pressure_advance(0.0);
|
||||
|
||||
if (m_draw_numbers) {
|
||||
// draw indicator lines
|
||||
gcode << writer.set_speed(fast);
|
||||
gcode << move_to(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 2));
|
||||
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short, y_pos + (num - 1) * m_space_y + 7), e * 7);
|
||||
gcode << move_to(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 7));
|
||||
gcode << writer.extrude_to_xy(Vec2d(start_x + m_length_short + m_length_long, y_pos + (num - 1) * m_space_y + 2), e * 7);
|
||||
|
||||
for (int i = 0; i < num; i += 2) {
|
||||
gcode << draw_number(start_x + m_length_short + m_length_long + m_length_short + 3, y_pos + i * m_space_y + m_space_y / 2, start_pa + i * step_pa);
|
||||
}
|
||||
}
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
|
||||
std::string calib_pressure_advance::draw_digit(double startx, double starty, char c) {
|
||||
auto& writer = mp_gcodegen->writer();
|
||||
std::stringstream gcode;
|
||||
const double lw = 0.48;
|
||||
Flow line_flow = Flow(lw, 0.2, mp_gcodegen->config().nozzle_diameter.get_at(0));
|
||||
const double len = 2;
|
||||
const double gap = lw / 2.0;
|
||||
const double e = line_flow.mm3_per_mm() / 2.40528; // filament_mm/extrusion_mm
|
||||
|
||||
// 0-------1
|
||||
// | |
|
||||
// 3-------2
|
||||
// | |
|
||||
// 4-------5
|
||||
const Vec2d p0(startx, starty);
|
||||
const Vec2d p1(startx + len, starty);
|
||||
const Vec2d p2(startx + len, starty - len);
|
||||
const Vec2d p3(startx, starty - len);
|
||||
const Vec2d p4(startx, starty - len * 2);
|
||||
const Vec2d p5(startx + len, starty - len * 2);
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '0':
|
||||
gcode << move_to(p0);
|
||||
gcode << writer.extrude_to_xy(p1, e * len);
|
||||
gcode << writer.extrude_to_xy(p5, e * len * 2);
|
||||
gcode << writer.extrude_to_xy(p4, e * len);
|
||||
gcode << writer.extrude_to_xy(p0 - Vec2d(0, gap), e * len * 2);
|
||||
break;
|
||||
case '1':
|
||||
gcode << move_to(p0 + Vec2d(len / 2, 0));
|
||||
gcode << writer.extrude_to_xy(p4 + Vec2d(len / 2, 0), e * len * 2);
|
||||
break;
|
||||
case '2':
|
||||
gcode << move_to(p0);
|
||||
gcode << writer.extrude_to_xy(p1, e * len);
|
||||
gcode << writer.extrude_to_xy(p2, e * len);
|
||||
gcode << writer.extrude_to_xy(p3, e * len);
|
||||
gcode << writer.extrude_to_xy(p4, e * len);
|
||||
gcode << writer.extrude_to_xy(p5, e * len);
|
||||
break;
|
||||
case '3':
|
||||
gcode << move_to(p0);
|
||||
gcode << writer.extrude_to_xy(p1, e * len);
|
||||
gcode << writer.extrude_to_xy(p5, e * len * 2);
|
||||
gcode << writer.extrude_to_xy(p4, e * len);
|
||||
gcode << move_to(p2 - Vec2d(gap, 0));
|
||||
gcode << writer.extrude_to_xy(p3, e * len);
|
||||
break;
|
||||
case '4':
|
||||
gcode << move_to(p0);
|
||||
gcode << writer.extrude_to_xy(p3, e * len);
|
||||
gcode << writer.extrude_to_xy(p2, e * len);
|
||||
gcode << move_to(p1);
|
||||
gcode << writer.extrude_to_xy(p5, e * len * 2);
|
||||
break;
|
||||
case '5':
|
||||
gcode << move_to(p1);
|
||||
gcode << writer.extrude_to_xy(p0, e * len);
|
||||
gcode << writer.extrude_to_xy(p3, e * len);
|
||||
gcode << writer.extrude_to_xy(p2, e * len);
|
||||
gcode << writer.extrude_to_xy(p5, e * len);
|
||||
gcode << writer.extrude_to_xy(p4, e * len);
|
||||
break;
|
||||
case '6':
|
||||
gcode << move_to(p1);
|
||||
gcode << writer.extrude_to_xy(p0, e * len);
|
||||
gcode << writer.extrude_to_xy(p4, e * len * 2);
|
||||
gcode << writer.extrude_to_xy(p5, e * len);
|
||||
gcode << writer.extrude_to_xy(p2, e * len);
|
||||
gcode << writer.extrude_to_xy(p3, e * len);
|
||||
break;
|
||||
case '7':
|
||||
gcode << move_to(p0);
|
||||
gcode << writer.extrude_to_xy(p1, e * len);
|
||||
gcode << writer.extrude_to_xy(p5, e * len * 2);
|
||||
break;
|
||||
case '8':
|
||||
gcode << move_to(p2);
|
||||
gcode << writer.extrude_to_xy(p3, e * len);
|
||||
gcode << writer.extrude_to_xy(p4, e * len);
|
||||
gcode << writer.extrude_to_xy(p5, e * len);
|
||||
gcode << writer.extrude_to_xy(p1, e * len * 2);
|
||||
gcode << writer.extrude_to_xy(p0, e * len);
|
||||
gcode << writer.extrude_to_xy(p3, e * len);
|
||||
break;
|
||||
case '9':
|
||||
gcode << move_to(p5);
|
||||
gcode << writer.extrude_to_xy(p1, e * len * 2);
|
||||
gcode << writer.extrude_to_xy(p0, e * len);
|
||||
gcode << writer.extrude_to_xy(p3, e * len);
|
||||
gcode << writer.extrude_to_xy(p2, e * len);
|
||||
break;
|
||||
case '.':
|
||||
gcode << move_to(p4 + Vec2d(len / 2, 0));
|
||||
gcode << writer.extrude_to_xy(p4 + Vec2d(len / 2, len / 2), e * len);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return gcode.str();
|
||||
}
|
||||
// draw number
|
||||
std::string calib_pressure_advance::draw_number(double startx, double starty, double value) {
|
||||
double spacing = 3.0;
|
||||
auto sNumber = std::to_string(value);
|
||||
sNumber.erase(sNumber.find_last_not_of('0') + 1, std::string::npos);
|
||||
sNumber.erase(sNumber.find_last_not_of('.') + 1, std::string::npos);
|
||||
std::stringstream gcode;
|
||||
gcode << mp_gcodegen->writer().set_speed(3600);
|
||||
|
||||
|
||||
for (int i = 0; i < sNumber.length(); ++i) {
|
||||
if (i > 5)
|
||||
break;
|
||||
gcode << draw_digit(startx + i * spacing, starty, sNumber[i]);
|
||||
|
||||
}
|
||||
|
||||
return gcode.str();
|
||||
}
|
||||
} // namespace Slic3r
|
||||
|
|
@ -13,9 +13,11 @@ enum class CalibMode : int {
|
|||
Calib_Flow_Rate,
|
||||
Calib_Temp_Tower,
|
||||
Calib_Vol_speed_Tower,
|
||||
Calib_VFA_Tower
|
||||
Calib_VFA_Tower,
|
||||
Calib_Retraction_tower
|
||||
|
||||
};
|
||||
|
||||
struct Calib_Params
|
||||
{
|
||||
Calib_Params() : mode(CalibMode::Calib_None){}
|
||||
|
@ -23,4 +25,35 @@ struct Calib_Params
|
|||
bool print_numbers;
|
||||
CalibMode mode;
|
||||
};
|
||||
|
||||
class calib_pressure_advance
|
||||
{
|
||||
public:
|
||||
calib_pressure_advance(GCode *gcodegen);
|
||||
~calib_pressure_advance() {}
|
||||
|
||||
std::string generate_test(double start_pa = 0, double step_pa = 0.002, int count = 50);
|
||||
void set_speed(double fast = 100.0, double slow = 20.0)
|
||||
{
|
||||
m_slow_speed = slow;
|
||||
m_fast_speed = fast;
|
||||
}
|
||||
double &line_width() { return m_line_width; };
|
||||
bool & draw_numbers() { return m_draw_numbers; }
|
||||
|
||||
private:
|
||||
std::string move_to(Vec2d pt);
|
||||
std::string print_pa_lines(double start_x, double start_y, double start_pa, double step_pa, int num);
|
||||
std::string draw_digit(double startx, double starty, char c);
|
||||
std::string draw_number(double startx, double starty, double value);
|
||||
|
||||
private:
|
||||
GCode *mp_gcodegen;
|
||||
double m_length_short, m_length_long;
|
||||
double m_space_y;
|
||||
double m_slow_speed, m_fast_speed;
|
||||
double m_line_width;
|
||||
bool m_draw_numbers;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -1849,98 +1849,124 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
}
|
||||
if (this->m_objsWithBrim.empty() && this->m_objSupportsWithBrim.empty()) m_brim_done = true;
|
||||
|
||||
//BBS: open spaghetti detector
|
||||
// if (print.config().spaghetti_detector.value)
|
||||
if (print.is_BBL_Printer())
|
||||
file.write("M981 S1 P20000 ;open spaghetti detector\n");
|
||||
|
||||
// Do all objects for each layer.
|
||||
if (print.config().print_sequence == PrintSequence::ByObject && !has_wipe_tower) {
|
||||
size_t finished_objects = 0;
|
||||
const PrintObject *prev_object = (*print_object_instance_sequential_active)->print_object;
|
||||
for (; print_object_instance_sequential_active != print_object_instances_ordering.end(); ++ print_object_instance_sequential_active) {
|
||||
const PrintObject &object = *(*print_object_instance_sequential_active)->print_object;
|
||||
if (&object != prev_object || tool_ordering.first_extruder() != final_extruder_id) {
|
||||
tool_ordering = ToolOrdering(object, final_extruder_id);
|
||||
unsigned int new_extruder_id = tool_ordering.first_extruder();
|
||||
if (new_extruder_id == (unsigned int)-1)
|
||||
// Skip this object.
|
||||
continue;
|
||||
initial_extruder_id = new_extruder_id;
|
||||
final_extruder_id = tool_ordering.last_extruder();
|
||||
assert(final_extruder_id != (unsigned int)-1);
|
||||
}
|
||||
print.throw_if_canceled();
|
||||
this->set_origin(unscale((*print_object_instance_sequential_active)->shift));
|
||||
|
||||
// BBS: prime extruder if extruder change happens before this object instance
|
||||
bool prime_extruder = false;
|
||||
if (finished_objects > 0) {
|
||||
// Move to the origin position for the copy we're going to print.
|
||||
// This happens before Z goes down to layer 0 again, so that no collision happens hopefully.
|
||||
m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer
|
||||
m_avoid_crossing_perimeters.use_external_mp_once();
|
||||
// BBS. change tool before moving to origin point.
|
||||
if (m_writer.need_toolchange(initial_extruder_id)) {
|
||||
const PrintObjectConfig& object_config = object.config();
|
||||
coordf_t initial_layer_print_height = print.config().initial_layer_print_height.value;
|
||||
file.write(this->set_extruder(initial_extruder_id, initial_layer_print_height));
|
||||
prime_extruder = true;
|
||||
}
|
||||
else {
|
||||
file.write(this->retract());
|
||||
}
|
||||
file.write(m_writer.travel_to_z(m_max_layer_z));
|
||||
file.write(this->travel_to(Point(0, 0), erNone, "move to origin position for next object"));
|
||||
m_enable_cooling_markers = true;
|
||||
// Disable motion planner when traveling to first object point.
|
||||
m_avoid_crossing_perimeters.disable_once();
|
||||
// Ff we are printing the bottom layer of an object, and we have already finished
|
||||
// another one, set first layer temperatures. This happens before the Z move
|
||||
// is triggered, so machine has more time to reach such temperatures.
|
||||
m_placeholder_parser.set("current_object_idx", int(finished_objects));
|
||||
//BBS: remove printing_by_object_gcode
|
||||
//std::string printing_by_object_gcode = this->placeholder_parser_process("printing_by_object_gcode", print.config().printing_by_object_gcode.value, initial_extruder_id);
|
||||
std::string printing_by_object_gcode;
|
||||
// Set first layer bed and extruder temperatures, don't wait for it to reach the temperature.
|
||||
this->_print_first_layer_bed_temperature(file, print, printing_by_object_gcode, initial_extruder_id, false);
|
||||
this->_print_first_layer_extruder_temperatures(file, print, printing_by_object_gcode, initial_extruder_id, false);
|
||||
file.writeln(printing_by_object_gcode);
|
||||
}
|
||||
// Reset the cooling buffer internal state (the current position, feed rate, accelerations).
|
||||
m_cooling_buffer->reset(this->writer().get_position());
|
||||
m_cooling_buffer->set_current_extruder(initial_extruder_id);
|
||||
// Process all layers of a single object instance (sequential mode) with a parallel pipeline:
|
||||
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
|
||||
// and export G-code into file.
|
||||
this->process_layers(print, tool_ordering, collect_layers_to_print(object), *print_object_instance_sequential_active - object.instances().data(), file, prime_extruder);
|
||||
//BBS: close powerlost recovery
|
||||
{
|
||||
if (m_second_layer_things_done && print.is_BBL_Printer()) {
|
||||
file.write("; close powerlost recovery\n");
|
||||
file.write("M1003 S0\n");
|
||||
}
|
||||
}
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
if (m_pressure_equalizer)
|
||||
file.write(m_pressure_equalizer->process("", true));
|
||||
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||
++ finished_objects;
|
||||
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
|
||||
// Reset it when starting another object from 1st layer.
|
||||
m_second_layer_things_done = false;
|
||||
prev_object = &object;
|
||||
// SoftFever: calib
|
||||
if (print.calib_params().mode == CalibMode::Calib_PA_Line) {
|
||||
std::string gcode;
|
||||
if ((m_config.default_acceleration.value > 0 && m_config.outer_wall_acceleration.value > 0)) {
|
||||
gcode += m_writer.set_acceleration((unsigned int) floor(m_config.outer_wall_acceleration.value + 0.5));
|
||||
}
|
||||
} else {
|
||||
// Sort layers by Z.
|
||||
// All extrusion moves with the same top layer height are extruded uninterrupted.
|
||||
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
|
||||
// Prusa Multi-Material wipe tower.
|
||||
if (has_wipe_tower && ! layers_to_print.empty()) {
|
||||
m_wipe_tower.reset(new WipeTowerIntegration(print.config(), print.get_plate_index(), print.get_plate_origin(), * print.wipe_tower_data().priming.get(), print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()));
|
||||
//BBS
|
||||
//file.write(m_writer.travel_to_z(initial_layer_print_height + m_config.z_offset.value, "Move to the first layer height"));
|
||||
file.write(m_writer.travel_to_z(initial_layer_print_height, "Move to the first layer height"));
|
||||
|
||||
// todo: 3rd party printer need
|
||||
//if (m_config.default_jerk.value > 0) {
|
||||
// double jerk = m_config.outer_wall_jerk.value;
|
||||
// gcode += m_writer.set_jerk_xy(jerk);
|
||||
//}
|
||||
|
||||
calib_pressure_advance pa_test(this);
|
||||
double filament_max_volumetric_speed = m_config.option<ConfigOptionFloats>("filament_max_volumetric_speed")->get_at(initial_extruder_id);
|
||||
Flow pattern_line = Flow(pa_test.line_width(), 0.2, m_config.nozzle_diameter.get_at(0));
|
||||
auto fast_speed = std::min(print.default_region_config().outer_wall_speed.value, filament_max_volumetric_speed / pattern_line.mm3_per_mm());
|
||||
auto slow_speed = std::max(20.0, fast_speed / 10.0);
|
||||
pa_test.set_speed(fast_speed, slow_speed);
|
||||
pa_test.draw_numbers() = print.calib_params().print_numbers;
|
||||
auto params = print.calib_params();
|
||||
gcode += pa_test.generate_test(params.start, params.step, std::llround(std::ceil((params.end - params.start) / params.step)));
|
||||
|
||||
file.write(gcode);
|
||||
}
|
||||
else {
|
||||
// BBS: open spaghetti detector
|
||||
// if (print.config().spaghetti_detector.value)
|
||||
if (print.is_BBL_Printer()) file.write("M981 S1 P20000 ;open spaghetti detector\n");
|
||||
|
||||
// Do all objects for each layer.
|
||||
if (print.config().print_sequence == PrintSequence::ByObject && !has_wipe_tower) {
|
||||
size_t finished_objects = 0;
|
||||
const PrintObject *prev_object = (*print_object_instance_sequential_active)->print_object;
|
||||
for (; print_object_instance_sequential_active != print_object_instances_ordering.end(); ++print_object_instance_sequential_active) {
|
||||
const PrintObject &object = *(*print_object_instance_sequential_active)->print_object;
|
||||
if (&object != prev_object || tool_ordering.first_extruder() != final_extruder_id) {
|
||||
tool_ordering = ToolOrdering(object, final_extruder_id);
|
||||
unsigned int new_extruder_id = tool_ordering.first_extruder();
|
||||
if (new_extruder_id == (unsigned int) -1)
|
||||
// Skip this object.
|
||||
continue;
|
||||
initial_extruder_id = new_extruder_id;
|
||||
final_extruder_id = tool_ordering.last_extruder();
|
||||
assert(final_extruder_id != (unsigned int) -1);
|
||||
}
|
||||
print.throw_if_canceled();
|
||||
this->set_origin(unscale((*print_object_instance_sequential_active)->shift));
|
||||
|
||||
// BBS: prime extruder if extruder change happens before this object instance
|
||||
bool prime_extruder = false;
|
||||
if (finished_objects > 0) {
|
||||
// Move to the origin position for the copy we're going to print.
|
||||
// This happens before Z goes down to layer 0 again, so that no collision happens hopefully.
|
||||
m_enable_cooling_markers = false; // we're not filtering these moves through CoolingBuffer
|
||||
m_avoid_crossing_perimeters.use_external_mp_once();
|
||||
// BBS. change tool before moving to origin point.
|
||||
if (m_writer.need_toolchange(initial_extruder_id)) {
|
||||
const PrintObjectConfig &object_config = object.config();
|
||||
coordf_t initial_layer_print_height = print.config().initial_layer_print_height.value;
|
||||
file.write(this->set_extruder(initial_extruder_id, initial_layer_print_height));
|
||||
prime_extruder = true;
|
||||
} else {
|
||||
file.write(this->retract());
|
||||
}
|
||||
file.write(m_writer.travel_to_z(m_max_layer_z));
|
||||
file.write(this->travel_to(Point(0, 0), erNone, "move to origin position for next object"));
|
||||
m_enable_cooling_markers = true;
|
||||
// Disable motion planner when traveling to first object point.
|
||||
m_avoid_crossing_perimeters.disable_once();
|
||||
// Ff we are printing the bottom layer of an object, and we have already finished
|
||||
// another one, set first layer temperatures. This happens before the Z move
|
||||
// is triggered, so machine has more time to reach such temperatures.
|
||||
m_placeholder_parser.set("current_object_idx", int(finished_objects));
|
||||
// BBS: remove printing_by_object_gcode
|
||||
// std::string printing_by_object_gcode = this->placeholder_parser_process("printing_by_object_gcode", print.config().printing_by_object_gcode.value,
|
||||
// initial_extruder_id);
|
||||
std::string printing_by_object_gcode;
|
||||
// Set first layer bed and extruder temperatures, don't wait for it to reach the temperature.
|
||||
this->_print_first_layer_bed_temperature(file, print, printing_by_object_gcode, initial_extruder_id, false);
|
||||
this->_print_first_layer_extruder_temperatures(file, print, printing_by_object_gcode, initial_extruder_id, false);
|
||||
file.writeln(printing_by_object_gcode);
|
||||
}
|
||||
// Reset the cooling buffer internal state (the current position, feed rate, accelerations).
|
||||
m_cooling_buffer->reset(this->writer().get_position());
|
||||
m_cooling_buffer->set_current_extruder(initial_extruder_id);
|
||||
// Process all layers of a single object instance (sequential mode) with a parallel pipeline:
|
||||
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
|
||||
// and export G-code into file.
|
||||
this->process_layers(print, tool_ordering, collect_layers_to_print(object), *print_object_instance_sequential_active - object.instances().data(), file,
|
||||
prime_extruder);
|
||||
// BBS: close powerlost recovery
|
||||
{
|
||||
if (m_second_layer_things_done && print.is_BBL_Printer()) {
|
||||
file.write("; close powerlost recovery\n");
|
||||
file.write("M1003 S0\n");
|
||||
}
|
||||
}
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
if (m_pressure_equalizer) file.write(m_pressure_equalizer->process("", true));
|
||||
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||
++finished_objects;
|
||||
// Flag indicating whether the nozzle temperature changes from 1st to 2nd layer were performed.
|
||||
// Reset it when starting another object from 1st layer.
|
||||
m_second_layer_things_done = false;
|
||||
prev_object = &object;
|
||||
}
|
||||
} else {
|
||||
// Sort layers by Z.
|
||||
// All extrusion moves with the same top layer height are extruded uninterrupted.
|
||||
std::vector<std::pair<coordf_t, std::vector<LayerToPrint>>> layers_to_print = collect_layers_to_print(print);
|
||||
// Prusa Multi-Material wipe tower.
|
||||
if (has_wipe_tower && !layers_to_print.empty()) {
|
||||
m_wipe_tower.reset(new WipeTowerIntegration(print.config(), print.get_plate_index(), print.get_plate_origin(), *print.wipe_tower_data().priming.get(),
|
||||
print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()));
|
||||
// BBS
|
||||
// file.write(m_writer.travel_to_z(initial_layer_print_height + m_config.z_offset.value, "Move to the first layer height"));
|
||||
file.write(m_writer.travel_to_z(initial_layer_print_height, "Move to the first layer height"));
|
||||
#if 0
|
||||
if (print.config().single_extruder_multi_material_priming) {
|
||||
file.write(m_wipe_tower->prime(*this));
|
||||
|
@ -1979,26 +2005,26 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
|||
//}
|
||||
}
|
||||
#endif
|
||||
print.throw_if_canceled();
|
||||
}
|
||||
// Process all layers of all objects (non-sequential mode) with a parallel pipeline:
|
||||
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
|
||||
// and export G-code into file.
|
||||
this->process_layers(print, tool_ordering, print_object_instances_ordering, layers_to_print, file);
|
||||
//BBS: close powerlost recovery
|
||||
{
|
||||
if (m_second_layer_things_done && print.is_BBL_Printer()) {
|
||||
file.write("; close powerlost recovery\n");
|
||||
file.write("M1003 S0\n");
|
||||
print.throw_if_canceled();
|
||||
}
|
||||
// Process all layers of all objects (non-sequential mode) with a parallel pipeline:
|
||||
// Generate G-code, run the filters (vase mode, cooling buffer), run the G-code analyser
|
||||
// and export G-code into file.
|
||||
this->process_layers(print, tool_ordering, print_object_instances_ordering, layers_to_print, file);
|
||||
// BBS: close powerlost recovery
|
||||
{
|
||||
if (m_second_layer_things_done && print.is_BBL_Printer()) {
|
||||
file.write("; close powerlost recovery\n");
|
||||
file.write("M1003 S0\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef HAS_PRESSURE_EQUALIZER
|
||||
if (m_pressure_equalizer)
|
||||
file.write(m_pressure_equalizer->process("", true));
|
||||
if (m_pressure_equalizer) file.write(m_pressure_equalizer->process("", true));
|
||||
#endif /* HAS_PRESSURE_EQUALIZER */
|
||||
if (m_wipe_tower)
|
||||
// Purge the extruder, pull out the active filament.
|
||||
file.write(m_wipe_tower->finalize(*this));
|
||||
if (m_wipe_tower)
|
||||
// Purge the extruder, pull out the active filament.
|
||||
file.write(m_wipe_tower->finalize(*this));
|
||||
}
|
||||
}
|
||||
|
||||
//BBS: the last retraction
|
||||
|
@ -2748,6 +2774,14 @@ GCode::LayerResult GCode::process_layer(
|
|||
auto _speed = print.calib_params().start + std::floor(print_z / 5.0) * print.calib_params().step;
|
||||
m_calib_config.set_key_value("outer_wall_speed", new ConfigOptionFloat(std::round(_speed)));
|
||||
}
|
||||
else if (print.calib_mode() == CalibMode::Calib_Retraction_tower) {
|
||||
auto _length = print.calib_params().start + std::floor(std::max(0.0, print_z - 0.4)) * print.calib_params().step;
|
||||
DynamicConfig _cfg;
|
||||
_cfg.set_key_value("retraction_length", new ConfigOptionFloats{_length});
|
||||
writer().config.apply(_cfg);
|
||||
sprintf(buf, "; Calib_Retraction_tower: Z_HEIGHT: %g, length:%g\n", print_z, _length);
|
||||
gcode += buf;
|
||||
}
|
||||
|
||||
//BBS
|
||||
if (first_layer) {
|
||||
|
|
|
@ -198,6 +198,11 @@ public:
|
|||
// append full config to the given string
|
||||
static void append_full_config(const Print& print, std::string& str);
|
||||
|
||||
// BBS: detect lift type in needs_retraction
|
||||
bool needs_retraction(const Polyline &travel, ExtrusionRole role, LiftType &lift_type);
|
||||
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::SpiralLift);
|
||||
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
|
||||
|
||||
// Object and support extrusions of the same PrintObject at the same print_z.
|
||||
// public, so that it could be accessed by free helper functions from GCode.cpp
|
||||
struct LayerToPrint
|
||||
|
@ -400,10 +405,7 @@ private:
|
|||
std::string travel_to(const Point &point, ExtrusionRole role, std::string comment);
|
||||
// BBS
|
||||
LiftType to_lift_type(ZHopType z_hop_types);
|
||||
// BBS: detect lift type in needs_retraction
|
||||
bool needs_retraction(const Polyline& travel, ExtrusionRole role, LiftType& lift_type);
|
||||
std::string retract(bool toolchange = false, bool is_last_retraction = false, LiftType lift_type = LiftType::SpiralLift);
|
||||
std::string unretract() { return m_writer.unlift() + m_writer.unretract(); }
|
||||
|
||||
std::string set_extruder(unsigned int extruder_id, double print_z);
|
||||
std::set<ObjectID> m_objsWithBrim; // indicates the objs with brim
|
||||
std::set<ObjectID> m_objSupportsWithBrim; // indicates the objs' supports with brim
|
||||
|
|
|
@ -182,6 +182,24 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
|
|||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::set_pressure_advance(double pa) const
|
||||
{
|
||||
std::ostringstream gcode;
|
||||
if (pa < 0) return gcode.str();
|
||||
if (false) { // todo: bbl printer
|
||||
// SoftFever: set L1000 to use linear model
|
||||
gcode << "M900 K" << std::setprecision(4) << pa << " L1000 M10 ; Override pressure advance value\n";
|
||||
} else {
|
||||
if (this->config.gcode_flavor == gcfKlipper)
|
||||
gcode << "SET_PRESSURE_ADVANCE ADVANCE=" << std::setprecision(4) << pa << "; Override pressure advance value\n";
|
||||
else if (this->config.gcode_flavor == gcfRepRapFirmware)
|
||||
gcode << ("M572 D0 S") << std::setprecision(4) << pa << "; Override pressure advance value\n";
|
||||
else
|
||||
gcode << "M900 K" << std::setprecision(4) << pa << "; Override pressure advance value\n";
|
||||
}
|
||||
return gcode.str();
|
||||
}
|
||||
|
||||
std::string GCodeWriter::reset_e(bool force)
|
||||
{
|
||||
if (FLAVOR_IS(gcfMach3)
|
||||
|
|
|
@ -50,6 +50,7 @@ public:
|
|||
std::string set_temperature(unsigned int temperature, bool wait = false, int tool = -1) const;
|
||||
std::string set_bed_temperature(int temperature, bool wait = false);
|
||||
std::string set_acceleration(unsigned int acceleration);
|
||||
std::string set_pressure_advance(double pa) const;
|
||||
std::string reset_e(bool force = false);
|
||||
std::string update_progress(unsigned int num, unsigned int tot, bool allow_100 = false) const;
|
||||
// return false if this extruder was already selected
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace Slic3r {
|
|||
|
||||
enum GCodeFlavor : unsigned char {
|
||||
gcfMarlinLegacy, gcfRepRapSprinter, gcfRepRapFirmware, gcfRepetier, gcfTeacup, gcfMakerWare, gcfMarlinFirmware, gcfSailfish, gcfMach3, gcfMachinekit,
|
||||
gcfSmoothie, gcfNoExtrusion,
|
||||
gcfSmoothie, gcfNoExtrusion, gcfKlipper
|
||||
};
|
||||
|
||||
enum class FuzzySkinType {
|
||||
|
|
|
@ -2782,7 +2782,7 @@ bool MaxVolumetricSpeedWizard::start_calibration(std::vector<int> tray_ids)
|
|||
std::string error_message;
|
||||
CalibUtils::calib_max_vol_speed(calib_info, error_message);
|
||||
if (!error_message.empty()) {
|
||||
MessageDialog msg_dlg(nullptr, error_message, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L(error_message), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return false;
|
||||
}
|
||||
|
@ -2960,7 +2960,7 @@ bool TemperatureWizard::start_calibration(std::vector<int> tray_ids)
|
|||
std::string error_message;
|
||||
CalibUtils::calib_temptue(calib_info, error_message);
|
||||
if (!error_message.empty()) {
|
||||
MessageDialog msg_dlg(nullptr, error_message, wxEmptyString, wxICON_WARNING | wxOK);
|
||||
MessageDialog msg_dlg(nullptr, _L(error_message), wxEmptyString, wxICON_WARNING | wxOK);
|
||||
msg_dlg.ShowModal();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7,9 +7,6 @@
|
|||
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
// todo test
|
||||
#include "../GUI/BBLStatusBar.hpp"
|
||||
|
||||
|
||||
namespace Slic3r {
|
||||
namespace GUI {
|
||||
|
@ -66,6 +63,16 @@ static void read_model_from_file(const std::string& input_file, Model& model)
|
|||
object->ensure_on_bed();
|
||||
}
|
||||
|
||||
std::array<Vec3d, 4> get_cut_plane(const BoundingBoxf3 &bbox, const double &cut_height)
|
||||
{
|
||||
std::array<Vec3d, 4> plane_pts;
|
||||
plane_pts[0] = Vec3d(bbox.min(0), bbox.min(1), cut_height);
|
||||
plane_pts[1] = Vec3d(bbox.max(0), bbox.min(1), cut_height);
|
||||
plane_pts[2] = Vec3d(bbox.max(0), bbox.max(1), cut_height);
|
||||
plane_pts[3] = Vec3d(bbox.min(0), bbox.max(1), cut_height);
|
||||
return plane_pts;
|
||||
}
|
||||
|
||||
void CalibUtils::calib_PA(const X1CCalibInfos& calib_infos, std::string& error_message)
|
||||
{
|
||||
DeviceManager *dev = Slic3r::GUI::wxGetApp().getDeviceManager();
|
||||
|
@ -306,6 +313,33 @@ void CalibUtils::calib_flowrate(int pass, const CalibInfo& calib_info, std::stri
|
|||
send_to_print(calib_info.dev_id, calib_info.select_ams, calib_info.process_bar, calib_info.bed_type, error_message);
|
||||
}
|
||||
|
||||
void CalibUtils::calib_generic_PA(const CalibInfo &calib_info, std::string &error_message)
|
||||
{
|
||||
const Calib_Params ¶ms = calib_info.params;
|
||||
if (params.mode != CalibMode::Calib_PA_Line)
|
||||
return;
|
||||
|
||||
Model model;
|
||||
std::string input_file = Slic3r::resources_dir() + "/calib/pressure_advance/pressure_advance_test.stl";
|
||||
read_model_from_file(input_file, model);
|
||||
|
||||
DynamicPrintConfig print_config = calib_info.print_prest->config;
|
||||
DynamicPrintConfig filament_config = calib_info.filament_prest->config;
|
||||
DynamicPrintConfig printer_config = calib_info.printer_prest->config;
|
||||
|
||||
DynamicPrintConfig full_config;
|
||||
full_config.apply(FullPrintConfig::defaults());
|
||||
full_config.apply(print_config);
|
||||
full_config.apply(filament_config);
|
||||
full_config.apply(printer_config);
|
||||
|
||||
process_and_store_3mf(&model, full_config, params, error_message);
|
||||
if (!error_message.empty())
|
||||
return;
|
||||
|
||||
send_to_print(calib_info.dev_id, calib_info.select_ams, calib_info.process_bar, calib_info.bed_type, error_message);
|
||||
}
|
||||
|
||||
void CalibUtils::calib_temptue(const CalibInfo& calib_info, std::string& error_message)
|
||||
{
|
||||
const Calib_Params ¶ms = calib_info.params;
|
||||
|
@ -509,6 +543,55 @@ void CalibUtils::calib_VFA(const CalibInfo& calib_info, std::string& error_messa
|
|||
send_to_print(calib_info.dev_id, calib_info.select_ams, calib_info.process_bar, calib_info.bed_type, error_message);
|
||||
}
|
||||
|
||||
void CalibUtils::calib_retraction(const CalibInfo &calib_info, std::string &error_message)
|
||||
{
|
||||
const Calib_Params ¶ms = calib_info.params;
|
||||
if (params.mode != CalibMode::Calib_Retraction_tower)
|
||||
return;
|
||||
|
||||
Model model;
|
||||
std::string input_file = Slic3r::resources_dir() + "/calib/retraction/retraction_tower.stl";
|
||||
read_model_from_file(input_file, model);
|
||||
|
||||
DynamicPrintConfig print_config = calib_info.print_prest->config;
|
||||
DynamicPrintConfig filament_config = calib_info.filament_prest->config;
|
||||
DynamicPrintConfig printer_config = calib_info.printer_prest->config;
|
||||
|
||||
auto obj = model.objects[0];
|
||||
|
||||
double layer_height = 0.2;
|
||||
|
||||
auto max_lh = printer_config.option<ConfigOptionFloats>("max_layer_height");
|
||||
if (max_lh->values[0] < layer_height) max_lh->values[0] = {layer_height};
|
||||
|
||||
obj->config.set_key_value("wall_loops", new ConfigOptionInt(2));
|
||||
obj->config.set_key_value("top_shell_layers", new ConfigOptionInt(0));
|
||||
obj->config.set_key_value("bottom_shell_layers", new ConfigOptionInt(3));
|
||||
obj->config.set_key_value("sparse_infill_density", new ConfigOptionPercent(0));
|
||||
obj->config.set_key_value("initial_layer_print_height", new ConfigOptionFloat(layer_height));
|
||||
obj->config.set_key_value("layer_height", new ConfigOptionFloat(layer_height));
|
||||
|
||||
// cut upper
|
||||
auto obj_bb = obj->bounding_box();
|
||||
auto height = 1.0 + 0.4 + ((params.end - params.start)) / params.step;
|
||||
if (height < obj_bb.size().z()) {
|
||||
std::array<Vec3d, 4> plane_pts = get_cut_plane(obj_bb, height);
|
||||
cut_model(model, plane_pts, ModelObjectCutAttribute::KeepLower);
|
||||
}
|
||||
|
||||
DynamicPrintConfig full_config;
|
||||
full_config.apply(FullPrintConfig::defaults());
|
||||
full_config.apply(print_config);
|
||||
full_config.apply(filament_config);
|
||||
full_config.apply(printer_config);
|
||||
|
||||
process_and_store_3mf(&model, full_config, params, error_message);
|
||||
if (!error_message.empty())
|
||||
return;
|
||||
|
||||
send_to_print(calib_info.dev_id, calib_info.select_ams, calib_info.process_bar, calib_info.bed_type, error_message);
|
||||
}
|
||||
|
||||
void CalibUtils::process_and_store_3mf(Model* model, const DynamicPrintConfig& full_config, const Calib_Params& params, std::string& error_message)
|
||||
{
|
||||
Pointfs bedfs = full_config.opt<ConfigOptionPoints>("printable_area")->values;
|
||||
|
@ -544,7 +627,7 @@ void CalibUtils::process_and_store_3mf(Model* model, const DynamicPrintConfig& f
|
|||
BuildVolume build_volume(bedfs, print_height);
|
||||
unsigned int count = model->update_print_volume_state(build_volume);
|
||||
if (count == 0) {
|
||||
error_message = "Nothing to be sliced, either the print is empty or no object is fully inside the print volume before apply.";
|
||||
error_message = "Unable to calibrate: maybe because the set calibration value range is too large, or the step is too small";
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,9 +42,11 @@ public:
|
|||
static bool get_flow_ratio_calib_results(std::vector<FlowRatioCalibResult> &flow_ratio_calib_results);
|
||||
static void calib_flowrate(int pass, const CalibInfo& calib_info, std::string& error_message);
|
||||
|
||||
static void calib_generic_PA(const CalibInfo& calib_info, std::string &error_message);
|
||||
static void calib_temptue(const CalibInfo& calib_info, std::string& error_message);
|
||||
static void calib_max_vol_speed(const CalibInfo& calib_info, std::string& error_message);
|
||||
static void calib_VFA(const CalibInfo& calib_info, std::string& error_message);
|
||||
static void calib_retraction(const CalibInfo &calib_info, std::string &error_message);
|
||||
|
||||
private:
|
||||
static void process_and_store_3mf(Model* model, const DynamicPrintConfig& full_config, const Calib_Params& params, std::string& error_message);
|
||||
|
|
Loading…
Reference in a new issue