diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index e1124edf50..ac9b49fe4d 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -3160,6 +3160,12 @@
#define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR and LPC)
+ //#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
+ #if ENABLED(AIR_EVACUATION)
+ #define AIR_EVACUATION_ACTIVE LOW // Set to "HIGH" if the on/off function is active HIGH
+ #define AIR_EVACUATION_PIN 42 // Override the default Cutter Vacuum or Laser Blower pin
+ #endif
+
//#define SPINDLE_SERVO // A servo converting an angle to spindle power
#ifdef SPINDLE_SERVO
#define SPINDLE_SERVO_NR 0 // Index of servo used for spindle control
diff --git a/Marlin/src/feature/spindle_laser.cpp b/Marlin/src/feature/spindle_laser.cpp
index 66c04a001c..78fa75cac6 100644
--- a/Marlin/src/feature/spindle_laser.cpp
+++ b/Marlin/src/feature/spindle_laser.cpp
@@ -68,6 +68,9 @@ void SpindleLaser::init() {
set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY);
TERN_(MARLIN_DEV_MODE, frequency = SPINDLE_LASER_FREQUENCY);
#endif
+ #if ENABLED(AIR_EVACUATION)
+ OUT_WRITE(AIR_EVACUATION_PIN, !AIR_EVACUATION_ACTIVE); // Init Vacuum/Blower OFF
+ #endif
}
#if ENABLED(SPINDLE_LASER_PWM)
@@ -135,4 +138,15 @@ void SpindleLaser::apply_power(const uint8_t opwr) {
}
#endif
+#if ENABLED(AIR_EVACUATION)
+
+ // Enable / disable Cutter Vacuum or Laser Blower motor
+ void SpindleLaser::air_evac_enable() { WRITE(AIR_EVACUATION_PIN, AIR_EVACUATION_ACTIVE); } // Turn ON
+
+ void SpindleLaser::air_evac_disable() { WRITE(AIR_EVACUATION_PIN, !AIR_EVACUATION_ACTIVE); } // Turn OFF
+
+ void SpindleLaser::air_evac_toggle() { TOGGLE(AIR_EVACUATION_PIN); } // Toggle state
+
+#endif
+
#endif // HAS_CUTTER
diff --git a/Marlin/src/feature/spindle_laser.h b/Marlin/src/feature/spindle_laser.h
index 88cf372a02..c3454d0b3c 100644
--- a/Marlin/src/feature/spindle_laser.h
+++ b/Marlin/src/feature/spindle_laser.h
@@ -212,6 +212,15 @@ public:
static bool is_reverse() { return false; }
#endif
+ #if ENABLED(AIR_EVACUATION)
+ static void air_evac_enable(); // Turn On Cutter Vacuum or Laser Blower motor
+ static void air_evac_disable(); // Turn Off Cutter Vacuum or Laser Blower motor
+ static void air_evac_toggle(); // Toggle Cutter Vacuum or Laser Blower motor
+ static inline bool air_evac_state() { // Get current state
+ return (READ(AIR_EVACUATION_PIN) == AIR_EVACUATION_ACTIVE);
+ }
+ #endif
+
static inline void disable() { isReady = false; set_enabled(false); }
#if HAS_LCD_MENU
diff --git a/Marlin/src/gcode/control/M10-M11.cpp b/Marlin/src/gcode/control/M10-M11.cpp
new file mode 100644
index 0000000000..26f67e6cb6
--- /dev/null
+++ b/Marlin/src/gcode/control/M10-M11.cpp
@@ -0,0 +1,47 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(AIR_EVACUATION)
+
+#include "../gcode.h"
+#include "../../module/planner.h"
+#include "../../feature/spindle_laser.h"
+
+/**
+ * M10: Vacuum or Blower On
+ */
+void GcodeSuite::M10() {
+ planner.synchronize(); // Wait for move to arrive (TODO: asynchronous)
+ cutter.air_evac_enable(); // Turn on Vacuum or Blower motor
+}
+
+/**
+ * M11: Vacuum or Blower OFF
+ */
+void GcodeSuite::M11() {
+ planner.synchronize(); // Wait for move to arrive (TODO: asynchronous)
+ cutter.air_evac_disable(); // Turn off Vacuum or Blower motor
+}
+
+#endif // AIR_EVACUATION
diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp
index efea087602..bf26fe5d89 100644
--- a/Marlin/src/gcode/gcode.cpp
+++ b/Marlin/src/gcode/gcode.cpp
@@ -432,6 +432,10 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) {
case 3: M3_M4(false); break; // M3: Turn ON Laser | Spindle (clockwise), set Power | Speed
case 4: M3_M4(true ); break; // M4: Turn ON Laser | Spindle (counter-clockwise), set Power | Speed
case 5: M5(); break; // M5: Turn OFF Laser | Spindle
+ #if ENABLED(AIR_EVACUATION)
+ case 10: M10(); break; // M10: Vacuum or Blower motor ON
+ case 11: M11(); break; // M11: Vacuum or Blower motor OFF
+ #endif
#endif
#if ENABLED(COOLANT_CONTROL)
diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h
index 977fc8bfd8..2904d30366 100644
--- a/Marlin/src/gcode/gcode.h
+++ b/Marlin/src/gcode/gcode.h
@@ -86,6 +86,8 @@
* M7 - Turn mist coolant ON. (Requires COOLANT_CONTROL)
* M8 - Turn flood coolant ON. (Requires COOLANT_CONTROL)
* M9 - Turn coolant OFF. (Requires COOLANT_CONTROL)
+ * M10 - Turn Vacuum or Blower motor ON (Requires AIR_EVACUATION)
+ * M11 - Turn Vacuum or Blower motor OFF (Requires AIR_EVACUATION)
* M12 - Set up closed loop control system. (Requires EXTERNAL_CLOSED_LOOP_CONTROLLER)
* M16 - Expected printer check. (Requires EXPECTED_PRINTER_CHECK)
* M17 - Enable/Power all stepper motors
@@ -548,6 +550,10 @@ private:
#if HAS_CUTTER
static void M3_M4(const bool is_M4);
static void M5();
+ #if ENABLED(AIR_EVACUATION)
+ static void M10();
+ static void M11();
+ #endif
#endif
#if ENABLED(COOLANT_CONTROL)
diff --git a/Marlin/src/lcd/language/language_en.h b/Marlin/src/lcd/language/language_en.h
index 81450d7385..c911120766 100644
--- a/Marlin/src/lcd/language/language_en.h
+++ b/Marlin/src/lcd/language/language_en.h
@@ -114,10 +114,12 @@ namespace Language_en {
PROGMEM Language_Str MSG_LASER_POWER = _UxGT("Laser Power");
PROGMEM Language_Str MSG_SPINDLE_POWER = _UxGT("Spindle Pwr");
PROGMEM Language_Str MSG_LASER_TOGGLE = _UxGT("Toggle Laser");
+ PROGMEM Language_Str MSG_LASER_EVAC_TOGGLE = _UxGT("Toggle Blower");
PROGMEM Language_Str MSG_LASER_PULSE_MS = _UxGT("Test Pulse ms");
PROGMEM Language_Str MSG_LASER_FIRE_PULSE = _UxGT("Fire Pulse");
PROGMEM Language_Str MSG_FLOWMETER_FAULT = _UxGT("Coolant Flow Fault");
PROGMEM Language_Str MSG_SPINDLE_TOGGLE = _UxGT("Toggle Spindle");
+ PROGMEM Language_Str MSG_SPINDLE_EVAC_TOGGLE = _UxGT("Toggle Vacuum");
PROGMEM Language_Str MSG_SPINDLE_FORWARD = _UxGT("Spindle Forward");
PROGMEM Language_Str MSG_SPINDLE_REVERSE = _UxGT("Spindle Reverse");
PROGMEM Language_Str MSG_SWITCH_PS_ON = _UxGT("Switch Power On");
diff --git a/Marlin/src/lcd/menu/menu_spindle_laser.cpp b/Marlin/src/lcd/menu/menu_spindle_laser.cpp
index 93ef224e6f..f0e702e2dd 100644
--- a/Marlin/src/lcd/menu/menu_spindle_laser.cpp
+++ b/Marlin/src/lcd/menu/menu_spindle_laser.cpp
@@ -51,6 +51,11 @@
editable.state = is_enabled;
EDIT_ITEM(bool, MSG_CUTTER(TOGGLE), &is_enabled, []{ if (editable.state) cutter.disable(); else cutter.enable_same_dir(); });
+ #if ENABLED(AIR_EVACUATION)
+ bool evac_state = cutter.air_evac_state();
+ EDIT_ITEM(bool, MSG_CUTTER(EVAC_TOGGLE), &evac_state, cutter.air_evac_toggle);
+ #endif
+
#if ENABLED(SPINDLE_CHANGE_DIR)
if (!is_enabled) {
editable.state = is_rev;
diff --git a/ini/features.ini b/ini/features.ini
index 864befa7a8..3121ef7241 100644
--- a/ini/features.ini
+++ b/ini/features.ini
@@ -164,6 +164,7 @@ SD_ABORT_ON_ENDSTOP_HIT = src_filter=+
BAUD_RATE_GCODE = src_filter=+
HAS_SMART_EFF_MOD = src_filter=+
COOLANT_CONTROL = src_filter=+
+AIR_EVACUATION = src_filter=+
HAS_SOFTWARE_ENDSTOPS = src_filter=+
HAS_DUPLICATION_MODE = src_filter=+
LIN_ADVANCE = src_filter=+
diff --git a/platformio.ini b/platformio.ini
index 8a747404e3..75e7f6a58b 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -155,6 +155,7 @@ default_src_filter = + - - +
-
-
-
+ -
- -
-
-