diff --git a/Grbl_Esp32/src/Config.h b/Grbl_Esp32/src/Config.h index a60b6832..17fa5f71 100644 --- a/Grbl_Esp32/src/Config.h +++ b/Grbl_Esp32/src/Config.h @@ -238,42 +238,6 @@ const int DWELL_TIME_STEP = 50; // Integer (1-255) (milliseconds) // #define RX_BUFFER_SIZE 128 // (1-254) Uncomment to override defaults in serial.h // #define TX_BUFFER_SIZE 100 // (1-254) -// A simple software debouncing feature for hard limit switches. When enabled, the limit -// switch interrupt unblock a waiting task which will recheck the limit switch pins after -// a short delay. Default disabled -//#define ENABLE_SOFTWARE_DEBOUNCE // Default disabled. Uncomment to enable. -const int DEBOUNCE_PERIOD = 32; // in milliseconds default 32 microseconds - -// Configures the position after a probing cycle during Grbl's check mode. Disabled sets -// the position to the probe target, when enabled sets the position to the start position. -// #define SET_CHECK_MODE_PROBE_TO_START // Default disabled. Uncomment to enable. - -// Force Grbl to check the state of the hard limit switches when the processor detects a pin -// change inside the hard limit ISR routine. By default, Grbl will trigger the hard limits -// alarm upon any pin change, since bouncing switches can cause a state check like this to -// misread the pin. When hard limits are triggered, they should be 100% reliable, which is the -// reason that this option is disabled by default. Only if your system/electronics can guarantee -// that the switches don't bounce, we recommend enabling this option. This will help prevent -// triggering a hard limit when the machine disengages from the switch. -// NOTE: This option has no effect if SOFTWARE_DEBOUNCE is enabled. -// #define HARD_LIMIT_FORCE_STATE_CHECK // Default disabled. Uncomment to enable. - -// Adjusts homing cycle search and locate scalars. These are the multipliers used by Grbl's -// homing cycle to ensure the limit switches are engaged and cleared through each phase of -// the cycle. The search phase uses the axes max-travel setting times the SEARCH_SCALAR to -// determine distance to look for the limit switch. Once found, the locate phase begins and -// uses the homing pull-off distance setting times the LOCATE_SCALAR to pull-off and re-engage -// the limit switch. -// NOTE: Both of these values must be greater than 1.0 to ensure proper function. -// #define HOMING_AXIS_SEARCH_SCALAR 1.5 // Uncomment to override defaults in limits.c. -// #define HOMING_AXIS_LOCATE_SCALAR 10.0 // Uncomment to override defaults in limits.c. - -// Additional settings have been added to the original set that you see with the $$ command -// Some senders may not be able to parse anything different from the original set -// You can still set these like $33=5000, but you cannot read them back. -// Default is off to limit support issues...you can enable here or in your machine definition file -// #define SHOW_EXTENDED_SETTINGS - // Writing to non-volatile storage (NVS) can take a long time and interfere with timely instruction // execution, causing problems for the stepper ISRs and serial comm ISRs and subsequent loss of // stepper position and serial data. This configuration option forces the planner buffer to completely diff --git a/Grbl_Esp32/src/Defaults.h b/Grbl_Esp32/src/Defaults.h index 52fe77e5..0804ccbc 100644 --- a/Grbl_Esp32/src/Defaults.h +++ b/Grbl_Esp32/src/Defaults.h @@ -31,14 +31,6 @@ */ // Grbl generic default settings. Should work across different machines. -#ifndef DEFAULT_STATUS_REPORT_MASK -# define DEFAULT_STATUS_REPORT_MASK 1 // $10 -#endif - -#ifndef SERVO_TIMER_INTERVAL -# define SERVO_TIMER_INTERVAL 75.0 // Hz This is the update inveral in milliseconds -#endif - #ifndef DEFAULT_USER_MACRO0 # define DEFAULT_USER_MACRO0 "" #endif diff --git a/Grbl_Esp32/src/GCode.cpp b/Grbl_Esp32/src/GCode.cpp index 56db75c9..f02d433b 100644 --- a/Grbl_Esp32/src/GCode.cpp +++ b/Grbl_Esp32/src/GCode.cpp @@ -93,9 +93,7 @@ void collapseGCode(char* line) { break; case ';': // NOTE: ';' comment to EOL is a LinuxCNC definition. Not NIST. -#ifdef REPORT_SEMICOLON_COMMENTS - report_gcode_comment(inPtr + 1); -#endif + // report_gcode_comment(inPtr + 1); *outPtr = '\0'; return; case '%': diff --git a/Grbl_Esp32/src/Limits.cpp b/Grbl_Esp32/src/Limits.cpp index 22d5a118..da7d35e1 100644 --- a/Grbl_Esp32/src/Limits.cpp +++ b/Grbl_Esp32/src/Limits.cpp @@ -32,14 +32,6 @@ xQueueHandle limit_sw_queue; // used by limit switch debouncing -// Homing axis search distance multiplier. Computed by this value times the cycle travel. -#ifndef HOMING_AXIS_SEARCH_SCALAR -# define HOMING_AXIS_SEARCH_SCALAR 1.1 // Must be > 1 to ensure limit switch will be engaged. -#endif -#ifndef HOMING_AXIS_LOCATE_SCALAR -# define HOMING_AXIS_LOCATE_SCALAR 5.0 // Must be > 1 to ensure limit switch is cleared. -#endif - void IRAM_ATTR isr_limit_switches(void* /*unused */) { // Ignore limit switches if already in an alarm state or in-process of executing an alarm. // When in the alarm state, Grbl should have been reset or will force a reset, so any pending @@ -48,24 +40,18 @@ void IRAM_ATTR isr_limit_switches(void* /*unused */) { // limit setting if their limits are constantly triggering after a reset and move their axes. if (sys.state != State::Alarm && sys.state != State::ConfigAlarm && sys.state != State::Homing) { if (sys_rt_exec_alarm == ExecAlarm::None) { -#ifdef ENABLE_SOFTWARE_DEBOUNCE - // we will start a task that will recheck the switches after a small delay - int evt; - xQueueSendFromISR(limit_sw_queue, &evt, NULL); -#else -# ifdef HARD_LIMIT_FORCE_STATE_CHECK - // Check limit pin state. - if (limits_get_state()) { - debug_all("Hard limits"); - mc_reset(); // Initiate system kill. - sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event + if (config->_softwareDebounceMs) { + // we will start a task that will recheck the switches after a small delay + int evt; + xQueueSendFromISR(limit_sw_queue, &evt, NULL); + } else { + // Check limit pin state. + if (limits_get_state()) { + debug_all("Hard limits"); + mc_reset(); // Initiate system kill. + sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event + } } -# else - debug_all("Hard limits"); - mc_reset(); // Initiate system kill. - sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event -# endif -#endif } } } @@ -188,11 +174,13 @@ void limits_go_home(uint8_t cycle_mask, uint n_locate_cycles) { } } // Scale the target array, currently in units of time, back to positions - // The SCALAR adds a small fudge factor to ensure that the limit is reached - limitingRate *= approach ? HOMING_AXIS_SEARCH_SCALAR : HOMING_AXIS_LOCATE_SCALAR; + // Add a small fudge factor to ensure that the limit is reached for (int axis = 0; axis < n_axis; axis++) { + auto axisConfig = config->_axes->_axis[axis]; + auto homing = axisConfig->_homing; + auto scaler = approach ? homing->_search_scaler : homing->_locate_scaler; if (bitnum_istrue(axislock, axis)) { - target[axis] *= limitingRate; + target[axis] *= limitingRate * scaler; } } homing_rate = sqrt(homing_rate); // Magnitude of homing rate vector @@ -274,7 +262,7 @@ void limits_go_home(uint8_t cycle_mask, uint n_locate_cycles) { // Set machine positions for homed limit switches. Don't update non-homed axes. for (int axis = 0; axis < n_axis; axis++) { Machine::Axis* axisConf = config->_axes->_axis[axis]; - auto homing = axisConf->_homing; + auto homing = axisConf->_homing; if (homing != nullptr && bitnum_istrue(cycle_mask, axis)) { auto mpos = homing->_mpos; auto pulloff = homing->_pulloff; @@ -310,22 +298,22 @@ void limits_init() { pin.detachInterrupt(); } - if (limit_sw_queue == NULL) { - info_serial("%s limit on %s", reportAxisNameMsg(axis, gang_index), pin.name().c_str()); - } + info_serial("%s limit on %s", reportAxisNameMsg(axis, gang_index), pin.name().c_str()); } } } - // setup task used for debouncing - if (limit_sw_queue == NULL) { - limit_sw_queue = xQueueCreate(10, sizeof(int)); - xTaskCreate(limitCheckTask, - "limitCheckTask", - 2048, - NULL, - 5, // priority - NULL); + if (limit_sw_queue == NULL && config->_softwareDebounceMs != 0) { + // setup task used for debouncing + if (limit_sw_queue == NULL) { + limit_sw_queue = xQueueCreate(10, sizeof(int)); + xTaskCreate(limitCheckTask, + "limitCheckTask", + 2048, + NULL, + 5, // priority + NULL); + } } } @@ -390,14 +378,13 @@ void limits_soft_check(float* target) { } } -// this is the task void limitCheckTask(void* pvParameters) { while (true) { std::atomic_thread_fence(std::memory_order::memory_order_seq_cst); // read fence for settings int evt; - xQueueReceive(limit_sw_queue, &evt, portMAX_DELAY); // block until receive queue - vTaskDelay(DEBOUNCE_PERIOD / portTICK_PERIOD_MS); // delay a while + xQueueReceive(limit_sw_queue, &evt, portMAX_DELAY); // block until receive queue + vTaskDelay(config->_softwareDebounceMs / portTICK_PERIOD_MS); // delay a while AxisMask switch_state; switch_state = limits_get_state(); if (switch_state) { diff --git a/Grbl_Esp32/src/Machine/Homing.h b/Grbl_Esp32/src/Machine/Homing.h index 1da73279..577bb545 100644 --- a/Grbl_Esp32/src/Machine/Homing.h +++ b/Grbl_Esp32/src/Machine/Homing.h @@ -33,6 +33,8 @@ namespace Machine { float _seekRate = 100; float _pulloff = 1.0; // mm int _debounce = 10; + float _search_scaler = 1.1; + float _locate_scaler = 5.0; // Configuration system helpers: void validate() const override { Assert(_cycle >= 1, "Cycle has to be defined as >= 1 for homing sequence."); } @@ -46,6 +48,8 @@ namespace Machine { handler.item("debounce", _debounce); handler.item("pulloff", _pulloff); handler.item("square", _square); + handler.item("search_scaler", _search_scaler); + handler.item("locate_scaler", _locate_scaler); } }; } diff --git a/Grbl_Esp32/src/Machine/MachineConfig.cpp b/Grbl_Esp32/src/Machine/MachineConfig.cpp index 8c96a6b8..953ec9ee 100644 --- a/Grbl_Esp32/src/Machine/MachineConfig.cpp +++ b/Grbl_Esp32/src/Machine/MachineConfig.cpp @@ -60,6 +60,7 @@ namespace Machine { handler.item("idle_time", _idleTime); handler.section("user_outputs", _userOutputs); handler.section("sdcard", _sdCard); + handler.item("software_debounce_ms", _softwareDebounceMs); handler.item("step_type", _stepType, stepTypes); // TODO: Consider putting these under a gcode: hierarchy level? Or motion control? diff --git a/Grbl_Esp32/src/Machine/MachineConfig.h b/Grbl_Esp32/src/Machine/MachineConfig.h index 87a684eb..eaade29f 100644 --- a/Grbl_Esp32/src/Machine/MachineConfig.h +++ b/Grbl_Esp32/src/Machine/MachineConfig.h @@ -38,8 +38,6 @@ #include "Communications.h" #include "UserOutputs.h" -// TODO FIXME: Split this file up into several files, perhaps put it in some folder and namespace Machine? - namespace Machine { class MachineConfig : public Configuration::Configurable { public: @@ -61,14 +59,15 @@ namespace Machine { int _directionDelayMicroSeconds = 0; int _disableDelayMicroSeconds = 0; - bool _laserMode = false; - float _arcTolerance = 0.002; - float _junctionDeviation = 0.01; - uint8_t _idleTime = 255; - bool _verboseErrors = false; - bool _reportInches = false; - bool _homingInitLock = false; - int _stepType = ST_RMT; + bool _laserMode = false; + float _arcTolerance = 0.002; + float _junctionDeviation = 0.01; + uint8_t _idleTime = 255; + bool _verboseErrors = false; + bool _reportInches = false; + bool _homingInitLock = false; + int _softwareDebounceMs = 0; + int _stepType = ST_RMT; // Enables a special set of M-code commands that enables and disables the parking motion. // These are controlled by `M56`, `M56 P1`, or `M56 Px` to enable and `M56 P0` to disable. diff --git a/Grbl_Esp32/src/MotionControl.cpp b/Grbl_Esp32/src/MotionControl.cpp index 586a6c47..7aaa86d5 100644 --- a/Grbl_Esp32/src/MotionControl.cpp +++ b/Grbl_Esp32/src/MotionControl.cpp @@ -403,11 +403,7 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par } // TODO: Need to update this cycle so it obeys a non-auto cycle start. if (sys.state == State::CheckMode) { -#ifdef SET_CHECK_MODE_PROBE_TO_START - return GCUpdatePos::None; -#else - return GCUpdatePos::Target; -#endif + return config->_probe->_check_mode_start ? GCUpdatePos::None : GCUpdatePos::Target; } // Finish all queued commands and empty planner buffer before starting probe cycle. protocol_buffer_synchronize(); diff --git a/Grbl_Esp32/src/Motors/Dynamixel2.cpp b/Grbl_Esp32/src/Motors/Dynamixel2.cpp index f1eba529..3ac833e5 100644 --- a/Grbl_Esp32/src/Motors/Dynamixel2.cpp +++ b/Grbl_Esp32/src/Motors/Dynamixel2.cpp @@ -54,7 +54,7 @@ namespace Motors { vTaskDelay(100); LED_on(false); - startUpdateTask(); + startUpdateTask(_timer_ms); } void Dynamixel2::config_message() { diff --git a/Grbl_Esp32/src/Motors/RcServo.cpp b/Grbl_Esp32/src/Motors/RcServo.cpp index c36154d9..15f8d495 100644 --- a/Grbl_Esp32/src/Motors/RcServo.cpp +++ b/Grbl_Esp32/src/Motors/RcServo.cpp @@ -47,7 +47,7 @@ namespace Motors { _disabled = true; config_message(); - startUpdateTask(); + startUpdateTask(_timer_ms); } void RcServo::config_message() { diff --git a/Grbl_Esp32/src/Motors/Servo.cpp b/Grbl_Esp32/src/Motors/Servo.cpp index 99473656..e1176f2f 100644 --- a/Grbl_Esp32/src/Motors/Servo.cpp +++ b/Grbl_Esp32/src/Motors/Servo.cpp @@ -42,13 +42,16 @@ namespace Motors { List = this; } - void Servo::startUpdateTask() { + void Servo::startUpdateTask(int ms) { + if (_timer_ms == 0 || ms < _timer_ms) { + _timer_ms = ms; + } info_serial("Servo Update Task Started"); if (this == List) { xTaskCreatePinnedToCore(updateTask, // task "servoUpdateTask", // name for task 4096, // size of task stack - NULL, // parameters + (void*)_timer_ms, // parameters 1, // priority NULL, // handle SUPPORT_TASK_CORE // core @@ -58,7 +61,7 @@ namespace Motors { void Servo::updateTask(void* pvParameters) { TickType_t xLastWakeTime; - const TickType_t xUpdate = SERVO_TIMER_INTERVAL; // in ticks (typically ms) + const TickType_t xUpdate = TickType_t(pvParameters) / portTICK_PERIOD_MS; // in ticks (typically ms) auto n_axis = config->_axes->_numberAxis; xLastWakeTime = xTaskGetTickCount(); // Initialise the xLastWakeTime variable with the current time. diff --git a/Grbl_Esp32/src/Motors/Servo.h b/Grbl_Esp32/src/Motors/Servo.h index 5656dbea..81cf3ff0 100644 --- a/Grbl_Esp32/src/Motors/Servo.h +++ b/Grbl_Esp32/src/Motors/Servo.h @@ -28,6 +28,8 @@ namespace Motors { class Servo : public Motor { public: + int _timer_ms = 75; + Servo(); #if 0 // Overrides for inherited methods @@ -37,13 +39,14 @@ namespace Motors { void set_disable(bool disable) override; #endif virtual void update() = 0; // This must be implemented by derived classes + void group(Configuration::HandlerBase& handler) override { handler.item("timer_ms", _timer_ms); } protected: // Start the servo update task. Each derived subclass instance calls this // during init(), which happens after all objects have been constructed. - // startUpdateTask() ignores all such calls except for the last one, where - // it starts the task. - void startUpdateTask(); + // startUpdateTask(ms) finds the smallest update interval among all + // the calls, and starts the task on the final call. + void startUpdateTask(int ms); private: // Linked list of servo instances, used by the servo task diff --git a/Grbl_Esp32/src/Probe.cpp b/Grbl_Esp32/src/Probe.cpp index 5a54f45f..4a228fdf 100644 --- a/Grbl_Esp32/src/Probe.cpp +++ b/Grbl_Esp32/src/Probe.cpp @@ -59,4 +59,5 @@ void Probe::validate() const {} void Probe::group(Configuration::HandlerBase& handler) { handler.item("pin", _probePin); + handler.item("check_mode_start", _check_mode_start); } diff --git a/Grbl_Esp32/src/Probe.h b/Grbl_Esp32/src/Probe.h index fedae603..523294ca 100644 --- a/Grbl_Esp32/src/Probe.h +++ b/Grbl_Esp32/src/Probe.h @@ -34,12 +34,19 @@ enum class ProbeState : uint8_t { }; class Probe : public Configuration::Configurable { - Pin _probePin; - // Inverts the probe pin state depending on user settings and probing cycle mode. bool _isProbeAway = false; + // Configurable + Pin _probePin; + public: + // Configurable + bool _check_mode_start = true; + // _check_mode_start configures the position after a probing cycle + // during check mode. false sets the position to the probe target, + // true sets the position to the start position. + Probe() = default; bool exists() const { return _probePin.defined(); } diff --git a/Grbl_Esp32/src/Serial.cpp b/Grbl_Esp32/src/Serial.cpp index 7c2de1d9..b7800ad4 100644 --- a/Grbl_Esp32/src/Serial.cpp +++ b/Grbl_Esp32/src/Serial.cpp @@ -324,11 +324,9 @@ void client_write(uint8_t client, const char* text) { } if (client == CLIENT_SERIAL || client == CLIENT_ALL) { -#ifdef REVERT_TO_ARDUINO_SERIAL - Serial.write(text); -#else + // This used to be Serial.write(text) before we made the Uart class + // The Arduino HardwareSerial class is buggy in some versions. Uart0.write(text); -#endif } } diff --git a/Grbl_Esp32/src/SettingsDefinitions.cpp b/Grbl_Esp32/src/SettingsDefinitions.cpp index 1d970946..ec8aa236 100644 --- a/Grbl_Esp32/src/SettingsDefinitions.cpp +++ b/Grbl_Esp32/src/SettingsDefinitions.cpp @@ -66,7 +66,7 @@ void make_settings() { // GRBL Numbered Settings build_info = new StringSetting(EXTENDED, WG, NULL, "Firmware/Build", ""); - status_mask = new IntSetting(GRBL, WG, "10", "Report/Status", DEFAULT_STATUS_REPORT_MASK, 0, 3); + status_mask = new IntSetting(GRBL, WG, "10", "Report/Status", 1, 0, 3); user_macro3 = new StringSetting(EXTENDED, WG, NULL, "User/Macro3", DEFAULT_USER_MACRO3); user_macro2 = new StringSetting(EXTENDED, WG, NULL, "User/Macro2", DEFAULT_USER_MACRO2);