diff --git a/README.md b/README.md index 83c5c1e..d8a900f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ It has been written to complement grblHAL and has features such as proper keyboa --- -Latest build date is 20220111, see the [changelog](changelog.md) for details. +Latest build date is 20220123, 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. @@ -83,4 +83,4 @@ List of Supported G-Codes: Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes. --- -2022-01-11 +2022-01-23 diff --git a/changelog.md b/changelog.md index af3a5d9..ba58a24 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,27 @@ ## grblHAL changelog +Build 20220123: + +Core: + +* The symbol `ENABLE_SAFETY_DOOR_INPUT_PIN` in _grbl/config.h_ has been replaced with `SAFETY_DOOR_ENABLE` in _my_machine.h_. +* Changed probe touch off handling to reduce deceleration overshoot. +Uncomment `//#define MINIMIZE_PROBE_OVERSHOOT` in _grbl/stepper.c_ to enable this feature. +Later it may be permanently enabled if no side-effects are experienced, test with care! + +Drivers: + +* Most: Added `\\#define SAFETY_DOOR_ENABLE 1` to options in _my_machine.h_, uncomment to enable. Requires board support for safety door input. +* RP2040: Added pin map and support code for the [C.ITOH CX-6000 plotter project](https://hackaday.io/project/183600-citoh-cx-6000-plotter-upgrade). Uses the HPGL and keypad plugins. +* RP2040: Added tentative support for BTT SKR Pico 1.0 board. Incomplete and untested! +* LPC176x: Made TMC2209 UART driver support for BTT SKR E3 Turbo board available for BTT SKR V1.4 Turbo, still untested! + +Templates: + +* Added [HPGL template plugin](https://github.com/grblHAL/Templates/tree/master/my_plugin/hpgl). Replaces the G-code parser with a HPGL parser and is a good example of grblHAL programmability. _Not a single line of code was changed in the core for this!_ + +--- + Build 20220111: Core: diff --git a/config.h b/config.h index d3a9fff..b4e8c0e 100644 --- a/config.h +++ b/config.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2020-2021 Terje Io + Copyright (c) 2020-2022 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -81,12 +81,6 @@ __NOTE:__ if switching to a level > 1 please reset non-volatile storage with \a // the speed is not limited to 115200 baud. An example is native USB streaming. //#define CHECK_MODE_DELAY 0 // ms -// This option enables the safety door switch. A safety door, when triggered, -// immediately forces a feed hold and then safely de-energizes the machine. Resuming is blocked until -// the safety door is re-engaged. When it is, Grbl will re-energize the machine and then resume on the -// previous tool path, as if nothing happened. -//#define ENABLE_SAFETY_DOOR_INPUT_PIN // Default disabled. Uncomment to enable. - // After the safety door switch has been toggled and restored, this setting sets the power-up delay // between restoring the spindle and coolant and resuming the cycle. //#define SAFETY_DOOR_SPINDLE_DELAY 4.0f // Float (seconds) diff --git a/core_handlers.h b/core_handlers.h index 6eb9221..a7649ec 100644 --- a/core_handlers.h +++ b/core_handlers.h @@ -31,6 +31,7 @@ #include "errors.h" #include "settings.h" #include "report.h" +#include "planner.h" /* TODO: add to grbl pointers so that a different formatting (xml, json etc) of reports may be implemented by driver? typedef struct { @@ -63,13 +64,10 @@ typedef struct { // Core event handler and other entry points. // Most of the event handlers defaults to NULL, a few is set up to call a dummy handler for simpler code. -// Trying to force a submodule update... - 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_probe_completed_ptr)(void); 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); @@ -83,6 +81,8 @@ typedef void (*on_stream_changed_ptr)(stream_type_t type); typedef bool (*on_laser_ppi_enable_ptr)(uint_fast16_t ppi, uint_fast16_t pulse_length); typedef void (*on_homing_rate_set_ptr)(axes_signals_t axes, float rate, bool pulloff); typedef bool (*on_probe_fixture_ptr)(tool_data_t *tool, bool at_g59_3, bool on); +typedef bool (*on_probe_start_ptr)(axes_signals_t axes, float *target, plan_line_data_t *pl_data); +typedef void (*on_probe_completed_ptr)(void); typedef bool (*on_spindle_select_ptr)(uint_fast8_t spindle_id); typedef status_code_t (*on_unknown_sys_command_ptr)(sys_state_t state, char *line); // return Status_Unhandled. typedef status_code_t (*on_user_command_ptr)(char *line); @@ -93,7 +93,6 @@ typedef struct { report_t report; // grbl core events - may be subscribed to by drivers or by the core. on_state_change_ptr on_state_change; - on_probe_completed_ptr on_probe_completed; on_program_completed_ptr on_program_completed; on_execute_realtime_ptr on_execute_realtime; on_execute_realtime_ptr on_execute_delay; @@ -113,6 +112,8 @@ typedef struct { on_stream_changed_ptr on_stream_changed; on_homing_rate_set_ptr on_homing_rate_set; on_probe_fixture_ptr on_probe_fixture; + on_probe_start_ptr on_probe_start; + on_probe_completed_ptr on_probe_completed; on_laser_ppi_enable_ptr on_laser_ppi_enable; on_spindle_select_ptr on_spindle_select; // core entry points - set up by core before driver_init() is called. diff --git a/driver_opts.h b/driver_opts.h index bb61525..73c3cec 100644 --- a/driver_opts.h +++ b/driver_opts.h @@ -220,11 +220,12 @@ #endif #endif +#ifndef SAFETY_DOOR_ENABLE +#define SAFETY_DOOR_ENABLE 0 +#endif -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN -#define SAFETY_DOOR_ENABLE 1 -#else -#define SAFETY_DOOR_ENABLE 0 +#if SAFETY_DOOR_ENABLE && defined(NO_SAFETY_DOOR_SUPPORT) +#error "Driver does not support safety door functionality!" #endif #ifndef ESTOP_ENABLE diff --git a/gcode.c b/gcode.c index acf5c54..d3c5d7f 100644 --- a/gcode.c +++ b/gcode.c @@ -742,7 +742,7 @@ status_code_t gc_execute_block(char *block) switch(int_value) { case 7: case 8: - if(settings.mode == Mode_Lathe) { + if(sys.mode == Mode_Lathe) { word_bit.modal_group.G15 = On; gc_block.modal.diameter_mode = int_value == 7; // TODO: find specs for implementation, only affects X calculation? reporting? current position? } else @@ -915,7 +915,7 @@ status_code_t gc_execute_block(char *block) break; */ case 96: case 97: - if(settings.mode == Mode_Lathe && hal.driver_cap.variable_spindle) { + if(sys.mode == Mode_Lathe && hal.driver_cap.variable_spindle) { word_bit.modal_group.G14 = On; gc_block.modal.spindle_rpm_mode = (spindle_rpm_mode_t)((int_value - 96) ^ 1); } else @@ -2467,7 +2467,7 @@ status_code_t gc_execute_block(char *block) } // If in laser mode, setup laser power based on current and past parser conditions. - if(settings.mode == Mode_Laser) { + if(sys.mode == Mode_Laser) { if(!motion_is_lasercut(gc_block.modal.motion)) gc_parser_flags.laser_disable = On; diff --git a/grbl.h b/grbl.h index abb5989..838fddd 100644 --- a/grbl.h +++ b/grbl.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2021 Terje Io + Copyright (c) 2017-2022 Terje Io Copyright (c) 2015-2016 Sungeun K. Jeon for Gnea Research LLC Grbl is free software: you can redistribute it and/or modify @@ -34,7 +34,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20220111 +#define GRBL_BUILD 20220123 // The following symbols are set here if not already set by the compiler or in config.h // Do NOT change here! diff --git a/grbllib.c b/grbllib.c index a27f49c..394e977 100644 --- a/grbllib.c +++ b/grbllib.c @@ -57,11 +57,10 @@ typedef union { uint8_t init :1, setup :1, spindle :1, - door :1, amass :1, pulse_delay :1, linearization :1, - unused :1; + unused :2; }; } driver_startup_t; @@ -169,10 +168,8 @@ int grbl_enter (void) hal.stream.suspend_read = NULL; #endif -#ifndef ENABLE_SAFETY_DOOR_INPUT_PIN +#ifdef NO_SAFETY_DOOR_SUPPORT hal.signals_cap.safety_door_ajar = Off; -#else - driver.door = hal.signals_cap.safety_door_ajar; #endif #ifdef BUFFER_NVSDATA diff --git a/motion_control.c b/motion_control.c index 44ddf8e..3f8e1a7 100644 --- a/motion_control.c +++ b/motion_control.c @@ -189,7 +189,7 @@ bool mc_line (float *target, plan_line_data_t *pl_data) // Plan and queue motion into planner buffer // bool plan_status; // Not used in normal operation. - if(!plan_buffer_line(target, pl_data) && settings.mode == Mode_Laser && pl_data->condition.spindle.on && !pl_data->condition.spindle.ccw) { + if(!plan_buffer_line(target, pl_data) && sys.mode == Mode_Laser && pl_data->condition.spindle.on && !pl_data->condition.spindle.ccw) { // Correctly set spindle state, if there is a coincident position passed. // Forces a buffer sync while in M3 laser mode only. hal.spindle.set_state(pl_data->condition.spindle, pl_data->spindle.rpm); @@ -247,8 +247,18 @@ void mc_arc (float *target, plan_line_data_t *pl_data, float *position, float *o pl_data->condition.inverse_time = Off; // Force as feed absolute mode over arc segments. } - float theta_per_segment = angular_travel/segments; + float theta_per_segment = angular_travel / segments; +#if N_AXIS > 3 + uint_fast8_t idx = N_AXIS; + float linear_per_segment[N_AXIS]; + do { + idx--; + if(!(idx == plane.axis_0 || idx == plane.axis_1)) + linear_per_segment[idx] = (target[idx] - position[idx]) / segments; + } while(idx); +#else float linear_per_segment = (target[plane.axis_linear] - position[plane.axis_linear]) / segments; +#endif /* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector, and phi is the angle of rotation. Solution approach by Jens Geisler. @@ -295,7 +305,7 @@ void mc_arc (float *target, plan_line_data_t *pl_data, float *position, float *o r_axis1 = r_axisi; count++; } else { - // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. ~375 usec + // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. // Compute exact location by applying transformation matrix from initial radius vector(=-offset). cos_Ti = cosf(i * theta_per_segment); sin_Ti = sinf(i * theta_per_segment); @@ -307,7 +317,16 @@ void mc_arc (float *target, plan_line_data_t *pl_data, float *position, float *o // Update arc_target location position[plane.axis_0] = center_axis0 + r_axis0; position[plane.axis_1] = center_axis1 + r_axis1; +#if N_AXIS > 3 + idx = N_AXIS; + do { + idx--; + if(!(idx == plane.axis_0 || idx == plane.axis_1)) + position[idx] += linear_per_segment[idx]; + } while(idx); +#else position[plane.axis_linear] += linear_per_segment; +#endif // Bail mid-circle on system abort. Runtime command check already performed by mc_line. if(!mc_line(position, pl_data)) @@ -882,6 +901,23 @@ gc_probe_t mc_probe_cycle (float *target, plan_line_data_t *pl_data, gc_parser_f return GCProbe_FailInit; // Nothing else to do but bail. } + if(grbl.on_probe_start) { + + uint_fast8_t idx = N_AXIS; + axes_signals_t axes = {0}; + coord_data_t position; + + system_convert_array_steps_to_mpos(position.values, sys.position); + + do { + idx--; + if(position.values[idx] != target[idx]) + bit_true(axes.mask, bit(idx)); + } while(idx--); + + grbl.on_probe_start(axes, target, pl_data); + } + // Setup and queue probing motion. Auto cycle-start should not start the cycle. if(!mc_line(target, pl_data)) return GCProbe_Abort; diff --git a/protocol.c b/protocol.c index e34a54e..70e20bf 100644 --- a/protocol.c +++ b/protocol.c @@ -167,9 +167,9 @@ bool protocol_main_loop (void) grbl.report.feedback_message(Message_AlarmLock); } else { state_set(STATE_IDLE); -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN +#ifndef NO_SAFETY_DOOR_SUPPORT // Check if the safety door is open. - if (!settings.safety_door.flags.ignore_when_idle && hal.control.get_state().safety_door_ajar) { + if (hal.signals_cap.safety_door_ajar && !settings.safety_door.flags.ignore_when_idle && hal.control.get_state().safety_door_ajar) { system_set_exec_state_flag(EXEC_SAFETY_DOOR); protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state. } diff --git a/report.c b/report.c index 25a76cf..e89e17e 100644 --- a/report.c +++ b/report.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2021 Terje Io + Copyright (c) 2017-2022 Terje Io Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC Grbl is free software: you can redistribute it and/or modify @@ -715,7 +715,7 @@ void report_gcode_modes (void) #endif - if(settings.mode == Mode_Lathe) + if(sys.mode == Mode_Lathe) hal.stream.write(gc_state.modal.diameter_mode ? " G7" : " G8"); hal.stream.write(" G"); @@ -728,7 +728,7 @@ void report_gcode_modes (void) hal.stream.write(" G"); hal.stream.write(uitoa((uint32_t)(94 - gc_state.modal.feed_mode))); - if(settings.mode == Mode_Lathe && hal.driver_cap.variable_spindle) + if(sys.mode == Mode_Lathe && hal.driver_cap.variable_spindle) hal.stream.write(gc_state.modal.spindle_rpm_mode == SpindleSpeedMode_RPM ? " G97" : " G96"); #if COMPATIBILITY_LEVEL < 10 @@ -1319,7 +1319,7 @@ void report_realtime_status (void) hal.stream.write_all(appendbuf(2, ",", uitoa(sys.homed.mask))); } - if(sys.report.xmode && settings.mode == Mode_Lathe) + if(sys.report.xmode && sys.mode == Mode_Lathe) hal.stream.write_all(gc_state.modal.diameter_mode ? "|D:1" : "|D:0"); if(sys.report.tool) diff --git a/settings.c b/settings.c index 268c286..ffac814 100644 --- a/settings.c +++ b/settings.c @@ -349,7 +349,7 @@ static status_code_t set_probe_allow_feed_override (setting_id_t id, uint_fast16 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_ganged_dir_invert (setting_id_t id, uint_fast16_t int_value); -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN +#ifndef NO_SAFETY_DOOR_SUPPORT static status_code_t set_parking_enable (setting_id_t id, uint_fast16_t int_value); static status_code_t set_restore_overrides (setting_id_t id, uint_fast16_t int_value); #endif @@ -435,9 +435,9 @@ PROGMEM static const setting_detail_t setting_detail[] = { { Setting_SpindlePPR, Group_Spindle, "Spindle pulses per revolution (PPR)", NULL, Format_Int16, "###0", NULL, NULL, Setting_IsExtended, &settings.spindle.ppr, NULL, is_setting_available }, { Setting_EnableLegacyRTCommands, Group_General, "Enable legacy RT commands", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_enable_legacy_rt_commands, get_int, NULL }, { Setting_JogSoftLimited, Group_Jogging, "Limit jog commands", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_jog_soft_limited, get_int, NULL }, -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN - { Setting_ParkingEnable, Group_SafetyDoor, "Parking cycle", NULL, Format_XBitfield, "Enable,Enable parking override control,Deactivate upon init", NULL, NULL, Setting_IsExtendedFn, set_parking_enable, get_int, NULL }, - { Setting_ParkingAxis, Group_SafetyDoor, "Parking axis", NULL, Format_RadioButtons, "X,Y,Z", NULL, NULL, Setting_IsExtended, &settings.parking.axis, NULL, NULL }, +#ifndef NO_SAFETY_DOOR_SUPPORT + { Setting_ParkingEnable, Group_SafetyDoor, "Parking cycle", NULL, Format_XBitfield, "Enable,Enable parking override control,Deactivate upon init", NULL, NULL, Setting_IsExtendedFn, set_parking_enable, get_int, is_setting_available }, + { Setting_ParkingAxis, Group_SafetyDoor, "Parking axis", NULL, Format_RadioButtons, "X,Y,Z", NULL, NULL, Setting_IsExtended, &settings.parking.axis, NULL, is_setting_available }, #endif { Setting_HomingLocateCycles, Group_Homing, "Homing passes", NULL, Format_Int8, "##0", "1", "128", Setting_IsExtended, &settings.homing.locate_cycles, NULL, NULL }, { Setting_HomingCycle_1, Group_Homing, "Axes homing, first pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL }, @@ -452,13 +452,13 @@ PROGMEM static const setting_detail_t setting_detail[] = { #ifdef C_AXIS { Setting_HomingCycle_6, Group_Homing, "Axes homing, sixth pass", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtendedFn, set_homing_cycle, get_int, NULL }, #endif -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN - { Setting_ParkingPulloutIncrement, Group_SafetyDoor, "Parking pull-out distance", "mm", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_increment, NULL, NULL }, - { Setting_ParkingPulloutRate, Group_SafetyDoor, "Parking pull-out rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_rate, NULL, NULL }, - { Setting_ParkingTarget, Group_SafetyDoor, "Parking target", "mm", Format_Decimal, "-###0.0", "-100000", NULL, Setting_IsExtended, &settings.parking.target, NULL, NULL }, - { Setting_ParkingFastRate, Group_SafetyDoor, "Parking fast rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.rate, NULL, NULL }, - { Setting_RestoreOverrides, Group_General, "Restore overrides", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_restore_overrides, get_int, NULL }, - { Setting_DoorOptions, Group_SafetyDoor, "Safety door options", NULL, Format_Bitfield, "Ignore when idle,Keep coolant state on open", NULL, NULL, Setting_IsExtended, &settings.safety_door.flags.value, NULL, NULL }, +#ifndef NO_SAFETY_DOOR_SUPPORT + { Setting_ParkingPulloutIncrement, Group_SafetyDoor, "Parking pull-out distance", "mm", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_increment, NULL, is_setting_available }, + { Setting_ParkingPulloutRate, Group_SafetyDoor, "Parking pull-out rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.pullout_rate, NULL, is_setting_available }, + { Setting_ParkingTarget, Group_SafetyDoor, "Parking target", "mm", Format_Decimal, "-###0.0", "-100000", NULL, Setting_IsExtended, &settings.parking.target, NULL, is_setting_available }, + { Setting_ParkingFastRate, Group_SafetyDoor, "Parking fast rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.rate, NULL, is_setting_available }, + { Setting_RestoreOverrides, Group_General, "Restore overrides", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_restore_overrides, get_int, is_setting_available }, + { Setting_DoorOptions, Group_SafetyDoor, "Safety door options", NULL, Format_Bitfield, "Ignore when idle,Keep coolant state on open", NULL, NULL, Setting_IsExtended, &settings.safety_door.flags.value, NULL, is_setting_available }, #endif { Setting_SleepEnable, Group_General, "Sleep enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_sleep_enable, get_int, NULL }, { 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 }, @@ -506,12 +506,11 @@ PROGMEM static const setting_detail_t setting_detail[] = { #elif N_AXIS > 5 { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis,B-Axis,C-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, #endif -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN - { Setting_DoorSpindleOnDelay, Group_SafetyDoor, "Spindle on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.spindle_on_delay, NULL, NULL }, - { Setting_DoorCoolantOnDelay, Group_SafetyDoor, "Coolant on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.coolant_on_delay, NULL, NULL }, -#else - { Setting_DoorSpindleOnDelay, Group_Spindle, "Spindle on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.spindle_on_delay, NULL, is_setting_available }, +#ifndef NO_SAFETY_DOOR_SUPPORT + { Setting_DoorSpindleOnDelay, Group_SafetyDoor, "Spindle on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.spindle_on_delay, NULL, is_setting_available }, + { Setting_DoorCoolantOnDelay, Group_SafetyDoor, "Coolant on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.coolant_on_delay, NULL, is_setting_available }, #endif + { Setting_SpindleOnDelay, Group_Spindle, "Spindle on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.spindle_on_delay, NULL, is_setting_available }, }; #ifndef NO_SETTINGS_DESCRIPTIONS @@ -599,7 +598,7 @@ PROGMEM static const setting_descr_t setting_descr[] = { { Setting_JogStepDistance, "Jog distance for single step jogging." }, { Setting_JogSlowDistance, "Jog distance before automatic stop." }, { Setting_JogFastDistance, "Jog distance before automatic stop." }, -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN +#ifndef NO_SAFETY_DOOR_SUPPORT { Setting_ParkingPulloutIncrement, "Spindle pull-out and plunge distance in mm.Incremental distance." }, { Setting_ParkingPulloutRate, "Spindle pull-out/plunge slow feed rate in mm/min." }, { Setting_ParkingTarget, "Parking axis target. In mm, as machine coordinate [-max_travel, 0]." }, @@ -647,7 +646,7 @@ PROGMEM static const setting_descr_t setting_descr[] = { #if COMPATIBILITY_LEVEL <= 1 { Setting_DisableG92Persistence, "Disables save/restore of G92 offset to non-volatile storage (NVS)." }, #endif -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN +#ifndef NO_SAFETY_DOOR_SUPPORT { Setting_DoorSpindleOnDelay, "Delay to allow spindle to spin up after safety door is opened." }, { Setting_DoorCoolantOnDelay, "Delay to allow coolant to restart after safety door is opened." }, #else @@ -912,12 +911,12 @@ static status_code_t set_mode (setting_id_t id, uint_fast16_t int_value) return Status_InvalidStatement; } - settings.mode = (machine_mode_t)int_value; + settings.mode = sys.mode = (machine_mode_t)int_value; return Status_OK; } -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN +#ifndef NO_SAFETY_DOOR_SUPPORT static status_code_t set_parking_enable (setting_id_t id, uint_fast16_t int_value) { @@ -1415,11 +1414,6 @@ static bool is_setting_available (const setting_detail_t *setting) available = hal.driver_cap.spindle_sync || hal.driver_cap.spindle_pid; break; - case Setting_SpindleAtSpeedTolerance: - case Setting_DoorSpindleOnDelay: - available = hal.driver_cap.spindle_at_speed; - break; - case Setting_RpmMax: case Setting_RpmMin: case Setting_PWMFreq: @@ -1437,6 +1431,29 @@ static bool is_setting_available (const setting_detail_t *setting) // available = hal.stepper.get_ganged && bit_istrue(hal.stepper.get_ganged(true).mask, setting->id - Setting_AxisAutoSquareOffset); break; +#ifndef NO_SAFETY_DOOR_SUPPORT + case Setting_ParkingEnable: + case Setting_ParkingAxis: + case Setting_ParkingPulloutIncrement: + case Setting_ParkingPulloutRate: + case Setting_ParkingTarget: + case Setting_ParkingFastRate: + case Setting_RestoreOverrides: + case Setting_DoorOptions: + case Setting_DoorSpindleOnDelay: + case Setting_DoorCoolantOnDelay: + available = hal.signals_cap.safety_door_ajar; + break; +#endif + + case Setting_SpindleAtSpeedTolerance: + available = hal.driver_cap.spindle_at_speed; + break; + + case Setting_SpindleOnDelay: + available = !hal.signals_cap.safety_door_ajar && hal.driver_cap.spindle_at_speed; + break; + default: break; } @@ -1559,6 +1576,8 @@ bool read_global_settings () if(settings.mode == Mode_Laser && !hal.driver_cap.variable_spindle) settings.mode = Mode_Standard; + sys.mode = settings.mode; + if(!(hal.driver_cap.spindle_sync || hal.driver_cap.spindle_pid)) settings.spindle.ppr = 0; @@ -1593,8 +1612,10 @@ void settings_restore (settings_restore_t restore) hal.nvs.put_byte(0, SETTINGS_VERSION); // Forces write to physical storage if (restore.defaults) { + memcpy(&settings, &defaults, sizeof(settings_t)); + sys.mode = settings.mode; settings.control_invert.mask &= hal.signals_cap.mask; settings.spindle.invert.ccw &= hal.driver_cap.spindle_dir; settings.spindle.invert.pwm &= hal.driver_cap.spindle_pwm_invert; diff --git a/settings.h b/settings.h index f214601..d03c471 100644 --- a/settings.h +++ b/settings.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2021 Terje Io + Copyright (c) 2017-2022 Terje Io Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -254,6 +254,7 @@ typedef enum { Setting_CoolantOkPort = 391, Setting_DoorSpindleOnDelay = 392, Setting_DoorCoolantOnDelay = 393, + Setting_SpindleOnDelay = 394, // made available if safety door input not provided Setting_EncoderSettingsBase = 400, // NOTE: Reserving settings values >= 400 for encoder settings. Up to 449. Setting_EncoderSettingsMax = 449, @@ -545,12 +546,6 @@ typedef struct { ioport_bus_t od_enable_out; } ioport_signals_t; -typedef enum { - Mode_Standard = 0, - Mode_Laser, - Mode_Lathe -} machine_mode_t; - typedef enum { ToolChange_Disabled = 0, ToolChange_Manual, diff --git a/spindle_control.c b/spindle_control.c index 2d78db7..e27e6ac 100644 --- a/spindle_control.c +++ b/spindle_control.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2021 Terje Io + Copyright (c) 2017-2022 Terje Io Copyright (c) 2012-2015 Sungeun K. Jeon Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -59,7 +59,7 @@ bool spindle_set_state (spindle_state_t state, float rpm) } else { // NOTE: Assumes all calls to this function is when Grbl is not moving or must remain off. // TODO: alarm/interlock if going from CW to CCW directly in non-laser mode? - if (settings.mode == Mode_Laser && state.ccw) + if (sys.mode == Mode_Laser && state.ccw) rpm = 0.0f; // TODO: May need to be rpm_min*(100/MAX_SPINDLE_RPM_OVERRIDE); hal.spindle.set_state(state, spindle_set_rpm(rpm, sys.override.spindle_rpm)); @@ -109,7 +109,7 @@ bool spindle_restore (spindle_state_t state, float rpm) { bool ok = true; - if(settings.mode == Mode_Laser) // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. + if(sys.mode == Mode_Laser) // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. sys.step_control.update_spindle_rpm = On; else { // TODO: add check for current spindle state matches restore state? spindle_set_state(state, rpm); diff --git a/state_machine.c b/state_machine.c index df36f4a..56c3cac 100644 --- a/state_machine.c +++ b/state_machine.c @@ -110,7 +110,7 @@ bool initiate_hold (uint_fast16_t new_state) restore_spindle_rpm = block->spindle.rpm; } - if (settings.mode == Mode_Laser && settings.flags.disable_laser_during_hold) + if (sys.mode == Mode_Laser && settings.flags.disable_laser_during_hold) enqueue_accessory_override(CMD_OVERRIDE_SPINDLE_STOP); if (sys_state & (STATE_CYCLE|STATE_JOG)) { @@ -267,7 +267,7 @@ void state_suspend_manager (void) // Handles restoring of spindle state if (sys.override.spindle_stop.restore) { grbl.report.feedback_message(Message_SpindleRestore); - if (settings.mode == Mode_Laser) // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. + if (sys.mode == Mode_Laser) // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. sys.step_control.update_spindle_rpm = On; else spindle_set_state(restore_condition.spindle, restore_spindle_rpm); @@ -409,7 +409,7 @@ static void state_await_hold (uint_fast16_t rt_exec) // Parking requires parking axis homed, the current location not exceeding the??? // parking target location, and laser mode disabled. - if (settings.parking.flags.enabled && !sys.override.control.parking_disable && settings.mode != Mode_Laser) { + if (settings.parking.flags.enabled && !sys.override.control.parking_disable && sys.mode != Mode_Laser) { // Get current position and store as restore location. if (!park.flags.active) { diff --git a/stepper.c b/stepper.c index 17243f5..f0572f2 100644 --- a/stepper.c +++ b/stepper.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2016-2021 Terje Io + Copyright (c) 2016-2022 Terje Io Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -29,6 +29,8 @@ #include "protocol.h" #include "state_machine.h" +//#define MINIMIZE_PROBE_OVERSHOOT + //#include "debug.h" //! \cond @@ -90,10 +92,14 @@ static amass_t amass; // Message to be output by foreground process static char *message = NULL; // TODO: do we need a queue for this? +// Used for blocking new segments beeing added to the seqment buffer until deceleration starts +// after probe signal has been asserted. +static volatile bool probe_asserted = false; + // Stepper timer ticks per minute static float cycles_per_min; -// Step segment ring buffer indices +// Step segment ring buffer pointers static volatile segment_t *segment_buffer_tail; static segment_t *segment_buffer_head, *segment_next_head; @@ -213,7 +219,6 @@ void st_wake_up (void) hal.stepper.wake_up(); } - // Stepper shutdown ISR_CODE void ISR_FUNC(st_go_idle)(void) { @@ -406,7 +411,7 @@ ISR_CODE void ISR_FUNC(stepper_driver_interrupt_handler)(void) st_go_idle(); // Ensure pwm is set properly upon completion of rate-controlled motion. - if (st.exec_block->dynamic_rpm && settings.mode == Mode_Laser) { + if (st.exec_block->dynamic_rpm && sys.mode == Mode_Laser) { #ifndef GRBL_ESP32 hal.spindle.set_state((spindle_state_t){0}, 0.0f); #else @@ -425,9 +430,20 @@ ISR_CODE void ISR_FUNC(stepper_driver_interrupt_handler)(void) // Monitors probe pin state and records the system position when detected. // NOTE: This function must be extremely efficient as to not bog down the stepper ISR. if (sys.probing_state == Probing_Active && hal.probe.get_state().triggered) { + sys.probing_state = Probing_Off; memcpy(sys.probe_position, sys.position, sizeof(sys.position)); bit_true(sys.rt_exec_state, EXEC_MOTION_CANCEL); + +#ifdef MINIMIZE_PROBE_OVERSHOOT + // "Flush" segment buffer if full in order to start deceleration early. + if((probe_asserted = segment_buffer_head->next == segment_buffer_tail)) { + segment_buffer_head = segment_buffer_tail->next; + if(st.step_count < 3 || st.step_count < (st.exec_segment->n_step >> 3)) + segment_buffer_head = segment_buffer_head->next; + segment_next_head = segment_next_head->next; + } +#endif } register axes_signals_t step_outbits = (axes_signals_t){0}; @@ -839,9 +855,15 @@ void st_prep_buffer (void) } if(state_get() != STATE_HOMING) - sys.step_control.update_spindle_rpm |= (settings.mode == Mode_Laser); // Force update whenever updating block in laser mode. + sys.step_control.update_spindle_rpm |= (sys.mode == Mode_Laser); // Force update whenever updating block in laser mode. + + probe_asserted = false; } + // Block adding new segments after probe is asserted until deceleration is started. + if(probe_asserted) + return; + // Initialize new segment segment_t *prep_segment = segment_buffer_head; diff --git a/system.c b/system.c index 2c68b63..2b7cd33 100644 --- a/system.c +++ b/system.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2021 Terje Io + Copyright (c) 2017-2022 Terje Io Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC Grbl is free software: you can redistribute it and/or modify @@ -105,15 +105,15 @@ ISR_CODE void ISR_FUNC(control_interrupt_handler)(control_signals_t signals) if ((signals.reset || signals.e_stop || signals.motor_fault) && state_get() != STATE_ESTOP) mc_reset(); else { -#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN - if (signals.safety_door_ajar) { +#ifndef NO_SAFETY_DOOR_SUPPORT + if (signals.safety_door_ajar && hal.signals_cap.safety_door_ajar) { if(settings.safety_door.flags.ignore_when_idle) { // Only stop the spindle (laser off) when idle or jogging, // this to allow positioning the controlled point (spindle) when door is open. // NOTE: at least for lasers there should be an external interlock blocking laser power. if(state_get() != STATE_IDLE && state_get() != STATE_JOG) system_set_exec_state_flag(EXEC_SAFETY_DOOR); - if(settings.mode == Mode_Laser) // Turn off spindle imeediately (laser) when in laser mode + if(sys.mode == Mode_Laser) // Turn off spindle imeediately (laser) when in laser mode hal.spindle.set_state((spindle_state_t){0}, 0.0f); } else system_set_exec_state_flag(EXEC_SAFETY_DOOR); diff --git a/system.h b/system.h index 01d7cff..58db347 100644 --- a/system.h +++ b/system.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2021 Terje Io + Copyright (c) 2017-2022 Terje Io Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC Grbl is free software: you can redistribute it and/or modify @@ -81,6 +81,12 @@ __NOTE:__ flags are mutually exclusive, bit map allows testing for multiple stat #define STATE_TOOL_CHANGE bit(9) //!< Manual tool change, similar to #STATE_HOLD - but stops spindle and allows jogging. ///@} +typedef enum { + Mode_Standard = 0, + Mode_Laser, + Mode_Lathe +} machine_mode_t; + typedef enum { Parking_DoorClosed = 0, //!< 0 Parking_DoorAjar, //!< 1 @@ -222,6 +228,7 @@ typedef struct system { bool suspend; //!< System suspend state flag. bool position_lost; //!< Set when mc_reset is called when machine is moving. volatile bool steppers_deenergize; //!< Set to true to deenergize stepperes + machine_mode_t mode; //!< Current machine mode, copied from settings.mode on startup. axes_signals_t tlo_reference_set; //!< Axes with tool length reference offset set int32_t tlo_reference[N_AXIS]; //!< Tool length reference offset alarm_code_t alarm_pending; //!< Delayed alarm, currently used for probe protection diff --git a/tool_change.c b/tool_change.c index 8057f95..28aa9e3 100644 --- a/tool_change.c +++ b/tool_change.c @@ -5,7 +5,7 @@ Part of grblHAL - Copyright (c) 2020-2021 Terje Io + Copyright (c) 2020-2022 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -423,7 +423,7 @@ void tc_clear_tlo_reference (axes_signals_t homing_cycle) #else gc_get_plane_data(&plane, gc_state.modal.plane_select); #endif - if(homing_cycle.mask & (settings.mode == Mode_Lathe ? (X_AXIS_BIT|Z_AXIS_BIT) : bit(plane.axis_linear))) { + if(homing_cycle.mask & (sys.mode == Mode_Lathe ? (X_AXIS_BIT|Z_AXIS_BIT) : bit(plane.axis_linear))) { sys.report.tlo_reference = sys.tlo_reference_set.mask != 0; sys.tlo_reference_set.mask = 0; // Invalidate tool length offset reference }