DEFAULT_ACCELERATION_SPINDLE (#27759)

This commit is contained in:
DerAndere 2025-04-14 23:50:26 +02:00 committed by GitHub
parent 7d82f95df8
commit b5d7b4aee6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 136 additions and 11 deletions

View file

@ -3682,6 +3682,8 @@
#define SPEED_POWER_MIN 5000 // (RPM) #define SPEED_POWER_MIN 5000 // (RPM)
#define SPEED_POWER_MAX 30000 // (RPM) SuperPID router controller 0 - 30,000 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_STARTUP 25000 // (RPM) M3/M4 speed/power default (with no arguments)
//#define DEFAULT_ACCELERATION_SPINDLE 1000 // (°/s/s) Default spindle acceleration (speed change with time)
#endif #endif
#else #else

View file

@ -43,6 +43,10 @@ bool SpindleLaser::enable_state; // Virtual
uint8_t SpindleLaser::power, // Actual power output 0-255 ocr or "0 = off" > 0 = "on" uint8_t SpindleLaser::power, // Actual power output 0-255 ocr or "0 = off" > 0 = "on"
SpindleLaser::last_power_applied; // = 0 // Basic power state tracking SpindleLaser::last_power_applied; // = 0 // Basic power state tracking
#if HAS_SPINDLE_ACCELERATION
uint32_t SpindleLaser::acceleration_spindle_deg_per_s2; // (°/s/s) Spindle acceleration. Initialized by settings.load
#endif
#if ENABLED(LASER_FEATURE) #if ENABLED(LASER_FEATURE)
cutter_test_pulse_t SpindleLaser::testPulse = 50; // (ms) Test fire pulse default duration cutter_test_pulse_t SpindleLaser::testPulse = 50; // (ms) Test fire pulse default duration
uint8_t SpindleLaser::last_block_power; // = 0 // Track power changes for dynamic inline power uint8_t SpindleLaser::last_block_power; // = 0 // Track power changes for dynamic inline power
@ -100,7 +104,22 @@ void SpindleLaser::init() {
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY #if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY
hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency); hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency);
#endif #endif
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF); #if HAS_SPINDLE_ACCELERATION
const int16_t diff = ocr - last_power_applied;
const uint8_t abs_diff = ABS(diff);
uint8_t current_ocr = last_power_applied;
// Duration between ocr increments. SPEED_POWER_MAX is in RPM.
const millis_t duration = (float(SPEED_POWER_MAX) * (60000.f / 2550.f) / float(acceleration_spindle_deg_per_s2)) * abs_diff;
millis_t next_ocr_change = millis() + duration;
while (current_ocr != ocr) {
while (PENDING(millis(), next_ocr_change)) idle();
current_ocr += diff > 0 ? 1 : -1;
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), current_ocr ^ SPINDLE_LASER_PWM_OFF);
next_ocr_change += duration;
}
#else
hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
#endif
} }
void SpindleLaser::set_ocr(const uint8_t ocr) { void SpindleLaser::set_ocr(const uint8_t ocr) {
@ -111,10 +130,10 @@ void SpindleLaser::init() {
} }
void SpindleLaser::ocr_off() { void SpindleLaser::ocr_off() {
_set_ocr(0);
#if PIN_EXISTS(SPINDLE_LASER_ENA) #if PIN_EXISTS(SPINDLE_LASER_ENA)
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Cutter OFF WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Cutter OFF
#endif #endif
_set_ocr(0);
} }
#endif // SPINDLE_LASER_USE_PWM #endif // SPINDLE_LASER_USE_PWM
@ -127,9 +146,8 @@ void SpindleLaser::init() {
*/ */
void SpindleLaser::apply_power(const uint8_t opwr) { void SpindleLaser::apply_power(const uint8_t opwr) {
if (enabled() || opwr == 0) { // 0 check allows us to disable where no ENA pin exists if (enabled() || opwr == 0) { // 0 check allows us to disable where no ENA pin exists
// Test and set the last power used to improve performance // Test the last power used to improve performance
if (opwr == last_power_applied) return; if (opwr == last_power_applied) return;
last_power_applied = opwr;
// Handle PWM driven or just simple on/off // Handle PWM driven or just simple on/off
#if ENABLED(SPINDLE_LASER_USE_PWM) #if ENABLED(SPINDLE_LASER_USE_PWM)
if (CUTTER_UNIT_IS(RPM) && unitPower == 0) if (CUTTER_UNIT_IS(RPM) && unitPower == 0)
@ -146,6 +164,7 @@ void SpindleLaser::apply_power(const uint8_t opwr) {
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);
isReadyForUI = true; isReadyForUI = true;
#endif #endif
last_power_applied = opwr;
} }
else { else {
#if PIN_EXISTS(SPINDLE_LASER_ENA) #if PIN_EXISTS(SPINDLE_LASER_ENA)

View file

@ -109,11 +109,14 @@ public:
static uint8_t power, static uint8_t power,
last_power_applied; // Basic power state tracking last_power_applied; // Basic power state tracking
static cutter_frequency_t frequency; // Set PWM frequency; range: 2K-50K static cutter_frequency_t frequency; // (Hz) Laser/Spindle PWM frequency (2000..50000)
static cutter_power_t menuPower, // Power as set via LCD menu in PWM, Percentage or RPM 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
#if HAS_SPINDLE_ACCELERATION
static uint32_t acceleration_spindle_deg_per_s2; // (°/s/s) Spindle acceleration
#endif
static void init(); static void init();
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY #if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY

View file

@ -1090,6 +1090,9 @@
#define _CUTTER_POWER_RPM 3 #define _CUTTER_POWER_RPM 3
#define _CUTTER_POWER(V) _CAT(_CUTTER_POWER_, V) #define _CUTTER_POWER(V) _CAT(_CUTTER_POWER_, V)
#define CUTTER_UNIT_IS(V) (_CUTTER_POWER(CUTTER_POWER_UNIT) == _CUTTER_POWER(V)) #define CUTTER_UNIT_IS(V) (_CUTTER_POWER(CUTTER_POWER_UNIT) == _CUTTER_POWER(V))
#if DEFAULT_ACCELERATION_SPINDLE
#define HAS_SPINDLE_ACCELERATION 1
#endif
#endif #endif
#if !defined(__AVR__) || !defined(USBCON) #if !defined(__AVR__) || !defined(USBCON)

View file

@ -4072,6 +4072,8 @@ static_assert(_PLUS_TEST(3), "DEFAULT_MAX_ACCELERATION values must be positive."
#error "SPINDLE_LASER_PWM_INVERT is required for (SPINDLE|LASER)_FEATURE." #error "SPINDLE_LASER_PWM_INVERT is required for (SPINDLE|LASER)_FEATURE."
#elif !(defined(SPEED_POWER_MIN) && defined(SPEED_POWER_MAX) && defined(SPEED_POWER_STARTUP)) #elif !(defined(SPEED_POWER_MIN) && defined(SPEED_POWER_MAX) && defined(SPEED_POWER_STARTUP))
#error "SPINDLE_LASER_USE_PWM equation constant(s) missing." #error "SPINDLE_LASER_USE_PWM equation constant(s) missing."
#elif DEFAULT_ACCELERATION_SPINDLE > SPEED_POWER_MAX - SPEED_POWER_MIN
#error "DEFAULT_ACCELERATION_SPINDLE must be <= SPEED_POWER_MAX - SPEED_POWER_MIN."
#elif _PIN_CONFLICT(X_MIN) #elif _PIN_CONFLICT(X_MIN)
#error "SPINDLE_LASER_PWM_PIN conflicts with X_MIN_PIN." #error "SPINDLE_LASER_PWM_PIN conflicts with X_MIN_PIN."
#elif _PIN_CONFLICT(X_MAX) #elif _PIN_CONFLICT(X_MAX)

View file

@ -65,6 +65,12 @@ constexpr xyze_float_t max_acceleration_edit_values =
#endif #endif
; ;
#if HAS_SPINDLE_ACCELERATION
constexpr float min_acceleration_edit_values_spindle = 1,
default_acceleration_spindle = DEFAULT_ACCELERATION_SPINDLE,
max_acceleration_edit_values_spindle = default_acceleration_spindle * DEFAULT_MAX_MULTIPLIER;
#endif
// //
// Max Jerk limits // Max Jerk limits
// //

View file

@ -1595,6 +1595,27 @@ void hmiMaxAccelerationXYZE() {
drawEditInteger4(select_acc.now, hmiValues.maxAcceleration, true); drawEditInteger4(select_acc.now, hmiValues.maxAcceleration, true);
} }
#if HAS_SPINDLE_ACCELERATION
void hmiSpindleAcceleration() {
EncoderState encoder_diffState = encoderReceiveAnalyze();
if (encoder_diffState == ENCODER_DIFF_NO) return;
if (applyEncoder(encoder_diffState, hmiValues.spindleAcceleration)) {
checkkey = ID_SpindleAcceleration;
encoderRate.enabled = false;
cutter.spindle_acceleration_deg_per_s2 = hmiValues.spindleAcceleration;
drawEditInteger4(select_acc.now, hmiValues.spindleAcceleration);
return;
}
// SpindleAcceleration limit
LIMIT(hmiValues.spindleAcceleration, min_acceleration_edit_values_spindle, max_acceleration_edit_values_spindle);
// SpindleAcceleration value
drawEditInteger4(select_acc.now, hmiValues.spindleAcceleration, true);
}
#endif // HAS_SPINDLE_ACCELERATION
#if ENABLED(CLASSIC_JERK) #if ENABLED(CLASSIC_JERK)
void hmiMaxJerkXYZE() { void hmiMaxJerkXYZE() {
@ -4283,6 +4304,9 @@ void dwinHandleScreen() {
case ID_PrintSpeed: hmiPrintSpeed(); break; case ID_PrintSpeed: hmiPrintSpeed(); break;
case ID_MaxSpeedValue: hmiMaxFeedspeedXYZE(); break; case ID_MaxSpeedValue: hmiMaxFeedspeedXYZE(); break;
case ID_MaxAccelerationValue: hmiMaxAccelerationXYZE(); break; case ID_MaxAccelerationValue: hmiMaxAccelerationXYZE(); break;
#if HAS_SPINDLE_ACCELERATION
case ID_SpindleAccelerationValue: hmiSpindleAcceleration(); break;
#endif
#if ENABLED(CLASSIC_JERK) #if ENABLED(CLASSIC_JERK)
case ID_MaxJerkValue: hmiMaxJerkXYZE(); break; case ID_MaxJerkValue: hmiMaxJerkXYZE(); break;
#endif #endif

View file

@ -53,6 +53,9 @@ enum processID : uint8_t {
#endif #endif
ID_MaxSpeed, ID_MaxSpeedValue, ID_MaxSpeed, ID_MaxSpeedValue,
ID_MaxAcceleration, ID_MaxAccelerationValue, ID_MaxAcceleration, ID_MaxAccelerationValue,
#if HAS_SPINDLE_ACCELERATION
ID_SpindleAccelerationValue,
#endif
ID_MaxJerk, ID_MaxJerkValue, ID_MaxJerk, ID_MaxJerkValue,
ID_Step, ID_StepValue, ID_Step, ID_StepValue,
ID_HomeOff, ID_HomeOffX, ID_HomeOffY, ID_HomeOffZ, ID_HomeOff, ID_HomeOffX, ID_HomeOffY, ID_HomeOffZ,
@ -105,6 +108,9 @@ typedef struct {
int16_t printSpeed = 100; int16_t printSpeed = 100;
float maxFeedSpeed = 0; float maxFeedSpeed = 0;
float maxAcceleration = 0; float maxAcceleration = 0;
#if HAS_SPINDLE_ACCELERATION
float spindleAcceleration = 0;
#endif
float maxJerkScaled = 0; float maxJerkScaled = 0;
float maxStepScaled = 0; float maxStepScaled = 0;
float offset_value = 0; float offset_value = 0;
@ -203,6 +209,9 @@ void hmiPrintSpeed();
void hmiMaxFeedspeedXYZE(); void hmiMaxFeedspeedXYZE();
void hmiMaxAccelerationXYZE(); void hmiMaxAccelerationXYZE();
#if HAS_SPINDLE_ACCELERATION
void hmiSpindleAcceleration();
#endif
void hmiMaxJerkXYZE(); void hmiMaxJerkXYZE();
#if ENABLED(EDITABLE_STEPS_PER_UNIT) #if ENABLED(EDITABLE_STEPS_PER_UNIT)
void hmiStepXYZE(); void hmiStepXYZE();

View file

@ -452,6 +452,7 @@ namespace LanguageNarrow_en {
LSTR MSG_AMAX_EN = _UxGT("Max * Accel"); LSTR MSG_AMAX_EN = _UxGT("Max * Accel");
LSTR MSG_A_RETRACT = _UxGT("Retract Accel"); LSTR MSG_A_RETRACT = _UxGT("Retract Accel");
LSTR MSG_A_TRAVEL = _UxGT("Travel Accel"); LSTR MSG_A_TRAVEL = _UxGT("Travel Accel");
LSTR MSG_A_SPINDLE = _UxGT("Spindle Accel");
LSTR MSG_INPUT_SHAPING = _UxGT("Input Shaping"); LSTR MSG_INPUT_SHAPING = _UxGT("Input Shaping");
LSTR MSG_SHAPING_ENABLE_N = _UxGT("Enable @ shaping"); LSTR MSG_SHAPING_ENABLE_N = _UxGT("Enable @ shaping");
LSTR MSG_SHAPING_DISABLE_N = _UxGT("Disable @ shaping"); LSTR MSG_SHAPING_DISABLE_N = _UxGT("Disable @ shaping");

View file

@ -37,6 +37,10 @@
#include "../../gcode/parser.h" #include "../../gcode/parser.h"
#endif #endif
#if HAS_SPINDLE_ACCELERATION
#include "../../feature/spindle_laser.h"
#endif
#if HAS_BED_PROBE #if HAS_BED_PROBE
#include "../../module/probe.h" #include "../../module/probe.h"
#endif #endif
@ -511,6 +515,9 @@ void menu_backlash();
#else #else
const xyze_ulong_t &max_accel_edit_scaled = max_accel_edit; const xyze_ulong_t &max_accel_edit_scaled = max_accel_edit;
#endif #endif
#if HAS_SPINDLE_ACCELERATION
constexpr uint32_t max_spindle_accel_edit = 99000;
#endif
START_MENU(); START_MENU();
BACK_ITEM(MSG_ADVANCED_SETTINGS); BACK_ITEM(MSG_ADVANCED_SETTINGS);
@ -544,6 +551,10 @@ void menu_backlash();
EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS], 100, max_accel_edit_scaled.e, []{ planner.refresh_acceleration_rates(); }); EDIT_ITEM_FAST(long5_25, MSG_AMAX_E, &planner.settings.max_acceleration_mm_per_s2[E_AXIS], 100, max_accel_edit_scaled.e, []{ planner.refresh_acceleration_rates(); });
#endif #endif
#if HAS_SPINDLE_ACCELERATION
EDIT_ITEM_FAST(long5_25, MSG_A_SPINDLE, &cutter.acceleration_spindle_deg_per_s2, 100, max_spindle_accel_edit);
#endif
#ifdef XY_FREQUENCY_LIMIT #ifdef XY_FREQUENCY_LIMIT
EDIT_ITEM(int8, MSG_XY_FREQUENCY_LIMIT, &planner.xy_freq_limit_hz, 0, 100, planner.refresh_frequency_limit, true); EDIT_ITEM(int8, MSG_XY_FREQUENCY_LIMIT, &planner.xy_freq_limit_hz, 0, 100, planner.refresh_frequency_limit, true);
editable.uint8 = uint8_t(LROUND(planner.xy_freq_min_speed_factor * 255)); // percent to u8 editable.uint8 = uint8_t(LROUND(planner.xy_freq_min_speed_factor * 255)); // percent to u8

View file

@ -60,6 +60,10 @@
#include "../HAL/shared/eeprom_api.h" #include "../HAL/shared/eeprom_api.h"
#endif #endif
#if HAS_SPINDLE_ACCELERATION
#include "../feature/spindle_laser.h"
#endif
#if HAS_BED_PROBE #if HAS_BED_PROBE
#include "probe.h" #include "probe.h"
#endif #endif
@ -252,6 +256,13 @@ typedef struct SettingsDataStruct {
xyz_pos_t hotend_offset[HOTENDS - 1]; // M218 XYZ xyz_pos_t hotend_offset[HOTENDS - 1]; // M218 XYZ
#endif #endif
//
// Spindle Acceleration
//
#if HAS_SPINDLE_ACCELERATION
uint32_t acceleration_spindle; // cutter.acceleration_spindle_deg_per_s2
#endif
// //
// FILAMENT_RUNOUT_SENSOR // FILAMENT_RUNOUT_SENSOR
// //
@ -941,7 +952,7 @@ void MarlinSettings::postprocess() {
#endif // NUM_AXES #endif // NUM_AXES
// //
// Hotend Offsets, if any // Hotend Offsets
// //
{ {
#if HAS_HOTEND_OFFSET #if HAS_HOTEND_OFFSET
@ -951,6 +962,16 @@ void MarlinSettings::postprocess() {
#endif #endif
} }
//
// Spindle Acceleration
//
{
#if HAS_SPINDLE_ACCELERATION
_FIELD_TEST(acceleration_spindle);
EEPROM_WRITE(cutter.acceleration_spindle_deg_per_s2);
#endif
}
// //
// Filament Runout Sensor // Filament Runout Sensor
// //
@ -1985,7 +2006,7 @@ void MarlinSettings::postprocess() {
#endif // NUM_AXES #endif // NUM_AXES
// //
// Hotend Offsets, if any // Hotend Offsets
// //
{ {
#if HAS_HOTEND_OFFSET #if HAS_HOTEND_OFFSET
@ -1995,6 +2016,16 @@ void MarlinSettings::postprocess() {
#endif #endif
} }
//
// Spindle Acceleration
//
{
#if HAS_SPINDLE_ACCELERATION
_FIELD_TEST(acceleration_spindle);
EEPROM_READ(cutter.acceleration_spindle_deg_per_s2);
#endif
}
// //
// Filament Runout Sensor // Filament Runout Sensor
// //
@ -2003,7 +2034,7 @@ void MarlinSettings::postprocess() {
_FIELD_TEST(runout_sensor_enabled); _FIELD_TEST(runout_sensor_enabled);
EEPROM_READ(runout_sensor_enabled); EEPROM_READ(runout_sensor_enabled);
#if HAS_FILAMENT_SENSOR #if HAS_FILAMENT_SENSOR
if (!validating) runout.enabled = runout_sensor_enabled < 0 ? FIL_RUNOUT_ENABLED_DEFAULT : runout_sensor_enabled; if (!validating) runout.enabled = runout_sensor_enabled < 0 ? FIL_RUNOUT_ENABLED_DEFAULT : runout_sensor_enabled;
#endif #endif
TERN_(HAS_FILAMENT_SENSOR, if (runout.enabled) runout.reset()); TERN_(HAS_FILAMENT_SENSOR, if (runout.enabled) runout.reset());
@ -3286,14 +3317,27 @@ void MarlinSettings::reset() {
TERN_(HAS_JUNCTION_DEVIATION, planner.junction_deviation_mm = float(JUNCTION_DEVIATION_MM)); TERN_(HAS_JUNCTION_DEVIATION, planner.junction_deviation_mm = float(JUNCTION_DEVIATION_MM));
//
// Home Offset
//
#if HAS_SCARA_OFFSET #if HAS_SCARA_OFFSET
scara_home_offset.reset(); scara_home_offset.reset();
#elif HAS_HOME_OFFSET #elif HAS_HOME_OFFSET
home_offset.reset(); home_offset.reset();
#endif #endif
//
// Hotend Offsets
//
TERN_(HAS_HOTEND_OFFSET, reset_hotend_offsets()); TERN_(HAS_HOTEND_OFFSET, reset_hotend_offsets());
//
// Spindle Acceleration
//
#if HAS_SPINDLE_ACCELERATION
cutter.acceleration_spindle_deg_per_s2 = DEFAULT_ACCELERATION_SPINDLE;
#endif
// //
// Filament Runout Sensor // Filament Runout Sensor
// //

View file

@ -19,7 +19,8 @@ restore_configs
opt_set LCD_LANGUAGE an \ opt_set LCD_LANGUAGE an \
POWER_MONITOR_CURRENT_PIN 14 POWER_MONITOR_VOLTAGE_PIN 15 \ POWER_MONITOR_CURRENT_PIN 14 POWER_MONITOR_VOLTAGE_PIN 15 \
CLOSED_LOOP_ENABLE_PIN 44 CLOSED_LOOP_MOVE_COMPLETE_PIN 45 CLOSED_LOOP_ENABLE_PIN 44 CLOSED_LOOP_MOVE_COMPLETE_PIN 45
opt_enable SPINDLE_FEATURE ULTIMAKERCONTROLLER LCD_BED_LEVELING EDITABLE_HOMING_FEEDRATE \ opt_enable SPINDLE_FEATURE DEFAULT_ACCELERATION_SPINDLE \
ULTIMAKERCONTROLLER LCD_BED_LEVELING EDITABLE_HOMING_FEEDRATE \
EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \ EEPROM_SETTINGS EEPROM_BOOT_SILENT EEPROM_AUTO_INIT \
SENSORLESS_BACKOFF_MM HOMING_BACKOFF_POST_MM HOME_Y_BEFORE_X CODEPENDENT_XY_HOMING \ SENSORLESS_BACKOFF_MM HOMING_BACKOFF_POST_MM HOME_Y_BEFORE_X CODEPENDENT_XY_HOMING \
MESH_BED_LEVELING ENABLE_LEVELING_FADE_HEIGHT MESH_G28_REST_ORIGIN \ MESH_BED_LEVELING ENABLE_LEVELING_FADE_HEIGHT MESH_G28_REST_ORIGIN \