diff --git a/Marlin/src/HAL/AVR/inc/SanityCheck.h b/Marlin/src/HAL/AVR/inc/SanityCheck.h index 85ee683685ec..bfc4f1132271 100644 --- a/Marlin/src/HAL/AVR/inc/SanityCheck.h +++ b/Marlin/src/HAL/AVR/inc/SanityCheck.h @@ -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 diff --git a/Marlin/src/HAL/LINUX/inc/SanityCheck.h b/Marlin/src/HAL/LINUX/inc/SanityCheck.h index 861bade10ffd..3526907188d1 100644 --- a/Marlin/src/HAL/LINUX/inc/SanityCheck.h +++ b/Marlin/src/HAL/LINUX/inc/SanityCheck.h @@ -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 diff --git a/Marlin/src/HAL/NATIVE_SIM/inc/SanityCheck.h b/Marlin/src/HAL/NATIVE_SIM/inc/SanityCheck.h index 615e5254c95b..7f73ad86ef58 100644 --- a/Marlin/src/HAL/NATIVE_SIM/inc/SanityCheck.h +++ b/Marlin/src/HAL/NATIVE_SIM/inc/SanityCheck.h @@ -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 diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index 74570ced76b5..9c13383a96c2 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -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 // diff --git a/Marlin/src/feature/spindle_laser.cpp b/Marlin/src/feature/spindle_laser.cpp index b83c1c17972f..a55940e776f3 100644 --- a/Marlin/src/feature/spindle_laser.cpp +++ b/Marlin/src/feature/spindle_laser.cpp @@ -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 @@ -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 @@ -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); } @@ -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()); @@ -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 diff --git a/Marlin/src/feature/spindle_laser.h b/Marlin/src/feature/spindle_laser.h index a443d7df5e0c..956e0b8ab9e0 100644 --- a/Marlin/src/feature/spindle_laser.h +++ b/Marlin/src/feature/spindle_laser.h @@ -32,6 +32,8 @@ #include "../libs/buzzer.h" +#include "../core/types.h" + // Inline laser power #include "../module/planner.h" @@ -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 @@ -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 @@ -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 diff --git a/Marlin/src/inc/Conditionals-4-adv.h b/Marlin/src/inc/Conditionals-4-adv.h index 1fd4716145a1..bebbbb5ba6a7 100644 --- a/Marlin/src/inc/Conditionals-4-adv.h +++ b/Marlin/src/inc/Conditionals-4-adv.h @@ -1081,6 +1081,9 @@ // #if ANY(SPINDLE_FEATURE, LASER_FEATURE) #define HAS_CUTTER 1 + #if ENABLED(LASER_FEATURE) + #define LASER_TOOL EXTRUDERS + #endif #define _CUTTER_POWER_PWM255 1 #define _CUTTER_POWER_PERCENT 2 #define _CUTTER_POWER_RPM 3 diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 71e8e612a4f0..176b3adb70e8 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -3980,73 +3980,140 @@ static_assert(_PLUS_TEST(3), "DEFAULT_MAX_ACCELERATION values must be positive." #endif #endif - #define _PIN_CONFLICT(P) (PIN_EXISTS(P) && P##_PIN == SPINDLE_LASER_PWM_PIN) - #if ALL(SPINDLE_FEATURE, LASER_FEATURE) - #error "Enable only one of SPINDLE_FEATURE or LASER_FEATURE." - #elif NONE(SPINDLE_SERVO, SPINDLE_LASER_USE_PWM) && !PIN_EXISTS(SPINDLE_LASER_ENA) - #error "(SPINDLE|LASER)_FEATURE requires SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_USE_PWM, or SPINDLE_SERVO to control the power." - #elif ENABLED(SPINDLE_CHANGE_DIR) && !PIN_EXISTS(SPINDLE_DIR) - #error "SPINDLE_DIR_PIN is required for SPINDLE_CHANGE_DIR." - #elif ENABLED(SPINDLE_LASER_USE_PWM) - #if !defined(SPINDLE_LASER_PWM_PIN) || SPINDLE_LASER_PWM_PIN < 0 - #error "SPINDLE_LASER_PWM_PIN is required for SPINDLE_LASER_USE_PWM." - #elif !_TEST_PWM(SPINDLE_LASER_PWM_PIN) - #error "SPINDLE_LASER_PWM_PIN not assigned to a PWM pin." - #elif !defined(SPINDLE_LASER_PWM_INVERT) - #error "SPINDLE_LASER_PWM_INVERT is required for (SPINDLE|LASER)_FEATURE." - #elif !(defined(SPEED_POWER_MIN) && defined(SPEED_POWER_MAX) && defined(SPEED_POWER_STARTUP)) - #error "SPINDLE_LASER_USE_PWM equation constant(s) missing." - #elif _PIN_CONFLICT(X_MIN) - #error "SPINDLE_LASER_PWM_PIN conflicts with X_MIN_PIN." - #elif _PIN_CONFLICT(X_MAX) - #error "SPINDLE_LASER_PWM_PIN conflicts with X_MAX_PIN." - #elif _PIN_CONFLICT(Z_STEP) - #error "SPINDLE_LASER_PWM_PIN conflicts with Z_STEP_PIN." - #elif _PIN_CONFLICT(CASE_LIGHT) - #error "SPINDLE_LASER_PWM_PIN conflicts with CASE_LIGHT_PIN." - #elif _PIN_CONFLICT(E0_AUTO_FAN) - #error "SPINDLE_LASER_PWM_PIN conflicts with E0_AUTO_FAN_PIN." - #elif _PIN_CONFLICT(E1_AUTO_FAN) - #error "SPINDLE_LASER_PWM_PIN conflicts with E1_AUTO_FAN_PIN." - #elif _PIN_CONFLICT(E2_AUTO_FAN) - #error "SPINDLE_LASER_PWM_PIN conflicts with E2_AUTO_FAN_PIN." - #elif _PIN_CONFLICT(E3_AUTO_FAN) - #error "SPINDLE_LASER_PWM_PIN conflicts with E3_AUTO_FAN_PIN." - #elif _PIN_CONFLICT(E4_AUTO_FAN) - #error "SPINDLE_LASER_PWM_PIN conflicts with E4_AUTO_FAN_PIN." - #elif _PIN_CONFLICT(E5_AUTO_FAN) - #error "SPINDLE_LASER_PWM_PIN conflicts with E5_AUTO_FAN_PIN." - #elif _PIN_CONFLICT(E6_AUTO_FAN) - #error "SPINDLE_LASER_PWM_PIN conflicts with E6_AUTO_FAN_PIN." - #elif _PIN_CONFLICT(E7_AUTO_FAN) - #error "SPINDLE_LASER_PWM_PIN conflicts with E7_AUTO_FAN_PIN." - #elif _PIN_CONFLICT(FAN0) - #error "SPINDLE_LASER_PWM_PIN conflicts with FAN0_PIN." - #elif _PIN_CONFLICT(FAN1) - #error "SPINDLE_LASER_PWM_PIN conflicts with FAN1_PIN." - #elif _PIN_CONFLICT(FAN2) - #error "SPINDLE_LASER_PWM_PIN conflicts with FAN2_PIN." - #elif _PIN_CONFLICT(FAN3) - #error "SPINDLE_LASER_PWM_PIN conflicts with FAN3_PIN." - #elif _PIN_CONFLICT(FAN4) - #error "SPINDLE_LASER_PWM_PIN conflicts with FAN4_PIN." - #elif _PIN_CONFLICT(FAN5) - #error "SPINDLE_LASER_PWM_PIN conflicts with FAN5_PIN." - #elif _PIN_CONFLICT(FAN6) - #error "SPINDLE_LASER_PWM_PIN conflicts with FAN6_PIN." - #elif _PIN_CONFLICT(FAN7) - #error "SPINDLE_LASER_PWM_PIN conflicts with FAN7_PIN." - #elif _PIN_CONFLICT(CONTROLLERFAN) - #error "SPINDLE_LASER_PWM_PIN conflicts with CONTROLLERFAN_PIN." - #elif _PIN_CONFLICT(MOTOR_CURRENT_PWM_XY) - #error "SPINDLE_LASER_PWM_PIN conflicts with MOTOR_CURRENT_PWM_XY." - #elif _PIN_CONFLICT(MOTOR_CURRENT_PWM_Z) - #error "SPINDLE_LASER_PWM_PIN conflicts with MOTOR_CURRENT_PWM_Z." - #elif _PIN_CONFLICT(MOTOR_CURRENT_PWM_E) - #error "SPINDLE_LASER_PWM_PIN conflicts with MOTOR_CURRENT_PWM_E." + #if ENABLED(SPINDLE_FEATURE) + #define _PIN_CONFLICT(P) (PIN_EXISTS(P) && P##_PIN == SPINDLE_LASER_PWM_PIN) + #if NONE(SPINDLE_SERVO, SPINDLE_LASER_USE_PWM) && !PIN_EXISTS(SPINDLE_LASER_ENA) + #error "(SPINDLE|LASER)_FEATURE requires SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_USE_PWM, or SPINDLE_SERVO to control the power." + #elif ENABLED(SPINDLE_CHANGE_DIR) && !PIN_EXISTS(SPINDLE_DIR) + #error "SPINDLE_DIR_PIN is required for SPINDLE_CHANGE_DIR." + #elif ENABLED(SPINDLE_LASER_USE_PWM) + #if (!defined(SPINDLE_LASER_PWM_PIN) || SPINDLE_LASER_PWM_PIN < 0) && (!defined(LASER_PWM_PIN) || LASER_PWM_PIN < 0) + #error "SPINDLE_LASER_PWM_PIN is required for SPINDLE_LASER_USE_PWM." + #elif !_TEST_PWM(SPINDLE_LASER_PWM_PIN) + #error "SPINDLE_LASER_PWM_PIN not assigned to a PWM pin." + #elif !defined(SPINDLE_LASER_PWM_INVERT) + #error "SPINDLE_LASER_PWM_INVERT is required for (SPINDLE|LASER)_FEATURE." + #elif !(defined(SPEED_POWER_MIN) && defined(SPEED_POWER_MAX) && defined(SPEED_POWER_STARTUP)) + #error "SPINDLE_LASER_USE_PWM equation constant(s) missing." + #elif _PIN_CONFLICT(X_MIN) + #error "SPINDLE_LASER_PWM_PIN conflicts with X_MIN_PIN." + #elif _PIN_CONFLICT(X_MAX) + #error "SPINDLE_LASER_PWM_PIN conflicts with X_MAX_PIN." + #elif _PIN_CONFLICT(Z_STEP) + #error "SPINDLE_LASER_PWM_PIN conflicts with Z_STEP_PIN." + #elif _PIN_CONFLICT(CASE_LIGHT) + #error "SPINDLE_LASER_PWM_PIN conflicts with CASE_LIGHT_PIN." + #elif _PIN_CONFLICT(E0_AUTO_FAN) + #error "SPINDLE_LASER_PWM_PIN conflicts with E0_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E1_AUTO_FAN) + #error "SPINDLE_LASER_PWM_PIN conflicts with E1_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E2_AUTO_FAN) + #error "SPINDLE_LASER_PWM_PIN conflicts with E2_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E3_AUTO_FAN) + #error "SPINDLE_LASER_PWM_PIN conflicts with E3_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E4_AUTO_FAN) + #error "SPINDLE_LASER_PWM_PIN conflicts with E4_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E5_AUTO_FAN) + #error "SPINDLE_LASER_PWM_PIN conflicts with E5_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E6_AUTO_FAN) + #error "SPINDLE_LASER_PWM_PIN conflicts with E6_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E7_AUTO_FAN) + #error "SPINDLE_LASER_PWM_PIN conflicts with E7_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(FAN0) + #error "SPINDLE_LASER_PWM_PIN conflicts with FAN0_PIN." + #elif _PIN_CONFLICT(FAN1) + #error "SPINDLE_LASER_PWM_PIN conflicts with FAN1_PIN." + #elif _PIN_CONFLICT(FAN2) + #error "SPINDLE_LASER_PWM_PIN conflicts with FAN2_PIN." + #elif _PIN_CONFLICT(FAN3) + #error "SPINDLE_LASER_PWM_PIN conflicts with FAN3_PIN." + #elif _PIN_CONFLICT(FAN4) + #error "SPINDLE_LASER_PWM_PIN conflicts with FAN4_PIN." + #elif _PIN_CONFLICT(FAN5) + #error "SPINDLE_LASER_PWM_PIN conflicts with FAN5_PIN." + #elif _PIN_CONFLICT(FAN6) + #error "SPINDLE_LASER_PWM_PIN conflicts with FAN6_PIN." + #elif _PIN_CONFLICT(FAN7) + #error "SPINDLE_LASER_PWM_PIN conflicts with FAN7_PIN." + #elif _PIN_CONFLICT(CONTROLLERFAN) + #error "SPINDLE_LASER_PWM_PIN conflicts with CONTROLLERFAN_PIN." + #elif _PIN_CONFLICT(MOTOR_CURRENT_PWM_XY) + #error "SPINDLE_LASER_PWM_PIN conflicts with MOTOR_CURRENT_PWM_XY." + #elif _PIN_CONFLICT(MOTOR_CURRENT_PWM_Z) + #error "SPINDLE_LASER_PWM_PIN conflicts with MOTOR_CURRENT_PWM_Z." + #elif _PIN_CONFLICT(MOTOR_CURRENT_PWM_E) + #error "SPINDLE_LASER_PWM_PIN conflicts with MOTOR_CURRENT_PWM_E." + #endif + #endif + #undef _PIN_CONFLICT + #endif + + + #if ENABLED(LASER_FEATURE) + #define _PIN_CONFLICT(P) (PIN_EXISTS(P) && P##_PIN == LASER_PWM_PIN) + #if NONE(SPINDLE_SERVO, SPINDLE_LASER_USE_PWM) && !PIN_EXISTS(LASER_ENA) + #error "(SPINDLE|LASER)_FEATURE requires LASER_ENA_PIN, SPINDLE_LASER_USE_PWM, or SPINDLE_SERVO to control the power." + #elif ENABLED(SPINDLE_LASER_USE_PWM) + #if (!defined(SPINDLE_LASER_PWM_PIN) || SPINDLE_LASER_PWM_PIN < 0) && (!defined(LASER_PWM_PIN) || LASER_PWM_PIN < 0) + #error "LASER_PWM_PIN is required for SPINDLE_LASER_USE_PWM." + #elif !_TEST_PWM(LASER_PWM_PIN) + #error "LASER_PWM_PIN not assigned to a PWM pin." + #elif !defined(SPINDLE_LASER_PWM_INVERT) + #error "SPINDLE_LASER_PWM_INVERT is required for (SPINDLE|LASER)_FEATURE." + #elif !(defined(SPEED_POWER_MIN) && defined(SPEED_POWER_MAX) && defined(SPEED_POWER_STARTUP)) + #error "SPINDLE_LASER_USE_PWM equation constant(s) missing." + #elif _PIN_CONFLICT(X_MIN) + #error "LASER_PWM_PIN conflicts with X_MIN_PIN." + #elif _PIN_CONFLICT(X_MAX) + #error "LASER_PWM_PIN conflicts with X_MAX_PIN." + #elif _PIN_CONFLICT(Z_STEP) + #error "LASER_PWM_PIN conflicts with Z_STEP_PIN." + #elif _PIN_CONFLICT(CASE_LIGHT) + #error "LASER_PWM_PIN conflicts with CASE_LIGHT_PIN." + #elif _PIN_CONFLICT(E0_AUTO_FAN) + #error "LASER_PWM_PIN conflicts with E0_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E1_AUTO_FAN) + #error "LASER_PWM_PIN conflicts with E1_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E2_AUTO_FAN) + #error "LASER_PWM_PIN conflicts with E2_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E3_AUTO_FAN) + #error "LASER_PWM_PIN conflicts with E3_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E4_AUTO_FAN) + #error "LASER_PWM_PIN conflicts with E4_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E5_AUTO_FAN) + #error "LASER_PWM_PIN conflicts with E5_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E6_AUTO_FAN) + #error "LASER_PWM_PIN conflicts with E6_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(E7_AUTO_FAN) + #error "LASER_PWM_PIN conflicts with E7_AUTO_FAN_PIN." + #elif _PIN_CONFLICT(FAN0) + #error "LASER_PWM_PIN conflicts with FAN0_PIN." + #elif _PIN_CONFLICT(FAN1) + #error "LASER_PWM_PIN conflicts with FAN1_PIN." + #elif _PIN_CONFLICT(FAN2) + #error "LASER_PWM_PIN conflicts with FAN2_PIN." + #elif _PIN_CONFLICT(FAN3) + #error "LASER_PWM_PIN conflicts with FAN3_PIN." + #elif _PIN_CONFLICT(FAN4) + #error "LASER_PWM_PIN conflicts with FAN4_PIN." + #elif _PIN_CONFLICT(FAN5) + #error "LASER_PWM_PIN conflicts with FAN5_PIN." + #elif _PIN_CONFLICT(FAN6) + #error "LASER_PWM_PIN conflicts with FAN6_PIN." + #elif _PIN_CONFLICT(FAN7) + #error "LASER_PWM_PIN conflicts with FAN7_PIN." + #elif _PIN_CONFLICT(CONTROLLERFAN) + #error "LASER_PWM_PIN conflicts with CONTROLLERFAN_PIN." + #elif _PIN_CONFLICT(MOTOR_CURRENT_PWM_XY) + #error "LASER_PWM_PIN conflicts with MOTOR_CURRENT_PWM_XY." + #elif _PIN_CONFLICT(MOTOR_CURRENT_PWM_Z) + #error "LASER_PWM_PIN conflicts with MOTOR_CURRENT_PWM_Z." + #elif _PIN_CONFLICT(MOTOR_CURRENT_PWM_E) + #error "LASER_PWM_PIN conflicts with MOTOR_CURRENT_PWM_E." + #endif #endif + #undef _PIN_CONFLICT #endif - #undef _PIN_CONFLICT #ifdef LASER_SAFETY_TIMEOUT_MS static_assert(LASER_SAFETY_TIMEOUT_MS < (DEFAULT_STEPPER_TIMEOUT_SEC) * 1000UL, "LASER_SAFETY_TIMEOUT_MS must be less than DEFAULT_STEPPER_TIMEOUT_SEC (" STRINGIFY(DEFAULT_STEPPER_TIMEOUT_SEC) " seconds)"); @@ -4508,4 +4575,4 @@ static_assert(WITHIN(MULTISTEPPING_LIMIT, 1, 128) && IS_POWER_OF_2(MULTISTEPPING // Misc. Cleanup #undef _TEST_PWM #undef _NUM_AXES_STR -#undef _LOGICAL_AXES_STR +#undef _LOGICAL_AXES_STR \ No newline at end of file diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp index 227f634b7d98..e937c36a4e13 100644 --- a/Marlin/src/module/tool_change.cpp +++ b/Marlin/src/module/tool_change.cpp @@ -1253,6 +1253,29 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { } #endif + #if HAS_CUTTER + // Store cutter state and stop cutter + bool old_cutter_state = cutter.enable_state; + uint8_t old_cutter_power = cutter.power; + uint8_t old_tool_type = cutter.active_tool_type; + cutter.power = 0; + cutter.apply_power(0); + #if ENABLED(LASER_FEATURE) + cutter.inline_power(cutter.power); + #endif + cutter.set_enabled(false); + TERN_(SPINDLE_FEATURE, safe_delay(1000)); + #endif + + #if ENABLED(COOLANT_MIST) + bool old_mist_coolant_state = TERN(COOLANT_MIST_INVERT, !READ(COOLANT_MIST_PIN), READ(COOLANT_MIST_PIN)); + WRITE(COOLANT_MIST_PIN, COOLANT_MIST_INVERT); // Turn off Mist coolant + #endif + #if ENABLED(COOLANT_FLOOD) + bool old_flood_coolant_state = TERN(COOLANT_FLOOD_INVERT, !READ(COOLANT_FLOOD_PIN), READ(COOLANT_FLOOD_PIN)); + WRITE(COOLANT_FLOOD_PIN, COOLANT_FLOOD_INVERT); // Turn off Flood coolant + #endif + // Toolchange park #if ENABLED(TOOLCHANGE_PARK) && !HAS_SWITCHING_NOZZLE if (can_move_away && toolchange_settings.enable_park) { @@ -1412,6 +1435,63 @@ void tool_change(const uint8_t new_tool, bool no_move/*=false*/) { TERN_(DUAL_X_CARRIAGE, idex_set_parked(false)); } // should_move + #if HAS_CUTTER + + #if ALL(SPINDLE_FEATURE, LASER_FEATURE) + if (new_tool == LASER_TOOL) { + cutter.active_tool_type = TYPE_LASER; + } + else if (new_tool < LASER_TOOL) { + cutter.active_tool_type = TYPE_EXTRUDER; + } + else { + cutter.active_tool_type = TYPE_SPINDLE; + } + // Restore cutter state + if (old_cutter_state && (old_tool == TYPE_SPINDLE) && new_tool > LASER_TOOL) { + #elif ENABLED(SPINDLE_FEATURE) + if (new_tool < EXTRUDERS) { + cutter.active_tool_type = TYPE_EXTRUDER; + } + else { + cutter.active_tool_type = TYPE_SPINDLE; + } + if (old_cutter_state && cutter.active_tool_type != TYPE_EXTRUDER) { + #elif ENABLED(LASER_FEATURE) + if (new_tool < LASER_TOOL) { + cutter.active_tool_type = TYPE_EXTRUDER; + } + else { + cutter.active_tool_type = TYPE_LASER; + } + if (old_cutter_state && cutter.active_tool_type != TYPE_EXTRUDER) { + #endif + cutter.power = old_cutter_power; + cutter.apply_power(cutter.power); + #if ENABLED(LASER_FEATURE) + if ((cutter.active_tool_type == TYPE_LASER ) && (cutter.cutter_mode != CUTTER_MODE_STANDARD)) { + cutter.inline_power(cutter.power); + } + #endif + cutter.set_enabled(true); + if (TERN0(SPINDLE_FEATURE, cutter.active_tool_type = TYPE_SPINDLE)) { + safe_delay(1000); + } + } + #endif + + + #if ENABLED(COOLANT_MIST) + if old_mist_coolant_state { + WRITE(COOLANT_MIST_PIN, !COOLANT_MIST_INVERT); // Turn on Mist coolant + } + #endif + #if ENABLED(COOLANT_FLOOD) + if old_flood_coolant_state { + WRITE(COOLANT_FLOOD_PIN, !COOLANT_FLOOD_INVERT); // Turn on Flood coolant + } + #endif + #if HAS_SWITCHING_NOZZLE // Move back down. (Including when the new tool is higher.) if (!should_move) diff --git a/Marlin/src/pins/rambo/pins_MINIRAMBO.h b/Marlin/src/pins/rambo/pins_MINIRAMBO.h index 18f73a81d562..25a7c177ebc8 100644 --- a/Marlin/src/pins/rambo/pins_MINIRAMBO.h +++ b/Marlin/src/pins/rambo/pins_MINIRAMBO.h @@ -135,12 +135,29 @@ #ifndef SPINDLE_LASER_PWM_PIN #define SPINDLE_LASER_PWM_PIN 9 // Hardware PWM #endif + #if ENABLED(LASER_FEATURE) + #ifndef LASER_PWM_PIN + #define LASER_PWM_PIN 9 // Hardware PWM + #endif + #endif + #ifndef SPINDLE_LASER_ENA_PIN #define SPINDLE_LASER_ENA_PIN 18 // Pullup! #endif + #if ENABLED(LASER_FEATURE) + #ifndef LASER_ENA_PIN + #define LASER_ENA_PIN 18 // Pullup! + #endif + #endif #ifndef SPINDLE_DIR_PIN #define SPINDLE_DIR_PIN 19 #endif + #if ENABLED(LASER_FEATURE) + #ifndef LASER_DIR_PIN + #define LASER_DIR_PIN 19 + #endif + #endif + #endif // diff --git a/Marlin/src/pins/ramps/pins_RAMPS.h b/Marlin/src/pins/ramps/pins_RAMPS.h index 2d82b36f7740..26974f033483 100644 --- a/Marlin/src/pins/ramps/pins_RAMPS.h +++ b/Marlin/src/pins/ramps/pins_RAMPS.h @@ -318,11 +318,26 @@ #ifndef SPINDLE_LASER_PWM_PIN #define SPINDLE_LASER_PWM_PIN 6 // Hardware PWM #endif + #if ENABLED(LASER_FEATURE) + #ifndef LASER_PWM_PIN + #define LASER_PWM_PIN 6 // Hardware PWM + #endif + #endif #define SPINDLE_LASER_ENA_PIN 4 // Pullup or pulldown! #define SPINDLE_DIR_PIN 5 #elif HAS_FREE_AUX2_PINS #define SPINDLE_LASER_PWM_PIN AUX2_07 // Hardware PWM + #if ENABLED(LASER_FEATURE) + #ifndef LASER_PWM_PIN + #define LASER_PWM_PIN AUX2_07 // Hardware PWM + #endif + #endif #define SPINDLE_LASER_ENA_PIN AUX2_06 // Pullup or pulldown! + #if ENABLED(LASER_FEATURE) + #ifndef LASER_ENA_PIN + #define LASER_ENA_PIN AUX2_06 // Pullup or pulldown! + #endif + #endif #define SPINDLE_DIR_PIN AUX2_10 #else #error "No auto-assignable Spindle/Laser pins available." diff --git a/Marlin/src/pins/ramps/pins_RUMBA.h b/Marlin/src/pins/ramps/pins_RUMBA.h index 24cc2bada089..9f2c0804fc36 100644 --- a/Marlin/src/pins/ramps/pins_RUMBA.h +++ b/Marlin/src/pins/ramps/pins_RUMBA.h @@ -179,12 +179,28 @@ #ifndef SPINDLE_LASER_PWM_PIN #define SPINDLE_LASER_PWM_PIN 4 // Hardware PWM. Pin 4 interrupts OC0* and OC1* always in use? #endif +#if ENABLED(LASER_FEATURE) + #ifndef LASER_PWM_PIN + #define LASER_PWM_PIN 4 // Hardware PWM. Pin 4 interrupts OC0* and OC1* always in use? + #endif +#endif + #ifndef SPINDLE_LASER_ENA_PIN #define SPINDLE_LASER_ENA_PIN 14 // Pullup! #endif +#if ENABLED(LASER_FEATURE) + #ifndef LASER_ENA_PIN + #define LASER_ENA_PIN 14 // Pullup! + #endif +#endif #ifndef SPINDLE_DIR_PIN #define SPINDLE_DIR_PIN 15 #endif +#if ENABLED(LASER_FEATURE) + #ifndef LASER_DIR_PIN + #define LASER_DIR_PIN 15 + #endif +#endif // // LCD / Controller diff --git a/Marlin/src/pins/stm32f4/pins_BTT_SKR_V2_0_common.h b/Marlin/src/pins/stm32f4/pins_BTT_SKR_V2_0_common.h index d0d78ed7f56c..9aeaaee0cf17 100644 --- a/Marlin/src/pins/stm32f4/pins_BTT_SKR_V2_0_common.h +++ b/Marlin/src/pins/stm32f4/pins_BTT_SKR_V2_0_common.h @@ -257,9 +257,21 @@ #ifndef SPINDLE_LASER_PWM_PIN #define SPINDLE_LASER_PWM_PIN PB5 #endif + #if ENABLED(LASER_FEATURE) + #ifndef LASER_PWM_PIN + #define LASER_PWM_PIN PB5 + #endif + #endif + #ifndef SPINDLE_LASER_ENA_PIN #define SPINDLE_LASER_ENA_PIN PB6 #endif + #if ENABLED(LASER_FEATURE) + #ifndef LASER_ENA_PIN + #define LASER_ENA_PIN PB6 + #endif + #endif + #else #ifndef FAN1_PIN #define FAN1_PIN PB6 // Fan1 diff --git a/Marlin/src/pins/stm32h7/pins_BTT_SKR_V3_0_common.h b/Marlin/src/pins/stm32h7/pins_BTT_SKR_V3_0_common.h index fce16aebf112..ab91e692e135 100644 --- a/Marlin/src/pins/stm32h7/pins_BTT_SKR_V3_0_common.h +++ b/Marlin/src/pins/stm32h7/pins_BTT_SKR_V3_0_common.h @@ -250,9 +250,21 @@ #ifndef SPINDLE_LASER_PWM_PIN #define SPINDLE_LASER_PWM_PIN PB5 #endif + #if ENABLED(LASER_FEATURE) + #ifndef LASER_PWM_PIN + #define LASER_PWM_PIN PB5 + #endif + #endif + #ifndef SPINDLE_LASER_ENA_PIN #define SPINDLE_LASER_ENA_PIN PB6 #endif + #if ENABLED(LASER_FEATURE) + #ifndef LASER_ENA_PIN + #define LASER_ENA_PIN PB6 + #endif + #endif + #else #ifndef FAN1_PIN #define FAN1_PIN PB6 // Fan1 diff --git a/buildroot/tests/BTT_SKR_PRO b/buildroot/tests/BTT_SKR_PRO index f20116d9a1fd..ff8aae080f35 100755 --- a/buildroot/tests/BTT_SKR_PRO +++ b/buildroot/tests/BTT_SKR_PRO @@ -24,7 +24,7 @@ exec_test $1 $2 "BigTreeTech SKR Pro | 3 Extruders | Auto-Fan | BLTOUCH | Mixed restore_configs opt_set MOTHERBOARD BOARD_BTT_SKR_PRO_V1_1 SERIAL_PORT -1 \ CUTTER_POWER_UNIT PERCENT \ - SPINDLE_LASER_PWM_PIN HEATER_1_PIN SPINDLE_LASER_ENA_PIN HEATER_2_PIN \ + LASER_PWM_PIN HEATER_1_PIN LASER_ENA_PIN HEATER_2_PIN \ TEMP_SENSOR_COOLER 1000 TEMP_COOLER_PIN PD13 opt_enable LASER_FEATURE LASER_SAFETY_TIMEOUT_MS REPRAP_DISCOUNT_SMART_CONTROLLER exec_test $1 $2 "BigTreeTech SKR Pro | HD44780 | Laser (Percent) | Cooling | LCD" "$3" diff --git a/buildroot/tests/I3DBEEZ9_V1 b/buildroot/tests/I3DBEEZ9_V1 index 810093282732..71122ca8ce8d 100755 --- a/buildroot/tests/I3DBEEZ9_V1 +++ b/buildroot/tests/I3DBEEZ9_V1 @@ -24,7 +24,7 @@ exec_test $1 $2 "I3DBEE Z9 Board | 3 Extruders | Auto-Fan | BLTOUCH | Mixed TMC" restore_configs opt_set MOTHERBOARD BOARD_I3DBEEZ9_V1 SERIAL_PORT -1 \ CUTTER_POWER_UNIT PERCENT \ - SPINDLE_LASER_PWM_PIN HEATER_1_PIN SPINDLE_LASER_ENA_PIN HEATER_2_PIN \ + LASER_PWM_PIN HEATER_1_PIN LASER_ENA_PIN HEATER_2_PIN \ TEMP_SENSOR_COOLER 1000 TEMP_COOLER_PIN PD13 opt_enable LASER_FEATURE LASER_SAFETY_TIMEOUT_MS REPRAP_DISCOUNT_SMART_CONTROLLER exec_test $1 $2 "I3DBEE Z9 Board | HD44780 | Laser (Percent) | Cooling | LCD" "$3"