From 080b3e4bfae44c6d426ba3c2c83641df7b97af77 Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Fri, 16 Aug 2024 18:20:44 +0200 Subject: [PATCH 01/13] Basic ATC: start with copy of manual ATC --- FluidNC/src/ToolChangers/atc_basic.cpp | 151 +++++++++++++++++++++++++ FluidNC/src/ToolChangers/atc_basic.h | 66 +++++++++++ 2 files changed, 217 insertions(+) create mode 100644 FluidNC/src/ToolChangers/atc_basic.cpp create mode 100644 FluidNC/src/ToolChangers/atc_basic.h diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp new file mode 100644 index 000000000..ca2e6d755 --- /dev/null +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -0,0 +1,151 @@ +// Copyright (c) 2024 - Bart Dring +// Use of this source code is governed by a GPLv3 license that can be found in the LICENSE file. + +#include "atc_basic.h" +#include "../Machine/MachineConfig.h" +#include +#include + +namespace ATCs { + void Basic_ATC::init() { + log_info("ATC:" << name()); + } + + void Basic_ATC::probe_notification() {} + + bool Basic_ATC::tool_change(uint8_t new_tool, bool pre_select, bool set_tool) { + bool spindle_was_on = false; // used to restore the spindle state + bool was_inch_mode = false; // allows use to restore inch mode if req'd + + protocol_buffer_synchronize(); // wait for all motion to complete + _macro.erase(); // clear previous gcode + + // M6T0 is used to reset this ATC and allow us to start a new job + if (new_tool == 0 || set_tool) { + _prev_tool = new_tool; + move_to_safe_z(); + move_to_change_location(); + reset(); + _macro.run(nullptr); + return true; + } + + was_inch_mode = (gc_state.modal.units == Units::Inches); + + if (was_inch_mode) { + _macro.addf("G21"); + } + + try { + if (_prev_tool == 0) { // M6T from T0 is used for a manual change before zero'ing + move_to_change_location(); + _macro.addf("G4P0 0.1"); + _macro.addf("G43.1Z0"); + _macro.addf("(MSG : Install tool #%d)", new_tool); + if (was_inch_mode) { + _macro.addf("G20"); + } + _macro.run(nullptr); + _prev_tool = new_tool; + return true; + } + + _prev_tool = new_tool; + + // save current location, so we can return after the tool change. + _macro.addf("#= #<_x>"); + _macro.addf("#= #<_y>"); + _macro.addf("#= #<_z>"); + + move_to_safe_z(); + + // turn off the spindle + if (gc_state.modal.spindle != SpindleState::Disable) { + spindle_was_on = true; + _macro.addf("M5"); + } + + // if we have not determined the tool setter offset yet, we need to do that. + if (!_have_tool_setter_offset) { + move_over_toolsetter(); + ets_probe(); + _macro.addf("#<_ets_tool1_z>=[#5063]"); // save the value of the tool1 ETS Z + _have_tool_setter_offset = true; + } + + move_to_change_location(); + + _macro.addf("G4P0 0.1"); + _macro.addf("(MSG: Install tool #%d then resume to continue)", new_tool); + _macro.addf("M0"); + + // probe the new tool + move_to_safe_z(); + move_over_toolsetter(); + ets_probe(); + + // TLO is simply the difference between the tool1 probe and the new tool probe. + _macro.addf("#<_my_tlo_z >=[#5063 - #<_ets_tool1_z>]"); + _macro.addf("G43.1Z#<_my_tlo_z>"); + + move_to_safe_z(); + + // return to location before the tool change + _macro.addf("G0X#Y#"); + _macro.addf("G0Z#"); + + if (spindle_was_on) { + _macro.addf("M3"); // spindle should handle spinup delay + } + + if (was_inch_mode) { + _macro.addf("G20"); + } + + _macro.run(nullptr); + + return true; + } catch (...) { log_info("Exception caught"); } + + return false; + } + + void Basic_ATC::reset() { + _is_OK = true; + _have_tool_setter_offset = false; + _prev_tool = gc_state.tool; // Double check this + _macro.addf("G4P0 0.1"); // reset the TLO to 0 + _macro.addf("(MSG: TLO Z reset to 0)"); // + } + + void Basic_ATC::move_to_change_location() { + move_to_safe_z(); + _macro.addf("G53G0X%0.3fY%0.3fZ%0.3f", _change_mpos[0], _change_mpos[1], _change_mpos[2]); + } + + void Basic_ATC::move_to_safe_z() { + _macro.addf("G53G0Z%0.3f", _safe_z); + } + + void Basic_ATC::move_over_toolsetter() { + move_to_safe_z(); + _macro.addf("G53G0X%0.3fY%0.3f", _ets_mpos[0], _ets_mpos[1]); + } + + void Basic_ATC::ets_probe() { + _macro.addf("G53G0Z #"); // rapid down + + // do a fast probe if there is a seek that is faster than feed + if (_probe_seek_rate > _probe_feed_rate) { + _macro.addf("G53 G38.2 Z%0.3f F%0.3f", _ets_mpos[2], _probe_seek_rate); + _macro.addf("G0Z[#<_z> + 5]"); // retract befor next probe + } + + // do the feed rate probe + _macro.addf("G53 G38.2 Z%0.3f F%0.3f", _ets_mpos[2], _probe_feed_rate); + } + + namespace { + ATCFactory::InstanceBuilder registration("atc_basic"); + } +} diff --git a/FluidNC/src/ToolChangers/atc_basic.h b/FluidNC/src/ToolChangers/atc_basic.h new file mode 100644 index 000000000..726f1c446 --- /dev/null +++ b/FluidNC/src/ToolChangers/atc_basic.h @@ -0,0 +1,66 @@ +// Copyright (c) 2024 - Bart Dring +// Use of this source code is governed by a GPLv3 license that can be found in the LICENSE file. + +#pragma once + +#include "src/Config.h" + +#include "src/Configuration/Configurable.h" + +#include "src/Channel.h" +#include "src/Module.h" +#include "atc.h" +#include "../Machine/Macros.h" + +namespace ATCs { + class Basic_ATC : public ATC { + public: + Basic_ATC(const char* name) : ATC(name) {} + + Basic_ATC(const Basic_ATC&) = delete; + Basic_ATC(Basic_ATC&&) = delete; + Basic_ATC& operator=(const Basic_ATC&) = delete; + Basic_ATC& operator=(Basic_ATC&&) = delete; + + virtual ~Basic_ATC() = default; + + private: + // config items + float _safe_z = 50.0; + float _probe_seek_rate = 200.0; + float _probe_feed_rate = 80.0; + std::vector _ets_mpos = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + std::vector _change_mpos = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; // manual tool change location + float _ets_rapid_z_mpos = 0; + + bool _is_OK = false; + uint8_t _prev_tool = 0; // TODO This could be a NV setting + bool _have_tool_setter_offset = false; + float _tool_setter_offset = 0.0; // have we established an offset. + float _tool_setter_position[MAX_N_AXIS]; + + void move_to_change_location(); + void move_to_safe_z(); + void move_over_toolsetter(); + void ets_probe(); + void reset(); + + Macro _macro; + + public: + void init() override; + void probe_notification() override; + bool tool_change(uint8_t value, bool pre_select, bool set_tool) override; + + void validate() override {} + + void group(Configuration::HandlerBase& handler) override { + handler.item("safe_z_mpos_mm", _safe_z, -100000, 100000); + handler.item("probe_seek_rate_mm_per_min", _probe_seek_rate, 1, 10000); + handler.item("probe_feed_rate_mm_per_min", _probe_feed_rate, 1, 10000); + handler.item("change_mpos_mm", _change_mpos); + handler.item("ets_mpos_mm", _ets_mpos); + handler.item("ets_rapid_z_mpos_mm", _ets_rapid_z_mpos); + } + }; +} From 29918880673a24723b1e1af9aa524a8fbee5a8cb Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Fri, 16 Aug 2024 21:20:44 +0200 Subject: [PATCH 02/13] Initial draft --- FluidNC/src/ToolChangers/atc_basic.cpp | 157 +++++++++++++------------ FluidNC/src/ToolChangers/atc_basic.h | 23 +++- 2 files changed, 98 insertions(+), 82 deletions(-) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index ca2e6d755..85c6737ba 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -14,94 +14,96 @@ namespace ATCs { void Basic_ATC::probe_notification() {} bool Basic_ATC::tool_change(uint8_t new_tool, bool pre_select, bool set_tool) { - bool spindle_was_on = false; // used to restore the spindle state - bool was_inch_mode = false; // allows use to restore inch mode if req'd - protocol_buffer_synchronize(); // wait for all motion to complete _macro.erase(); // clear previous gcode + + if (pre_select) { // not implemented + return true; + } - // M6T0 is used to reset this ATC and allow us to start a new job - if (new_tool == 0 || set_tool) { + // set_tool is used to update the current tool and reset the TLO to 0 + if (set_tool) { _prev_tool = new_tool; - move_to_safe_z(); - move_to_change_location(); - reset(); + _macro.addf("G4P0 0.0"); + if (!_have_tool_setter_offset) { + get_ets_offset(); + } _macro.run(nullptr); return true; } - - was_inch_mode = (gc_state.modal.units == Units::Inches); - - if (was_inch_mode) { + + //save machine states + bool spindle_was_on = (gc_state.modal.spindle != SpindleState::Disable); // used to restore the spindle state + bool was_inch_mode = (gc_state.modal.units == Units::Inches); + bool was_absolute_mode = (gc_state.modal.distance == Distance::Absolute); + bool mistcoolant_was_on= (gc_state.modal.coolant.Mist); + bool floodcoolant_was_on = (gc_state.modal.coolant.Flood); + // save current location, so we can return after the tool change. + _macro.addf("#= #<_x>"); + _macro.addf("#= #<_y>"); + _macro.addf("#= #<_z>"); + + if (mistcoolant_was_on || floodcoolant_was_on) { + _macro.addf("M9"); + } + if (was_inch_mode) { // become Metric _macro.addf("G21"); } + if (!was_absolute_mode) { // become absolute + _macro.addf("G90"); + } + if (spindle_was_on) { // turn off the spindle + _macro.addf("M5"); + } try { - if (_prev_tool == 0) { // M6T from T0 is used for a manual change before zero'ing - move_to_change_location(); - _macro.addf("G4P0 0.1"); - _macro.addf("G43.1Z0"); - _macro.addf("(MSG : Install tool #%d)", new_tool); - if (was_inch_mode) { - _macro.addf("G20"); - } - _macro.run(nullptr); - _prev_tool = new_tool; - return true; + if (_prev_tool > 0) { + // return tool + move_to_tool_position(_prev_tool); + _macro.addf(_toolreturn_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to return tool, operating the ATC using M62 & M63 + // ensure the macro didn't change positioning mode + _macro.addf("G90"); + _macro.addf("G21"); } - _prev_tool = new_tool; - - // save current location, so we can return after the tool change. - _macro.addf("#= #<_x>"); - _macro.addf("#= #<_y>"); - _macro.addf("#= #<_z>"); - - move_to_safe_z(); - - // turn off the spindle - if (gc_state.modal.spindle != SpindleState::Disable) { - spindle_was_on = true; - _macro.addf("M5"); - } - - // if we have not determined the tool setter offset yet, we need to do that. - if (!_have_tool_setter_offset) { - move_over_toolsetter(); - ets_probe(); - _macro.addf("#<_ets_tool1_z>=[#5063]"); // save the value of the tool1 ETS Z - _have_tool_setter_offset = true; + if (new_tool > 0) { + //pickup tool + move_to_tool_position(_prev_tool); + _macro.addf(_toolpickup_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to pickup tool, operating the ATC using M62 & M63 + // ensure the macro didn't change positioning mode + _macro.addf("G90"); + _macro.addf("G21"); + if (!_have_tool_setter_offset) { + get_ets_offset(); + } } - move_to_change_location(); - - _macro.addf("G4P0 0.1"); - _macro.addf("(MSG: Install tool #%d then resume to continue)", new_tool); - _macro.addf("M0"); - // probe the new tool - move_to_safe_z(); - move_over_toolsetter(); ets_probe(); // TLO is simply the difference between the tool1 probe and the new tool probe. _macro.addf("#<_my_tlo_z >=[#5063 - #<_ets_tool1_z>]"); _macro.addf("G43.1Z#<_my_tlo_z>"); - move_to_safe_z(); - // return to location before the tool change - _macro.addf("G0X#Y#"); - _macro.addf("G0Z#"); - + move_to_safe_z(); + _macro.addf("G0 X#Y#"); + _macro.addf("G0 Z#"); + if (was_inch_mode) { + _macro.addf("G20"); + } + if (!was_absolute_mode) { // become relative + _macro.addf("G91"); + } if (spindle_was_on) { _macro.addf("M3"); // spindle should handle spinup delay } - - if (was_inch_mode) { - _macro.addf("G20"); + if (mistcoolant_was_on) { + _macro.addf("M7"); + } + if (floodcoolant_was_on) { + _macro.addf("M8"); } - _macro.run(nullptr); return true; @@ -110,37 +112,40 @@ namespace ATCs { return false; } - void Basic_ATC::reset() { - _is_OK = true; - _have_tool_setter_offset = false; - _prev_tool = gc_state.tool; // Double check this - _macro.addf("G4P0 0.1"); // reset the TLO to 0 - _macro.addf("(MSG: TLO Z reset to 0)"); // - } - - void Basic_ATC::move_to_change_location() { + void Basic_ATC::move_to_tool_position(uint8_t tool_index) { + tool_index -= 1; move_to_safe_z(); - _macro.addf("G53G0X%0.3fY%0.3fZ%0.3f", _change_mpos[0], _change_mpos[1], _change_mpos[2]); + _macro.addf("G53 G0 X%0.3f Y%0.3f", _tool_mpos[tool_index][X_AXIS], _tool_mpos[tool_index][Y_AXIS]); + _macro.addf("#<_tc_tool_x >=%0.3f",_tool_mpos[tool_index][X_AXIS]); + _macro.addf("#<_tc_tool_y >=%0.3f",_tool_mpos[tool_index][Y_AXIS]); + _macro.addf("#<_tc_tool_z >=%0.3f",_tool_mpos[tool_index][Z_AXIS]); } void Basic_ATC::move_to_safe_z() { - _macro.addf("G53G0Z%0.3f", _safe_z); + _macro.addf("G53 G0 Z%0.3f", _safe_z); } void Basic_ATC::move_over_toolsetter() { move_to_safe_z(); - _macro.addf("G53G0X%0.3fY%0.3f", _ets_mpos[0], _ets_mpos[1]); + _macro.addf("G53 G0 X%0.3fY%0.3f", _ets_mpos[0], _ets_mpos[1]); + } + + void Basic_ATC::get_ets_offset(){ + ets_probe(); + _macro.addf("#<_ets_tool1_z>=[#5063]"); // save the value of the tool1 ETS Z + _have_tool_setter_offset = true; } void Basic_ATC::ets_probe() { - _macro.addf("G53G0Z #"); // rapid down + move_to_safe_z(); + move_over_toolsetter(); + _macro.addf("G53 G0 Z #"); // rapid down // do a fast probe if there is a seek that is faster than feed if (_probe_seek_rate > _probe_feed_rate) { _macro.addf("G53 G38.2 Z%0.3f F%0.3f", _ets_mpos[2], _probe_seek_rate); - _macro.addf("G0Z[#<_z> + 5]"); // retract befor next probe + _macro.addf("G0 Z[#<_z> + 5]"); // retract before next probe } - // do the feed rate probe _macro.addf("G53 G38.2 Z%0.3f F%0.3f", _ets_mpos[2], _probe_feed_rate); } diff --git a/FluidNC/src/ToolChangers/atc_basic.h b/FluidNC/src/ToolChangers/atc_basic.h index 726f1c446..b9b82052e 100644 --- a/FluidNC/src/ToolChangers/atc_basic.h +++ b/FluidNC/src/ToolChangers/atc_basic.h @@ -13,6 +13,8 @@ #include "../Machine/Macros.h" namespace ATCs { + const int TOOL_COUNT = 8; + class Basic_ATC : public ATC { public: Basic_ATC(const char* name) : ATC(name) {} @@ -30,22 +32,22 @@ namespace ATCs { float _probe_seek_rate = 200.0; float _probe_feed_rate = 80.0; std::vector _ets_mpos = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; - std::vector _change_mpos = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; // manual tool change location float _ets_rapid_z_mpos = 0; + std::vector _tool_mpos[TOOL_COUNT]; - bool _is_OK = false; uint8_t _prev_tool = 0; // TODO This could be a NV setting bool _have_tool_setter_offset = false; float _tool_setter_offset = 0.0; // have we established an offset. float _tool_setter_position[MAX_N_AXIS]; - void move_to_change_location(); void move_to_safe_z(); void move_over_toolsetter(); void ets_probe(); - void reset(); - + void get_ets_offset(); + void move_to_tool_position(uint8_t tool_index); Macro _macro; + Macro _toolreturn_macro; + Macro _toolpickup_macro; public: void init() override; @@ -58,9 +60,18 @@ namespace ATCs { handler.item("safe_z_mpos_mm", _safe_z, -100000, 100000); handler.item("probe_seek_rate_mm_per_min", _probe_seek_rate, 1, 10000); handler.item("probe_feed_rate_mm_per_min", _probe_feed_rate, 1, 10000); - handler.item("change_mpos_mm", _change_mpos); handler.item("ets_mpos_mm", _ets_mpos); handler.item("ets_rapid_z_mpos_mm", _ets_rapid_z_mpos); + handler.item("toolreturn_macro", _toolreturn_macro); + handler.item("toolpickup_macro", _toolpickup_macro); + handler.item("tool1_mpos_mm", _tool_mpos[0]); + handler.item("tool2_mpos_mm", _tool_mpos[1]); + handler.item("tool3_mpos_mm", _tool_mpos[2]); + handler.item("tool4_mpos_mm", _tool_mpos[3]); + handler.item("tool5_mpos_mm", _tool_mpos[4]); + handler.item("tool6_mpos_mm", _tool_mpos[5]); + handler.item("tool7_mpos_mm", _tool_mpos[6]); + handler.item("tool8_mpos_mm", _tool_mpos[7]); } }; } From 04360e8ac437ed4ff7506b56dbefcaff2dac9175 Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Sat, 17 Aug 2024 18:03:39 +0200 Subject: [PATCH 03/13] Use Macros to save and restore machine state --- FluidNC/src/ToolChangers/atc_basic.cpp | 94 ++++++++++++-------------- FluidNC/src/ToolChangers/atc_basic.h | 12 ++-- 2 files changed, 48 insertions(+), 58 deletions(-) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index 85c6737ba..bd1085509 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -15,12 +15,42 @@ namespace ATCs { bool Basic_ATC::tool_change(uint8_t new_tool, bool pre_select, bool set_tool) { protocol_buffer_synchronize(); // wait for all motion to complete - _macro.erase(); // clear previous gcode - - if (pre_select) { // not implemented + _macro.erase(); // clear previous gcode + + if (pre_select) { // not implemented return true; } + // save current location, so we can return after the tool change. + _macro.addf("#= #<_x>"); + _macro.addf("#= #<_y>"); + _macro.addf("#= #<_z>"); + + //save machine states + Macro set_state; + Macro restore_state; + set_state.addf("M9"); // Disable coolant + if (gc_state.modal.coolant.Mist) { + restore_state.addf("M7"); + } + if (gc_state.modal.coolant.Flood) { + restore_state.addf("M8"); + } + set_state.addf("G21"); // become Metric + if (gc_state.modal.units == Units::Inches) { + restore_state.addf("G20"); + } + set_state.addf("G90"); // become absolute + if (gc_state.modal.distance != Distance::Absolute) { + restore_state.addf("G91"); + } + set_state.addf("M5"); // turn off the spindle + if (gc_state.modal.spindle != SpindleState::Disable) { + restore_state.addf("M3"); + } + + _macro.addf(set_state._gcode.c_str()); + // set_tool is used to update the current tool and reset the TLO to 0 if (set_tool) { _prev_tool = new_tool; @@ -28,51 +58,24 @@ namespace ATCs { if (!_have_tool_setter_offset) { get_ets_offset(); } + _macro.addf(restore_state._gcode.c_str()); _macro.run(nullptr); return true; } - - //save machine states - bool spindle_was_on = (gc_state.modal.spindle != SpindleState::Disable); // used to restore the spindle state - bool was_inch_mode = (gc_state.modal.units == Units::Inches); - bool was_absolute_mode = (gc_state.modal.distance == Distance::Absolute); - bool mistcoolant_was_on= (gc_state.modal.coolant.Mist); - bool floodcoolant_was_on = (gc_state.modal.coolant.Flood); - // save current location, so we can return after the tool change. - _macro.addf("#= #<_x>"); - _macro.addf("#= #<_y>"); - _macro.addf("#= #<_z>"); - - if (mistcoolant_was_on || floodcoolant_was_on) { - _macro.addf("M9"); - } - if (was_inch_mode) { // become Metric - _macro.addf("G21"); - } - if (!was_absolute_mode) { // become absolute - _macro.addf("G90"); - } - if (spindle_was_on) { // turn off the spindle - _macro.addf("M5"); - } try { if (_prev_tool > 0) { // return tool move_to_tool_position(_prev_tool); _macro.addf(_toolreturn_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to return tool, operating the ATC using M62 & M63 - // ensure the macro didn't change positioning mode - _macro.addf("G90"); - _macro.addf("G21"); + _macro.addf(set_state._gcode.c_str()); // ensure the previous user macro didn't change modes } if (new_tool > 0) { //pickup tool move_to_tool_position(_prev_tool); _macro.addf(_toolpickup_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to pickup tool, operating the ATC using M62 & M63 - // ensure the macro didn't change positioning mode - _macro.addf("G90"); - _macro.addf("G21"); + _macro.addf(set_state._gcode.c_str()); // ensure the previous user macro didn't change modes if (!_have_tool_setter_offset) { get_ets_offset(); } @@ -89,21 +92,8 @@ namespace ATCs { move_to_safe_z(); _macro.addf("G0 X#Y#"); _macro.addf("G0 Z#"); - if (was_inch_mode) { - _macro.addf("G20"); - } - if (!was_absolute_mode) { // become relative - _macro.addf("G91"); - } - if (spindle_was_on) { - _macro.addf("M3"); // spindle should handle spinup delay - } - if (mistcoolant_was_on) { - _macro.addf("M7"); - } - if (floodcoolant_was_on) { - _macro.addf("M8"); - } + + _macro.addf(restore_state._gcode.c_str()); _macro.run(nullptr); return true; @@ -116,9 +106,9 @@ namespace ATCs { tool_index -= 1; move_to_safe_z(); _macro.addf("G53 G0 X%0.3f Y%0.3f", _tool_mpos[tool_index][X_AXIS], _tool_mpos[tool_index][Y_AXIS]); - _macro.addf("#<_tc_tool_x >=%0.3f",_tool_mpos[tool_index][X_AXIS]); - _macro.addf("#<_tc_tool_y >=%0.3f",_tool_mpos[tool_index][Y_AXIS]); - _macro.addf("#<_tc_tool_z >=%0.3f",_tool_mpos[tool_index][Z_AXIS]); + _macro.addf("#<_tc_tool_x >=%0.3f", _tool_mpos[tool_index][X_AXIS]); + _macro.addf("#<_tc_tool_y >=%0.3f", _tool_mpos[tool_index][Y_AXIS]); + _macro.addf("#<_tc_tool_z >=%0.3f", _tool_mpos[tool_index][Z_AXIS]); } void Basic_ATC::move_to_safe_z() { @@ -130,7 +120,7 @@ namespace ATCs { _macro.addf("G53 G0 X%0.3fY%0.3f", _ets_mpos[0], _ets_mpos[1]); } - void Basic_ATC::get_ets_offset(){ + void Basic_ATC::get_ets_offset() { ets_probe(); _macro.addf("#<_ets_tool1_z>=[#5063]"); // save the value of the tool1 ETS Z _have_tool_setter_offset = true; diff --git a/FluidNC/src/ToolChangers/atc_basic.h b/FluidNC/src/ToolChangers/atc_basic.h index b9b82052e..845dbabcb 100644 --- a/FluidNC/src/ToolChangers/atc_basic.h +++ b/FluidNC/src/ToolChangers/atc_basic.h @@ -14,7 +14,7 @@ namespace ATCs { const int TOOL_COUNT = 8; - + class Basic_ATC : public ATC { public: Basic_ATC(const char* name) : ATC(name) {} @@ -40,11 +40,11 @@ namespace ATCs { float _tool_setter_offset = 0.0; // have we established an offset. float _tool_setter_position[MAX_N_AXIS]; - void move_to_safe_z(); - void move_over_toolsetter(); - void ets_probe(); - void get_ets_offset(); - void move_to_tool_position(uint8_t tool_index); + void move_to_safe_z(); + void move_over_toolsetter(); + void ets_probe(); + void get_ets_offset(); + void move_to_tool_position(uint8_t tool_index); Macro _macro; Macro _toolreturn_macro; Macro _toolpickup_macro; From 6fcf80a0034597917515a4b52553313ba9e5ba8b Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Sat, 17 Aug 2024 18:10:43 +0200 Subject: [PATCH 04/13] ensure we moved back to start position in all cases --- FluidNC/src/ToolChangers/atc_basic.cpp | 17 +++++++++++------ FluidNC/src/ToolChangers/atc_basic.h | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index bd1085509..a83e1a6d8 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -52,6 +52,7 @@ namespace ATCs { _macro.addf(set_state._gcode.c_str()); // set_tool is used to update the current tool and reset the TLO to 0 + // if we dont have_tool_setter_offset then we also do an initial probe if (set_tool) { _prev_tool = new_tool; _macro.addf("G4P0 0.0"); @@ -59,6 +60,7 @@ namespace ATCs { get_ets_offset(); } _macro.addf(restore_state._gcode.c_str()); + move_to_start_position(); _macro.run(nullptr); return true; } @@ -72,7 +74,7 @@ namespace ATCs { } if (new_tool > 0) { - //pickup tool + //pickup tool, if this is the 1st pickup ever, we also probe the tool_setter_offset move_to_tool_position(_prev_tool); _macro.addf(_toolpickup_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to pickup tool, operating the ATC using M62 & M63 _macro.addf(set_state._gcode.c_str()); // ensure the previous user macro didn't change modes @@ -83,15 +85,11 @@ namespace ATCs { // probe the new tool ets_probe(); - // TLO is simply the difference between the tool1 probe and the new tool probe. _macro.addf("#<_my_tlo_z >=[#5063 - #<_ets_tool1_z>]"); _macro.addf("G43.1Z#<_my_tlo_z>"); - // return to location before the tool change - move_to_safe_z(); - _macro.addf("G0 X#Y#"); - _macro.addf("G0 Z#"); + move_to_start_position(); _macro.addf(restore_state._gcode.c_str()); _macro.run(nullptr); @@ -101,6 +99,13 @@ namespace ATCs { return false; } + + void Basic_ATC::move_to_start_position(){ + // return to location before the tool change + move_to_safe_z(); + _macro.addf("G0 X#Y#"); + _macro.addf("G0 Z#"); + } void Basic_ATC::move_to_tool_position(uint8_t tool_index) { tool_index -= 1; diff --git a/FluidNC/src/ToolChangers/atc_basic.h b/FluidNC/src/ToolChangers/atc_basic.h index 845dbabcb..bae7a5d48 100644 --- a/FluidNC/src/ToolChangers/atc_basic.h +++ b/FluidNC/src/ToolChangers/atc_basic.h @@ -45,6 +45,8 @@ namespace ATCs { void ets_probe(); void get_ets_offset(); void move_to_tool_position(uint8_t tool_index); + void move_to_start_position(); + Macro _macro; Macro _toolreturn_macro; Macro _toolpickup_macro; From dbd3f06e773ee4f719075a7b9e48a068fae05e54 Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Fri, 23 Aug 2024 21:15:28 +0200 Subject: [PATCH 05/13] Fixed: use new_tool for pickup --- FluidNC/src/ToolChangers/atc_basic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index a83e1a6d8..a1cb1e622 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -75,7 +75,7 @@ namespace ATCs { if (new_tool > 0) { //pickup tool, if this is the 1st pickup ever, we also probe the tool_setter_offset - move_to_tool_position(_prev_tool); + move_to_tool_position(new_tool); _macro.addf(_toolpickup_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to pickup tool, operating the ATC using M62 & M63 _macro.addf(set_state._gcode.c_str()); // ensure the previous user macro didn't change modes if (!_have_tool_setter_offset) { From aa33d3b7286446cff6b59a36e70349297962664d Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Fri, 23 Aug 2024 21:16:25 +0200 Subject: [PATCH 06/13] Fixed: update _prev_tool variable --- FluidNC/src/ToolChangers/atc_basic.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index a1cb1e622..7e531aa51 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -94,6 +94,8 @@ namespace ATCs { _macro.addf(restore_state._gcode.c_str()); _macro.run(nullptr); + _prev_tool = new_tool; + return true; } catch (...) { log_info("Exception caught"); } From 635be00ec35c1b2806120a95e042deeb27cc4f28 Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Fri, 23 Aug 2024 21:17:55 +0200 Subject: [PATCH 07/13] Add some debug messages --- FluidNC/src/ToolChangers/atc_basic.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index 7e531aa51..d298d55b3 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -14,10 +14,14 @@ namespace ATCs { void Basic_ATC::probe_notification() {} bool Basic_ATC::tool_change(uint8_t new_tool, bool pre_select, bool set_tool) { + std::string message = "ATC:tool_change: from " + std::to_string(_prev_tool) + " to " + std::to_string(new_tool); + log_info(message); + protocol_buffer_synchronize(); // wait for all motion to complete _macro.erase(); // clear previous gcode if (pre_select) { // not implemented + log_debug("ATC: Preselect"); return true; } @@ -54,6 +58,7 @@ namespace ATCs { // set_tool is used to update the current tool and reset the TLO to 0 // if we dont have_tool_setter_offset then we also do an initial probe if (set_tool) { + log_debug("ATC: Set Tool"); _prev_tool = new_tool; _macro.addf("G4P0 0.0"); if (!_have_tool_setter_offset) { @@ -67,14 +72,15 @@ namespace ATCs { try { if (_prev_tool > 0) { - // return tool + log_debug("ATC: return tool"); move_to_tool_position(_prev_tool); _macro.addf(_toolreturn_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to return tool, operating the ATC using M62 & M63 _macro.addf(set_state._gcode.c_str()); // ensure the previous user macro didn't change modes } if (new_tool > 0) { - //pickup tool, if this is the 1st pickup ever, we also probe the tool_setter_offset + log_debug("ATC: pickup tool"); + //if this is the 1st pickup ever, we also probe the tool_setter_offset move_to_tool_position(new_tool); _macro.addf(_toolpickup_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to pickup tool, operating the ATC using M62 & M63 _macro.addf(set_state._gcode.c_str()); // ensure the previous user macro didn't change modes From 5b0a37ce3ee89666a8715082b9064a1b047cbca1 Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Fri, 23 Aug 2024 21:32:02 +0200 Subject: [PATCH 08/13] Fixed: Use correct cfg namespace --- FluidNC/src/ToolChangers/atc_basic.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index d298d55b3..1e0614413 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -142,7 +142,7 @@ namespace ATCs { void Basic_ATC::ets_probe() { move_to_safe_z(); move_over_toolsetter(); - _macro.addf("G53 G0 Z #"); // rapid down + _macro.addf("G53 G0 Z #"); // rapid down // do a fast probe if there is a seek that is faster than feed if (_probe_seek_rate > _probe_feed_rate) { From 64a9cbc1679a88019471acef78096ad311631c72 Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Fri, 23 Aug 2024 22:38:15 +0200 Subject: [PATCH 09/13] Fix: only probe if required --- FluidNC/src/ToolChangers/atc_basic.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index 1e0614413..6485d2a97 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -86,15 +86,15 @@ namespace ATCs { _macro.addf(set_state._gcode.c_str()); // ensure the previous user macro didn't change modes if (!_have_tool_setter_offset) { get_ets_offset(); + _macro.addf("#<_my_tlo_z >=0.0"); //first tool is reference with 0 offset + } else { + ets_probe(); // probe the new tool + // TLO is simply the difference between the tool1 probe and the new tool probe. + _macro.addf("#<_my_tlo_z >=[#5063 - #<_ets_tool1_z>]"); } + _macro.addf("G43.1Z#<_my_tlo_z>"); } - // probe the new tool - ets_probe(); - // TLO is simply the difference between the tool1 probe and the new tool probe. - _macro.addf("#<_my_tlo_z >=[#5063 - #<_ets_tool1_z>]"); - _macro.addf("G43.1Z#<_my_tlo_z>"); - move_to_start_position(); _macro.addf(restore_state._gcode.c_str()); @@ -107,8 +107,8 @@ namespace ATCs { return false; } - - void Basic_ATC::move_to_start_position(){ + + void Basic_ATC::move_to_start_position(){ // return to location before the tool change move_to_safe_z(); _macro.addf("G0 X#Y#"); From 03ab4255fa5e89f450526354ff0dfd61fa9fa39d Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Sun, 25 Aug 2024 19:50:09 +0200 Subject: [PATCH 10/13] Add activate/deactivate Macros --- FluidNC/src/ToolChangers/atc_basic.cpp | 7 +++++++ FluidNC/src/ToolChangers/atc_basic.h | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index 6485d2a97..97562f20c 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -1,4 +1,5 @@ // Copyright (c) 2024 - Bart Dring +// Copyright (c) 2024 - Nicolas Lang // Use of this source code is governed by a GPLv3 license that can be found in the LICENSE file. #include "atc_basic.h" @@ -71,6 +72,9 @@ namespace ATCs { } try { + _macro.addf(_atc_activate_macro._gcode.c_str()); + _macro.addf(set_state._gcode.c_str()); + if (_prev_tool > 0) { log_debug("ATC: return tool"); move_to_tool_position(_prev_tool); @@ -97,6 +101,9 @@ namespace ATCs { move_to_start_position(); + _macro.addf(_atc_deactivate_macro._gcode.c_str()); + _macro.addf(set_state._gcode.c_str()); + _macro.addf(restore_state._gcode.c_str()); _macro.run(nullptr); diff --git a/FluidNC/src/ToolChangers/atc_basic.h b/FluidNC/src/ToolChangers/atc_basic.h index bae7a5d48..dd26c3aaa 100644 --- a/FluidNC/src/ToolChangers/atc_basic.h +++ b/FluidNC/src/ToolChangers/atc_basic.h @@ -50,6 +50,8 @@ namespace ATCs { Macro _macro; Macro _toolreturn_macro; Macro _toolpickup_macro; + Macro _atc_activate_macro; + Macro _atc_deactivate_macro; public: void init() override; @@ -66,6 +68,8 @@ namespace ATCs { handler.item("ets_rapid_z_mpos_mm", _ets_rapid_z_mpos); handler.item("toolreturn_macro", _toolreturn_macro); handler.item("toolpickup_macro", _toolpickup_macro); + handler.item("atc_activate_macro", _atc_activate_macro); + handler.item("atc_deactivate_macro", _atc_deactivate_macro); handler.item("tool1_mpos_mm", _tool_mpos[0]); handler.item("tool2_mpos_mm", _tool_mpos[1]); handler.item("tool3_mpos_mm", _tool_mpos[2]); From dca8a313c32dc25e0ccea7aa5f9ef841afde85e9 Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Thu, 19 Sep 2024 21:01:04 +0200 Subject: [PATCH 11/13] use macros and variables --- FluidNC/src/ToolChangers/atc_basic.cpp | 11 ++++++----- FluidNC/src/ToolChangers/atc_basic.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/FluidNC/src/ToolChangers/atc_basic.cpp b/FluidNC/src/ToolChangers/atc_basic.cpp index 97562f20c..a560a6587 100644 --- a/FluidNC/src/ToolChangers/atc_basic.cpp +++ b/FluidNC/src/ToolChangers/atc_basic.cpp @@ -77,7 +77,8 @@ namespace ATCs { if (_prev_tool > 0) { log_debug("ATC: return tool"); - move_to_tool_position(_prev_tool); + move_to_safe_z(); + set_tool_position(_prev_tool); _macro.addf(_toolreturn_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to return tool, operating the ATC using M62 & M63 _macro.addf(set_state._gcode.c_str()); // ensure the previous user macro didn't change modes } @@ -85,7 +86,8 @@ namespace ATCs { if (new_tool > 0) { log_debug("ATC: pickup tool"); //if this is the 1st pickup ever, we also probe the tool_setter_offset - move_to_tool_position(new_tool); + move_to_safe_z(); + set_tool_position(new_tool); _macro.addf(_toolpickup_macro._gcode.c_str()); // use macro with G91 movements or the _tc_tool_* variables to to pickup tool, operating the ATC using M62 & M63 _macro.addf(set_state._gcode.c_str()); // ensure the previous user macro didn't change modes if (!_have_tool_setter_offset) { @@ -96,6 +98,7 @@ namespace ATCs { // TLO is simply the difference between the tool1 probe and the new tool probe. _macro.addf("#<_my_tlo_z >=[#5063 - #<_ets_tool1_z>]"); } + _macro.addf("(print,ATC: New TLO #<_my_tlo_z>)"); _macro.addf("G43.1Z#<_my_tlo_z>"); } @@ -122,10 +125,8 @@ namespace ATCs { _macro.addf("G0 Z#"); } - void Basic_ATC::move_to_tool_position(uint8_t tool_index) { + void Basic_ATC::set_tool_position(uint8_t tool_index) { tool_index -= 1; - move_to_safe_z(); - _macro.addf("G53 G0 X%0.3f Y%0.3f", _tool_mpos[tool_index][X_AXIS], _tool_mpos[tool_index][Y_AXIS]); _macro.addf("#<_tc_tool_x >=%0.3f", _tool_mpos[tool_index][X_AXIS]); _macro.addf("#<_tc_tool_y >=%0.3f", _tool_mpos[tool_index][Y_AXIS]); _macro.addf("#<_tc_tool_z >=%0.3f", _tool_mpos[tool_index][Z_AXIS]); diff --git a/FluidNC/src/ToolChangers/atc_basic.h b/FluidNC/src/ToolChangers/atc_basic.h index dd26c3aaa..ff7ddb546 100644 --- a/FluidNC/src/ToolChangers/atc_basic.h +++ b/FluidNC/src/ToolChangers/atc_basic.h @@ -44,7 +44,7 @@ namespace ATCs { void move_over_toolsetter(); void ets_probe(); void get_ets_offset(); - void move_to_tool_position(uint8_t tool_index); + void set_tool_position(uint8_t tool_index); void move_to_start_position(); Macro _macro; From 203e8d916da1a2491e592bc2e3446ef8f43a4714 Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Thu, 19 Sep 2024 21:50:08 +0200 Subject: [PATCH 12/13] Added cfg example --- FluidNC/src/ToolChangers/atc_basic.md | 63 +++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 FluidNC/src/ToolChangers/atc_basic.md diff --git a/FluidNC/src/ToolChangers/atc_basic.md b/FluidNC/src/ToolChangers/atc_basic.md new file mode 100644 index 000000000..a3b239ef3 --- /dev/null +++ b/FluidNC/src/ToolChangers/atc_basic.md @@ -0,0 +1,63 @@ +### Disclaimer: Use at Your Own Risk + +The configuration and source code provided are made available "as is" without any guarantees or warranties, express or implied. By using this configuration and source code, you acknowledge that you do so at your own risk. The creator is not responsible for any damages, malfunctions, or issues that may arise from their use. Please review and modify the code according to your own requirements and ensure proper testing and safety measures are in place. + +# Example cfg + +```yaml +atc_basic: + safe_z_mpos_mm: -1.000 + probe_seek_rate_mm_per_min: 400.000 + probe_feed_rate_mm_per_min: 100.000 + ets_mpos_mm: -72.500 -7.500 -30.000 + ets_rapid_z_mpos_mm: -10.000 + atc_activate_macro: $LocalFS/Run=/ATC/atc_activate_macro.g + atc_deactivate_macro: $LocalFS/Run=/ATC/atc_deactivate_macro.g + toolpickup_macro: $LocalFS/Run=/ATC/toolpickup_macro.g + toolreturn_macro: $LocalFS/Run=/ATC/toolreturn_macro.g + tool8_mpos_mm: -844.000 -2.000 -76.000 + tool7_mpos_mm: -844.000 -2.000 -76.000 + tool6_mpos_mm: -784.000 -2.000 -76.000 + tool5_mpos_mm: -724.000 -2.000 -76.000 + tool4_mpos_mm: -664.000 -2.000 -76.000 + tool3_mpos_mm: -604.000 -2.000 -76.000 + tool2_mpos_mm: -544.000 -2.000 -76.000 + tool1_mpos_mm: -484.000 -2.000 -76.000 +``` + +```gcode +(atc_activate_macro) +G53 G0 Z-1 +G53 G0 X-694 Y-150 +``` + +```gcode +(atc_deactivate_macro) +``` + +```gcode +(toolpickup_macro) +G91 +G53 G0 X#<_tc_tool_x> Y#<_tc_tool_y> +M62 P6 +G4 P0 1.0 +G53 G0 Z#<_tc_tool_z> +M63 P6 +G4 P0 1.0 +G1 Y-15.0 F500 +G0 Y-20.0 +G53 G0 Z-1.0 +``` + +```gcode +(toolreturn_macro) +G91 +G53 G0 X#<_tc_tool_x> Y[#<_tc_tool_y> -35.0] +G53 G0 Z#<_tc_tool_z> +G0 Y+20.0 +G1 Y+15.0 F500 +M62 P6 +G4 P0 1.0 +G53 G0 Z-1.0 +M63 P6 +``` \ No newline at end of file From 58c8abf7667d42da6ed83c7ec2325a68d0975d2c Mon Sep 17 00:00:00 2001 From: Nicolas Lang Date: Thu, 26 Sep 2024 19:11:04 +0200 Subject: [PATCH 13/13] updated ATC_Basic.md --- FluidNC/src/ToolChangers/atc_basic.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/FluidNC/src/ToolChangers/atc_basic.md b/FluidNC/src/ToolChangers/atc_basic.md index a3b239ef3..33308c7dd 100644 --- a/FluidNC/src/ToolChangers/atc_basic.md +++ b/FluidNC/src/ToolChangers/atc_basic.md @@ -25,18 +25,19 @@ atc_basic: tool1_mpos_mm: -484.000 -2.000 -76.000 ``` +the following macros need to be saved to `$LocalFS/ATC/` ```gcode -(atc_activate_macro) +(/ATC/atc_activate_macro.g) G53 G0 Z-1 G53 G0 X-694 Y-150 ``` ```gcode -(atc_deactivate_macro) +(/ATC/atc_deactivate_macro.g) ``` ```gcode -(toolpickup_macro) +(/ATC/toolpickup_macro.g) G91 G53 G0 X#<_tc_tool_x> Y#<_tc_tool_y> M62 P6 @@ -50,7 +51,7 @@ G53 G0 Z-1.0 ``` ```gcode -(toolreturn_macro) +(/ATC/toolreturn_macro.g) G91 G53 G0 X#<_tc_tool_x> Y[#<_tc_tool_y> -35.0] G53 G0 Z#<_tc_tool_z>