Skip to content

Commit

Permalink
clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
thinkyhead committed Sep 3, 2021
1 parent dabb946 commit dff9229
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 191 deletions.
107 changes: 44 additions & 63 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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).
Expand All @@ -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)
Expand Down
11 changes: 8 additions & 3 deletions Marlin/src/feature/spindle_laser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand Down
82 changes: 36 additions & 46 deletions Marlin/src/feature/spindle_laser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -206,33 +203,35 @@ 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);
}

#if ENABLED(SPINDLE_CHANGE_DIR)
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

Expand Down Expand Up @@ -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;
4 changes: 2 additions & 2 deletions Marlin/src/gcode/calibrate/G28.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand All @@ -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!

Expand Down
Loading

0 comments on commit dff9229

Please sign in to comment.