Add SPINDLE_SERVO option (#19971)

This commit is contained in:
Alexander Semion 2020-11-01 01:42:05 +03:00 committed by Scott Lahteine
parent 2a61ce80b8
commit c9c17b8863
6 changed files with 38 additions and 8 deletions

View file

@ -2943,11 +2943,18 @@
#define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR and LPC) #define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR and LPC)
//#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
#define SPINDLE_SERVO_MIN 10 // Minimum angle for servo spindle
#endif
/** /**
* Speed / Power can be set ('M3 S') and displayed in terms of: * Speed / Power can be set ('M3 S') and displayed in terms of:
* - PWM255 (S0 - S255) * - PWM255 (S0 - S255)
* - PERCENT (S0 - S100) * - PERCENT (S0 - S100)
* - RPM (S0 - S50000) Best for use with a spindle * - RPM (S0 - S50000) Best for use with a spindle
* - SERVO (S0 - S180)
*/ */
#define CUTTER_POWER_UNIT PWM255 #define CUTTER_POWER_UNIT PWM255

View file

@ -30,6 +30,10 @@
#include "spindle_laser.h" #include "spindle_laser.h"
#if ENABLED(SPINDLE_SERVO)
#include "../module/servo.h"
#endif
SpindleLaser cutter; SpindleLaser cutter;
uint8_t SpindleLaser::power; uint8_t SpindleLaser::power;
bool SpindleLaser::isReady; // Ready to apply power setting from the UI to OCR bool SpindleLaser::isReady; // Ready to apply power setting from the UI to OCR
@ -45,7 +49,11 @@ cutter_power_t SpindleLaser::menuPower, // Power s
// Init the cutter to a safe OFF state // Init the cutter to a safe OFF state
// //
void SpindleLaser::init() { void SpindleLaser::init() {
OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off #if ENABLED(SPINDLE_SERVO)
MOVE_SERVO(SPINDLE_SERVO_NR, SPINDLE_SERVO_MIN);
#else
OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off
#endif
#if ENABLED(SPINDLE_CHANGE_DIR) #if ENABLED(SPINDLE_CHANGE_DIR)
OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR ? 255 : 0); // Init rotation to clockwise (M3) OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR ? 255 : 0); // Init rotation to clockwise (M3)
#endif #endif
@ -97,6 +105,8 @@ void SpindleLaser::apply_power(const uint8_t opwr) {
ocr_off(); ocr_off();
isReady = false; isReady = false;
} }
#elif ENABLED(SPINDLE_SERVO)
MOVE_SERVO(SPINDLE_SERVO_NR, power);
#else #else
WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE); WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
isReady = true; isReady = true;

View file

