Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TOOLS setting to allow up to 127 optional spindle tools, and all combos of HOTENDS, EXTRUDERS, LASER and SPINDLE tools #27614

Draft
wants to merge 3 commits into
base: bugfix-2.1.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,15 @@

// @section extruder

/**
* This defines the number of tools, including extruders, laser and spindle tools.
* Tool indices, starting with 0, must be assigned in the following order: opional extruders (requires EXTRUDERS > 0),
* an optional laser (requires LASER_FEATURE), and finally optional tools for a spindle (requires SPINDLE_FEATURE).
* Offsets of each tool from tool 0 must be defined with HOTEND_OFFSET_X, HOTEND_OFFSET_Y and HOTEND_OFFSET_Z
*/
// :[0, 1, 2, ..., 127]
//#define TOOLS 1

// This defines the number of extruders
// :[0, 1, 2, 3, 4, 5, 6, 7, 8]
#define EXTRUDERS 1
Expand Down
2 changes: 2 additions & 0 deletions Marlin/src/HAL/AVR/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@
#include "../ServoTimers.h" // Needed to check timer availability (_useTimer3)
#if SPINDLE_LASER_PWM_PIN == 4 || WITHIN(SPINDLE_LASER_PWM_PIN, 11, 13)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by a system interrupt."
#elif LASER_PWM_PIN == 4 || WITHIN(LASER_PWM_PIN, 11, 13)
#error "Counter/Timer for LASER_PWM_PIN is used by a system interrupt."
#elif NUM_SERVOS > 0 && defined(_useTimer3) && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by the servo system."
#endif
Expand Down
4 changes: 4 additions & 0 deletions Marlin/src/HAL/LINUX/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
#error "SPINDLE_LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
#endif

#if ENABLED(LASER_USE_PWM) && !(LASER_PWM_PIN == 4 || LASER_PWM_PIN == 6 || LASER_PWM_PIN == 11)
#error "LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
#endif

#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported for HAL/LINUX."
#endif
Expand Down
4 changes: 4 additions & 0 deletions Marlin/src/HAL/NATIVE_SIM/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
#error "SPINDLE_LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
#endif

#if ENABLED(LASER_USE_PWM) && !(LASER_PWM_PIN == 4 || LASER_PWM_PIN == 6 || LASER_PWM_PIN == 11)
#error "LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
#endif

