Juntion Deviation + Documentation

Junction Deviation Calibration Test
Base documentation
 - VFA
 - Input Shaping
 - Junction Deviation

Co-Authored-By: Rodrigo <162915171+rf47@users.noreply.github.com>
This commit is contained in:
Ian Bassi
2025-03-30 14:23:17 -03:00
parent 3662b5139c
commit 428cba9a25
13 changed files with 307 additions and 15 deletions

View File

@@ -3749,7 +3749,6 @@ LayerResult GCode::process_layer(
//BBS: set layer time fan speed after layer change gcode
gcode += ";_SET_FAN_SPEED_CHANGING_LAYER\n";
//TODO: Why this is not a Switch-case?
if (print.calib_mode() == CalibMode::Calib_PA_Tower) {
gcode += writer().set_pressure_advance(print.calib_params().start + static_cast<int>(print_z) * print.calib_params().step);
} else if (print.calib_mode() == CalibMode::Calib_Temp_Tower) {
@@ -3770,9 +3769,13 @@ LayerResult GCode::process_layer(
gcode += buf;
} else if (print.calib_mode() == CalibMode::Calib_Input_shaping_freq) {
if (m_layer_index == 1){
if (print.config().gcode_flavor.value == gcfMarlinFirmware) {
gcode += writer().set_junction_deviation(0.25);//Set junction deviation at high value to maximize ringing.
}
gcode += writer().set_input_shaping('A', print.calib_params().start, 0.f);
} else {
if (print.calib_params().freqStartX == print.calib_params().freqStartY && print.calib_params().freqEndX == print.calib_params().freqEndY) {
gcode += writer().set_junction_deviation(0.25);
gcode += writer().set_input_shaping('A', 0.f, (print.calib_params().freqStartX) + ((print.calib_params().freqEndX)-(print.calib_params().freqStartX)) * (m_layer_index - 2) / (m_layer_count - 3));
} else {
gcode += writer().set_input_shaping('X', 0.f, (print.calib_params().freqStartX) + ((print.calib_params().freqEndX)-(print.calib_params().freqStartX)) * (m_layer_index - 2) / (m_layer_count - 3));
@@ -3781,11 +3784,16 @@ LayerResult GCode::process_layer(
}
} else if (print.calib_mode() == CalibMode::Calib_Input_shaping_damp) {
if (m_layer_index == 1){
gcode += writer().set_input_shaping('X', 0.f, print.calib_params().freqStartX);
if (print.config().gcode_flavor.value == gcfMarlinFirmware) {
gcode += writer().set_junction_deviation(0.25); // Set junction deviation at high value to maximize ringing.
}
gcode += writer().set_input_shaping('X', 0.f, print.calib_params().freqStartX);
gcode += writer().set_input_shaping('Y', 0.f, print.calib_params().freqStartY);
} else {
gcode += writer().set_input_shaping('A', print.calib_params().start + ((print.calib_params().end)-(print.calib_params().start)) * (m_layer_index) / (m_layer_count), 0.f);
}
} else if (print.calib_mode() == CalibMode::Calib_Junction_Deviation){
gcode += writer().set_junction_deviation(print.calib_params().start + ((print.calib_params().end)-(print.calib_params().start)) * (m_layer_index) / (m_layer_count));
}
//BBS

View File

@@ -313,6 +313,16 @@ std::string GCodeWriter::set_accel_and_jerk(unsigned int acceleration, double je
}
std::string GCodeWriter::set_junction_deviation(double junction_deviation){
std::ostringstream gcode;
if (FLAVOR_IS_NOT(gcfMarlinFirmware)) {
throw std::runtime_error("Junction deviation is only supported by Marlin firmware");
}
gcode << "M205 J" << junction_deviation << " ; Junction Deviation\n";
return gcode.str();
}
std::string GCodeWriter::set_pressure_advance(double pa) const
{
std::ostringstream gcode;

View File

@@ -53,6 +53,7 @@ public:
std::string set_jerk_xy(double jerk);
// Orca: set acceleration and jerk in one command for Klipper
std::string set_accel_and_jerk(unsigned int acceleration, double jerk);
std::string set_junction_deviation(double junction_deviation);
std::string set_pressure_advance(double pa) const;
std::string set_input_shaping(char axis, float damp, float freq) const;
std::string reset_e(bool force = false);

View File

@@ -23,7 +23,8 @@ enum class CalibMode : int {
Calib_VFA_Tower,
Calib_Retraction_tower,
Calib_Input_shaping_freq,
Calib_Input_shaping_damp
Calib_Input_shaping_damp,
Calib_Junction_Deviation
};
enum class CalibState { Start = 0, Preset, Calibration, CoarseSave, FineCalibration, Save, Finish };

View File

@@ -48,6 +48,8 @@ static wxString get_default_name(wxString filament_name, CalibMode mode){
break;
case Slic3r::CalibMode::Calib_Input_shaping_damp:
break;
case Slic3r::CalibMode::Calib_Junction_Deviation:
break;
default:
break;
}

View File

@@ -3000,6 +3000,17 @@ void MainFrame::init_menubar_as_editor()
m_topbar->GetCalibMenu()->AppendSubMenu(input_shaping_menu, _L("Input Shaping"));
// Add Junction Deviation option to More menu
append_menu_item(
advance_menu, wxID_ANY, _L("Junction Deviation"), _L("Junction Deviation calibration"),
[this](wxCommandEvent&) {
if (!m_junction_deviation_calib_dlg)
m_junction_deviation_calib_dlg = new Junction_Deviation_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater);
m_junction_deviation_calib_dlg->ShowModal();
},
"", nullptr,
[this]() {return m_plater->is_view3D_shown();; }, this);
m_topbar->GetCalibMenu()->AppendSubMenu(advance_menu, _L("More..."));
// help
@@ -3098,6 +3109,16 @@ void MainFrame::init_menubar_as_editor()
}, "", nullptr,
[this]() {return m_plater->is_view3D_shown();; }, this);
// Add Junction Deviation option to More menu
append_menu_item(
advance_menu, wxID_ANY, _L("Junction Deviation"), _L("Junction Deviation calibration"),
[this](wxCommandEvent&) {
if (!m_junction_deviation_calib_dlg)
m_junction_deviation_calib_dlg = new Junction_Deviation_Test_Dlg((wxWindow*)this, wxID_ANY, m_plater);
m_junction_deviation_calib_dlg->ShowModal();
}, "", nullptr,
[this]() {return m_plater->is_view3D_shown();; }, this);
// Input Shaping calibrations
auto input_shaping_menu = new wxMenu();

View File

@@ -356,6 +356,7 @@ public:
Retraction_Test_Dlg* m_retraction_calib_dlg{ nullptr };
Input_Shaping_Freq_Test_Dlg* m_IS_freq_calib_dlg{ nullptr };
Input_Shaping_Damp_Test_Dlg* m_IS_damp_calib_dlg{ nullptr };
Junction_Deviation_Test_Dlg* m_junction_deviation_calib_dlg{ nullptr };
// BBS. Replace title bar and menu bar with top bar.
BBLTopbar* m_topbar{ nullptr };

View File

@@ -10220,6 +10220,41 @@ void Plater::calib_input_shaping_damp(const Calib_Params& params)
p->background_process.fff_print()->set_calib_params(params);
}
void Plater::calib_junction_deviation(const Calib_Params& params)
{
const auto calib_junction_deviation = wxString::Format(L"Input shaping Damping test");
new_project(false, false, calib_junction_deviation);
wxGetApp().mainframe->select_tab(size_t(MainFrame::tp3DEditor));
if (params.mode != CalibMode::Calib_Junction_Deviation)
return;
add_model(false, Slic3r::resources_dir() + (params.test_model < 1 ? "/calib/input_shaping/ringing_tower.stl" : "/calib/input_shaping/fast_input_shaping_test.stl"));
auto print_config = &wxGetApp().preset_bundle->prints.get_edited_preset().config;
auto filament_config = &wxGetApp().preset_bundle->filaments.get_edited_preset().config;
filament_config->set_key_value("slow_down_layer_time", new ConfigOptionFloats { 2.0 });
filament_config->set_key_value("filament_max_volumetric_speed", new ConfigOptionFloats { 200 });
print_config->set_key_value("enable_overhang_speed", new ConfigOptionBool { false });
print_config->set_key_value("timelapse_type", new ConfigOptionEnum<TimelapseType>(tlTraditional));
print_config->set_key_value("wall_loops", new ConfigOptionInt(1));
print_config->set_key_value("top_shell_layers", new ConfigOptionInt(0));
print_config->set_key_value("bottom_shell_layers", new ConfigOptionInt(1));
print_config->set_key_value("sparse_infill_density", new ConfigOptionPercent(0));
print_config->set_key_value("detect_thin_wall", new ConfigOptionBool(false));
print_config->set_key_value("spiral_mode", new ConfigOptionBool(true));
print_config->set_key_value("spiral_mode_smooth", new ConfigOptionBool(true));
model().objects[0]->config.set_key_value("brim_type", new ConfigOptionEnum<BrimType>(btOuterOnly));
model().objects[0]->config.set_key_value("brim_width", new ConfigOptionFloat(3.0));
model().objects[0]->config.set_key_value("brim_object_gap", new ConfigOptionFloat(0.0));
changed_objects({ 0 });
wxGetApp().get_tab(Preset::TYPE_PRINT)->update_dirty();
wxGetApp().get_tab(Preset::TYPE_FILAMENT)->update_dirty();
wxGetApp().get_tab(Preset::TYPE_PRINT)->update_ui_from_settings();
wxGetApp().get_tab(Preset::TYPE_FILAMENT)->update_ui_from_settings();
p->background_process.fff_print()->set_calib_params(params);
}
BuildVolume_Type Plater::get_build_volume_type() const { return p->bed.get_build_volume_type(); }
void Plater::import_zip_archive()

View File

@@ -275,6 +275,7 @@ public:
void calib_VFA(const Calib_Params& params);
void calib_input_shaping_freq(const Calib_Params& params);
void calib_input_shaping_damp(const Calib_Params& params);
void calib_junction_deviation(const Calib_Params& params);
BuildVolume_Type get_build_volume_type() const;

View File

@@ -1068,4 +1068,111 @@ void Input_Shaping_Damp_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) {
Fit();
}
}} // namespace Slic3r::GUI
// Junction_Deviation_Test_Dlg
//
Junction_Deviation_Test_Dlg::Junction_Deviation_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater)
: DPIDialog(parent, id, _L("Junction Deviation test"), wxDefaultPosition, parent->FromDIP(wxSize(-1, 280)), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER), m_plater(plater)
{
wxBoxSizer* v_sizer = new wxBoxSizer(wxVERTICAL);
SetSizer(v_sizer);
// Model selection
wxString m_rbModelChoices[] = { _L("Ringing Tower"), _L("Fast Tower") };
int m_rbModelNChoices = sizeof(m_rbModelChoices) / sizeof(wxString);
m_rbModel = new wxRadioBox(this, wxID_ANY, _L("Test model"), wxDefaultPosition, wxDefaultSize, m_rbModelNChoices, m_rbModelChoices, 1, wxRA_SPECIFY_ROWS);
m_rbModel->SetSelection(1);
v_sizer->Add(m_rbModel, 0, wxALL | wxEXPAND, 5);
// Settings
wxString start_jd_str = _L("Start junction deviation: ");
wxString end_jd_str = _L("End junction deviation: ");
auto text_size = wxWindow::GetTextExtent(start_jd_str);
text_size.IncTo(wxWindow::GetTextExtent(end_jd_str));
text_size.x = text_size.x * 1.5;
wxStaticBoxSizer* settings_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _L("Junction Deviation settings"));
auto st_size = FromDIP(wxSize(text_size.x, -1));
auto ti_size = FromDIP(wxSize(90, -1));
// Start junction deviation
auto start_jd_sizer = new wxBoxSizer(wxHORIZONTAL);
auto start_jd_text = new wxStaticText(this, wxID_ANY, start_jd_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiJDStart = new TextInput(this, wxString::Format("%.3f", 0.000), _L("mm"), "", wxDefaultPosition, ti_size, wxTE_CENTRE);
m_tiJDStart->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
start_jd_sizer->Add(start_jd_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2);
start_jd_sizer->Add(m_tiJDStart, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2);
settings_sizer->Add(start_jd_sizer);
// End junction deviation
auto end_jd_sizer = new wxBoxSizer(wxHORIZONTAL);
auto end_jd_text = new wxStaticText(this, wxID_ANY, end_jd_str, wxDefaultPosition, st_size, wxALIGN_LEFT);
m_tiJDEnd = new TextInput(this, wxString::Format("%.3f", 0.250), _L("mm"), "", wxDefaultPosition, ti_size, wxTE_CENTRE);
m_tiJDEnd->GetTextCtrl()->SetValidator(wxTextValidator(wxFILTER_NUMERIC));
end_jd_sizer->Add(end_jd_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2);
end_jd_sizer->Add(m_tiJDEnd, 0, wxALL | wxALIGN_CENTER_VERTICAL, 2);
settings_sizer->Add(end_jd_sizer);
// Add note about junction deviation
auto note_text = new wxStaticText(this, wxID_ANY, _L("Note: Lower values = sharper corners but slower speeds"),
wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
note_text->SetForegroundColour(wxColour(128, 128, 128));
settings_sizer->Add(note_text, 0, wxALL, 5);
v_sizer->Add(settings_sizer);
v_sizer->Add(0, FromDIP(10), 0, wxEXPAND, 5);
m_btnStart = new Button(this, _L("OK"));
StateColor btn_bg_green(std::pair<wxColour, int>(wxColour(0, 137, 123), StateColor::Pressed),
std::pair<wxColour, int>(wxColour(38, 166, 154), StateColor::Hovered),
std::pair<wxColour, int>(wxColour(0, 150, 136), StateColor::Normal));
m_btnStart->SetBackgroundColor(btn_bg_green);
m_btnStart->SetBorderColor(wxColour(0, 150, 136));
m_btnStart->SetTextColor(wxColour("#FFFFFE"));
m_btnStart->SetSize(wxSize(FromDIP(48), FromDIP(24)));
m_btnStart->SetMinSize(wxSize(FromDIP(48), FromDIP(24)));
m_btnStart->SetCornerRadius(FromDIP(3));
m_btnStart->Bind(wxEVT_BUTTON, &Junction_Deviation_Test_Dlg::on_start, this);
v_sizer->Add(m_btnStart, 0, wxALL | wxALIGN_RIGHT, FromDIP(5));
m_btnStart->Connect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Junction_Deviation_Test_Dlg::on_start), NULL, this);
Layout();
Fit();
}
Junction_Deviation_Test_Dlg::~Junction_Deviation_Test_Dlg() {
// Disconnect Events
m_btnStart->Disconnect(wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(Junction_Deviation_Test_Dlg::on_start), NULL, this);
}
void Junction_Deviation_Test_Dlg::on_start(wxCommandEvent& event) {
bool read_double = false;
read_double = m_tiJDStart->GetTextCtrl()->GetValue().ToDouble(&m_params.start);
read_double = read_double && m_tiJDEnd->GetTextCtrl()->GetValue().ToDouble(&m_params.end);
if (!read_double || m_params.start < 0 || m_params.end >= 1 || m_params.start >= m_params.end) {
MessageDialog msg_dlg(nullptr, _L("Please input valid values\n(0 <= Junction Deviation < 1)"), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
} else if (m_params.end > 0.3) {
MessageDialog msg_dlg(nullptr, _L("NOTE: High values may cause Layer shift"), wxEmptyString, wxICON_WARNING | wxOK);
msg_dlg.ShowModal();
return;
}
m_params.mode = CalibMode::Calib_Junction_Deviation;
// Set model type based on selection
m_params.test_model = m_rbModel->GetSelection() == 0 ? 0 : 1; // 0 = Ringing Tower, 1 = Fast Tower
m_plater->calib_junction_deviation(m_params);
EndModal(wxID_OK);
}
void Junction_Deviation_Test_Dlg::on_dpi_changed(const wxRect& suggested_rect) {
this->Refresh();
Fit();
}
}} // namespace Slic3r::GUI

