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<