@ -35,6 +35,7 @@
#endif #endif
#define PCT_TO_PWM(X) ((X) * 255 / 100) #define PCT_TO_PWM(X) ((X) * 255 / 100)
#define PCT_TO_SERVO(X) ((X) * 180 / 100)
#ifndef SPEED_POWER_INTERCEPT #ifndef SPEED_POWER_INTERCEPT
#define SPEED_POWER_INTERCEPT 0 #define SPEED_POWER_INTERCEPT 0
@ -60,7 +61,7 @@ public:
} }
// Convert a cpower (e.g., SPEED_POWER_STARTUP) to unit power (upwr, upower), // Convert a cpower (e.g., SPEED_POWER_STARTUP) to unit power (upwr, upower),
// which can be PWM, Percent, or RPM (rel/abs). // which can be PWM, Percent, Servo angle, or RPM (rel/abs).
static const inline cutter_power_t cpwr_to_upwr(const cutter_cpower_t cpwr) { // STARTUP power to Unit power static const inline cutter_power_t cpwr_to_upwr(const cutter_cpower_t cpwr) { // STARTUP power to Unit power
const cutter_power_t upwr = ( const cutter_power_t upwr = (
#if ENABLED(SPINDLE_FEATURE) #if ENABLED(SPINDLE_FEATURE)
@ -69,6 +70,8 @@ public:
cpwr // to RPM cpwr // to RPM
#elif CUTTER_UNIT_IS(PERCENT) // to PCT #elif CUTTER_UNIT_IS(PERCENT) // to PCT
cpwr_to_pct(cpwr) cpwr_to_pct(cpwr)
#elif CUTTER_UNIT_IS(SERVO) // to SERVO angle
PCT_TO_SERVO(cpwr_to_pct(cpwr))
#else // to PWM #else // to PWM
PCT_TO_PWM(cpwr_to_pct(cpwr)) PCT_TO_PWM(cpwr_to_pct(cpwr))
#endif #endif

View file

@ -69,9 +69,13 @@ void GcodeSuite::M3_M4(const bool is_M4) {
auto get_s_power = [] { auto get_s_power = [] {
if (parser.seenval('S')) { if (parser.seenval('S')) {
const float spwr = parser.value_float(); const float spwr = parser.value_float();
cutter.unitPower = TERN(SPINDLE_LASER_PWM, #if ENABLED(SPINDLE_SERVO)
cutter.unitPower = spwr;
#else
cutter.unitPower = TERN(SPINDLE_LASER_PWM,
cutter.power_to_range(cutter_power_t(round(spwr))), cutter.power_to_range(cutter_power_t(round(spwr))),
spwr > 0 ? 255 : 0); spwr > 0 ? 255 : 0);
#endif
} }
else else
cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP); cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP);
@ -108,6 +112,8 @@ void GcodeSuite::M3_M4(const bool is_M4) {
} }
else else
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 #else
cutter.set_enabled(true); cutter.set_enabled(true);
#endif #endif

View file

@ -33,7 +33,7 @@
// Determine NUM_SERVOS if none was supplied // Determine NUM_SERVOS if none was supplied
#ifndef NUM_SERVOS #ifndef NUM_SERVOS
#define NUM_SERVOS 0 #define NUM_SERVOS 0
#if ANY(CHAMBER_VENT, HAS_Z_SERVO_PROBE, SWITCHING_EXTRUDER, SWITCHING_NOZZLE) #if ANY(HAS_Z_SERVO_PROBE, CHAMBER_VENT, SWITCHING_TOOLHEAD, SWITCHING_EXTRUDER, SWITCHING_NOZZLE, SPINDLE_SERVO)
#if NUM_SERVOS <= Z_PROBE_SERVO_NR #if NUM_SERVOS <= Z_PROBE_SERVO_NR
#undef NUM_SERVOS #undef NUM_SERVOS
#define NUM_SERVOS (Z_PROBE_SERVO_NR + 1) #define NUM_SERVOS (Z_PROBE_SERVO_NR + 1)
@ -62,6 +62,10 @@
#undef NUM_SERVOS #undef NUM_SERVOS
#define NUM_SERVOS (SWITCHING_EXTRUDER_E23_SERVO_NR + 1) #define NUM_SERVOS (SWITCHING_EXTRUDER_E23_SERVO_NR + 1)
#endif #endif
#if NUM_SERVOS <= SPINDLE_SERVO_NR
#undef NUM_SERVOS
#define NUM_SERVOS (SPINDLE_SERVO_NR + 1)
#endif
#endif #endif
#endif #endif

View file

@ -3007,8 +3007,8 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
#if HAS_CUTTER #if HAS_CUTTER
#ifndef CUTTER_POWER_UNIT #ifndef CUTTER_POWER_UNIT
#error "CUTTER_POWER_UNIT is required with a spindle or laser. Please update your Configuration_adv.h." #error "CUTTER_POWER_UNIT is required with a spindle or laser. Please update your Configuration_adv.h."
#elif !CUTTER_UNIT_IS(PWM255) && !CUTTER_UNIT_IS(PERCENT) && !CUTTER_UNIT_IS(RPM) #elif !CUTTER_UNIT_IS(PWM255) && !CUTTER_UNIT_IS(PERCENT) && !CUTTER_UNIT_IS(RPM) && !CUTTER_UNIT_IS(SERVO)
#error "CUTTER_POWER_UNIT must be PWM255, PERCENT, or RPM. Please update your Configuration_adv.h." #error "CUTTER_POWER_UNIT must be PWM255, PERCENT, RPM, or SERVO. Please update your Configuration_adv.h."
#endif #endif
#if ENABLED(LASER_POWER_INLINE) #if ENABLED(LASER_POWER_INLINE)
@ -3047,8 +3047,8 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
#define _PIN_CONFLICT(P) (PIN_EXISTS(P) && P##_PIN == SPINDLE_LASER_PWM_PIN) #define _PIN_CONFLICT(P) (PIN_EXISTS(P) && P##_PIN == SPINDLE_LASER_PWM_PIN)
#if BOTH(SPINDLE_FEATURE, LASER_FEATURE) #if BOTH(SPINDLE_FEATURE, LASER_FEATURE)
#error "Enable only one of SPINDLE_FEATURE or LASER_FEATURE." #error "Enable only one of SPINDLE_FEATURE or LASER_FEATURE."
#elif !PIN_EXISTS(SPINDLE_LASER_ENA) #elif !PIN_EXISTS(SPINDLE_LASER_ENA) && DISABLED(SPINDLE_SERVO)
#error "(SPINDLE|LASER)_FEATURE requires SPINDLE_LASER_ENA_PIN." #error "(SPINDLE|LASER)_FEATURE requires SPINDLE_LASER_ENA_PIN or SPINDLE_SERVO to control the power."
#elif ENABLED(SPINDLE_CHANGE_DIR) && !PIN_EXISTS(SPINDLE_DIR) #elif ENABLED(SPINDLE_CHANGE_DIR) && !PIN_EXISTS(SPINDLE_DIR)
#error "SPINDLE_DIR_PIN is required for SPINDLE_CHANGE_DIR." #error "SPINDLE_DIR_PIN is required for SPINDLE_CHANGE_DIR."
#elif ENABLED(SPINDLE_LASER_PWM) #elif ENABLED(SPINDLE_LASER_PWM)