Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Laser Refactor #22721

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
902f816
laser code refactor (FSM)
shizacat Sep 6, 2021
5e50c6f
cleanup
thinkyhead Sep 6, 2021
6f7e2c3
expand set_enabled
thinkyhead Sep 6, 2021
a410565
use _CUTTER_POWER macros
thinkyhead Sep 6, 2021
bd6cb1c
Merge branch 'bugfix-2.0.x' into pr/22721
thinkyhead Sep 6, 2021
05b1f38
apply_power => set_power
thinkyhead Sep 6, 2021
c259045
All set_power is OCR
thinkyhead Sep 7, 2021
22014e6
Add state for direction spindle
shizacat Sep 9, 2021
b7106b6
Fix spelling, SPINDLE_CHANGE_DIR
thinkyhead Sep 9, 2021
3a040c8
Remove last_power_applied
shizacat Sep 9, 2021
1bec7c3
Merge 'upstream/bugfix-2.0.x' into pr/22721
thinkyhead Sep 9, 2021
fe2f329
Add separate pin control for PWM
shizacat Sep 10, 2021
31036a2
Merge remote-tracking branch 'upstream/bugfix-2.0.x' into pr/22721
thinkyhead Sep 10, 2021
a77c010
Fix speling
thinkyhead Sep 10, 2021
d54108e
Delete 'cutter.unitPower == 0' into get_event
shizacat Sep 10, 2021
69dbf96
Change enable. Move inner variable and method in private. Added DIR_C…
shizacat Sep 11, 2021
e8439f4
Updated M3/M4 for work with new api interface
shizacat Sep 12, 2021
a68d2c7
Init Spindle DIR as HIGH / LOW
thinkyhead Sep 12, 2021
83c2929
Simplify cutter state, etc.
thinkyhead Sep 12, 2021
0f2da09
Fix some cutter pins
thinkyhead Sep 12, 2021
f4ec18b
Remove confusing option, add conditional
thinkyhead Sep 12, 2021
b988e7e
SPINDLE_LASER_PWM => SPINDLE_LASER_USE_PWM
thinkyhead Sep 13, 2021
1a9c0f1
SPINDLE_LASER_PWM => SPINDLE_LASER_USE_PWM
thinkyhead Sep 13, 2021
9555f80
Merge remote-tracking branch 'upstream/bugfix-2.0.x' into pr/22721
thinkyhead Sep 13, 2021
a504fd7
merge followup
thinkyhead Sep 13, 2021
6b1a7ff
Merge remote-tracking branch 'upstream/bugfix-2.0.x' into pr/22721
thinkyhead Sep 13, 2021
f66135d
PWM value setting only when laser is on
shizacat Sep 14, 2021
352c94a
Test added BigTreeTech SKR Pro | Laser (one ENA PIN)
shizacat Sep 14, 2021
daf81d3
miss
shizacat Sep 14, 2021
2c163ed
miss
shizacat Sep 14, 2021
0909878
reset
shizacat Sep 14, 2021
7881187
Use enum for spindle direction
thinkyhead Sep 16, 2021
69c7c2d
Separate spindle test
thinkyhead Sep 16, 2021
fc3b349
Drop inline hints
thinkyhead Apr 24, 2022
d3c406d
Merge branch 'bugfix-2.0.x' into pr/22721
thinkyhead Apr 24, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 139 additions & 47 deletions Marlin/src/feature/spindle_laser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,18 @@
#endif