#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported for HAL/LINUX."
#endif
Expand Down
10 changes: 10 additions & 0 deletions Marlin/src/core/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,16 @@ enum AxisEnum : uint8_t {
#define LOOP_DISTINCT_AXES(VAR) for (uint8_t VAR = 0; VAR < DISTINCT_AXES; ++VAR)
#define LOOP_DISTINCT_E(VAR) for (uint8_t VAR = 0; VAR < DISTINCT_E; ++VAR)


//
// Enumerates tool types
//
enum ToolTypeEnum : uint8_t {
TYPE_EXTRUDER,
TYPE_LASER,
TYPE_SPINDLE
};

//
// feedRate_t is just a humble float that can represent mm/s or mm/min
//
Expand Down
4 changes: 2 additions & 2 deletions Marlin/src/feature/powerloss.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ void PrintJobRecovery::resume() {
#endif

// Restore the previously active tool (with no_move)
#if HAS_MULTI_EXTRUDER || HAS_MULTI_HOTEND
#if HAS_TOOLCHANGE
PROCESS_SUBCOMMANDS_NOW(TS('T', info.active_extruder, 'S'));
#endif

Expand Down Expand Up @@ -652,7 +652,7 @@ void PrintJobRecovery::resume() {
DEBUG_EOL();
#endif

#if HAS_MULTI_EXTRUDER
#if HAS_MULTI_TOOLS
DEBUG_ECHOLNPGM("active_extruder: ", info.active_extruder);
#endif

Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/feature/powerloss.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ typedef struct {
#if HAS_WORKSPACE_OFFSET
xyz_pos_t workspace_offset;
#endif
#if HAS_MULTI_EXTRUDER
#if HAS_MULTI_TOOLS
uint8_t active_extruder;
#endif

Expand Down
83 changes: 72 additions & 11 deletions Marlin/src/feature/spindle_laser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#endif

SpindleLaser cutter;
ToolTypeEnum SpindleLaser::active_tool_type; // Tool type: 0 for extruder, 1 for spindle, 2 for laser
bool SpindleLaser::enable_state; // Virtual enable state, controls enable pin if present and or apply power if > 0
uint8_t SpindleLaser::power, // Actual power output 0-255 ocr or "0 = off" > 0 = "on"
SpindleLaser::last_power_applied; // = 0 // Basic power state tracking
Expand All @@ -65,21 +66,42 @@ cutter_frequency_t SpindleLaser::frequency; // PWM fre
* Init the cutter to a safe OFF state
*/
void SpindleLaser::init() {
#if ENABLED(LASER_FEATURE) && LASER_TOOL == 0
active_tool_type = TYPE_LASER;
#elif ENABLED(SPINDLE_FEATURE) && DISABLED(LASER_FEATURE) && !EXTRUDERS
active_tool_type = TYPE_SPINDLE;
#else
active_tool_type = TYPE_EXTRUDER;
#endif
#if ENABLED(SPINDLE_SERVO)
servo[SPINDLE_SERVO_NR].move(SPINDLE_SERVO_MIN);
#elif PIN_EXISTS(SPINDLE_LASER_ENA)
OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off
#endif
#if PIN_EXISTS(LASER_ENA)
OUT_WRITE(LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init laser to off
#endif
#if ENABLED(SPINDLE_CHANGE_DIR)
OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR); // Init rotation to clockwise (M3)
#endif
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
frequency = SPINDLE_LASER_FREQUENCY;
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY);
#if ENABLED(SPINDLE_FEATURE)
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY);
#endif
#if ENABLED(LASER_FEATURE)
hal.set_pwm_frequency(pin_t(LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY);
#endif
#endif
#if ENABLED(SPINDLE_LASER_USE_PWM)
SET_PWM(SPINDLE_LASER_PWM_PIN);
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed
#if ENABLED(SPINDLE_FEATURE)
SET_PWM(SPINDLE_LASER_PWM_PIN);
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed
#endif
#if ENABLED(LASER_FEATURE)
SET_PWM(LASER_PWM_PIN);
hal.set_pwm_duty(pin_t(LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed
#endif
#endif
#if ENABLED(AIR_EVACUATION)
OUT_WRITE(AIR_EVACUATION_PIN, !AIR_EVACUATION_ACTIVE); // Init Vacuum/Blower OFF
Expand All @@ -98,21 +120,46 @@ void SpindleLaser::init() {
*/
void SpindleLaser::_set_ocr(const uint8_t ocr) {
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency);
#if ENABLED(LASER_FEATURE)
if (active_tool_type == TYPE_LASER)
hal.set_pwm_frequency(pin_t(LASER_PWM_PIN), frequency);
#endif
#if ENABLED(SPINDLE_FEATURE)
if (active_tool_type != TYPE_LASER)
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency);
#endif
#endif

#if ENABLED(LASER_FEATURE)
if (active_tool_type == TYPE_LASER)
hal.set_pwm_duty(pin_t(LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
#endif
#if ENABLED(SPINDLE_FEATURE)
if (active_tool_type != TYPE_LASER)
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
#endif
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
}

void SpindleLaser::set_ocr(const uint8_t ocr) {
#if PIN_EXISTS(LASER_ENA)
if (active_tool_type == TYPE_LASER)
WRITE(LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_STATE); // Cutter ON
#endif
#if PIN_EXISTS(SPINDLE_LASER_ENA)
WRITE(SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_STATE); // Cutter ON
if (active_tool_type != TYPE_LASER)
WRITE(SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_STATE); // Cutter ON
#endif
_set_ocr(ocr);
}

void SpindleLaser::ocr_off() {
#if PIN_EXISTS(LASER_ENA)
if (active_tool_type == TYPE_LASER)
WRITE(LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Cutter OFF
#endif
#if PIN_EXISTS(SPINDLE_LASER_ENA)
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Cutter OFF
if (active_tool_type == TYPE_SPINDLE)
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Cutter OFF
#endif
_set_ocr(0);
}
Expand Down Expand Up @@ -143,13 +190,25 @@ void SpindleLaser::apply_power(const uint8_t opwr) {
#elif ENABLED(SPINDLE_SERVO)
servo[SPINDLE_SERVO_NR].move(opwr);
#else
WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
#if ENABLED(LASER_FEATURE)
if (active_tool_type == TYPE_LASER)
WRITE(LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
#endif
#if ENABLED(SPINDLE_FEATURE)
if (active_tool_type == TYPE_SPINDLE)
WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
#endif
isReadyForUI = true;
#endif
}
else {
#if PIN_EXISTS(LASER_ENA)
if (active_tool_type == TYPE_LASER)
WRITE(LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE);
#endif
#if PIN_EXISTS(SPINDLE_LASER_ENA)
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE);
if (active_tool_type == TYPE_SPINDLE)
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE);
#endif
isReadyForUI = false; // Only used for UI display updates.
TERN_(SPINDLE_LASER_USE_PWM, ocr_off());
Expand All @@ -163,8 +222,10 @@ void SpindleLaser::apply_power(const uint8_t opwr) {
*/
void SpindleLaser::set_reverse(const bool reverse) {
const bool dir_state = (reverse == SPINDLE_INVERT_DIR); // Forward (M3) HIGH when not inverted
if (TERN0(SPINDLE_STOP_ON_DIR_CHANGE, enabled()) && READ(SPINDLE_DIR_PIN) != dir_state) disable();
WRITE(SPINDLE_DIR_PIN, dir_state);
if (active_tool_type == TYPE_SPINDLE) {
if (TERN0(SPINDLE_STOP_ON_DIR_CHANGE, enabled()) && READ(SPINDLE_DIR_PIN) != dir_state) disable();
WRITE(SPINDLE_DIR_PIN, dir_state);
}
}
#endif

Expand Down
19 changes: 18 additions & 1 deletion Marlin/src/feature/spindle_laser.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@

#include "../libs/buzzer.h"

#include "../core/types.h"

// Inline laser power
#include "../module/planner.h"

Expand Down Expand Up @@ -105,6 +107,7 @@ class SpindleLaser {
#endif

static bool isReadyForUI; // Ready to apply power setting from the UI to OCR
static ToolTypeEnum active_tool_type; // Tool type: 0 for extruder, 1 for spindle, 2 for laser
static bool enable_state;
static uint8_t power,
last_power_applied; // Basic power state tracking
Expand All @@ -117,7 +120,18 @@ class SpindleLaser {
static void init();

#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
static void refresh_frequency() { hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency); }
static void refresh_frequency() {
#if ENABLED(LASER_FEATURE)
if (active_tool_type == TYPE_LASER) {
hal.set_pwm_frequency(pin_t(LASER_PWM_PIN), frequency);
}
#endif
#if ENABLED(SPINDLE_FEATURE)
if (active_tool_type != TYPE_LASER) {
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency);
}
#endif
}
#endif

// Modifying this function should update everywhere
Expand Down Expand Up @@ -211,6 +225,9 @@ class SpindleLaser {
enable = false;
apply_power(0);
}
#if PIN_EXISTS(LASER_ENA)
WRITE(LASER_ENA_PIN, enable ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
#endif
#if PIN_EXISTS(SPINDLE_LASER_ENA)
WRITE(SPINDLE_LASER_ENA_PIN, enable ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
#endif
Expand Down
6 changes: 3 additions & 3 deletions Marlin/src/gcode/calibrate/G28.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
#include "../../module/motion.h" // for set/restore_homing_current
#endif

#if HAS_MULTI_HOTEND
#if HAS_TOOLCHANGE
#include "../../module/tool_change.h"
#endif

Expand Down Expand Up @@ -285,7 +285,7 @@ void GcodeSuite::G28() {
#endif

// Always home with tool 0 active
#if HAS_MULTI_HOTEND
#if HAS_TOOLCHANGE
#if DISABLED(DELTA) || ENABLED(DELTA_HOME_TO_SAFE_ZONE)
const uint8_t old_tool_index = active_extruder;
#endif
Expand Down Expand Up @@ -548,7 +548,7 @@ void GcodeSuite::G28() {
TERN_(CAN_SET_LEVELING_AFTER_G28, if (leveling_restore_state) set_bed_leveling_enabled());

// Restore the active tool after homing
#if HAS_MULTI_HOTEND && (DISABLED(DELTA) || ENABLED(DELTA_HOME_TO_SAFE_ZONE))
#if HAS_TOOLCHANGE && (DISABLED(DELTA) || ENABLED(DELTA_HOME_TO_SAFE_ZONE))
tool_change(old_tool_index, TERN(PARKING_EXTRUDER, !pe_final_change_must_unpark, DISABLED(DUAL_X_CARRIAGE))); // Do move if one of these
#endif

Expand Down
15 changes: 8 additions & 7 deletions Marlin/src/gcode/calibrate/G425.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#include "../../module/endstops.h"
#include "../../feature/bedlevel/bedlevel.h"

#if HAS_MULTI_HOTEND
#if HAS_TOOLCHANGE
#include "../../module/tool_change.h"
#endif

Expand Down Expand Up @@ -174,7 +174,7 @@ inline void park_above_object(measurements_t &m, const float uncertainty) {
#if HAS_HOTEND_OFFSET

inline void normalize_hotend_offsets() {
for (uint8_t e = 1; e < HOTENDS; ++e)
for (uint8_t e = 1; e < TOOLS; ++e)
hotend_offset[e] -= hotend_offset[0];
hotend_offset[0].reset();
}
Expand Down Expand Up @@ -617,7 +617,7 @@ inline void probe_sides(measurements_t &m, const float uncertainty) {
// This function requires normalize_hotend_offsets() to be called
//
inline void report_hotend_offsets() {
for (uint8_t e = 1; e < HOTENDS; ++e)
for (uint8_t e = 1; e < TOOLS; ++e)
SERIAL_ECHOLNPGM_P(PSTR("T"), e, PSTR(" Hotend Offset X"), hotend_offset[e].x, SP_Y_STR, hotend_offset[e].y, SP_Z_STR, hotend_offset[e].z);
}
#endif
Expand Down Expand Up @@ -750,7 +750,7 @@ inline void calibrate_toolhead(measurements_t &m, const float uncertainty, const
TEMPORARY_BACKLASH_CORRECTION(backlash.all_on);
TEMPORARY_BACKLASH_SMOOTHING(0.0f);

TERN(HAS_MULTI_HOTEND, set_nozzle(m, extruder), UNUSED(extruder));
TERN(HAS_TOOLCHANGE, set_nozzle(m, extruder), UNUSED(extruder));

probe_sides(m, uncertainty);

Expand Down Expand Up @@ -794,7 +794,7 @@ inline void calibrate_all_toolheads(measurements_t &m, const float uncertainty)

TERN_(HAS_HOTEND_OFFSET, normalize_hotend_offsets());

TERN_(HAS_MULTI_HOTEND, set_nozzle(m, 0));
TERN_(HAS_TOOLCHANGE, set_nozzle(m, 0));
}

/**
Expand Down Expand Up @@ -822,8 +822,9 @@ inline void calibrate_all() {
TERN_(BACKLASH_GCODE, calibrate_backlash(m, CALIBRATION_MEASUREMENT_UNCERTAIN));

// Cycle the toolheads so the servos settle into their "natural" positions
#if HAS_MULTI_HOTEND
HOTEND_LOOP() set_nozzle(m, e);
#if HAS_TOOLCHANGE
for (int8_t t = 0; t < TOOLS; t++)
set_nozzle(m, t);
#endif

// Do a slow and precise calibration of the toolheads
Expand Down
4 changes: 2 additions & 2 deletions Marlin/src/gcode/config/M217.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

#include "../../inc/MarlinConfigPre.h"

#if HAS_MULTI_EXTRUDER
#if HAS_MULTI_TOOLS

#include "../gcode.h"

Expand Down Expand Up @@ -220,4 +220,4 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) {
SERIAL_ECHOLNPGM_P(SP_Z_STR, LINEAR_UNIT(toolchange_settings.z_raise));
}

#endif // HAS_MULTI_EXTRUDER
#endif // HAS_MULTI_TOOLS
Loading