1
0
mirror of https://github.com/MarlinFirmware/Marlin.git synced 2024-11-23 12:04:19 +00:00

🔧 Clarify axis disable / timeout (#25571)

This commit is contained in:
Scott Lahteine 2023-03-26 17:24:40 -05:00
parent ee088146c0
commit 4a0b539f60
16 changed files with 133 additions and 68 deletions

View File

@ -1645,8 +1645,8 @@
// @section extruder
#define DISABLE_E false // Disable the extruder when not stepping
#define DISABLE_INACTIVE_EXTRUDER // Keep only the active extruder enabled
#define DISABLE_E false // Disable the extruder when not stepping
#define DISABLE_OTHER_EXTRUDERS // Keep only the active extruder enabled
// @section motion

View File

@ -1114,20 +1114,20 @@
/**
* Idle Stepper Shutdown
* Set DISABLE_INACTIVE_? 'true' to shut down axis steppers after an idle period.
* The Deactive Time can be overridden with M18 and M84. Set to 0 for No Timeout.
* Enable DISABLE_IDLE_* to shut down axis steppers after an idle period.
* The default timeout duration can be overridden with M18 and M84. Set to 0 for No Timeout.
*/
#define DEFAULT_STEPPER_DEACTIVE_TIME 120
#define DISABLE_INACTIVE_X true
#define DISABLE_INACTIVE_Y true
#define DISABLE_INACTIVE_Z true // Set 'false' if the nozzle could fall onto your printed part!
#define DISABLE_INACTIVE_I true
#define DISABLE_INACTIVE_J true
#define DISABLE_INACTIVE_K true
#define DISABLE_INACTIVE_U true
#define DISABLE_INACTIVE_V true
#define DISABLE_INACTIVE_W true
#define DISABLE_INACTIVE_E true
#define DEFAULT_STEPPER_TIMEOUT_SEC 120
#define DISABLE_IDLE_X
#define DISABLE_IDLE_Y
#define DISABLE_IDLE_Z // Disable if the nozzle could fall onto your printed part!
//#define DISABLE_IDLE_I
//#define DISABLE_IDLE_J
//#define DISABLE_IDLE_K
//#define DISABLE_IDLE_U
//#define DISABLE_IDLE_V
//#define DISABLE_IDLE_W
#define DISABLE_IDLE_E // Shut down all idle extruders
// Default Minimum Feedrates for printing and travel moves
#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s. °/s for rotational-only moves) Minimum feedrate. Set with M205 S.

View File

@ -127,7 +127,7 @@ busy_while_heating = on
default_ejerk = 5.0
default_keepalive_interval = 2
default_leveling_fade_height = 0.0
disable_inactive_extruder = on
disable_other_extruders = on
display_charset_hd44780 = JAPANESE
eeprom_boot_silent = on
eeprom_chitchat = on
@ -176,12 +176,12 @@ auto_report_temperatures = on
autotemp = on
autotemp_oldweight = 0.98
bed_check_interval = 5000
default_stepper_deactive_time = 120
default_stepper_timeout_sec = 120
default_volumetric_extruder_limit = 0.00
disable_inactive_e = true
disable_inactive_x = true
disable_inactive_y = true
disable_inactive_z = true
disable_idle_x = on
disable_idle_y = on
disable_idle_z = on
disable_idle_e = on
e0_auto_fan_pin = -1
encoder_100x_steps_per_sec = 80
encoder_10x_steps_per_sec = 30

View File

@ -431,7 +431,7 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
if (has_blocks) gcode.reset_stepper_timeout(ms); // Reset timeout for M18/M84, M85 max 'kill', and laser.
// M18 / M84 : Handle steppers inactive time timeout
#if HAS_DISABLE_INACTIVE_AXIS
#if HAS_DISABLE_IDLE_AXES
if (gcode.stepper_inactive_time) {
static bool already_shutdown_steppers; // = false
@ -441,16 +441,16 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) {
already_shutdown_steppers = true;
// Individual axes will be disabled if configured
TERN_(DISABLE_INACTIVE_X, stepper.disable_axis(X_AXIS));
TERN_(DISABLE_INACTIVE_Y, stepper.disable_axis(Y_AXIS));
TERN_(DISABLE_INACTIVE_Z, stepper.disable_axis(Z_AXIS));
TERN_(DISABLE_INACTIVE_I, stepper.disable_axis(I_AXIS));
TERN_(DISABLE_INACTIVE_J, stepper.disable_axis(J_AXIS));
TERN_(DISABLE_INACTIVE_K, stepper.disable_axis(K_AXIS));
TERN_(DISABLE_INACTIVE_U, stepper.disable_axis(U_AXIS));
TERN_(DISABLE_INACTIVE_V, stepper.disable_axis(V_AXIS));
TERN_(DISABLE_INACTIVE_W, stepper.disable_axis(W_AXIS));
TERN_(DISABLE_INACTIVE_E, stepper.disable_e_steppers());
TERN_(DISABLE_IDLE_X, stepper.disable_axis(X_AXIS));
TERN_(DISABLE_IDLE_Y, stepper.disable_axis(Y_AXIS));
TERN_(DISABLE_IDLE_Z, stepper.disable_axis(Z_AXIS));
TERN_(DISABLE_IDLE_I, stepper.disable_axis(I_AXIS));
TERN_(DISABLE_IDLE_J, stepper.disable_axis(J_AXIS));
TERN_(DISABLE_IDLE_K, stepper.disable_axis(K_AXIS));
TERN_(DISABLE_IDLE_U, stepper.disable_axis(U_AXIS));
TERN_(DISABLE_IDLE_V, stepper.disable_axis(V_AXIS));
TERN_(DISABLE_IDLE_W, stepper.disable_axis(W_AXIS));
TERN_(DISABLE_IDLE_E, stepper.disable_e_steppers());
TERN_(AUTO_BED_LEVELING_UBL, bedlevel.steppers_were_disabled());
}

View File

@ -212,7 +212,7 @@ void try_to_disable(const stepper_flags_t to_disable) {
void GcodeSuite::M18_M84() {
if (parser.seenval('S')) {
reset_stepper_timeout();
#if HAS_DISABLE_INACTIVE_AXIS
#if HAS_DISABLE_IDLE_AXES
const millis_t ms = parser.value_millis_from_seconds();
#if LASER_SAFETY_TIMEOUT_MS > 0
if (ms && ms <= LASER_SAFETY_TIMEOUT_MS) {

View File

@ -75,8 +75,8 @@ GcodeSuite gcode;
millis_t GcodeSuite::previous_move_ms = 0,
GcodeSuite::max_inactive_time = 0;
#if HAS_DISABLE_INACTIVE_AXIS
millis_t GcodeSuite::stepper_inactive_time = SEC_TO_MS(DEFAULT_STEPPER_DEACTIVE_TIME);
#if HAS_DISABLE_IDLE_AXES
millis_t GcodeSuite::stepper_inactive_time = SEC_TO_MS(DEFAULT_STEPPER_TIMEOUT_SEC);
#endif
// Relative motion mode for each logical axis

View File

@ -403,7 +403,7 @@ public:
}
FORCE_INLINE static void reset_stepper_timeout(const millis_t ms=millis()) { previous_move_ms = ms; }
#if HAS_DISABLE_INACTIVE_AXIS
#if HAS_DISABLE_IDLE_AXES
static millis_t stepper_inactive_time;
FORCE_INLINE static bool stepper_inactive_timeout(const millis_t ms=millis()) {
return ELAPSED(ms, previous_move_ms + stepper_inactive_time);

View File

@ -608,7 +608,7 @@
#undef PREVENT_LENGTHY_EXTRUDE
#undef FILAMENT_RUNOUT_SENSOR
#undef FILAMENT_RUNOUT_DISTANCE_MM
#undef DISABLE_INACTIVE_EXTRUDER
#undef DISABLE_OTHER_EXTRUDERS
#endif
#define E_OPTARG(N) OPTARG(HAS_MULTI_EXTRUDER, N)
@ -654,8 +654,8 @@
#endif
// No inactive extruders with SWITCHING_NOZZLE or Průša MMU1
#if ENABLED(SWITCHING_NOZZLE) || HAS_PRUSA_MMU1
#undef DISABLE_INACTIVE_EXTRUDER
#if EITHER(SWITCHING_NOZZLE, HAS_PRUSA_MMU1)
#undef DISABLE_OTHER_EXTRUDERS
#endif
// Průša MMU1, MMU(S) 2.0 and EXTENDABLE_EMU_MMU2(S) force SINGLENOZZLE
@ -908,6 +908,15 @@
#undef MAX_SOFTWARE_ENDSTOP_W
#endif
#define _OR_HAS_DA(A) ENABLED(DISABLE_##A) ||
#if MAP(_OR_HAS_DA, X, Y, Z, I, J, K, U, V, W) 0
#define HAS_DISABLE_MAIN_AXES 1
#endif
#if HAS_DISABLE_MAIN_AXES || ENABLED(DISABLE_E)
#define HAS_DISABLE_AXES 1
#endif
#undef _OR_HAS_DA
#ifdef X2_DRIVER_TYPE
#define HAS_X2_STEPPER 1
// Dual X Carriage isn't known yet. TODO: Consider moving it to Configuration.h.

View File

@ -88,6 +88,7 @@
// Some options are disallowed without required axes
#if !HAS_Y_AXIS
#undef DISABLE_IDLE_Y
#undef SAFE_BED_LEVELING_START_Y
#undef ARC_SUPPORT
#undef INPUT_SHAPING_Y
@ -95,30 +96,42 @@
#undef SHAPING_BUFFER_Y
#endif
#if !HAS_Z_AXIS
#undef DISABLE_IDLE_Z
#undef ENABLE_LEVELING_FADE_HEIGHT
#undef HOME_Z_FIRST
#undef HOMING_Z_WITH_PROBE
#undef NUM_Z_STEPPERS
#undef SAFE_BED_LEVELING_START_Z
#endif
#if !HAS_I_AXIS
#undef DISABLE_IDLE_I
#undef SAFE_BED_LEVELING_START_I
#endif
#if !HAS_J_AXIS
#undef DISABLE_IDLE_J
#undef SAFE_BED_LEVELING_START_J
#endif
#if !HAS_K_AXIS
#undef DISABLE_IDLE_K
#undef SAFE_BED_LEVELING_START_K
#endif
#if !HAS_U_AXIS
#undef DISABLE_IDLE_U
#undef SAFE_BED_LEVELING_START_U
#endif
#if !HAS_V_AXIS
#undef DISABLE_IDLE_V
#undef SAFE_BED_LEVELING_START_V
#endif
#if !HAS_W_AXIS
#undef DISABLE_IDLE_W
#undef SAFE_BED_LEVELING_START_W
#endif
// Disallowed with no extruders
#if !HAS_EXTRUDERS
#define NO_VOLUMETRICS
#undef DISABLE_IDLE_E
#undef FWRETRACT
#undef PIDTEMP
#undef AUTOTEMP
@ -135,6 +148,43 @@
#undef STEALTHCHOP_E
#endif
#if ENABLED(DISABLE_X) && !defined(DISABLE_IDLE_X)
#define DISABLE_IDLE_X
#endif
#if ENABLED(DISABLE_Y) && !defined(DISABLE_IDLE_Y)
#define DISABLE_IDLE_Y
#endif
#if ENABLED(DISABLE_Z) && !defined(DISABLE_IDLE_Z)
#define DISABLE_IDLE_Z
#endif
#if ENABLED(DISABLE_I) && !defined(DISABLE_IDLE_I)
#define DISABLE_IDLE_I
#endif
#if ENABLED(DISABLE_J) && !defined(DISABLE_IDLE_J)
#define DISABLE_IDLE_J
#endif
#if ENABLED(DISABLE_K) && !defined(DISABLE_IDLE_K)
#define DISABLE_IDLE_K
#endif
#if ENABLED(DISABLE_U) && !defined(DISABLE_IDLE_U)
#define DISABLE_IDLE_U
#endif
#if ENABLED(DISABLE_V) && !defined(DISABLE_IDLE_V)
#define DISABLE_IDLE_V
#endif
#if ENABLED(DISABLE_W) && !defined(DISABLE_IDLE_W)
#define DISABLE_IDLE_W
#endif
#if ENABLED(DISABLE_E) && !defined(DISABLE_IDLE_E)
#define DISABLE_IDLE_E
#endif
#define _OR_HAS_DI(A) || BOTH(HAS_##A##_AXIS, DISABLE_IDLE_##A)
#if BOTH(HAS_EXTRUDERS, DISABLE_IDLE_E) MAP(_OR_HAS_DI, X, Y, Z, I, J, K, U, V, W)
#define HAS_DISABLE_IDLE_AXES 1
#endif
#undef _OR_HAS_DI
#if HOTENDS <= 7
#undef E7_AUTO_FAN_PIN
#if HOTENDS <= 6

View File

@ -662,6 +662,12 @@
#error "TMC_SW_(MOSI|MISO|SCK) is now TMC_SPI_(MOSI|MISO|SCK)."
#elif defined(BTT_MINI_12864_V1)
#error "BTT_MINI_12864_V1 is now BTT_MINI_12864."
#elif defined(DISABLE_INACTIVE_X) || defined(DISABLE_INACTIVE_Y) || defined(DISABLE_INACTIVE_Z) \
|| defined(DISABLE_INACTIVE_I) || defined(DISABLE_INACTIVE_J) || defined(DISABLE_INACTIVE_K) \
|| defined(DISABLE_INACTIVE_U) || defined(DISABLE_INACTIVE_V) || defined(DISABLE_INACTIVE_W) || defined(DISABLE_INACTIVE_E)
#error "DISABLE_INACTIVE_[XYZIJKUVWE] is now DISABLE_IDLE_[XYZIJKUVWE]."
#elif defined(DEFAULT_STEPPER_DEACTIVE_TIME)
#error "DEFAULT_STEPPER_DEACTIVE_TIME is now DEFAULT_STEPPER_TIMEOUT_SEC."
#endif
// L64xx stepper drivers have been removed
@ -1333,8 +1339,8 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
#error "Please select either MIXING_EXTRUDER or SWITCHING_EXTRUDER, not both."
#elif ENABLED(SINGLENOZZLE)
#error "MIXING_EXTRUDER is incompatible with SINGLENOZZLE."
#elif ENABLED(DISABLE_INACTIVE_EXTRUDER)
#error "MIXING_EXTRUDER is incompatible with DISABLE_INACTIVE_EXTRUDER."
#elif ENABLED(DISABLE_OTHER_EXTRUDERS)
#error "MIXING_EXTRUDER is incompatible with DISABLE_OTHER_EXTRUDERS."
#elif HAS_FILAMENT_RUNOUT_DISTANCE
#error "MIXING_EXTRUDER is incompatible with FILAMENT_RUNOUT_DISTANCE_MM."
#endif
@ -2195,10 +2201,8 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE, "Movement bounds (X_MIN_POS, X_MAX_POS
/**
* Make sure DISABLE_[XYZ] compatible with selected homing options
*/
#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_U, DISABLE_V, DISABLE_W)
#if ANY(HOME_AFTER_DEACTIVATE, Z_SAFE_HOMING)
#error "DISABLE_[XYZIJKUVW] is not compatible with HOME_AFTER_DEACTIVATE or Z_SAFE_HOMING."
#endif
#if HAS_DISABLE_MAIN_AXES && ANY(HOME_AFTER_DEACTIVATE, Z_SAFE_HOMING)
#error "DISABLE_[XYZIJKUVW] is not compatible with HOME_AFTER_DEACTIVATE or Z_SAFE_HOMING."
#endif
/**
@ -4133,7 +4137,7 @@ static_assert(_PLUS_TEST(4), "HOMING_FEEDRATE_MM_M values must be positive.");
#undef _PIN_CONFLICT
#ifdef LASER_SAFETY_TIMEOUT_MS
static_assert(LASER_SAFETY_TIMEOUT_MS < (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL, "LASER_SAFETY_TIMEOUT_MS must be less than DEFAULT_STEPPER_DEACTIVE_TIME (" STRINGIFY(DEFAULT_STEPPER_DEACTIVE_TIME) " seconds)");
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)");
#endif
#endif

View File

@ -216,7 +216,7 @@ uint32_t Planner::acceleration_long_cutoff;
xyze_float_t Planner::previous_speed;
float Planner::previous_nominal_speed;
#if ENABLED(DISABLE_INACTIVE_EXTRUDER)
#if ENABLED(DISABLE_OTHER_EXTRUDERS)
last_move_t Planner::g_uc_extruder_last_move[E_STEPPERS] = { 0 };
#endif
@ -1321,7 +1321,7 @@ void Planner::recalculate(TERN_(HINTS_SAFE_EXIT_SPEED, const_float_t safe_exit_s
*/
void Planner::check_axes_activity() {
#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_U, DISABLE_V, DISABLE_W, DISABLE_E)
#if HAS_DISABLE_AXES
xyze_bool_t axis_active = { false };
#endif
@ -1361,7 +1361,7 @@ void Planner::check_axes_activity() {
TERN_(HAS_HEATER_2, tail_e_to_p_pressure = block->e_to_p_pressure);
#endif
#if ANY(DISABLE_X, DISABLE_Y, DISABLE_Z, DISABLE_I, DISABLE_J, DISABLE_K, DISABLE_E)
#if HAS_DISABLE_AXES
for (uint8_t b = block_buffer_tail; b != block_buffer_head; b = next_block_index(b)) {
block_t * const bnext = &block_buffer[b];
LOGICAL_AXIS_CODE(
@ -1402,18 +1402,20 @@ void Planner::check_axes_activity() {
//
// Disable inactive axes
//
LOGICAL_AXIS_CODE(
if (TERN0(DISABLE_E, !axis_active.e)) stepper.disable_e_steppers(),
if (TERN0(DISABLE_X, !axis_active.x)) stepper.disable_axis(X_AXIS),
if (TERN0(DISABLE_Y, !axis_active.y)) stepper.disable_axis(Y_AXIS),
if (TERN0(DISABLE_Z, !axis_active.z)) stepper.disable_axis(Z_AXIS),
if (TERN0(DISABLE_I, !axis_active.i)) stepper.disable_axis(I_AXIS),
if (TERN0(DISABLE_J, !axis_active.j)) stepper.disable_axis(J_AXIS),
if (TERN0(DISABLE_K, !axis_active.k)) stepper.disable_axis(K_AXIS),
if (TERN0(DISABLE_U, !axis_active.u)) stepper.disable_axis(U_AXIS),
if (TERN0(DISABLE_V, !axis_active.v)) stepper.disable_axis(V_AXIS),
if (TERN0(DISABLE_W, !axis_active.w)) stepper.disable_axis(W_AXIS)
);
#if HAS_DISABLE_AXES
LOGICAL_AXIS_CODE(
if (TERN0(DISABLE_E, !axis_active.e)) stepper.disable_e_steppers(),
if (TERN0(DISABLE_X, !axis_active.x)) stepper.disable_axis(X_AXIS),
if (TERN0(DISABLE_Y, !axis_active.y)) stepper.disable_axis(Y_AXIS),
if (TERN0(DISABLE_Z, !axis_active.z)) stepper.disable_axis(Z_AXIS),
if (TERN0(DISABLE_I, !axis_active.i)) stepper.disable_axis(I_AXIS),
if (TERN0(DISABLE_J, !axis_active.j)) stepper.disable_axis(J_AXIS),
if (TERN0(DISABLE_K, !axis_active.k)) stepper.disable_axis(K_AXIS),
if (TERN0(DISABLE_U, !axis_active.u)) stepper.disable_axis(U_AXIS),
if (TERN0(DISABLE_V, !axis_active.v)) stepper.disable_axis(V_AXIS),
if (TERN0(DISABLE_W, !axis_active.w)) stepper.disable_axis(W_AXIS)
);
#endif
//
// Update Fan speeds
@ -2314,7 +2316,7 @@ bool Planner::_populate_block(
if (esteps) {
TERN_(AUTO_POWER_CONTROL, powerManager.power_on());
#if ENABLED(DISABLE_INACTIVE_EXTRUDER) // Enable only the selected extruder
#if ENABLED(DISABLE_OTHER_EXTRUDERS) // Enable only the selected extruder
// Count down all steppers that were recently moved
for (uint8_t i = 0; i < E_STEPPERS; ++i)

View File

@ -346,7 +346,7 @@ typedef struct {
#endif
} skew_factor_t;
#if ENABLED(DISABLE_INACTIVE_EXTRUDER)
#if ENABLED(DISABLE_OTHER_EXTRUDERS)
typedef IF<(BLOCK_BUFFER_SIZE > 64), uint16_t, uint8_t>::type last_move_t;
#endif
@ -520,7 +520,7 @@ class Planner {
static float last_fade_z;
#endif
#if ENABLED(DISABLE_INACTIVE_EXTRUDER)
#if ENABLED(DISABLE_OTHER_EXTRUDERS)
// Counters to manage disabling inactive extruder steppers
static last_move_t g_uc_extruder_last_move[E_STEPPERS];
#endif

View File

@ -81,7 +81,7 @@ opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO MIXING_STEPPERS 5 LCD_LANGUAGE ru \
opt_enable MIXING_EXTRUDER GRADIENT_MIX GRADIENT_VTOOL CR10_STOCKDISPLAY \
USE_CONTROLLER_FAN CONTROLLER_FAN_EDITABLE CONTROLLER_FAN_IGNORE_Z \
FILAMENT_RUNOUT_SENSOR ADVANCED_PAUSE_FEATURE NOZZLE_PARK_FEATURE INPUT_SHAPING_X INPUT_SHAPING_Y
opt_disable DISABLE_INACTIVE_EXTRUDER
opt_disable DISABLE_OTHER_EXTRUDERS
exec_test $1 $2 "Azteeg X3 | Mixing Extruder (x5) | Gradient Mix | Input Shaping | Greek" "$3"
#

View File

@ -125,7 +125,7 @@ opt_enable COREYX USE_XMAX_PLUG MIXING_EXTRUDER GRADIENT_MIX \
SD_ABORT_ON_ENDSTOP_HIT HOST_ACTION_COMMANDS HOST_PROMPT_SUPPORT HOST_PAUSE_M76 ADVANCED_OK M114_DETAIL \
VOLUMETRIC_DEFAULT_ON NO_WORKSPACE_OFFSETS EXTRA_FAN_SPEED FWRETRACT \
USE_CONTROLLER_FAN CONTROLLER_FAN_EDITABLE CONTROLLER_FAN_USE_Z_ONLY
opt_disable DISABLE_INACTIVE_EXTRUDER
opt_disable DISABLE_OTHER_EXTRUDERS
exec_test $1 $2 "Rambo | CoreXY, Gradient Mix | Endstop Int. | Home Y > X | FW Retract ..." "$3"
# clean up

View File

@ -67,7 +67,7 @@ exec_test $1 $2 "PARKING_EXTRUDER with LCD" "$3"
restore_configs
opt_set MOTHERBOARD BOARD_TEENSY35_36 MIXING_STEPPERS 2
opt_enable MIXING_EXTRUDER DIRECT_MIXING_IN_G1 GRADIENT_MIX GRADIENT_VTOOL REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
opt_disable DISABLE_INACTIVE_EXTRUDER
opt_disable DISABLE_OTHER_EXTRUDERS
exec_test $1 $2 "Mixing Extruder" "$3"
#

View File

@ -71,7 +71,7 @@ exec_test $1 $2 "Ethernet, EEPROM, Magnetic Parking Extruder, No LCD" "$3"
restore_configs
opt_set MOTHERBOARD BOARD_TEENSY41 MIXING_STEPPERS 2
opt_enable MIXING_EXTRUDER DIRECT_MIXING_IN_G1 GRADIENT_MIX GRADIENT_VTOOL
opt_disable DISABLE_INACTIVE_EXTRUDER
opt_disable DISABLE_OTHER_EXTRUDERS
exec_test $1 $2 "Mixing Extruder" "$3"
#