Fix for issue #191, allow homing of rotary axes with infinite rotation (max travel = 0)

Added spindle type property to HAL, "hardened" code.
Added new setting $346 for action to take after tool change: either return controlled point (tool tip) back to the same position as before the M6 command (default) or move spindle to Z home.
This commit is contained in:
Terje Io
2022-10-21 11:50:00 +02:00
parent 2f42b7226b
commit 893f0de66a
17 changed files with 151 additions and 49 deletions
+3 -3
View File
@@ -1,6 +1,6 @@
## grblHAL ##
__New:__ The core now has support for up to 8 axes, and for 4-6 axes configurations ABC axis letters can be remapped to UVW.
__New:__ A web app for [building for some drivers](http://svn.io-engineering.com:8080/) is now in the works, feedback will be appreciated.
grblHAL has [many extensions](https://github.com/grblHAL/core/wiki) that may cause issues with some senders. As a workaround for these a [compile time option](https://github.com/grblHAL/core/wiki/Changes-from-grbl-1.1#workaround) has been added that disables extensions selectively.
@@ -13,7 +13,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
---
Latest build date is 20221005, see the [changelog](changelog.md) for details.
Latest build date is 20221018, see the [changelog](changelog.md) for details.
__NOTE:__ A settings reset will be performed on an update for versions earlier than 20211122. Backup and restore of settings is recommended.
__IMPORTANT!__ A new setting has been introduced for ganged axes motors in version 20211121.
I have only bench tested this for a couple of drivers, correct function should be verified after updating by those who have more than three motors configured.
@@ -86,4 +86,4 @@ List of Supported G-Codes:
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
---
2022-10-07
2022-10-21
+32 -1
View File
@@ -1,10 +1,41 @@
## grblHAL changelog
Build 202210118
Core:
* Added new setting `$346` for action to take after tool change: either return controlled point \(tool tip\) back to the same position as before the M6 command \(default\) or move spindle to Z home only.
* Added spindle type property to HAL, "hardened" code.
* Fix for issue #191, allow homing of rotary axes with infinite rotation \(max travel = 0\).
Plugins:
* Spindle: Added spindle type property to registration data.
* Fans: Bug fix, added off delay option for fan 0 with setting `$480` specifying number of minutes to delay. Useful for allowing an exhaust fan to clear a laser cutter enclosure before turning it off.
__Note:__ The new setting may cause a reset of other plugin settings to default values, backup and restore.
* Laser coolant: implemented off delay and coolant lost monitoring.
Drivers:
* STM32F4xx: Fix for [issue #99](https://github.com/grblHAL/STM32F4xx/issues/99). Updated spindle registration.
* SAM3X8E: Fix for [issue #15](https://github.com/grblHAL/SAM3X8E/issues/15).
* Many: Improved driver PWM spindle code.
* Some: Updated for [Web Builder](http://svn.io-engineering.com:8080/) requirements.
---
Build 20221009
Core:
* Fix for bug preventing some hosts (Win7) querying SSDP information.
* Fix for bug preventing some hosts \(Win7\) querying SSDP information.
Plugins:
+2
View File
@@ -68,6 +68,7 @@ typedef bool (*enqueue_gcode_ptr)(char *data);
typedef bool (*protocol_enqueue_realtime_command_ptr)(char c);
typedef void (*on_state_change_ptr)(sys_state_t state);
typedef void (*on_spindle_programmed_ptr)(spindle_state_t spindle, float rpm, spindle_rpm_mode_t mode);
typedef void (*on_program_completed_ptr)(program_flow_t program_flow, bool check_mode);
typedef void (*on_execute_realtime_ptr)(sys_state_t state);
typedef void (*on_unknown_accessory_override_ptr)(uint8_t cmd);
@@ -99,6 +100,7 @@ typedef struct {
// grbl core events - may be subscribed to by drivers or by the core.
on_state_change_ptr on_state_change;
on_report_handlers_init_ptr on_report_handlers_init;
on_spindle_programmed_ptr on_spindle_programmed;
on_program_completed_ptr on_program_completed;
on_execute_realtime_ptr on_execute_realtime;
on_execute_realtime_ptr on_execute_delay;
+2 -2
View File
@@ -372,12 +372,12 @@
#define NETWORK_AP_HOSTNAME "grblHAL_AP"
#endif
#ifndef NETWORK_AP_IPMODE
#define NETWORK_AP_IPMODE 0 // 0 = static, 1 = DHCP, 2 = AutoIP
#define NETWORK_AP_IPMODE 0 // static
#endif
#ifndef NETWORK_AP_IP
#define NETWORK_AP_IP "192.168.5.1"
#endif
#ifndef NETWORK_AP_GATEWAYs
#ifndef NETWORK_AP_GATEWAY
#define NETWORK_AP_GATEWAY "192.168.5.1"
#endif
#ifndef NETWORK_AP_MASK
+7 -2
View File
@@ -609,7 +609,7 @@ status_code_t gc_execute_block(char *block)
memset(&gc_block, 0, sizeof(gc_block)); // Initialize the parser block struct.
memcpy(&gc_block.modal, &gc_state.modal, sizeof(gc_state.modal)); // Copy current modes
bool set_tool = false;
bool set_tool = false, spindle_programmed = false;
axis_command_t axis_command = AxisCommand_None;
uint_fast8_t port_command = 0;
plane_t plane;
@@ -1437,6 +1437,8 @@ status_code_t gc_execute_block(char *block)
gc_state.modal.spindle_rpm_mode = gc_block.modal.spindle_rpm_mode;
}
spindle_programmed = gc_block.words.s && !user_words.s;
if (!gc_block.words.s)
gc_block.values.s = gc_state.modal.spindle_rpm_mode == SpindleSpeedMode_RPM ? gc_state.spindle.rpm : gc_state.spindle.css.surface_speed;
else if(!user_words.s && gc_state.modal.spindle_rpm_mode == SpindleSpeedMode_CSS)
@@ -2698,10 +2700,13 @@ status_code_t gc_execute_block(char *block)
// Update spindle control and apply spindle speed when enabling it in this block.
// NOTE: All spindle state changes are synced, even in laser mode. Also, plan_data,
// rather than gc_state, is used to manage laser state for non-laser motions.
if(spindle_sync(0, gc_block.modal.spindle, plan_data.spindle.rpm))
if((spindle_programmed = spindle_sync(0, gc_block.modal.spindle, plan_data.spindle.rpm)))
gc_state.modal.spindle = gc_block.modal.spindle;
}
if(spindle_programmed && grbl.on_spindle_programmed)
grbl.on_spindle_programmed(gc_state.modal.spindle, gc_state.spindle.rpm, gc_state.modal.spindle_rpm_mode);
// TODO: Recheck spindle running in CCS mode (is_rpm_pos_adjusted = On)?
plan_data.condition.spindle = gc_state.modal.spindle; // Set condition flag for planner use.
+1 -1
View File
@@ -34,7 +34,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20221009
#define GRBL_BUILD 20221018
#define GRBL_URL "https://github.com/grblHAL"
+1
View File
@@ -135,6 +135,7 @@ int grbl_enter (void)
nvs_buffer_alloc(); // Allocate memory block for NVS buffer
#endif
settings_clear();
report_init_fns();
#ifdef KINEMATICS_API
+12 -3
View File
@@ -272,14 +272,23 @@ static bool limits_homing_cycle (axes_signals_t cycle, axes_signals_t auto_squar
step_pin[idx] = bit(idx);
#endif
// Set target based on max_travel setting. Ensure homing switches engaged with search scalar.
// NOTE: settings.max_travel[] is stored as a negative value.
if (bit_istrue(cycle.mask, bit(idx))) {
max_travel = max(max_travel,(-HOMING_AXIS_SEARCH_SCALAR) * settings.axis[idx].max_travel);
// NOTE: settings.axis[].max_travel is stored as a negative value.
if(bit_istrue(cycle.mask, bit(idx))) {
#if N_AXIS > 3
if(bit_istrue(settings.steppers.is_rotational.mask, bit(idx)))
max_travel = max(max_travel, (-HOMING_AXIS_SEARCH_SCALAR) * (settings.axis[idx].max_travel < -0.0f ? settings.axis[idx].max_travel : -360.0f));
else
#endif
max_travel = max(max_travel, (-HOMING_AXIS_SEARCH_SCALAR) * settings.axis[idx].max_travel);
if(bit_istrue(auto_square.mask, bit(idx)))
dual_motor_axis = idx;
}
} while(idx);
if(max_travel == 0.0f)
return true;
if(auto_square.mask) {
float fail_distance = (-settings.homing.dual_axis.fail_length_percent / 100.0f) * settings.axis[dual_motor_axis].max_travel;
fail_distance = min(fail_distance, settings.homing.dual_axis.fail_distance_max);
-1
View File
@@ -196,6 +196,5 @@ typedef struct {
} nvs_transfer_t;
extern nvs_transfer_result_t i2c_nvs_transfer (nvs_transfer_t *i2c, bool read);
extern void my_plugin_init (void);
#endif
+1
View File
@@ -85,6 +85,7 @@
webui_init();
#endif
extern void my_plugin_init (void);
my_plugin_init();
// Third party plugin definitions.
+2 -2
View File
@@ -407,7 +407,7 @@ bool protocol_exec_rt_system (void)
if (sys.rt_exec_alarm && (rt_exec = system_clear_exec_alarm())) { // Enter only if any bit flag is true
if(sys.rt_exec_state & EXEC_RESET) {
if((sys.reset_pending = !!(sys.rt_exec_state & EXEC_RESET))) {
// Kill spindle and coolant.
killed = true;
hal.spindle.set_state((spindle_state_t){0}, 0.0f);
@@ -463,7 +463,7 @@ bool protocol_exec_rt_system (void)
if (sys.rt_exec_state && (rt_exec = system_clear_exec_states())) { // Get and clear volatile sys.rt_exec_state atomically.
// Execute system abort.
if (rt_exec & EXEC_RESET) {
if((sys.reset_pending = !!(rt_exec & EXEC_RESET))) {
if(!killed) {
// Kill spindle and coolant.
+25 -1
View File
@@ -122,7 +122,7 @@ PROGMEM const settings_t defaults = {
#endif
.steppers.deenergize.mask = ST_DEENERGIZE_MASK,
#if N_AXIS > 3
.steppers.is_rotational.mask = (ST_ROTATIONAL_MASK & AXES_BITMASK) >> 3,
.steppers.is_rotational.mask = (ST_ROTATIONAL_MASK & AXES_BITMASK) & 0b11111000,
#endif
#if DEFAULT_HOMING_ENABLE
.homing.flags.enabled = DEFAULT_HOMING_ENABLE,
@@ -378,6 +378,7 @@ static status_code_t set_force_initialization_alarm (setting_id_t id, uint_fast1
static status_code_t set_probe_allow_feed_override (setting_id_t id, uint_fast16_t int_value);
static status_code_t set_tool_change_mode (setting_id_t id, uint_fast16_t int_value);
static status_code_t set_tool_change_probing_distance (setting_id_t id, float value);
static status_code_t set_tool_restore_pos (setting_id_t id, uint_fast16_t int_value);
static status_code_t set_ganged_dir_invert (setting_id_t id, uint_fast16_t int_value);
static status_code_t set_stepper_deenergize_mask (setting_id_t id, uint_fast16_t int_value);
#ifndef NO_SAFETY_DOOR_SUPPORT
@@ -532,6 +533,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_ToolChangeFeedRate, Group_Toolchange, "Tool change locate feed rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.feed_rate, NULL, NULL },
{ Setting_ToolChangeSeekRate, Group_Toolchange, "Tool change search seek rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.seek_rate, NULL, NULL },
{ Setting_ToolChangePulloffRate, Group_Toolchange, "Tool change probe pull-off rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.pulloff_rate, NULL, NULL },
{ Setting_ToolChangeRestorePosition, Group_Toolchange, "Restore position after M6", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_tool_restore_pos, get_int, NULL },
{ Setting_DualAxisLengthFailPercent, Group_Limits_DualAxis, "Dual axis length fail", "percent", Format_Decimal, "##0.0", "0", "100", Setting_IsExtended, &settings.homing.dual_axis.fail_length_percent, NULL, is_setting_available },
{ Setting_DualAxisLengthFailMin, Group_Limits_DualAxis, "Dual axis length fail min", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtended, &settings.homing.dual_axis.fail_distance_min, NULL, is_setting_available },
{ Setting_DualAxisLengthFailMax, Group_Limits_DualAxis, "Dual axis length fail max", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtended, &settings.homing.dual_axis.fail_distance_max, NULL, is_setting_available },
@@ -703,6 +705,7 @@ PROGMEM static const setting_descr_t setting_descr[] = {
{ Setting_ToolChangeFeedRate, "Feed rate to slowly engage tool change sensor to determine the tool offset accurately." },
{ Setting_ToolChangeSeekRate, "Seek rate to quickly find the tool change sensor before the slower locating phase." },
{ Setting_ToolChangePulloffRate, "Pull-off rate for the retract move before the slower locating phase." },
{ Setting_ToolChangeRestorePosition, "When set the spindle is moved so that the controlled point (tool tip) is the same as before the M6 command, if not the spindle is only moved to the Z home position." },
{ Setting_DualAxisLengthFailPercent, "Dual axis length fail in percent of axis max travel." },
{ Setting_DualAxisLengthFailMin, "Dual axis length fail minimum distance." },
{ Setting_DualAxisLengthFailMax, "Dual axis length fail minimum distance." },
@@ -1123,6 +1126,16 @@ static status_code_t set_tool_change_probing_distance (setting_id_t id, float va
return Status_OK;
}
static status_code_t set_tool_restore_pos (setting_id_t id, uint_fast16_t int_value)
{
if(hal.driver_cap.atc)
return Status_InvalidStatement;
settings.flags.no_restore_position_after_M6 = int_value == 0;
return Status_OK;
}
#if N_AXIS > 3
static status_code_t set_rotational_axes (setting_id_t id, uint_fast16_t int_value)
{
@@ -1441,6 +1454,10 @@ static uint32_t get_int (setting_id_t id)
value = settings.tool_change.mode;
break;
case Setting_ToolChangeRestorePosition:
value = settings.flags.no_restore_position_after_M6 ? 0 : 1;
break;
case Setting_DisableG92Persistence:
value = settings.flags.g92_is_volatile;
break;
@@ -2486,6 +2503,13 @@ bool settings_add_spindle_type (const char *type)
return ok;
}
// Clear settings chain
void settings_clear (void)
{
setting_details.next = NULL;
settingsd = &setting_details;
}
// Initialize the config subsystem
void settings_init (void)
{
+8 -1
View File
@@ -212,6 +212,7 @@ typedef enum {
Setting_ToolChangeFeedRate = 343,
Setting_ToolChangeSeekRate = 344,
Setting_ToolChangePulloffRate = 345,
Setting_ToolChangeRestorePosition = 346,
Setting_DualAxisLengthFailPercent = 347,
Setting_DualAxisLengthFailMin = 348,
@@ -299,6 +300,8 @@ typedef enum {
Setting_VFD_20 = 472,
Setting_VFD_21 = 473,
Setting_Fan0OffDelay = 480,
Setting_SettingsMax,
Setting_SettingsAll = Setting_SettingsMax,
@@ -362,7 +365,8 @@ typedef union {
unused1 :1,
g92_is_volatile :1,
compatibility_level :4,
unassigned :2;
no_restore_position_after_M6 :1,
unassigned :1;
};
} settingflags_t;
@@ -770,6 +774,9 @@ typedef setting_details_t *(*on_get_settings_ptr)(void);
extern settings_t settings;
// Clear settings chain (unlinks plugin/driver settings from core settings)
void settings_clear (void);
// Initialize the configuration subsystem (load settings from persistent storage)
void settings_init();
+36 -27
View File
@@ -33,13 +33,14 @@
#endif
static uint8_t n_spindle = 0;
static const spindle_ptrs_t *spindles[N_SPINDLE];
static spindle_id_t current_spindle = 0;
static const spindle_ptrs_t *spindles[N_SPINDLE], *current_spindle = NULL;
spindle_id_t spindle_register (const spindle_ptrs_t *spindle, const char *name)
{
if(n_spindle == 0)
if(n_spindle == 0) {
memcpy(&hal.spindle, spindle, sizeof(spindle_ptrs_t));
current_spindle = spindle;
}
if(n_spindle < N_SPINDLE && settings_add_spindle_type(name)) {
spindles[n_spindle++] = spindle;
@@ -56,39 +57,36 @@ bool spindle_select (spindle_id_t spindle_id)
if(n_spindle == 0) {
if(hal.spindle.set_state)
spindles[n_spindle++] = &hal.spindle;
spindles[n_spindle++] = current_spindle = &hal.spindle;
else
spindle_add_null();
}
if((ok = spindle_id >= 0 && spindle_id < n_spindle)) {
if(hal.spindle.set_state && hal.spindle.set_state != spindles[spindle_id]->set_state)
spindle_ptrs_t spindle_org;
if(hal.spindle.set_state && current_spindle != spindles[spindle_id])
gc_spindle_off();
if(ok) {
memcpy(&spindle_org, &hal.spindle, offsetof(spindle_ptrs_t, get_data));
memcpy(&hal.spindle, spindles[spindle_id], offsetof(spindle_ptrs_t, get_data));
spindle_ptrs_t spindle_org;
memcpy(&spindle_org, &hal.spindle, offsetof(spindle_ptrs_t, get_data));
memcpy(&hal.spindle, spindles[spindle_id], offsetof(spindle_ptrs_t, get_data));
if(!hal.spindle.cap.rpm_range_locked) {
hal.spindle.rpm_min = settings.spindle.rpm_min;
hal.spindle.rpm_max = settings.spindle.rpm_max;
}
if(hal.spindle.config)
ok = hal.spindle.config();
if(ok) {
current_spindle = spindle_id;
sys.mode = settings.mode == Mode_Laser && !hal.spindle.cap.laser ? Mode_Standard : settings.mode;
if(grbl.on_spindle_select)
grbl.on_spindle_select(spindle_id);
} else
memcpy(&spindle_org, &hal.spindle, offsetof(spindle_ptrs_t, get_data));
if(!hal.spindle.cap.rpm_range_locked) {
hal.spindle.rpm_min = settings.spindle.rpm_min;
hal.spindle.rpm_max = settings.spindle.rpm_max;
}
if(hal.spindle.config)
ok = hal.spindle.config();
if(ok) {
current_spindle = spindles[spindle_id];
sys.mode = settings.mode == Mode_Laser && !hal.spindle.cap.laser ? Mode_Standard : settings.mode;
if(grbl.on_spindle_select)
grbl.on_spindle_select(spindle_id);
} else
memcpy(&spindle_org, &hal.spindle, offsetof(spindle_ptrs_t, get_data));
}
return ok;
@@ -104,7 +102,14 @@ const spindle_ptrs_t *spindle_get (spindle_id_t spindle_id)
spindle_id_t spindle_get_current (void)
{
return current_spindle;
spindle_id_t spindle_id = spindle_get_count();
do {
if(spindles[--spindle_id] == current_spindle)
break;
} while(spindle_id);
return spindle_id;
}
spindle_cap_t spindle_get_caps (void)
@@ -123,6 +128,7 @@ spindle_cap_t spindle_get_caps (void)
void spindle_update_caps (spindle_pwm_t *pwm_caps)
{
hal.spindle.type = pwm_caps ? SpindleType_PWM : SpindleType_Basic;
hal.spindle.cap.laser = !!pwm_caps && !!hal.spindle.update_pwm;
hal.spindle.pwm_off_value = pwm_caps ? pwm_caps->off_value : 0;
sys.mode = settings.mode == Mode_Laser && !hal.spindle.cap.laser ? Mode_Standard : settings.mode;
@@ -172,6 +178,7 @@ static void null_update_rpm (float rpm)
void spindle_add_null (void)
{
static const spindle_ptrs_t spindle = {
.type = SpindleType_Null,
.cap.variable = Off,
.cap.at_speed = Off,
.cap.direction = Off,
@@ -203,6 +210,8 @@ void spindle_set_override (uint_fast8_t speed_override)
else
sys.step_control.update_spindle_rpm = On;
sys.report.overrides = On; // Set to report change immediately
if(grbl.on_spindle_programmed)
grbl.on_spindle_programmed(gc_state.modal.spindle, spindle_set_rpm(gc_state.spindle.rpm, sys.override.spindle_rpm), gc_state.modal.spindle_rpm_mode);
}
}
+9
View File
@@ -75,6 +75,14 @@ typedef enum {
SpindleData_AngularPosition //!< 2
} spindle_data_request_t;
typedef enum {
SpindleType_PWM, //!< 0
SpindleType_Basic, //!< 1 - on/off + optional direction
SpindleType_VFD, //!< 2
SpindleType_Solenoid, //!< 3
SpindleType_Null, //!< 4
} spindle_type_t;
/*! \brief Pointer to function for configuring the spindle.
\returns state in a \a spindle_state_t union variable.
*/
@@ -134,6 +142,7 @@ typedef void (*spindle_pulse_on_ptr)(uint_fast16_t pulse_length);
//! Handlers for spindle support.
typedef struct {
spindle_type_t type; //!< Spindle type.
spindle_cap_t cap; //!< Spindle capabilities.
uint_fast16_t pwm_off_value; //!< Value for switching PWM signal off.
float rpm_min; //!< Minimum spindle RPM.
+1
View File
@@ -227,6 +227,7 @@ typedef struct system {
bool cancel; //!< System cancel flag.
bool suspend; //!< System suspend state flag.
bool position_lost; //!< Set when mc_reset is called when machine is moving.
bool reset_pending; //!< Set when reset processing is underway.
volatile bool steppers_deenergize; //!< Set to true to deenergize stepperes
axes_signals_t tlo_reference_set; //!< Axes with tool length reference offset set
int32_t tlo_reference[N_AXIS]; //!< Tool length reference offset
+9 -5
View File
@@ -117,9 +117,11 @@ static bool restore (void)
target.values[plane.axis_linear] = tool_change_position;
mc_line(target.values, &plan_data);
memcpy(&target, &previous, sizeof(coord_data_t));
target.values[plane.axis_linear] = tool_change_position;
mc_line(target.values, &plan_data);
if(!settings.flags.no_restore_position_after_M6) {
memcpy(&target, &previous, sizeof(coord_data_t));
target.values[plane.axis_linear] = tool_change_position;
mc_line(target.values, &plan_data);
}
if(protocol_buffer_synchronize()) {
@@ -128,8 +130,10 @@ static bool restore (void)
coolant_sync(gc_state.modal.coolant);
spindle_restore(gc_state.modal.spindle, gc_state.spindle.rpm);
previous.values[plane.axis_linear] += gc_get_offset(plane.axis_linear);
mc_line(previous.values, &plan_data);
if(!settings.flags.no_restore_position_after_M6) {
previous.values[plane.axis_linear] += gc_get_offset(plane.axis_linear);
mc_line(previous.values, &plan_data);
}
}
if(protocol_buffer_synchronize()) {