SpindleLaser cutter;
uint8_t SpindleLaser::power;
uint8_t SpindleLaser::ocr_power = 0; // Startup disable
SpindleDir SpindleLaser::spindle_dir = SpindleDirCW; // Startup clockwise
CutterState SpindleLaser::state = STAY_OFF; // Startup OFF
#if ENABLED(LASER_FEATURE)
cutter_test_pulse_t SpindleLaser::testPulse = 50; // Test fire Pulse time ms value.
cutter_test_pulse_t SpindleLaser::testPulse = 50; // Test fire Pulse time ms value.
#endif
bool SpindleLaser::isReady; // Ready to apply power setting from the UI to OCR
cutter_power_t SpindleLaser::menuPower, // Power set via LCD menu in PWM, PERCENT, or RPM
SpindleLaser::unitPower; // LCD status power in PWM, PERCENT, or RPM
bool SpindleLaser::isReady; // Ready to apply power setting from the UI to OCR
cutter_power_t SpindleLaser::menuPower, // Power set via LCD menu in PWM, PERCENT, or RPM
SpindleLaser::unitPower; // LCD status power in PWM, PERCENT, or RPM

#if ENABLED(MARLIN_DEV_MODE)
cutter_frequency_t SpindleLaser::frequency; // PWM frequency setting; range: 2K - 50K
cutter_frequency_t SpindleLaser::frequency; // PWM frequency setting; range: 2K - 50K
#endif
#define SPINDLE_LASER_PWM_OFF TERN(SPINDLE_LASER_PWM_INVERT, 255, 0)

Expand All @@ -62,7 +64,8 @@ void SpindleLaser::init() {
OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off
#endif
#if ENABLED(SPINDLE_CHANGE_DIR)
OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR); // Init rotation to clockwise (M3)
SET_OUTPUT(SPINDLE_DIR_PIN);
dir_pin_set(); // Init rotation to clockwise (M3)
#endif
#if ENABLED(SPINDLE_LASER_USE_PWM)
SET_PWM(SPINDLE_LASER_PWM_PIN);
Expand All @@ -87,66 +90,155 @@ void SpindleLaser::init() {
*
* @param ocr Power value
*/
void SpindleLaser::_set_ocr(const uint8_t ocr) {
void SpindleLaser::ocr_set(const uint8_t ocr) {
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), TERN(MARLIN_DEV_MODE, frequency, SPINDLE_LASER_FREQUENCY));
#endif
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
}

void SpindleLaser::set_ocr(const uint8_t ocr) {
WRITE(SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_STATE); // Cutter ON
_set_ocr(ocr);
}
#endif // SPINDLE_LASER_USE_PWM