View File

@@ -168,5 +168,22 @@ protected:
Plater* m_plater;
};
class Junction_Deviation_Test_Dlg : public DPIDialog
{
public:
Junction_Deviation_Test_Dlg(wxWindow* parent, wxWindowID id, Plater* plater);
~Junction_Deviation_Test_Dlg();
void on_dpi_changed(const wxRect& suggested_rect) override;
protected:
virtual void on_start(wxCommandEvent& event);
Calib_Params m_params;
wxRadioBox* m_rbModel;
TextInput* m_tiJDStart;
TextInput* m_tiJDEnd;
Button* m_btnStart;
Plater* m_plater;
};
}} // namespace Slic3r::GUI
#endif

View File

@@ -61,6 +61,8 @@ std::string get_calib_mode_name(CalibMode cali_mode, int stage)
return "input_shaping_freq_calib_mode";
case CalibMode::Calib_Input_shaping_damp:
return "input_shaping_damp_calib_mode";
case CalibMode::Calib_Junction_Deviation:
return "junction_deviation_calib_mode";
default:
assert(false);
return "";
@@ -204,6 +206,8 @@ CalibMode CalibUtils::get_calib_mode_by_name(const std::string name, int& cali_s
return CalibMode::Calib_Input_shaping_freq;
else if (name == "input_shaping_damp_calib_mode")
return CalibMode::Calib_Input_shaping_damp;
else if (name == "junction_deviation_calib_mode")
return CalibMode::Calib_Junction_Deviation;
return CalibMode::Calib_None;
}