diff --git a/Grbl_Esp32/src/Config.h b/Grbl_Esp32/src/Config.h index fde95aab..d33e1337 100644 --- a/Grbl_Esp32/src/Config.h +++ b/Grbl_Esp32/src/Config.h @@ -395,18 +395,6 @@ const int DEBOUNCE_PERIOD = 32; // in milliseconds default 32 microseconds // repeatable. If needed, you can disable this behavior by uncommenting the define below. // #define ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES // Default disabled. Uncomment to enable. -// Enables and configures parking motion methods upon a safety door state. Primarily for OEMs -// that desire this feature for their integrated machines. At the moment, Grbl assumes that -// the parking motion only involves one axis, although the parking implementation was written -// to be easily refactored for any number of motions on different axes by altering the parking -// source code. At this time, Grbl only supports parking one axis (typically the Z-axis) that -// moves in the positive direction upon retracting and negative direction upon restoring position. -// The motion executes with a slow pull-out retraction motion, power-down, and a fast park. -// Restoring to the resume position follows these set motions in reverse: fast restore to -// pull-out position, power-up with a time-out, and plunge back to the original position at the -// slower pull-out rate. -#define PARKING_ENABLE // Default disabled. Uncomment to enable - // Configure options for the parking motion, if enabled. #define PARKING_AXIS Z_AXIS // Define which axis that performs the parking motion const double PARKING_TARGET = -5.0; // Parking axis target. In mm, as machine coordinate. @@ -419,7 +407,8 @@ const double PARKING_PULLOUT_INCREMENT = 5.0; // Spindle pull-out and plunge // These are controlled by `M56`, `M56 P1`, or `M56 Px` to enable and `M56 P0` to disable. // The command is modal and will be set after a planner sync. Since it is GCode, it is // executed in sync with GCode commands. It is not a real-time command. -// NOTE: PARKING_ENABLE is required. By default, M56 is active upon initialization. Use +// +// By default, M56 is active upon initialization. Use // DEACTIVATE_PARKING_UPON_INIT to set M56 P0 as the power-up default. // #define ENABLE_PARKING_OVERRIDE_CONTROL // Default disabled. Uncomment to enable // #define DEACTIVATE_PARKING_UPON_INIT // Default disabled. Uncomment to enable. diff --git a/Grbl_Esp32/src/GCode.cpp b/Grbl_Esp32/src/GCode.cpp index eff145f4..04965d4f 100644 --- a/Grbl_Esp32/src/GCode.cpp +++ b/Grbl_Esp32/src/GCode.cpp @@ -47,8 +47,14 @@ parser_block_t gc_block; void gc_init() { // Reset parser state: memset(&gc_state, 0, sizeof(parser_state_t)); + // Load default G54 coordinate system. gc_state.modal.coord_select = CoordIndex::G54; + if (config->_deactivateParkingUponInit) { + gc_state.modal.override = Override::Disabled; + } else { + gc_state.modal.override = Override::ParkingMotion; + } coords[gc_state.modal.coord_select]->get(gc_state.coord_system); } @@ -519,12 +525,14 @@ Error gc_execute_line(char* line, uint8_t client) { } mg_word_bit = ModalGroup::MM8; break; -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL case 56: - gc_block.modal.override = Override::ParkingMotion; - mg_word_bit = ModalGroup::MM9; + if (config->_enableParkingOverrideControl) { + gc_block.modal.override = Override::ParkingMotion; + mg_word_bit = ModalGroup::MM9; + } else { + FAIL(Error::GcodeUnsupportedCommand); // [Unsupported M command] + } break; -#endif case 62: gc_block.modal.io_control = IoControl::DigitalOnSync; mg_word_bit = ModalGroup::MM10; @@ -803,16 +811,17 @@ Error gc_execute_line(char* line, uint8_t client) { // [8. Coolant control ]: N/A // [9. Enable/disable feed rate or spindle overrides ]: NOT SUPPORTED. } -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL - if (bit_istrue(command_words, bit(ModalGroup::MM9))) { // Already set as enabled in parser. - if (bit_istrue(value_words, bit(GCodeWord::P))) { - if (gc_block.values.p == 0.0) { - gc_block.modal.override = Override::Disabled; + + if (config->_enableParkingOverrideControl) { + if (bit_istrue(command_words, bit(ModalGroup::MM9))) { // Already set as enabled in parser. + if (bit_istrue(value_words, bit(GCodeWord::P))) { + if (gc_block.values.p == 0.0) { + gc_block.modal.override = Override::Disabled; + } + bit_false(value_words, bit(GCodeWord::P)); } - bit_false(value_words, bit(GCodeWord::P)); } } -#endif // [10. Dwell ]: P value missing. P is negative (done.) NOTE: See below. if (gc_block.non_modal_command == NonModal::Dwell) { if (bit_isfalse(value_words, bit(GCodeWord::P))) { @@ -1427,12 +1436,13 @@ Error gc_execute_line(char* line, uint8_t client) { } // [9. Override control ]: NOT SUPPORTED. Always enabled. Except for a Grbl-only parking control. -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL - if (gc_state.modal.override != gc_block.modal.override) { - gc_state.modal.override = gc_block.modal.override; - mc_override_ctrl_update(gc_state.modal.override); + if (config->_enableParkingOverrideControl) { + if (gc_state.modal.override != gc_block.modal.override) { + gc_state.modal.override = gc_block.modal.override; + mc_override_ctrl_update(gc_state.modal.override); + } } -#endif + // [10. Dwell ]: if (gc_block.non_modal_command == NonModal::Dwell) { mc_dwell(int32_t(gc_block.values.p * 1000.0f)); @@ -1581,13 +1591,14 @@ Error gc_execute_line(char* line, uint8_t client) { gc_state.modal.coord_select = CoordIndex::G54; gc_state.modal.spindle = SpindleState::Disable; gc_state.modal.coolant = {}; -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL -# ifdef DEACTIVATE_PARKING_UPON_INIT - gc_state.modal.override = Override::Disabled; -# else - gc_state.modal.override = Override::ParkingMotion; -# endif -#endif + if (config->_enableParkingOverrideControl) { + if (config->_deactivateParkingUponInit) { + gc_state.modal.override = Override::Disabled; + } else { + gc_state.modal.override = Override::ParkingMotion; + } + } + // gc_state.modal.override = OVERRIDE_DISABLE; // Not supported. #ifdef RESTORE_OVERRIDES_AFTER_PROGRAM_END sys.f_override = FeedOverride::Default; diff --git a/Grbl_Esp32/src/GCode.h b/Grbl_Esp32/src/GCode.h index 443cb03d..c087c09f 100644 --- a/Grbl_Esp32/src/GCode.h +++ b/Grbl_Esp32/src/GCode.h @@ -263,7 +263,7 @@ enum CoordIndex : uint8_t { CoordIndex& operator++(CoordIndex& i); // NOTE: When this struct is zeroed, the 0 values in the above types set the system defaults. -typedef struct { +struct gc_modal_t { Motion motion; // {G0,G1,G2,G3,G38.2,G80} FeedRate feed_rate; // {G93,G94} Units units; // {G20,G21} @@ -280,9 +280,9 @@ typedef struct { ToolChange tool_change; // {M6} IoControl io_control; // {M62, M63, M67} Override override; // {M56} -} gc_modal_t; +}; -typedef struct { +struct gc_values_t { uint8_t e; // M67 float f; // Feed float ijk[3]; // I,J,K Axis arc offsets - only 3 are possible @@ -294,9 +294,9 @@ typedef struct { float s; // Spindle speed uint8_t t; // Tool selection float xyz[MAX_N_AXIS]; // X,Y,Z Translational axes -} gc_values_t; +}; -typedef struct { +struct parser_state_t { gc_modal_t modal; float spindle_speed; // RPM @@ -311,15 +311,16 @@ typedef struct { float coord_offset[MAX_N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to // machine zero in mm. Non-persistent. Cleared upon reset and boot. float tool_length_offset; // Tracks tool length offset value when enabled. -} parser_state_t; +}; + extern parser_state_t gc_state; -typedef struct { +struct parser_block_t { NonModal non_modal_command; gc_modal_t modal; gc_values_t values; GCodeCoolant coolant; -} parser_block_t; +}; enum class AxisCommand : uint8_t { None = 0, diff --git a/Grbl_Esp32/src/MachineConfig.cpp b/Grbl_Esp32/src/MachineConfig.cpp index a955bf19..1da31a7b 100644 --- a/Grbl_Esp32/src/MachineConfig.cpp +++ b/Grbl_Esp32/src/MachineConfig.cpp @@ -417,6 +417,9 @@ void MachineConfig::group(Configuration::HandlerBase& handler) { handler.item("verbose_errors", _verboseErrors); handler.item("report_inches", _reportInches); handler.item("homing_init_lock", _homingInitLock); + handler.item("enable_parking_override_control", _enableParkingOverrideControl); + handler.item("deactivate_parking_upon_init", _deactivateParkingUponInit); + Spindles::SpindleFactory::factory(handler, _spindle); } diff --git a/Grbl_Esp32/src/MachineConfig.h b/Grbl_Esp32/src/MachineConfig.h index c8e592fb..39356ef2 100644 --- a/Grbl_Esp32/src/MachineConfig.h +++ b/Grbl_Esp32/src/MachineConfig.h @@ -362,6 +362,9 @@ public: bool _homingInitLock = false; int _stepType = ST_RMT; + bool _enableParkingOverrideControl = false; + bool _deactivateParkingUponInit = false; + String _board = "None"; String _name = "None"; diff --git a/Grbl_Esp32/src/MotionControl.cpp b/Grbl_Esp32/src/MotionControl.cpp index 85a6c1b2..5b38eb10 100644 --- a/Grbl_Esp32/src/MotionControl.cpp +++ b/Grbl_Esp32/src/MotionControl.cpp @@ -507,7 +507,6 @@ void mc_parking_motion(float* parking_target, plan_line_data_t* pl_data) { } } -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL void mc_override_ctrl_update(Override override_state) { // Finish all queued commands before altering override control state protocol_buffer_synchronize(); @@ -516,7 +515,6 @@ void mc_override_ctrl_update(Override override_state) { } sys.override_ctrl = override_state; } -#endif // Method to ready the system to reset by setting the realtime reset command and killing any // active processes in the system. This also checks if a system reset is issued while Grbl diff --git a/Grbl_Esp32/src/Protocol.cpp b/Grbl_Esp32/src/Protocol.cpp index 96c44471..5f1fa017 100644 --- a/Grbl_Esp32/src/Protocol.cpp +++ b/Grbl_Esp32/src/Protocol.cpp @@ -94,11 +94,11 @@ Error execute_line(char* line, uint8_t client, WebUI::AuthenticationLevel auth_l } bool can_park() { - return -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL - sys.override_ctrl == Override::ParkingMotion && -#endif - homingAxes() && !config->_laserMode; + if (config->_enableParkingOverrideControl) { + return sys.override_ctrl == Override::ParkingMotion && homingAxes() && !config->_laserMode; + } else { + return homingAxes() && !config->_laserMode; + } } void protocol_reset() { @@ -407,7 +407,6 @@ static void protocol_do_safety_door() { break; case State::SafetyDoor: if (!sys.suspend.bit.jogCancel && sys.suspend.bit.initiateRestore) { // Actively restoring -#ifdef PARKING_ENABLE // Set hold and reset appropriate control flags to restart parking sequence. if (sys.step_control.executeSysMotion) { st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration. @@ -416,7 +415,7 @@ static void protocol_do_safety_door() { sys.step_control.executeSysMotion = true; sys.suspend.bit.holdComplete = false; } // else NO_MOTION is active. -#endif + sys.suspend.bit.retractComplete = false; sys.suspend.bit.initiateRestore = false; sys.suspend.bit.restoreComplete = false; @@ -798,7 +797,6 @@ void protocol_exec_rt_system() { // // already retracting, parked or in sleep state. // if (sys.state == State::SafetyDoor) { // if (sys.suspend.bit.initiateRestore) { // Actively restoring -//#ifdef PARKING_ENABLE // // Set hold and reset appropriate control flags to restart parking sequence. // if (sys.step_control.executeSysMotion) { // st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration. @@ -807,7 +805,6 @@ void protocol_exec_rt_system() { // sys.step_control.executeSysMotion = true; // sys.suspend.bit.holdComplete = false; // } // else NO_MOTION is active. -//#endif // sys.suspend.bit.retractComplete = false; // sys.suspend.bit.initiateRestore = false; // sys.suspend.bit.restoreComplete = false; @@ -991,7 +988,6 @@ void protocol_exec_rt_system() { // This function is written in a way to promote custom parking motions. Simply use this as a // template static void protocol_exec_rt_suspend() { -#ifdef PARKING_ENABLE // Declare and initialize parking local variables float restore_target[MAX_N_AXIS]; float retract_waypoint = PARKING_PULLOUT_INCREMENT; @@ -1001,10 +997,10 @@ static void protocol_exec_rt_suspend() { pl_data->motion = {}; pl_data->motion.systemMotion = 1; pl_data->motion.noFeedOverride = 1; -# ifdef USE_LINE_NUMBERS +#ifdef USE_LINE_NUMBERS pl_data->line_number = PARKING_MOTION_LINE_NUMBER; -# endif #endif + plan_block_t* block = plan_get_current_block(); CoolantState restore_coolant; SpindleState restore_spindle; @@ -1040,16 +1036,11 @@ static void protocol_exec_rt_suspend() { // the safety door and sleep states. if (sys.state == State::SafetyDoor || sys.state == State::Sleep) { // Handles retraction motions and de-energizing. -#ifdef PARKING_ENABLE float* parking_target = system_get_mpos(); -#endif if (!sys.suspend.bit.retractComplete) { // Ensure any prior spindle stop override is disabled at start of safety door routine. sys.spindle_stop_ovr.value = 0; // Disable override -#ifndef PARKING_ENABLE - config->_spindle->spinDown(); - config->_coolant->off(); -#else + // Get current position and store restore location and spindle retract waypoint. if (!sys.suspend.bit.restartRetract) { memcpy(restore_target, parking_target, sizeof(restore_target[0]) * config->_axes->_numberAxis); @@ -1091,7 +1082,7 @@ static void protocol_exec_rt_suspend() { config->_spindle->spinDown(); config->_coolant->off(); } -#endif + sys.suspend.bit.restartRetract = false; sys.suspend.bit.retractComplete = true; } else { @@ -1114,7 +1105,6 @@ static void protocol_exec_rt_suspend() { } // Handles parking restore and safety door resume. if (sys.suspend.bit.initiateRestore) { -#ifdef PARKING_ENABLE // Execute fast restore motion to the pull-out position. Parking requires homing enabled. // NOTE: State is will remain DOOR, until the de-energizing and retract is complete. if (can_park()) { @@ -1125,7 +1115,6 @@ static void protocol_exec_rt_suspend() { mc_parking_motion(parking_target, pl_data); } } -#endif // Delayed Tasks: Restart spindle and coolant, delay to power-up, then resume cycle. if (gc_state.modal.spindle != SpindleState::Disable) { // Block if safety door re-opened during prior restore actions. @@ -1144,7 +1133,7 @@ static void protocol_exec_rt_suspend() { config->_coolant->set_state(restore_coolant); } } -#ifdef PARKING_ENABLE + // Execute slow plunge motion from pull-out position to resume position. if (can_park()) { // Block if safety door re-opened during prior restore actions. @@ -1159,7 +1148,6 @@ static void protocol_exec_rt_suspend() { mc_parking_motion(restore_target, pl_data); } } -#endif if (!sys.suspend.bit.restartRetract) { sys.suspend.bit.restoreComplete = true; rtCycleStart = true; // Set to resume program. diff --git a/Grbl_Esp32/src/Report.cpp b/Grbl_Esp32/src/Report.cpp index 9fb56d5b..dac9977d 100644 --- a/Grbl_Esp32/src/Report.cpp +++ b/Grbl_Esp32/src/Report.cpp @@ -503,11 +503,9 @@ void report_gcode_modes(uint8_t client) { } } -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL - if (sys.override_ctrl == Override::ParkingMotion) { + if (config->_enableParkingOverrideControl && sys.override_ctrl == Override::ParkingMotion) { strcat(modes_rpt, " M56"); } -#endif sprintf(temp, " T%d", gc_state.tool); strcat(modes_rpt, temp); @@ -535,9 +533,7 @@ void report_build_info(const char* line, uint8_t client) { if (config->_coolant->hasMist()) { grbl_send(client, "M"); // TODO Need to deal with M8...it could be disabled } -#ifdef PARKING_ENABLE grbl_send(client, "P"); -#endif #ifdef HOMING_SINGLE_AXIS_COMMANDS grbl_send(client, "H"); #endif @@ -551,9 +547,9 @@ void report_build_info(const char* line, uint8_t client) { grbl_send(client, "B"); } grbl_send(client, "S"); -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL - grbl_send(client, "R"); -#endif + if (config->_enableParkingOverrideControl) { + grbl_send(client, "R"); + } #ifdef ENABLE_WIFI grbl_send(client, "W"); #endif diff --git a/Grbl_Esp32/src/Stepper.cpp b/Grbl_Esp32/src/Stepper.cpp index c67daebd..26ac7444 100644 --- a/Grbl_Esp32/src/Stepper.cpp +++ b/Grbl_Esp32/src/Stepper.cpp @@ -103,12 +103,10 @@ typedef struct { float step_per_mm; float req_mm_increment; -#ifdef PARKING_ENABLE uint8_t last_st_block_index; float last_steps_remaining; float last_step_per_mm; float last_dt_remainder; -#endif uint8_t ramp_type; // Current segment ramp state float mm_complete; // End of velocity profile from end of current planner block in (mm). @@ -441,7 +439,6 @@ void st_update_plan_block_parameters() { } } -#ifdef PARKING_ENABLE // Changes the run state of the step segment buffer to execute the special parking motion. void st_parking_setup_buffer() { // Store step execution data of partially completed block, if necessary. @@ -475,7 +472,6 @@ void st_parking_restore_buffer() { pl_block = NULL; // Set to reload next block. } -#endif // Increments the step segment buffer block data ring buffer. static uint8_t st_next_block_index(uint8_t block_index) { @@ -518,15 +514,11 @@ void st_prep_buffer() { // Check if we need to only recompute the velocity profile or load a new block. if (prep.recalculate_flag.recalculate) { -#ifdef PARKING_ENABLE if (prep.recalculate_flag.parking) { prep.recalculate_flag.recalculate = 0; } else { prep.recalculate_flag = {}; } -#else - prep.recalculate_flag = {}; -#endif } else { // Load the Bresenham stepping data for the block. prep.st_block_index = st_next_block_index(prep.st_block_index); @@ -816,11 +808,9 @@ void st_prep_buffer() { // Less than one step to decelerate to zero speed, but already very close. AMASS // requires full steps to execute. So, just bail. sys.step_control.endMotion = true; -#ifdef PARKING_ENABLE if (!(prep.recalculate_flag.parking)) { prep.recalculate_flag.holdPartialBlock = 1; } -#endif return; // Segment not generated, but current step data still retained. } } @@ -874,11 +864,9 @@ void st_prep_buffer() { // the segment queue, where realtime protocol will set new state upon receiving the // cycle stop flag from the ISR. Prep_segment is blocked until then. sys.step_control.endMotion = true; -#ifdef PARKING_ENABLE if (!(prep.recalculate_flag.parking)) { prep.recalculate_flag.holdPartialBlock = 1; } -#endif return; // Bail! } else { // End of planner block // The planner block is complete. All steps are set to be executed in the segment buffer. diff --git a/Grbl_Esp32/src/System.h b/Grbl_Esp32/src/System.h index 0130fcfe..db5b7036 100644 --- a/Grbl_Esp32/src/System.h +++ b/Grbl_Esp32/src/System.h @@ -74,13 +74,8 @@ typedef uint8_t Percent; // Integer percent typedef uint8_t Counter; // Report interval enum class Override : uint8_t { -#ifdef DEACTIVATE_PARKING_UPON_INIT - Disabled = 0, // (Default: Must be zero) - ParkingMotion = 1, // M56 -#else ParkingMotion = 0, // M56 (Default: Must be zero) Disabled = 1, // Parking disabled. -#endif }; // Spindle stop override control states. @@ -96,7 +91,7 @@ union SpindleStop { }; // Global system variables -typedef struct { +struct system_t { volatile State state; // Tracks the current system state of Grbl. bool abort; // System abort flag. Forces exit back to main loop for reset. Suspend suspend; // System suspend bitflag variable that manages holds, cancels, and safety door. @@ -110,11 +105,10 @@ typedef struct { SpindleStop spindle_stop_ovr; // Tracks spindle stop override states Counter report_ovr_counter; // Tracks when to add override data to status reports. Counter report_wco_counter; // Tracks when to add work coordinate offset data to status reports. -#ifdef ENABLE_PARKING_OVERRIDE_CONTROL - Override override_ctrl; // Tracks override control states. -#endif - uint32_t spindle_speed; -} system_t; + Override override_ctrl; // Tracks override control states. + uint32_t spindle_speed; +}; + extern system_t sys; // NOTE: These position variables may need to be declared as volatiles, if problems arise.