diff --git a/README.md b/README.md
index 43a41df..4b2acf0 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
## grblHAL ##
-Latest build date is 20250116, see the [changelog](changelog.md) for details.
+Latest build date is 20250118, see the [changelog](changelog.md) for details.
> [!NOTE]
> A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended.
@@ -93,4 +93,4 @@ G/M-codes not supported by [legacy Grbl](https://github.com/gnea/grbl/wiki) are
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
---
-20250116
+20250118
diff --git a/changelog.md b/changelog.md
index 3ee0ed8..5cca9d8 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,27 @@
## grblHAL changelog
+Build 20250118
+
+Core:
+
+* Added HAL support for stepper driver status signals \(warning and fault\) and new HAL entry point for querying/resetting driver status.
+
+* Added driver capability flags and settings, `$742` - `$745`, for enabling and inverting motor warning and fault input signals \(per axis\).
+
+* Improved jerk acceleration. Ref. PR [#660](https://github.com/grblHAL/core/pull/660).
+
+Plugins:
+
+* Trinamic: added up to 5 seconds startup delay to allow motor power to come up. Ref. issue [#19](https://github.com/grblHAL/Plugins_motor/issues/19).
+Partially implemended new HAL entry point for querying/resetting driver status.
+
+Drivers:
+
+* STM32F4xx: added driver support for per motor stepper driver fault signals, updated SuperLongBoard EXT map/board specific code to match.
+Fixed issue with homing/hard limits alarm affecting SuperLongBoards.
+
+---
+
Build 20250116
Core:
@@ -11,7 +33,7 @@ Core:
Drivers:
-* STM32F4xx: fixed random freezes when WizNet plugin is enabled for ethernet. Ref. issue [#208](https://github.com/grblHAL/STM32F4xx/issues/208).
+* STM32F4xx: fixed random freezes when WizNet plugin is enabled for ethernet. Ref. issue [#208](https://github.com/grblHAL/STM32F4xx/issues/208).
Added tentative board map for Sienci SuperLongBoard with external drivers \(SLB EXT\) and added support for toolsetter state for both SLB and SLB EXT.
Plugins:
diff --git a/config.h b/config.h
index 9487742..b7683a6 100644
--- a/config.h
+++ b/config.h
@@ -1903,6 +1903,46 @@ For the controller the distance is unitless and and can be in degrees, radians,
#endif
///@}
+/*! @name $742 - Setting_MotorWarningsEnable
+\brief \ref axismask controlling the which motor warning signals to enable.
+Set this value to -1 or AXES_BITMASK to enable for all axes or specify which by mask.
+*/
+///@{
+#if !defined DEFAULT_MOTOR_WARNING_SIGNALS_ENABLE || defined __DOXYGEN__
+#define DEFAULT_MOTOR_WARNING_SIGNALS_ENABLE 0
+#endif
+///@}
+
+/*! @name $743 - Setting_MotorWarningsInvert
+\brief \ref axismask controlling the which motor warning signals to to invert.
+Set this value to -1 or AXES_BITMASK to invert all warning signals or specify for which axes by mask.
+*/
+///@{
+#if !defined DEFAULT_MOTOR_WARNING_SIGNALS_INVERT || defined __DOXYGEN__
+#define DEFAULT_MOTOR_WARNING_SIGNALS_INVERT 0
+#endif
+///@}
+
+/*! @name $744 - Setting_MotorFaultsEnable
+\brief \ref axismask controlling the which motor fault signals to enable.
+Set this value to -1 or AXES_BITMASK to enable for all axes or specify which by mask.
+*/
+///@{
+#if !defined DEFAULT_MOTOR_FAULT_SIGNALS_ENABLE || defined __DOXYGEN__
+#define DEFAULT_MOTOR_FAULT_SIGNALS_ENABLE 0
+#endif
+///@}
+
+/*! @name $745 - Setting_MotorFaultsInvert
+\brief \ref axismask controlling the which motor fault signals to to invert.
+Set this value to -1 or AXES_BITMASK to invert all fault signals or specify for which axes by mask.
+*/
+///@{
+#if !defined DEFAULT_MOTOR_FAULT_SIGNALS_INVERT || defined __DOXYGEN__
+#define DEFAULT_MOTOR_FAULT_SIGNALS_INVERT 0
+#endif
+///@}
+
/*! @name $481 - Setting_AutoReportInterval
Auto status report interval, allowed range is 100 - 1000. Set to 0 to disable.
*/
diff --git a/crossbar.c b/crossbar.c
index 43921f1..5f9862e 100644
--- a/crossbar.c
+++ b/crossbar.c
@@ -3,7 +3,7 @@
Part of grblHAL
- Copyright (c) 2023-2024 Terje Io
+ Copyright (c) 2023-2025 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -33,6 +33,8 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn)
case Input_LimitX_Max:
case Input_LimitX_2:
case Input_HomeX:
+ case Input_MotorFaultX:
+ case Input_MotorFaultX_2:
mask.x = On;
break;
@@ -40,6 +42,8 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn)
case Input_LimitY_Max:
case Input_LimitY_2:
case Input_HomeY:
+ case Input_MotorFaultY:
+ case Input_MotorFaultY_2:
mask.y = On;
break;
@@ -47,6 +51,8 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn)
case Input_LimitZ_Max:
case Input_LimitZ_2:
case Input_HomeZ:
+ case Input_MotorFaultZ:
+ case Input_MotorFaultZ_2:
mask.z = On;
break;
@@ -54,6 +60,7 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn)
case Input_LimitA:
case Input_LimitA_Max:
case Input_HomeA:
+ case Input_MotorFaultA:
mask.a = On;
break;
#endif
@@ -61,6 +68,7 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn)
case Input_LimitB:
case Input_LimitB_Max:
case Input_HomeB:
+ case Input_MotorFaultB:
mask.b = On;
break;
#endif
@@ -68,6 +76,7 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn)
case Input_LimitC:
case Input_LimitC_Max:
case Input_HomeC:
+ case Input_MotorFaultC:
mask.c = On;
break;
#endif
@@ -75,6 +84,7 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn)
case Input_LimitU:
case Input_LimitU_Max:
case Input_HomeU:
+ case Input_MotorFaultU:
mask.u = On;
break;
#endif
@@ -82,6 +92,7 @@ axes_signals_t xbar_fn_to_axismask (pin_function_t fn)
case Input_LimitV:
case Input_LimitV_Max:
case Input_HomeV:
+ case Input_MotorFaultV:
mask.v = On;
break;
#endif
diff --git a/crossbar.h b/crossbar.h
index 7cd4547..2bfc9e5 100644
--- a/crossbar.h
+++ b/crossbar.h
@@ -3,7 +3,7 @@
Part of grblHAL
- Copyright (c) 2021-2024 Terje Io
+ Copyright (c) 2021-2025 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -42,6 +42,17 @@ typedef enum {
Input_ProbeOvertravel,
Input_Probe,
// end control_signals_t sequence
+ Input_MotorFaultX,
+ Input_MotorFaultY,
+ Input_MotorFaultZ,
+ Input_MotorFaultA,
+ Input_MotorFaultB,
+ Input_MotorFaultC,
+ Input_MotorFaultU,
+ Input_MotorFaultV,
+ Input_MotorFaultX_2,
+ Input_MotorFaultY_2,
+ Input_MotorFaultZ_2,
Input_Toolsetter,
Input_ToolsetterOvertravel,
Input_MPGSelect,
@@ -90,7 +101,11 @@ typedef enum {
Input_Aux9,
Input_Aux10,
Input_Aux11,
- Input_AuxMax = Input_Aux11,
+ Input_Aux12,
+ Input_Aux13,
+ Input_Aux14,
+ Input_Aux15,
+ Input_AuxMax = Input_Aux15,
Input_Analog_Aux0,
Input_Analog_Aux1,
Input_Analog_Aux2,
@@ -250,6 +265,12 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_SingleBlock, .name = "Single block" },
{ .function = Input_ProbeOvertravel, .name = "Probe overtravel" },
{ .function = Input_Probe, .name = "Probe" },
+ { .function = Input_MotorFaultX, .name = "X motor fault" },
+ { .function = Input_MotorFaultY, .name = "Y motor fault" },
+ { .function = Input_MotorFaultZ, .name = "Z motor fault" },
+ { .function = Input_MotorFaultX_2, .name = "X motor fault 2" },
+ { .function = Input_MotorFaultY_2, .name = "Y motor fault 2" },
+ { .function = Input_MotorFaultZ_2, .name = "Z motor fault 2" },
{ .function = Input_Toolsetter, .name = "Toolsetter" },
{ .function = Input_ToolsetterOvertravel, .name = "Toolsetter overtravel" },
{ .function = Input_MPGSelect, .name = "MPG mode select" },
@@ -283,6 +304,10 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_Aux9, .name = "Aux in 9" },
{ .function = Input_Aux10, .name = "Aux in 10" },
{ .function = Input_Aux11, .name = "Aux in 11" },
+ { .function = Input_Aux12, .name = "Aux in 12" },
+ { .function = Input_Aux13, .name = "Aux in 13" },
+ { .function = Input_Aux14, .name = "Aux in 14" },
+ { .function = Input_Aux15, .name = "Aux in 15" },
{ .function = Input_Analog_Aux0, .name = "Aux analog in 0" },
{ .function = Input_Analog_Aux1, .name = "Aux analog in 1" },
{ .function = Input_Analog_Aux2, .name = "Aux analog in 2" },
@@ -317,6 +342,7 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_LimitA, .name = "A limit min" },
{ .function = Input_LimitA_Max, .name = "A limit max" },
{ .function = Input_HomeA, .name = "A home" },
+ { .function = Input_MotorFaultA, .name = "A motor fault" },
#endif
#ifdef B_AXIS
{ .function = Output_StepB, .name = "B step" },
@@ -326,6 +352,7 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_LimitB, .name = "B limit min" },
{ .function = Input_LimitB_Max, .name = "B limit max" },
{ .function = Input_HomeB, .name = "B home" },
+ { .function = Input_MotorFaultB, .name = "B motor fault" },
#endif
#ifdef C_AXIS
{ .function = Output_StepC, .name = "C step" },
@@ -334,6 +361,7 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_LimitC, .name = "C limit min" },
{ .function = Input_LimitC_Max, .name = "C limit max" },
{ .function = Input_HomeC, .name = "C home" },
+ { .function = Input_MotorFaultC, .name = "C motor fault" },
#endif
#ifdef U_AXIS
{ .function = Output_StepU, .name = "U step" },
@@ -342,6 +370,7 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_LimitU, .name = "U limit min" },
{ .function = Input_LimitU_Max, .name = "U limit max" },
{ .function = Input_HomeU, .name = "U home" },
+ { .function = Input_MotorFaultU, .name = "U motor fault" },
#endif
#ifdef V_AXIS
{ .function = Output_StepV, .name = "V step" },
@@ -350,6 +379,7 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_LimitV, .name = "V limit min" },
{ .function = Input_LimitV_Max, .name = "V limit max" },
{ .function = Input_HomeV, .name = "V home" },
+ { .function = Input_MotorFaultV, .name = "V motor fault" },
#endif
#ifndef NO_SETTINGS_DESCRIPTIONS
{ .function = Output_MotorChipSelect, .name = "Motor CS" },
@@ -684,6 +714,11 @@ typedef union {
};
} pin_debounce_t;
+static inline uint8_t xbar_fault_pin_to_axis (pin_function_t fn)
+{
+ return fn >= Input_MotorFaultX && fn <= Input_MotorFaultV ? fn - Input_MotorFaultX : (fn >= Input_MotorFaultX_2 && fn <= Input_MotorFaultZ_2 ? fn - Input_MotorFaultX_2 : 0);
+}
+
void xbar_set_homing_source (void);
limit_signals_t xbar_get_homing_source (void);
limit_signals_t xbar_get_homing_source_from_cycle (axes_signals_t homing_cycle);
diff --git a/gcode.c b/gcode.c
index 5f5406a..ac1561f 100644
--- a/gcode.c
+++ b/gcode.c
@@ -51,6 +51,12 @@
#define MACH3_SCALING
+#ifdef NO_SETTINGS_DESCRIPTIONS
+#define GCODE_ADVANCED 0
+#else
+#define GCODE_ADVANCED 1
+#endif
+
// Do not change, must be same as axis indices
#define I_VALUE X_AXIS
#define J_VALUE Y_AXIS
@@ -117,7 +123,6 @@ parser_state_t gc_state;
#define FAIL(status) return(status);
-static gc_thread_data thread;
static output_command_t *output_commands = NULL; // Linked list
static scale_factor_t scale_factor = {
.ijk[X_AXIS] = 1.0f,
@@ -492,6 +497,10 @@ static bool add_output_command (output_command_t *command)
return add_cmd != NULL;
}
+#if GCODE_ADVANCED
+
+static gc_thread_data thread;
+
static status_code_t init_sync_motion (plan_line_data_t *pl_data, float pitch)
{
if(pl_data->spindle.hal->get_data == NULL)
@@ -519,6 +528,8 @@ static status_code_t init_sync_motion (plan_line_data_t *pl_data, float pitch)
return Status_OK;
}
+#endif // GCODE_ADVANCED
+
// Output and free previously allocated message
void gc_output_message (char *message)
{
@@ -698,6 +709,8 @@ status_code_t gc_execute_block (char *block)
#endif
};
+#if GCODE_ADVANCED
+
static const parameter_words_t pq_words = {
.p = On,
.q = On
@@ -708,6 +721,8 @@ status_code_t gc_execute_block (char *block)
.j = On
};
+#endif
+
static const parameter_words_t positive_only_words = {
.d = On,
.f = On,
@@ -1053,7 +1068,7 @@ status_code_t gc_execute_block (char *block)
mantissa = 0; // Set to zero to indicate valid non-integer G command.
}
break;
-
+#if GCODE_ADVANCED
case 33: case 76:
if(mantissa != 0)
FAIL(Status_GcodeUnsupportedCommand); // [G33.1 not yet supported]
@@ -1066,7 +1081,7 @@ status_code_t gc_execute_block (char *block)
// gc_block.modal.motion = MotionMode_RigidTapping;
gc_block.modal.canned_cycle_active = false;
break;
-
+#endif
case 38:
if(!(hal.probe.get_state && ((mantissa == 20) || (mantissa == 30) || (mantissa == 40) || (mantissa == 50))))
FAIL(Status_GcodeUnsupportedCommand); // [probing not supported by driver or unsupported G38.x command]
@@ -1074,7 +1089,10 @@ status_code_t gc_execute_block (char *block)
mantissa = 0; // Set to zero to indicate valid non-integer G command.
// No break. Continues to next line.
- case 0: case 1: case 2: case 3: case 5:
+ case 0: case 1: case 2: case 3:
+#if GCODE_ADVANCED
+ case 5:
+#endif
// Check for G0/1/2/3/38 being called with G10/28/30/92 on same block.
// * G43.1 is also an axis command but is not explicitly defined this way.
if (axis_command)
@@ -1094,7 +1112,7 @@ status_code_t gc_execute_block (char *block)
gc_block.modal.motion = (motion_mode_t)int_value;
gc_block.modal.canned_cycle_active = false;
break;
-
+#if GCODE_ADVANCED
case 73: case 81: case 82: case 83: case 85: case 86: case 89:
if (axis_command)
FAIL(Status_GcodeAxisCommandConflict); // [Axis word/command conflict]
@@ -1104,7 +1122,7 @@ status_code_t gc_execute_block (char *block)
gc_block.modal.motion = (motion_mode_t)int_value;
gc_parser_flags.canned_cycle_change = gc_block.modal.motion != gc_state.modal.motion;
break;
-
+#endif
case 17: case 18: case 19:
word_bit.modal_group.G2 = On;
gc_block.modal.plane_select = (plane_select_t)(int_value - 17);
@@ -2562,6 +2580,8 @@ status_code_t gc_execute_block (char *block)
if(gc_block.spindle_modal.rpm_mode == SpindleSpeedMode_CSS && (!gc_block.spindle_modal.state.on || gc_block.values.s == 0.0f))
FAIL(Status_GcodeSpindleNotRunning);
+#if GCODE_ADVANCED
+
// Check if feed rate is defined for the motion modes that require it.
if(gc_block.modal.motion == MotionMode_SpindleSynchronized) {
@@ -2666,10 +2686,10 @@ status_code_t gc_execute_block (char *block)
gc_block.words.e = gc_block.words.h = gc_block.words.i = gc_block.words.j = gc_block.words.k = gc_block.words.l = gc_block.words.p = gc_block.words.q = gc_block.words.r = Off;
- } else if (gc_block.values.f == 0.0f)
+ } else if(gc_block.values.f == 0.0f)
FAIL(Status_GcodeUndefinedFeedRate); // [Feed rate undefined]
- if (gc_block.modal.canned_cycle_active) {
+ if(gc_block.modal.canned_cycle_active) {
if(gc_parser_flags.canned_cycle_change) {
@@ -2757,8 +2777,15 @@ status_code_t gc_execute_block (char *block)
break;
} // end switch gc_state.canned.motion
+ } else
+#else
- } else switch (gc_block.modal.motion) {
+ if(gc_block.values.f == 0.0f)
+ FAIL(Status_GcodeUndefinedFeedRate); // [Feed rate undefined]
+
+#endif // GCODE_ADVANCED
+
+ switch (gc_block.modal.motion) {
case MotionMode_Linear:
// [G1 Errors]: Feed rate undefined. Axis letter not configured or without real value.
@@ -2950,6 +2977,8 @@ status_code_t gc_execute_block (char *block)
}
break;
+#if GCODE_ADVANCED
+
case MotionMode_CubicSpline:
// [G5 Errors]: Feed rate undefined.
// [G5 Plane Errors]: The active plane is not G17.
@@ -3030,6 +3059,8 @@ status_code_t gc_execute_block (char *block)
gc_block.words.i = gc_block.words.j = Off;
break;
+#endif // GCODE_ADVANCED
+
case MotionMode_ProbeTowardNoError:
case MotionMode_ProbeAwayNoError:
gc_parser_flags.probe_is_no_error = On;
@@ -3720,6 +3751,8 @@ status_code_t gc_execute_block (char *block)
plane, gc_parser_flags.arc_is_clockwise ? -gc_block.arc_turns : gc_block.arc_turns);
break;
+#if GCODE_ADVANCED
+
case MotionMode_CubicSpline:
{
point_2d_t cp1 = {
@@ -3792,6 +3825,8 @@ status_code_t gc_execute_block (char *block)
mc_canned_drill(gc_state.modal.motion, gc_block.values.xyz, &plan_data, gc_state.position, plane, gc_block.values.l, &gc_state.canned);
break;
+#endif // GCODE_ADVANCED
+
case MotionMode_ProbeToward:
case MotionMode_ProbeTowardNoError:
case MotionMode_ProbeAway:
diff --git a/grbl.h b/grbl.h
index c88fdd7..bd9b79c 100644
--- a/grbl.h
+++ b/grbl.h
@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
-#define GRBL_BUILD 20250116
+#define GRBL_BUILD 20250118
#define GRBL_URL "https://github.com/grblHAL"
diff --git a/hal.h b/hal.h
index c7fd106..5411e53 100644
--- a/hal.h
+++ b/hal.h
@@ -3,7 +3,7 @@
Part of grblHAL
- Copyright (c) 2016-2024 Terje Io
+ Copyright (c) 2016-2025 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -314,6 +314,13 @@ typedef axes_signals_t (*stepper_get_ganged_ptr)(bool auto_squared);
*/
typedef void (*stepper_claim_motor_ptr)(uint_fast8_t axis_id, bool claim);
+/*! \brief Pointer to function for querying or resetting stepper driver status.
+
+\param reset \a true to reset status, \a false to query it.
+\returns stepper driver warning and fault status in a \a stepper_status_t struct.
+*/
+typedef stepper_status_t (*stepper_status_ptr)(bool reset);
+
/*! \brief Pointer to callback function for outputting the next direction and step pulse signals. _Set by the core on startup._
To be called by the driver from the main stepper interrupt handler (when the timer times out).
@@ -333,6 +340,7 @@ typedef struct {
stepper_claim_motor_ptr claim_motor; //!< Optional handler for claiming/releasing motor(s) from normal step/dir control.
stepper_output_step_ptr output_step; //!< Optional handler for outputting a single step pulse. _Experimental._ Called from interrupt context.
motor_iterator_ptr motor_iterator; //!< Optional handler iteration over motor vs. axis mappings. Required for the motors plugin (Trinamic drivers).
+ stepper_status_ptr stepper_status; //!< Optional handler handler for querying steppper driver status or attempting to reset it.
} stepper_ptrs_t;
@@ -662,7 +670,8 @@ typedef struct {
limit_signals_t limits_cap; //!< Limit input signals supported by the driver.
home_signals_t home_cap; //!< Home input signals supported by the driver.
coolant_state_t coolant_cap; //!< Coolant outputs supported by the driver.
-
+ home_signals_t motor_warning_cap; //!< Motor warning input signals (per motor) supported by the driver.
+ home_signals_t motor_fault_cap; //!< Motor fault input signals (per motor) supported by the driver.
} grbl_hal_t;
extern grbl_hal_t hal; //!< Global HAL struct.
diff --git a/motor_pins.h b/motor_pins.h
index 9254595..44bdfa8 100644
--- a/motor_pins.h
+++ b/motor_pins.h
@@ -5,7 +5,7 @@
Part of grblHAL
- Copyright (c) 2021-2024 Terje Io
+ Copyright (c) 2021-2025 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -98,6 +98,11 @@
#define X2_ENABLE_PIN M3_ENABLE_PIN
#define X2_ENABLE_BIT (1<