mirror of
https://github.com/grblHAL/core.git
synced 2026-08-17 08:31:43 +08:00
Added option to setting $63 to set spindle RPM to minimum (typically 0) on feed hold. Ref. issue #991.
Fixed reset (abort) not turning off laser in some circumstances.
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
## grblHAL ##
|
## grblHAL ##
|
||||||
|
|
||||||
Latest build date is 20260811, see the [changelog](changelog.md) for details.
|
Latest build date is 20260813, see the [changelog](changelog.md) for details.
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended.
|
> A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended.
|
||||||
|
|||||||
@@ -47,7 +47,8 @@ PROGMEM static const alarm_detail_t alarm_detail[] = {
|
|||||||
{ Alarm_HomingFail, "Homing fail. Bad configuration." },
|
{ Alarm_HomingFail, "Homing fail. Bad configuration." },
|
||||||
{ Alarm_ModbusException, "Modbus exception. Timeout or message error." },
|
{ Alarm_ModbusException, "Modbus exception. Timeout or message error." },
|
||||||
{ Alarm_ExpanderException, "I/O expander communication failed." },
|
{ Alarm_ExpanderException, "I/O expander communication failed." },
|
||||||
{ Alarm_NVS_Failed, "Non Volatile Storage (EEPROM) failure." }
|
{ Alarm_NVS_Failed, "Non Volatile Storage (EEPROM) failure." },
|
||||||
|
{ Alarm_BufferOverflow, "Buffer overflow." }
|
||||||
};
|
};
|
||||||
|
|
||||||
static alarm_details_t details = {
|
static alarm_details_t details = {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
Part of grblHAL
|
Part of grblHAL
|
||||||
|
|
||||||
Copyright (c) 2017-2025 Terje Io
|
Copyright (c) 2017-2026 Terje Io
|
||||||
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
|
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
|
||||||
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
Copyright (c) 2009-2011 Simen Svale Skogsrud
|
||||||
|
|
||||||
@@ -49,7 +49,8 @@ typedef enum {
|
|||||||
Alarm_ModbusException = 19, //!< 19
|
Alarm_ModbusException = 19, //!< 19
|
||||||
Alarm_ExpanderException = 20, //!< 20
|
Alarm_ExpanderException = 20, //!< 20
|
||||||
Alarm_NVS_Failed = 21, //!< 21
|
Alarm_NVS_Failed = 21, //!< 21
|
||||||
Alarm_AlarmMax = Alarm_NVS_Failed
|
Alarm_BufferOverflow = 22, //!< 22
|
||||||
|
Alarm_AlarmMax = Alarm_BufferOverflow
|
||||||
} __attribute__ ((__packed__)) alarm_code_t;
|
} __attribute__ ((__packed__)) alarm_code_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -1,5 +1,29 @@
|
|||||||
## grblHAL changelog
|
## grblHAL changelog
|
||||||
|
|
||||||
|
<a name="20260813">Build 20260813
|
||||||
|
|
||||||
|
Core:
|
||||||
|
|
||||||
|
* Added option to setting `$63` - _Feed hold actions_ to set spindle RPM to minimum \(typically 0\) on feed hold.
|
||||||
|
Ref. issue [#991](https://github.com/grblHAL/core/issues/991).
|
||||||
|
> [!NOTE]
|
||||||
|
> This is ignored for laser enabled spindles when M4 is active.
|
||||||
|
|
||||||
|
* Fixed reset \(abort\) not turning off laser in some circumstances.
|
||||||
|
|
||||||
|
Drivers:
|
||||||
|
|
||||||
|
* ESP32: fixed pin conflict with Modbus port for BTT Rodent board. Ref. [#211](https://github.com/grblHAL/ESP32/issues/211).
|
||||||
|
Fixed issues with second PWM spindle.
|
||||||
|
|
||||||
|
Plugins:
|
||||||
|
|
||||||
|
* Laser, LigthBurn clusters: Added fix for for modal state RPM left incorrect after processing line.
|
||||||
|
"Hardened" code to mostly ignore malformed/malign input, may raise alarm if really off the charts.
|
||||||
|
Ref. PR[#4](/https://github.com/grblHAL/Plugins_laser/pull/4).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
<a name="20260811">Build 20260811
|
<a name="20260811">Build 20260811
|
||||||
|
|
||||||
Core:
|
Core:
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
#else
|
#else
|
||||||
#define GRBL_VERSION "1.1f"
|
#define GRBL_VERSION "1.1f"
|
||||||
#endif
|
#endif
|
||||||
#define GRBL_BUILD 20260811
|
#define GRBL_BUILD 20260813
|
||||||
|
|
||||||
#define GRBL_URL "https://github.com/grblHAL"
|
#define GRBL_URL "https://github.com/grblHAL"
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -179,10 +179,12 @@ bool mc_line (float *target, plan_line_data_t *pl_data)
|
|||||||
// Plan and queue motion into planner buffer.
|
// Plan and queue motion into planner buffer.
|
||||||
// While in M3 laser mode also set spindle state and force a buffer sync
|
// While in M3 laser mode also set spindle state and force a buffer sync
|
||||||
// if there is a coincident position passed.
|
// if there is a coincident position passed.
|
||||||
if(!plan_buffer_line(target, pl_data) && pl_data->spindle.hal->cap.laser && pl_data->spindle.state.on && !pl_data->spindle.state.ccw) {
|
if(!plan_buffer_line(target, pl_data) &&
|
||||||
protocol_buffer_synchronize();
|
pl_data->spindle.hal->cap.laser &&
|
||||||
|
pl_data->spindle.state.on &&
|
||||||
|
!pl_data->spindle.state.ccw &&
|
||||||
|
protocol_buffer_synchronize())
|
||||||
pl_data->spindle.hal->set_state(pl_data->spindle.hal, pl_data->spindle.state, pl_data->spindle.rpm);
|
pl_data->spindle.hal->set_state(pl_data->spindle.hal, pl_data->spindle.state, pl_data->spindle.rpm);
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef KINEMATICS_API
|
#ifdef KINEMATICS_API
|
||||||
if(pl_data->condition.jog_motion) {
|
if(pl_data->condition.jog_motion) {
|
||||||
|
|||||||
+3
-2
@@ -1226,6 +1226,7 @@ static status_code_t set_hold_actions (setting_id_t id, uint_fast16_t int_value)
|
|||||||
{
|
{
|
||||||
settings.flags.disable_laser_during_hold = bit_istrue(int_value, bit(0));
|
settings.flags.disable_laser_during_hold = bit_istrue(int_value, bit(0));
|
||||||
settings.flags.restore_after_feed_hold = bit_istrue(int_value, bit(1));
|
settings.flags.restore_after_feed_hold = bit_istrue(int_value, bit(1));
|
||||||
|
settings.flags.set_rpm_0_during_hold = bit_istrue(int_value, bit(2));
|
||||||
|
|
||||||
return Status_OK;
|
return Status_OK;
|
||||||
}
|
}
|
||||||
@@ -1762,7 +1763,7 @@ FLASHMEM static uint32_t get_int (setting_id_t id)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case Setting_HoldActions:
|
case Setting_HoldActions:
|
||||||
value = settings.flags.disable_laser_during_hold | (settings.flags.restore_after_feed_hold << 1);
|
value = settings.flags.disable_laser_during_hold | (settings.flags.restore_after_feed_hold << 1) | (settings.flags.set_rpm_0_during_hold << 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Setting_ForceInitAlarm:
|
case Setting_ForceInitAlarm:
|
||||||
@@ -2392,7 +2393,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
|
|||||||
{ Setting_DoorOptions, Group_SafetyDoor, "Safety door options", NULL, Format_Bitfield, door_options, NULL, NULL, Setting_IsExtended, &settings.safety_door.flags.value, NULL, is_setting_available },
|
{ Setting_DoorOptions, Group_SafetyDoor, "Safety door options", NULL, Format_Bitfield, door_options, NULL, NULL, Setting_IsExtended, &settings.safety_door.flags.value, NULL, is_setting_available },
|
||||||
#endif
|
#endif
|
||||||
{ Setting_SleepEnable, Group_General, "Sleep enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_sleep_enable, get_int, is_setting_available },
|
{ Setting_SleepEnable, Group_General, "Sleep enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_sleep_enable, get_int, is_setting_available },
|
||||||
{ Setting_HoldActions, Group_General, "Feed hold actions", NULL, Format_Bitfield, "Disable laser during hold,Restore spindle and coolant state on resume", NULL, NULL, Setting_IsExtendedFn, set_hold_actions, get_int, NULL },
|
{ Setting_HoldActions, Group_General, "Feed hold actions", NULL, Format_Bitfield, "Disable laser during hold,Restore spindle and coolant state on resume,Set RPM to minimum (except for laser M4)", NULL, NULL, Setting_IsExtendedFn, set_hold_actions, get_int, NULL },
|
||||||
{ Setting_ForceInitAlarm, Group_General, "Force init alarm", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_force_initialization_alarm, get_int, NULL },
|
{ Setting_ForceInitAlarm, Group_General, "Force init alarm", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_force_initialization_alarm, get_int, NULL },
|
||||||
{ Setting_ProbingFlags, Group_Probing, "Probing options", NULL, Format_Bitfield, probing_options, NULL, NULL, Setting_IsExtendedFn, set_probe_flags, get_int, is_setting_available },
|
{ Setting_ProbingFlags, Group_Probing, "Probing options", NULL, Format_Bitfield, probing_options, NULL, NULL, Setting_IsExtendedFn, set_probe_flags, get_int, is_setting_available },
|
||||||
#if ENABLE_SPINDLE_LINEARIZATION
|
#if ENABLE_SPINDLE_LINEARIZATION
|
||||||
|
|||||||
+2
-1
@@ -611,7 +611,8 @@ typedef union {
|
|||||||
m98_prescan_enable :1,
|
m98_prescan_enable :1,
|
||||||
rotary_fix_enable :1,
|
rotary_fix_enable :1,
|
||||||
revert_metric_conversion :1, // For rotary axes inch/min -> mm/min
|
revert_metric_conversion :1, // For rotary axes inch/min -> mm/min
|
||||||
unassigned :6;
|
set_rpm_0_during_hold :1,
|
||||||
|
unassigned :5;
|
||||||
};
|
};
|
||||||
} settingflags_t;
|
} settingflags_t;
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -845,11 +845,13 @@ FLASHMEM bool spindle_restore (spindle_ptrs_t *spindle, spindle_state_t state, f
|
|||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
|
|
||||||
if(spindle->cap.laser) { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts.
|
if(!spindle->param->option.restore_rpm && spindle->cap.laser) { // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts.
|
||||||
if(!(ok = !settings.flags.disable_laser_during_hold))
|
if(!(ok = !settings.flags.disable_laser_during_hold))
|
||||||
ok = (sys.step_control.update_spindle_rpm = _spindle_set_state(spindle, state, 0.0f, 0));
|
ok = (sys.step_control.update_spindle_rpm = _spindle_set_state(spindle, state, 0.0f, 0));
|
||||||
} else if(!(ok = spindle_check_state(spindle, state) && spindle->param->rpm == rpm))
|
} else if(!(ok = !spindle->param->option.restore_rpm && spindle_check_state(spindle, state) && spindle->param->rpm == rpm)) {
|
||||||
ok = spindle_set_state_wait(spindle, state, rpm, delay_ms);
|
ok = spindle_set_state_wait(spindle, state, rpm, delay_ms);
|
||||||
|
spindle->param->option.restore_rpm = Off;
|
||||||
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -889,6 +891,7 @@ FLASHMEM void spindle_all_off (bool reset)
|
|||||||
|
|
||||||
spindle->param->rpm = spindle->param->rpm_overridden = 0.0f;
|
spindle->param->rpm = spindle->param->rpm_overridden = 0.0f;
|
||||||
spindle->param->state.value = 0;
|
spindle->param->state.value = 0;
|
||||||
|
spindle->param->option.restore_rpm = Off;
|
||||||
#ifdef GRBL_ESP32
|
#ifdef GRBL_ESP32
|
||||||
spindle->esp32_off(spindle);
|
spindle->esp32_off(spindle);
|
||||||
#else
|
#else
|
||||||
|
|||||||
+2
-1
@@ -364,7 +364,8 @@ typedef struct spindle_param {
|
|||||||
uint8_t ramp_up :1,
|
uint8_t ramp_up :1,
|
||||||
ramp_down :1,
|
ramp_down :1,
|
||||||
ignore_delays :1,
|
ignore_delays :1,
|
||||||
override_disable :1;
|
override_disable :1,
|
||||||
|
restore_rpm :1;
|
||||||
} option;
|
} option;
|
||||||
spindle_ptrs_t *hal;
|
spindle_ptrs_t *hal;
|
||||||
} spindle_param_t;
|
} spindle_param_t;
|
||||||
|
|||||||
+22
-9
@@ -370,13 +370,13 @@ void state_set (sys_state_t new_state)
|
|||||||
// Suspend manager. Controls spindle overrides in hold states.
|
// Suspend manager. Controls spindle overrides in hold states.
|
||||||
FLASHMEM void state_suspend_manager (void)
|
FLASHMEM void state_suspend_manager (void)
|
||||||
{
|
{
|
||||||
if(stateHandler != state_await_resume || !gc_spindle_get(0)->state.on)
|
spindle_t *spindle = &restore_condition.spindle[restore_condition.spindle_num];
|
||||||
|
|
||||||
|
if(stateHandler != state_await_resume || !gc_spindle_get(0)->state.on || (spindle->hal && spindle->hal->param->option.restore_rpm))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(sys.override.spindle_stop.value) {
|
if(sys.override.spindle_stop.value) {
|
||||||
|
|
||||||
spindle_t *spindle = &restore_condition.spindle[restore_condition.spindle_num];
|
|
||||||
|
|
||||||
// Handles beginning of spindle stop
|
// Handles beginning of spindle stop
|
||||||
if(sys.override.spindle_stop.initiate) {
|
if(sys.override.spindle_stop.initiate) {
|
||||||
sys.override.spindle_stop.value = 0; // Clear stop override state
|
sys.override.spindle_stop.value = 0; // Clear stop override state
|
||||||
@@ -399,9 +399,9 @@ FLASHMEM void state_suspend_manager (void)
|
|||||||
grbl.on_override_changed(OverrideChanged_SpindleState);
|
grbl.on_override_changed(OverrideChanged_SpindleState);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if(sys.step_control.update_spindle_rpm && restore_condition.spindle[0].hal->get_state(restore_condition.spindle[0].hal).on) {
|
} else if(sys.step_control.update_spindle_rpm && spindle->hal && spindle->hal->get_state(spindle->hal).on) {
|
||||||
// Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state.
|
// Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state.
|
||||||
state_spindle_restore(&restore_condition.spindle[restore_condition.spindle_num], settings.spindle.on_delay);
|
state_spindle_restore(spindle, settings.spindle.on_delay);
|
||||||
sys.step_control.update_spindle_rpm = Off;
|
sys.step_control.update_spindle_rpm = Off;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -595,6 +595,18 @@ FLASHMEM static void state_await_hold (uint_fast16_t rt_exec)
|
|||||||
sys.flags.is_parking = false;
|
sys.flags.is_parking = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case STATE_HOLD:
|
||||||
|
{
|
||||||
|
spindle_t *spindle;
|
||||||
|
if((spindle = &restore_condition.spindle[restore_condition.spindle_num])->hal && settings.flags.set_rpm_0_during_hold) {
|
||||||
|
if(spindle->state.on && !(spindle->hal->cap.laser && spindle->state.ccw)) {
|
||||||
|
spindle->hal->param->option.restore_rpm = settings.flags.restore_after_feed_hold;
|
||||||
|
spindle->hal->set_state(spindle->hal, spindle->state, spindle->hal->rpm_min);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -674,18 +686,19 @@ FLASHMEM static void state_await_resume (uint_fast16_t rt_exec)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (!settings.flags.restore_after_feed_hold) {
|
if(!settings.flags.restore_after_feed_hold) {
|
||||||
if (!restore_condition.spindle[restore_condition.spindle_num].hal->get_state(restore_condition.spindle[restore_condition.spindle_num].hal).on)
|
if (!restore_condition.spindle[restore_condition.spindle_num].hal->get_state(restore_condition.spindle[restore_condition.spindle_num].hal).on)
|
||||||
gc_spindle_off();
|
gc_spindle_off();
|
||||||
sys.override.spindle_stop.value = 0; // Clear spindle stop override states
|
sys.override.spindle_stop.value = 0; // Clear spindle stop override states
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (restore_condition.spindle[restore_condition.spindle_num].state.on != restore_condition.spindle[restore_condition.spindle_num].hal->get_state(restore_condition.spindle[restore_condition.spindle_num].hal).on) {
|
spindle_t *spindle;
|
||||||
|
if((spindle = &restore_condition.spindle[restore_condition.spindle_num])->hal && (spindle->hal->param->option.restore_rpm || spindle->state.on != spindle->hal->get_state(spindle->hal).on)) {
|
||||||
grbl.report.feedback_message(Message_SpindleRestore);
|
grbl.report.feedback_message(Message_SpindleRestore);
|
||||||
state_spindle_restore(&restore_condition.spindle[restore_condition.spindle_num], settings.spindle.on_delay);
|
state_spindle_restore(spindle, settings.spindle.on_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restore_condition.coolant.value != hal.coolant.get_state().value) {
|
if(restore_condition.coolant.value != hal.coolant.get_state().value) {
|
||||||
// NOTE: Laser mode will honor this delay. An exhaust system is often controlled by coolant signals.
|
// NOTE: Laser mode will honor this delay. An exhaust system is often controlled by coolant signals.
|
||||||
coolant_restore(restore_condition.coolant, settings.coolant.on_delay);
|
coolant_restore(restore_condition.coolant, settings.coolant.on_delay);
|
||||||
gc_coolant(restore_condition.coolant);
|
gc_coolant(restore_condition.coolant);
|
||||||
|
|||||||
Reference in New Issue
Block a user