diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 9dff37144d4d1..23f69996af1df 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -1549,7 +1549,7 @@ // Enable if SD detect is rendered useless (e.g., by using an SD extender) //#define NO_SD_DETECT -// Multiple volume support - EXPERIMENTAL. + // Multiple volume support - EXPERIMENTAL. //#define MULTI_VOLUME #if ENABLED(MULTI_VOLUME) #define VOLUME_SD_ONBOARD @@ -3326,6 +3326,7 @@ #define SPINDLE_LASER_ACTIVE_STATE LOW // Set to "HIGH" if the on/off function is active HIGH #define SPINDLE_LASER_PWM true // Set to "true" if your controller supports setting the speed/power #define SPINDLE_LASER_PWM_INVERT false // Set to "true" if the speed/power goes up when you want it to go slower + #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 @@ -3369,6 +3370,7 @@ //#define SPINDLE_CHANGE_DIR // Enable if your spindle controller can change spindle direction #define SPINDLE_CHANGE_DIR_STOP // Enable if the spindle should stop before changing spin direction #define SPINDLE_INVERT_DIR false // Set to "true" if the spin direction is reversed + #define SPINDLE_LASER_POWERUP_DELAY 5000 // (ms) Delay to allow the spindle/laser to come up to speed/power #define SPINDLE_LASER_POWERDOWN_DELAY 5000 // (ms) Delay to allow the spindle to stop @@ -3381,46 +3383,46 @@ * Speed/Power = (PWMDC / 255 * 100 - SPEED_POWER_INTERCEPT) / SPEED_POWER_SLOPE * PWMDC = (spdpwr - SPEED_POWER_MIN) / (SPEED_POWER_MAX - SPEED_POWER_MIN) / SPEED_POWER_SLOPE */ - #define SPEED_POWER_INTERCEPT 0 // (%) 0-100 i.e., Minimum power percentage - #define SPEED_POWER_MIN 5000 // (RPM) - #define SPEED_POWER_MAX 30000 // (RPM) SuperPID router controller 0 - 30,000 RPM - #define SPEED_POWER_STARTUP 25000 // (RPM) M3/M4 speed/power default (with no arguments) + #define SPEED_POWER_INTERCEPT 0 // (%) 0-100 i.e., Minimum power percentage + #define SPEED_POWER_MIN 5000 // (RPM) + #define SPEED_POWER_MAX 30000 // (RPM) SuperPID router controller 0 - 30,000 RPM + #define SPEED_POWER_STARTUP 25000 // (RPM) M3/M4 speed/power default (with no arguments) #else - #define SPEED_POWER_INTERCEPT 0 // (%) 0-100 i.e., Minimum power percentage - #define SPEED_POWER_MIN 0 // (%) 0-100 - #define SPEED_POWER_MAX 100 // (%) 0-100 - #define SPEED_POWER_STARTUP 80 // (%) M3/M4 speed/power default (with no arguments) + #define SPEED_POWER_INTERCEPT 0 // (%) 0-100 i.e., Minimum power percentage + #define SPEED_POWER_MIN 0 // (%) 0-100 + #define SPEED_POWER_MAX 100 // (%) 0-100 + #define SPEED_POWER_STARTUP 80 // (%) M3/M4 speed/power default (with no arguments) // Define the minimum and maximum test pulse time values for a laser test fire function - #define LASER_TEST_PULSE_MIN 1 // Used with Laser Control Menu - #define LASER_TEST_PULSE_MAX 999 // Caution: Menu may not show more than 3 characters - - #define SPINDLE_LASER_POWERUP_DELAY 50 // (ms) Delay to allow the spindle/laser to come up to speed/power - #define SPINDLE_LASER_POWERDOWN_DELAY 50 // (ms) Delay to allow the spindle to stop - - - /**#define LASER_POWER_INLINE <- This define is no longer required - * Any M3 G1/2/3/5 gcode that includes an I parameter will enable continuous inline power mode - * e.g M3 I enables continuous inline power and it is processed by the planner. Move blocks are - * calculated and each block power buffer value is set there. The Stepper ISR then processes the blocks inline. - * M4I sets dynamic mode which taked the currently set feedrate and calculated a laser power OCR value. - * Setting a powered move G1/2/3/5 gcode F parameter sets a porportional power output from 1-255, S1-65535 respectively - * Anything over F65535 calculate as 255. - * More refined power control is possible but not in this release. - * M5 I clears inline mode and set power to 0, M5 sets the power output to 0 but leaves inline mode on. - */ - - /** - * Scale the laser's power in proportion to the movement rate. - * - * - Sets the entry power proportional to the entry speed over the nominal speed. - * - Ramps the power up every N steps to approximate the speed trapezoid. - * - Due to the limited power resolution this is only approximate. - */ + #define LASER_TEST_PULSE_MIN 1 // (ms) Used with Laser Control Menu + #define LASER_TEST_PULSE_MAX 999 // (ms) Caution: Menu may not show more than 3 characters + + #define SPINDLE_LASER_POWERUP_DELAY 50 // (ms) Delay to allow the spindle/laser to come up to speed/power + #define SPINDLE_LASER_POWERDOWN_DELAY 50 // (ms) Delay to allow the spindle to stop + + /** + * Any M3 or G1/2/3/5 command with the 'I' parameter enables continuous inline power mode. + * e.g., 'M3 I' enables continuous inline power which is processed by the planner. + * Power is stored in move blocks and applied when blocks are processed by the Stepper ISR. + * + * 'M4 I' sets dynamic mode which uses the current feedrate to calculate a laser power OCR value. + * + * Setting a powered move G1/2/3/5 G-code 'F' parameter sets a proportional power output from 1-255, S1-65535 respectively. + * Anything over F65535 evaluates as 255. + * More refined power control will be possible in a future release. + * M5 I clears inline mode and set power to 0, M5 sets the power output to 0 but leaves inline mode on. + */ + + /** + * Scale the laser's power in proportion to the movement rate. + * + * - Sets the entry power proportional to the entry speed over the nominal speed. + * - Ramps the power up every N steps to approximate the speed trapezoid. + * - Due to the limited power resolution this is only approximate. + */ //#define LASER_POWER_INLINE_TRAPEZOID - /** * Continuously calculate the current power (nominal_power * current_rate / nominal_rate). @@ -3440,39 +3442,18 @@ */ //#define LASER_POWER_INLINE_TRAPEZOID_CONT_PER 10 - /** * Include laser power in G1/G2/G3/G5 commands with the 'S' parameter */ //#define LASER_MOVE_POWER - // Discussion - G0 and G28 should never allow laser power! Travel and homming are not powered, so why have a feature for it? - //#if ENABLED(LASER_MOVE_POWER) - // Turn off the laser on G0 moves with no power parameter. - // If a power parameter is provided, use that instead. - //#define LASER_MOVE_G0_OFF - - // Turn off the laser on G28 homing. - //#define LASER_MOVE_G28_OFF - //#endif - - // Discussion - this is not possible in the code prior to this PR, looks like it needs a cleanup. - /** - * Inline flag inverted - * - * WARNING: M5 will NOT turn off the laser unless another move - * is done (so G-code files must end with 'M5 I'). - */ - //#define LASER_POWER_INLINE_INVERT - - // Discussion - Never used by any software out there and is also broken - /** - * Continuously apply inline power. ('M3 S3' == 'G1 S3' == 'M3 S3 I') - * - * The laser might do some weird things, so only enable this - * feature if you understand the implications. - */ - //#define LASER_POWER_INLINE_CONTINUOUS + #if ENABLED(LASER_MOVE_POWER) + // Turn off the laser on G0 moves unless a power parameter is provided. + //#define LASER_MOVE_G0_OFF + + // Turn off the laser on G28 homing. + //#define LASER_MOVE_G28_OFF + #endif // // Laser I2C Ammeter (High precision INA226 low/high side module) diff --git a/Marlin/src/feature/spindle_laser.cpp b/Marlin/src/feature/spindle_laser.cpp index 8d26c2d6c164a..dbeb27ec693be 100644 --- a/Marlin/src/feature/spindle_laser.cpp +++ b/Marlin/src/feature/spindle_laser.cpp @@ -40,10 +40,15 @@ SpindleLaser cutter; uint8_t SpindleLaser::power = 0; -TERN_(LASER_FEATURE,cutter_test_pulse_t SpindleLaser::testPulse = 50;)// Test fire pulse default time value in ms. + +#if ENABLED(LASER_FEATURE) + cutter_test_pulse_t SpindleLaser::testPulse = 50; // (ms) Test fire pulse default duration +#endif + bool SpindleLaser::isReady = false; // Ready to apply power setting from the UI to OCR +CutterMode SpindleLaser::cutter_mode = CUTTER_MODE_STANDARD; + uint8_t SpindleLaser::last_power_applied = 0; // Power state tracking -int8_t SpindleLaser::cutter_mode = STANDARD_MODE; // Mode values, -1 = error, 0 = standard, 1 = continuous, 2 = dynamic cutter_power_t SpindleLaser::menuPower = 0, // Power set via LCD menu in PWM, PERCENT, or RPM SpindleLaser::unitPower = 0; // LCD status power in PWM, PERCENT, or RPM @@ -110,7 +115,7 @@ void SpindleLaser::init() { // // Set cutter ON/OFF state (and PWM) to the given cutter power value // -void SpindleLaser::apply_power(const uint8_t opwr) { +void SpindleLaser::apply_power(const uint8_t opwr) { if (opwr == last_power_applied) return; last_power_applied = opwr; power = opwr; diff --git a/Marlin/src/feature/spindle_laser.h b/Marlin/src/feature/spindle_laser.h index 46b064e1daaf8..dee25fe96b524 100644 --- a/Marlin/src/feature/spindle_laser.h +++ b/Marlin/src/feature/spindle_laser.h @@ -44,6 +44,14 @@ #define SPEED_POWER_INTERCEPT 0 #endif +// Laser/Cutter operation mode +enum CutterMode : int8_t { + CUTTER_MODE_ERROR = -1, + CUTTER_MODE_STANDARD, // M3 power is applied directly and waits for planner moves to sync. + CUTTER_MODE_CONTINUOUS, // M3 or G1/2/3 move power is controlled within planner blocks, set with 'M3 I', cleared with 'M5 I'. + CUTTER_MODE_DYNAMIC // M4 laser power is proportional to the feed rate, set with 'M4 I', cleared with 'M5 I'. +}; + class SpindleLaser { public: static constexpr float @@ -52,18 +60,7 @@ class SpindleLaser { static const inline uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); } - // Laser/Cutter operation mode - // 0 - STANDARD_MODE - M3 power applied directly and waits for planner moves to sync - // 1 - CONTINUOUS_MODE - M3 or G1/2/3 move power is controlled within planner blocks, set with M3 I, cleared with M5 I - // 2 - DYNAMIC_MODE - M4 laser power is porpotional to the feed rate, set with M4 I, cleared with M5 I - - enum laser_modes { - STANDARD_MODE, // M3/4/5 Basic Spindle/Laser operation - CONTINUOUS_MODE, // M3 or G1/2/3/5 move power is set within planner/stepper - DYNAMIC_MODE // M4 laser power is controlled within the stepper and is porpotional to the feed rate - } ; - - static int8_t cutter_mode; // Mode values, -1 error, 0 = default, 1 = continuos, 2 = dynamic + static CutterMode cutter_mode; // cpower = configured values (e.g., SPEED_POWER_MAX) // Convert configured power range to a percentage @@ -103,20 +100,20 @@ class SpindleLaser { static const cutter_power_t mpower_min() { return cpwr_to_upwr(SPEED_POWER_MIN); } static const cutter_power_t mpower_max() { return cpwr_to_upwr(SPEED_POWER_MAX); } - TERN_(LASER_FEATURE, static cutter_test_pulse_t testPulse;) // Test fire pulse time in ms. + #if ENABLED(LASER_FEATURE) + static cutter_test_pulse_t testPulse; // (ms) Test fire pulse duration + #endif static bool isReady; // Ready to apply power setting from the UI to OCR static uint8_t power; static uint8_t last_power_applied; - - - + #if ENABLED(MARLIN_DEV_MODE) static cutter_frequency_t frequency; // Set PWM frequency; range: 2K-50K #endif static cutter_power_t menuPower, // Power as set via LCD menu in PWM, Percentage or RPM - unitPower; // Power as displayed status in PWM, Percentage or RPM + unitPower; // Power as displayed status in PWM, Percentage or RPM static void init(); @@ -206,25 +203,27 @@ class SpindleLaser { // Enable laser output. // If we are in standard mode and no power was spec'd set it to the startup value. - // With any inline mode set the power to the current one from the last cutter.power value. + // With any inline mode set the power to the current one from the last cutter.power value. static inline void set_enabled(const bool enable) { - if (cutter_mode == STANDARD_MODE ) { + if (cutter_mode == CUTTER_MODE_STANDARD) { set_power(enable ? TERN(SPINDLE_LASER_PWM, (power ?: (unitPower ? upower_to_ocr(cpwr_to_upwr(SPEED_POWER_STARTUP)) : 0)), 255) : 0); - } else if (cutter_mode == CONTINUOUS_MODE || cutter_mode == DYNAMIC_MODE ) { + } + else if (cutter_mode == CUTTER_MODE_CONTINUOUS || cutter_mode == CUTTER_MODE_DYNAMIC) { TERN_(LASER_FEATURE, set_inline_enabled(enable)); apply_power(0); - } else if (cutter_mode == -1) apply_power(0); // Error mode, no enable and kill power. + } + else if (cutter_mode == -1) apply_power(0); // Error mode, no enable and kill power. } // Wait for spindle/laser to startup or shutdown static inline void power_delay(const bool on) { - safe_delay(on ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY); - } - - static inline uint8_t calc_dynamic_power(){ - if (feedrate_mm_m > 65535) return 255; // Too fast, go always on - uint16_t rate = uint16_t(feedrate_mm_m); // 32 bits from the gcode parser float input - rate = rate >> 8; // We take the gcode input e.g. F40000 and shift off the lower bits to get an ocr value from 1-255 + safe_delay(on ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY); + } + + static inline uint8_t calc_dynamic_power() { + if (feedrate_mm_m > 65535) return 255; // Too fast, go always on + uint16_t rate = uint16_t(feedrate_mm_m); // 32 bits from the G-code parser float input + rate >>= 8; // Take the G-code input e.g. F40000 and shift off the lower bits to get an OCR value from 1-255 return uint8_t(rate); } @@ -232,7 +231,7 @@ class SpindleLaser { static void set_reverse(const bool reverse); static bool is_reverse() { return READ(SPINDLE_DIR_PIN) == SPINDLE_INVERT_DIR; } #else - static inline void set_reverse(const bool) {cutter_mode = DYNAMIC_MODE; } + static inline void set_reverse(const bool) {cutter_mode = CUTTER_MODE_DYNAMIC; } static bool is_reverse() { return false; } #endif @@ -287,38 +286,29 @@ class SpindleLaser { */ static inline void test_fire_pulse() { TERN_(USE_BEEPER, buzzer.tone(30, 3000)); - enable_forward(); // Turn Laser on (Spindle speak but same funct) + enable_forward(); // Laser on (Spindle speak but same funct) delay(testPulse); // Delay for time set by user in pulse ms menu screen. - disable(); // Turn laser off - + disable(); // Laser off } #endif #endif // HAS_LCD_MENU - #if ENABLED(LASER_FEATURE ) - // Inline modes of all other functions; all enable planner inline power control - static inline void set_inline_enabled(const bool enable) { - if (enable) { - planner.laser_inline.status.isEnabled = true; - } else { - planner.laser_inline.status.isEnabled = false; - } - } + #if ENABLED(LASER_FEATURE) + // Inline modes of all other functions; all enable planner inline power control + static inline void set_inline_enabled(const bool enable) { planner.laser_inline.status.isEnabled = enable; } - // Set the power for subsequent movement blocks + // Set the power for subsequent movement blocks static void inline_power(const cutter_power_t upwr) { unitPower = menuPower = upwr; TERN(SPINDLE_LASER_PWM, planner.laser_inline.power = upower_to_ocr(upwr), planner.laser_inline.power = upwr > 0 ? 255 : 0); planner.laser_inline.status.isEnabled = upwr > 0; - } + } #endif // LASER_FEATURE - static inline void kill() { - disable(); - } + static inline void kill() { disable(); } }; extern SpindleLaser cutter; diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index cb9403ec23ac6..886e22c66f1d9 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -215,7 +215,7 @@ void GcodeSuite::G28() { #if ENABLED(LASER_FEATURE) planner.laser_inline.status.isPowered = false; - #endif + #endif TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_HOMING)); @@ -241,7 +241,7 @@ void GcodeSuite::G28() { } TERN_(DWIN_CREALITY_LCD, DWIN_StartHoming()); - TERN_(EXTENSIBLE_UI, ExtUI::onHomingStart()); + TERN_(EXTENSIBLE_UI, ExtUI::onHomingStart()); planner.synchronize(); // Wait for planner moves to finish! diff --git a/Marlin/src/gcode/control/M3-M5.cpp b/Marlin/src/gcode/control/M3-M5.cpp index 1c0a228061aa3..6153fe531063c 100644 --- a/Marlin/src/gcode/control/M3-M5.cpp +++ b/Marlin/src/gcode/control/M3-M5.cpp @@ -26,7 +26,7 @@ #include "../gcode.h" #include "../../feature/spindle_laser.h" -#include "../../module/stepper.h" +#include "../../module/stepper.h" /** * Laser: @@ -69,37 +69,34 @@ void GcodeSuite::M3_M4(const bool is_M4) { planner.synchronize(); // Wait for previous movement commands (G0/G1/G2/G3) to complete before changing power if (parser.seen('I')) { - if (is_M4 == false) { - cutter.cutter_mode = cutter.CONTINUOUS_MODE; - } else { - cutter.cutter_mode = cutter.DYNAMIC_MODE; - } + cutter.cutter_mode = is_M4 ? CUTTER_MODE_DYNAMIC : CUTTER_MODE_CONTINUOUS; cutter.set_enabled(true); } auto get_s_power = [] { if (parser.seen('S')) { - //const float spwr = parser.value_float(); cutter.unitPower = parser.value_ushort(); - // PWM is implied and would range from S0 to S180 for a positional servo. Typical use would be a pen up/down function. + // PWM implied and ranges from S0 to S180 for a positional servo. Typical use would be a pen up/down function. #if ENABLED(SPINDLE_SERVO) - cutter.power = cutter.unitPower; + cutter.power = cutter.unitPower; #else - if (cutter.cutter_mode == cutter.STANDARD_MODE) - // PWM is not implied, power is converted to ocr from unit definition and min/max or on/off if not PWM. - cutter.power = TERN(SPINDLE_LASER_PWM, cutter.power_to_range(cutter_power_t(cutter.unitPower)), cutter.unitPower > 0 ? 255 : 0); + if (cutter.cutter_mode == CUTTER_MODE_STANDARD) // PWM not implied, power converted to OCR from unit definition and min/max or on/off if not PWM. + cutter.power = TERN(SPINDLE_LASER_PWM, cutter.power_to_range(cutter_power_t(cutter.unitPower)), cutter.unitPower > 0 ? 255 : 0); #endif cutter.menuPower = cutter.unitPower; - } else - if (cutter.cutter_mode == cutter.STANDARD_MODE) cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP); - return cutter.unitPower; + } + else if (cutter.cutter_mode == CUTTER_MODE_STANDARD) + cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP); + + return cutter.unitPower; }; - if (cutter.cutter_mode > cutter.STANDARD_MODE) { // Laser power in inline mode + if (cutter.cutter_mode > CUTTER_MODE_STANDARD) { // Laser power in inline mode TERN_(LASER_FEATURE, cutter.inline_power(cutter.upower_to_ocr(get_s_power()))); - } else { + } + else { #if ENABLED(SPINDLE_LASER_PWM) - cutter.set_power(cutter.upower_to_ocr(get_s_power())); + cutter.set_power(cutter.upower_to_ocr(get_s_power())); #elif ENABLED(SPINDLE_SERVO) cutter.set_power(get_s_power()); #else @@ -114,10 +111,10 @@ void GcodeSuite::M3_M4(const bool is_M4) { void GcodeSuite::M5() { planner.synchronize(); if (parser.seen('I')) { - cutter.set_enabled(false); // Clear inline mode flags - cutter.cutter_mode = cutter.STANDARD_MODE; // Switch from inline to standard mode, has no effect on current power output! - } - cutter.apply_power(0); // M5 kills power in either mode but if it's in inline it will be still be the active mode + cutter.set_enabled(false); // Clear inline mode flags + cutter.cutter_mode = CUTTER_MODE_STANDARD; // Switch from inline to standard mode, has no effect on current power output! + } + cutter.apply_power(0); // M5 kills power in either mode but if it's in inline it will be still be the active mode } #endif // HAS_CUTTER diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp index 6621472b4d51e..bdabf1bc9cfdb 100644 --- a/Marlin/src/gcode/gcode.cpp +++ b/Marlin/src/gcode/gcode.cpp @@ -196,20 +196,19 @@ void GcodeSuite::get_destination_from_command() { #endif #if ENABLED(LASER_FEATURE) - if (cutter.cutter_mode == cutter.CONTINUOUS_MODE || cutter.cutter_mode == cutter.DYNAMIC_MODE) { + if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS || cutter.cutter_mode == CUTTER_MODE_DYNAMIC) { // Set the cutter power in the planner to configure this move last_feedrate_mm_m = 0; - if ((parser.codenum > 0 && parser.codenum < 4) || (parser.codenum == 5)) { + if (WITHIN(parser.codenum, 1, TERN(ARC_SUPPORT, 3, 1)) || TERN0(BEZIER_CURVE_SUPPORT, parser.codenum == 5)) { planner.laser_inline.status.isPowered = true; if (parser.seen('S')) { const float spwr = parser.value_ushort(); cutter.inline_power(cutter.power_to_range(cutter_power_t(spwr))); } - } else { - if (parser.codenum == 0) { - planner.laser_inline.status.isPowered = false; // For dynamic mode we need to flag it off - planner.laser_inline.power = 0; // This is planner based so only set power and do not disable inline control flags. - } + } + else if (parser.codenum == 0) { + planner.laser_inline.status.isPowered = false; // For dynamic mode we need to flag it off + planner.laser_inline.power = 0; // This is planner-based so only set power and do not disable inline control flags. } } #endif // LASER_FEATURE diff --git a/Marlin/src/inc/SanityCheck.h b/Marlin/src/inc/SanityCheck.h index 2097c505af9ca..f7d75c582cf03 100644 --- a/Marlin/src/inc/SanityCheck.h +++ b/Marlin/src/inc/SanityCheck.h @@ -593,6 +593,8 @@ #error "ARC_SUPPORT no longer uses ARC_SEGMENTS_PER_R." #elif ENABLED(ARC_SUPPORT) && (!defined(MIN_ARC_SEGMENT_MM) || !defined(MAX_ARC_SEGMENT_MM)) #error "ARC_SUPPORT now requires MIN_ARC_SEGMENT_MM and MAX_ARC_SEGMENT_MM." +#elif defined(LASER_POWER_INLINE) + #error "LASER_POWER_INLINE is obsolete." #endif #if MOTHERBOARD == BOARD_DUE3DOM_MINI && PIN_EXISTS(TEMP_2) && DISABLED(TEMP_SENSOR_BOARD) @@ -3523,9 +3525,9 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2) #if ENABLED(LASER_FEATURE) //#if ENABLED(SPINDLE_CHANGE_DIR) // #error "SPINDLE_CHANGE_DIR and LASER_POWER_INLINE are incompatible." - // Discussion - G0 and G28 should never allow laser power! - // #elif ENABLED(LASER_MOVE_G0_OFF) && DISABLED(LASER_MOVE_POWER) - // #error "LASER_MOVE_G0_OFF requires LASER_MOVE_POWER." + // Discussion - G0 and G28 should never allow laser power! + //#elif ENABLED(LASER_MOVE_G0_OFF) && DISABLED(LASER_MOVE_POWER) + // #error "LASER_MOVE_G0_OFF requires LASER_MOVE_POWER." //#endif // Discussion - Does anyone expect DYNAMIC mode to work wihtout PWM? Thus do we need to say it? //#if ENABLED(LASER_POWER_INLINE_TRAPEZOID) @@ -3540,24 +3542,11 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2) //#endif #endif //#endif - // Discussion - Obscure feature that's never used by any software out there and does nothing useful - // This does not invert the output! - // #if ENABLED(LASER_POWER_INLINE_INVERT) - // #ifndef LASER_POWER_INLINE_INVERT_WARN - // #define LASER_POWER_INLINE_INVERT_WARN - // #warning "Enabling LASER_POWER_INLINE_INVERT means that `M5` won't kill the laser immediately; use `M5 I` instead." - // #endif - // #endif #else #if SPINDLE_LASER_POWERUP_DELAY < 1 #error "SPINDLE_LASER_POWERUP_DELAY must be greater than 0." #elif SPINDLE_LASER_POWERDOWN_DELAY < 1 #error "SPINDLE_LASER_POWERDOWN_DELAY must be greater than 0." - // Discussion - G0 and G28 should never allow laser power! - // #elif ENABLED(LASER_MOVE_POWER) - // #error "LASER_MOVE_POWER requires LASER_POWER_INLINE." - // #elif ANY(LASER_POWER_INLINE_TRAPEZOID, LASER_POWER_INLINE_INVERT, LASER_MOVE_G0_OFF, LASER_MOVE_POWER) // not useful - // #error "Enabled an inline laser feature without inline laser power being enabled." #endif #endif #define _PIN_CONFLICT(P) (PIN_EXISTS(P) && P##_PIN == SPINDLE_LASER_PWM_PIN) diff --git a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/theme/bitmaps.h b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/theme/bitmaps.h index c689f239057ec..59394b89a68ad 100644 --- a/Marlin/src/lcd/extui/ftdi_eve_touch_ui/theme/bitmaps.h +++ b/Marlin/src/lcd/extui/ftdi_eve_touch_ui/theme/bitmaps.h @@ -239,7 +239,7 @@ namespace Theme { .width = 31, .height = 32, }; - + const unsigned char Light_Bulb[128] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x00, 0x00, 0x40, diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp index d25e76ba8a320..b814cadc7bdf9 100644 --- a/Marlin/src/module/motion.cpp +++ b/Marlin/src/module/motion.cpp @@ -139,7 +139,7 @@ feedRate_t feedrate_mm_s = MMM_TO_MMS(1500); int16_t feedrate_percentage = 100; #if ENABLED(LASER_FEATURE) - // The feed rate value from a move gcode in mm per minute, used for laser dynamic power. + // The feed rate value from a move gcode in mm per minute, used for laser dynamic power. feedRate_t feedrate_mm_m = 1500; feedRate_t last_feedrate_mm_m = 0; // Should initally be 0 for any first move power calc. #endif diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index d464a7bf6bf09..5832f1963825d 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -848,7 +848,7 @@ void Planner::calculate_trapezoid_for_block(block_t * const block, const_float_t * Note this may behave unreliably when running with S_CURVE_ACCELERATION */ #if ENABLED(LASER_POWER_INLINE_TRAPEZOID) - if (cutter.cutter_mode == cutter.CONTINUOUS_MODE) { + if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS) { if (block->laser.power > 0) { // No need to care if power == 0 const uint8_t entry_power = block->laser.power * entry_factor; // Power on block entry #if DISABLED(LASER_POWER_INLINE_TRAPEZOID_CONT) @@ -1980,21 +1980,21 @@ bool Planner::_populate_block(block_t * const block, bool split_move, // Update block laser power #if HAS_CUTTER - if (cutter.cutter_mode == cutter.STANDARD_MODE) + if (cutter.cutter_mode == CUTTER_MODE_STANDARD) block->cutter_power = cutter.power; - #if ENABLED(LASER_FEATURE) - else { + #if ENABLED(LASER_FEATURE) + else { block->laser.power = laser_inline.power; block->laser.status = laser_inline.status; - } - if (cutter.cutter_mode == cutter.DYNAMIC_MODE) { - if (last_feedrate_mm_m !=feedrate_mm_m) { // Only process the changes in rate - laser_inline.power = cutter.calc_dynamic_power(); + } + if (cutter.cutter_mode == CUTTER_MODE_DYNAMIC) { + if (last_feedrate_mm_m !=feedrate_mm_m) { // Only process the changes in rate + laser_inline.power = cutter.calc_dynamic_power(); last_feedrate_mm_m = feedrate_mm_m; - block->laser.power = laser_inline.power; + block->laser.power = laser_inline.power; } } - #endif // LASER_FEATURE + #endif // LASER_FEATURE #endif // HAS_CUTTER // Number of steps for each axis diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 4945fde2929b0..ed7a0813ebb07 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -129,7 +129,7 @@ enum BlockFlag : char { #if ENABLED(LASER_FEATURE) typedef struct { - bool isEnabled:1; // Set to engage the inline laser power output. + bool isEnabled:1; // Set to engage the inline laser power output. bool dir:1; bool isPowered:1; // Set on any parsed G1,G2,G3 or G5 powered move, cleared on G0 and G28. bool Reserved:6; diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index f3395b0af184e..fd0395ba0cf6d 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -153,7 +153,7 @@ uint8_t Stepper::last_direction_bits, // = 0 Stepper::axis_did_move; // = 0 bool Stepper::abort_current_block; -uint8_t Stepper::last_laser_power; +uint8_t Stepper::last_laser_power; #if DISABLED(MIXING_EXTRUDER) && HAS_MULTI_EXTRUDER uint8_t Stepper::last_moved_extruder = 0xFF; @@ -1901,11 +1901,9 @@ uint32_t Stepper::block_phase_isr() { else if (LA_steps) nextAdvanceISR = 0; #endif - - // Update laser - Accelerating #if ENABLED(LASER_POWER_INLINE_TRAPEZOID) - if (cutter.cutter_mode == cutter.CONTINUOUS_MODE) { + if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS) { if (laser_trap.enabled) { #if DISABLED(LASER_POWER_INLINE_TRAPEZOID_CONT) if (current_block->laser.entry_per) { @@ -1984,7 +1982,7 @@ uint32_t Stepper::block_phase_isr() { // Update laser - Decelerating #if ENABLED(LASER_POWER_INLINE_TRAPEZOID) - if (cutter.cutter_mode == cutter.CONTINUOUS_MODE) { + if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS) { if (laser_trap.enabled) { #if DISABLED(LASER_POWER_INLINE_TRAPEZOID_CONT) if (current_block->laser.exit_per) { @@ -2032,7 +2030,7 @@ uint32_t Stepper::block_phase_isr() { // Update laser - Cruising #if ENABLED(LASER_POWER_INLINE_TRAPEZOID) - if (cutter.cutter_mode == cutter.CONTINUOUS_MODE ) { + if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS ) { if (laser_trap.enabled) { if (!laser_trap.cruise_set) { laser_trap.cur_power = current_block->laser.power; @@ -2049,20 +2047,20 @@ uint32_t Stepper::block_phase_isr() { #endif } } - #if ENABLED(LASER_FEATURE) + #if ENABLED(LASER_FEATURE) // Super fast method of dynamically adjusting the laser power ocr value based on the input feedrate in mm per minute // TODO Setup Min/Max ocr ofsets to allow tuning and scaling of various lasers - // TODO Integrate accell/decell +-rate into the dynamic laser power calc - if (cutter.cutter_mode == cutter.DYNAMIC_MODE) { + // TODO Integrate accell/decell +-rate into the dynamic laser power calc + if (cutter.cutter_mode == CUTTER_MODE_DYNAMIC) { if (planner.laser_inline.status.isPowered) { // isPowered flag set on any parsed G1,G2,G3 or G5 move, cleared on any others. - if (last_laser_power != current_block->laser.power) { // Prevent constant update without change - cutter.apply_power(current_block->laser.power); + if (last_laser_power != current_block->laser.power) { // Prevent constant update without change + cutter.apply_power(current_block->laser.power); last_laser_power = current_block->laser.power; } - } + } } } else { - if (cutter.cutter_mode == cutter.DYNAMIC_MODE) cutter.apply_power(0); //No movement in dynamic mode then turn Laser off + if (cutter.cutter_mode == CUTTER_MODE_DYNAMIC) cutter.apply_power(0); //No movement in dynamic mode then turn Laser off #endif } @@ -2094,7 +2092,7 @@ uint32_t Stepper::block_phase_isr() { // For non-inline cutter, grossly apply power #if HAS_CUTTER - if (cutter.cutter_mode == cutter.STANDARD_MODE) cutter.apply_power(current_block->cutter_power); + if (cutter.cutter_mode == CUTTER_MODE_STANDARD) cutter.apply_power(current_block->cutter_power); #endif TERN_(POWER_LOSS_RECOVERY, recovery.info.sdpos = current_block->sdpos); @@ -2260,7 +2258,7 @@ uint32_t Stepper::block_phase_isr() { } #if ENABLED(LASER_FEATURE) - if (cutter.cutter_mode == cutter.CONTINUOUS_MODE) { // Planner controls the laser + if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS) { // Planner controls the laser const power_status_t stat = current_block->laser.status; if (stat.isEnabled) { #if ENABLED(LASER_POWER_INLINE_TRAPEZOID) @@ -2276,12 +2274,12 @@ uint32_t Stepper::block_phase_isr() { // Always have PWM in this case cutter.apply_power(stat.isPowered ? laser_trap.cur_power : 0 ); // ON with power or OFF #else - if (stat.isPowered) - cutter.apply_power(TERN(SPINDLE_LASER_PWM, current_block->laser.power, current_block->laser.power > 0 ? 255 : 0)); + if (stat.isPowered) + cutter.apply_power(TERN(SPINDLE_LASER_PWM, current_block->laser.power, current_block->laser.power > 0 ? 255 : 0)); else cutter.apply_power(0); #endif - } + } } #endif // LASER_FEATURE diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index 9d7aaa91073eb..e10e14501d53c 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -1626,7 +1626,7 @@ void Temperature::manage_heater() { cooler.flowmeter_task(ms); #if ENABLED(FLOWMETER_SAFETY) if (cooler.check_flow_too_low()) { - if (cutter.enabled()) TERN_(HAS_DISPLAY, ui.flow_fault()); + if (cutter.enabled()) TERN_(HAS_DISPLAY, ui.flow_fault()); cutter.disable(); cutter.cutter_mode = -1; // Set mode to error, this immediately kills stepper inline power output }