/**
* Set state for pin spindle/laser
* @param enable true = on; false = off
*/
void SpindleLaser::ena_pin_set(const bool enable) {
WRITE(SPINDLE_LASER_ENA_PIN, enable ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
}

void SpindleLaser::ocr_off() {
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Cutter OFF
_set_ocr(0);
#if ENABLED(SPINDLE_CHANGE_DIR)
/**
* Set direction pin for spindle
*/
void SpindleLaser::dir_pin_set() {
// Forward (M3) HIGH when not inverted
const uint8_t dir_state = (spindle_dir == TERN(SPINDLE_INVERT_DIR, SpindleDirCCW, SpindleDirCW)) ? HIGH : LOW;
WRITE(SPINDLE_DIR_PIN, dir_state);
}
#endif // SPINDLE_LASER_USE_PWM
#endif

/**
* Apply power for laser/spindle
*
* Apply cutter power value for PWM, Servo, and on/off pin.
* Get a change event based on current and new state
*
* @param opwr Power value. Range 0 to MAX. When 0 disable spindle/laser.
* @param opwr New power value
* @param odir New direction spindle
* @param oena_pin_on New ena_pin state
*/
void SpindleLaser::apply_power(const uint8_t opwr) {
static uint8_t last_power_applied = 0;
if (opwr == last_power_applied) return;
last_power_applied = opwr;
power = opwr;
#if ENABLED(SPINDLE_LASER_USE_PWM)
if (cutter.unitPower == 0 && CUTTER_UNIT_IS(RPM)) {
ocr_off();
isReady = false;
}
else if (ENABLED(CUTTER_POWER_RELATIVE) || enabled()) {
set_ocr(power);
isReady = true;
}
else {
ocr_off();
isReady = false;
}
#elif ENABLED(SPINDLE_SERVO)
MOVE_SERVO(SPINDLE_SERVO_NR, power);
#else
WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
isReady = true;
CutterState SpindleLaser::get_event(const uint8_t opwr, const SpindleDir odir, const bool oena_pin_on) {
// Setting PWM and ENA both off
if (opwr == 0 && !oena_pin_on)
return state == STAY_OFF ? STAY_OFF : TURN_OFF;

// Setting PWM or ENA while OFF
if (state == STAY_OFF)
return TURN_ON;

// Changing direction while already ON
if (odir != spindle_dir)
return STAY_ON_REV;

return state;
}

/**
* Change hardware state
*/
void SpindleLaser::_change_hw(const bool ena_pin_on) {
TERN_(SPINDLE_LASER_USE_PWM, ocr_set(ocr_power));

TERN(SPINDLE_SERVO, MOVE_SERVO(SPINDLE_SERVO_NR, ocr_power), ena_pin_set(ena_pin_on));

#if ENABLED(SPINDLE_LASER_USE_PWM) || DISABLED(SPINDLE_SERVO)
isReady = ena_pin_on; // This is a hack. isReady state and ena_pin_on are equivalent.
#endif
}

/**
* Set cutter ocr_power value for PWM, Servo, and on/off pin.
*
* @param opwr Power value. Range 0 to MAX. When 0 disable spindle/laser.
* @param odir Direction spindle (default SpindleDirSame)
* @param ena_pin_on Enable/disable ENA_PIN. Work only in separate mode PWM.
* If separate mode is disable - ENA_PIN is managed through opwr value
* if true - enable pin; false - disable pin (default true)
*/
void SpindleLaser::ocr_set_power(const uint8_t opwr, const SpindleDir odir/*=SpindleDirSame*/, const bool ena_pin_on/*=true*/) {
const SpindleDir dir_value = TERN(SPINDLE_CHANGE_DIR, (odir == SpindleDirSame) ? spindle_dir : odir, SpindleDirCW);

const bool ena_pin_on_value = TERN(HAS_CUTTER_PWM_AND_ENA, ena_pin_on, opwr > 0);

switch (get_event(opwr, dir_value, ena_pin_on_value)) {
// Already ON and staying ON
case STAY_ON:
state = STAY_ON; // Probably already the current state
if (opwr != ocr_power) {
ocr_power = opwr;
_change_hw(ena_pin_on_value);
}
break;

case TURN_ON:
state = STAY_ON;
ocr_power = opwr;
spindle_dir = dir_value;
dir_pin_set();
_change_hw(ena_pin_on_value);
power_delay(true);
break;
thinkyhead marked this conversation as resolved.
Show resolved Hide resolved

case STAY_OFF:
state = STAY_OFF; // Probably already the current state
spindle_dir = dir_value;
break;

case TURN_OFF:
state = STAY_OFF;
ocr_power = opwr;
spindle_dir = dir_value;
dir_pin_set();
_change_hw(false);
power_delay(false);
break;

case STAY_ON_REV: {
state = STAY_ON;
ocr_power = opwr;
spindle_dir = dir_value;

#if ENABLED(SPINDLE_CHANGE_DIR_STOP)
// Stop Spindle and wait
const uint8_t curr_power = ocr_power;
ocr_power = 0;
_change_hw(false);
power_delay(false);
// Start spindle and wait
ocr_power = curr_power;
dir_pin_set();
_change_hw(ena_pin_on_value);
power_delay(true);
#else
dir_pin_set();
#endif
} break;
}

UNUSED(ena_pin_on);
}

/**
* Return value ocr_power
*/
uint8_t SpindleLaser::get_ocr_power(){ return ocr_power; }

#if ENABLED(SPINDLE_CHANGE_DIR)
/**
* Set the spindle direction and apply immediately
* Stop on direction change if SPINDLE_STOP_ON_DIR_CHANGE is enabled
* ! deprecate and need delete
* @param reverse If True is SpindleDirCCW, false is SpindleDirCW
*/
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);
ocr_set_power(ocr_power, reverse ? SpindleDirCCW : SpindleDirCW);
}
#endif

Expand Down
Loading