diff --git a/limits.c b/limits.c index 1da9c54..91180ce 100644 --- a/limits.c +++ b/limits.c @@ -73,6 +73,7 @@ ISR(LIMIT_INT_vect) if (sys.state != STATE_ALARM) { if (bit_isfalse(sys.execute,EXEC_ALARM)) { mc_reset(); // Initiate system kill. + report_alarm_message(ALARM_HARD_LIMIT); sys.execute |= EXEC_CRIT_EVENT; // Indicate hard limit critical event } } diff --git a/motion_control.c b/motion_control.c index ca23c87..6305bb4 100644 --- a/motion_control.c +++ b/motion_control.c @@ -35,6 +35,7 @@ #include "planner.h" #include "limits.h" #include "protocol.h" +#include "report.h" // Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second // unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in @@ -49,9 +50,21 @@ // backlash segment(s). void mc_line(float x, float y, float z, float feed_rate, uint8_t invert_feed_rate) { - // TODO: Perform soft limit check here. Just check if the target x,y,z values are outside the + // TO TEST: Perform soft limit check here. Just check if the target x,y,z values are outside the // work envelope. Should be straightforward and efficient. By placing it here, rather than in // the g-code parser, it directly picks up motions from everywhere in Grbl. + if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) { + if( (x> settings.mm_soft_limit[X_AXIS])||(y>settings.mm_soft_limit[Y_AXIS])||(z>settings.mm_soft_limit[Z_AXIS])) { + if (sys.state != STATE_ALARM) { + if (bit_isfalse(sys.execute,EXEC_ALARM)) { + mc_reset(); // Initiate system kill. + report_alarm_message(ALARM_SOFT_LIMIT); + sys.state = STATE_ALARM; + sys.execute |= EXEC_CRIT_EVENT; // Indicate hard limit critical event + } + } + } + } // If in check gcode mode, prevent motion by blocking planner. if (sys.state == STATE_CHECK_MODE) { return; } diff --git a/protocol.c b/protocol.c index c97770a..fd64c3d 100644 --- a/protocol.c +++ b/protocol.c @@ -104,10 +104,8 @@ void protocol_execute_runtime() // loop until system reset/abort. if (rt_exec & (EXEC_ALARM | EXEC_CRIT_EVENT)) { sys.state = STATE_ALARM; // Set system alarm state - - // Critical event. Only hard limit qualifies. Update this as new critical events surface. - if (rt_exec & EXEC_CRIT_EVENT) { - report_alarm_message(ALARM_HARD_LIMIT); + + if (rt_exec & EXEC_CRIT_EVENT) { report_feedback_message(MESSAGE_CRITICAL_EVENT); bit_false(sys.execute,EXEC_RESET); // Disable any existing reset do { diff --git a/report.c b/report.c index 6b810ad..0895c6a 100644 --- a/report.c +++ b/report.c @@ -88,6 +88,8 @@ void report_alarm_message(int8_t alarm_code) printPgmString(PSTR("Hard limit")); break; case ALARM_ABORT_CYCLE: printPgmString(PSTR("Abort during cycle")); break; + case ALARM_SOFT_LIMIT: + printPgmString(PSTR("Soft Limit")); break; } printPgmString(PSTR(". MPos?\r\n")); delay_ms(500); // Force delay to ensure message clears serial write buffer. @@ -172,7 +174,11 @@ void report_grbl_settings() { printPgmString(PSTR(" (homing feed, mm/min)\r\n$23=")); printFloat(settings.homing_seek_rate); printPgmString(PSTR(" (homing seek, mm/min)\r\n$24=")); printInteger(settings.homing_debounce_delay); printPgmString(PSTR(" (homing debounce, msec)\r\n$25=")); printFloat(settings.homing_pulloff); - printPgmString(PSTR(" (homing pull-off, mm)\r\n")); + printPgmString(PSTR(" (homing pull-off, mm)\r\n$26=")); printFloat(settings.mm_soft_limit[X_AXIS]); + printPgmString(PSTR(" (x, max travel)\r\n$27=")); printFloat(settings.mm_soft_limit[Y_AXIS]); + printPgmString(PSTR(" (y, max travel)\r\n$28=")); printFloat(settings.mm_soft_limit[Z_AXIS]); + printPgmString(PSTR(" (z, max travel)\r\n$29=")); printInteger(bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)); + printPgmString(PSTR(" (soft limits enabled, bool)\r\n")); } diff --git a/report.h b/report.h index 8f1555c..cd3cb2b 100644 --- a/report.h +++ b/report.h @@ -39,6 +39,7 @@ // Define Grbl alarm codes. Less than zero to distinguish alarm error from status error. #define ALARM_HARD_LIMIT -1 #define ALARM_ABORT_CYCLE -2 +#define ALARM_SOFT_LIMIT -3 // Define Grbl feedback message codes. #define MESSAGE_CRITICAL_EVENT 1 diff --git a/settings.c b/settings.c index 2f75e6e..798d62c 100644 --- a/settings.c +++ b/settings.c @@ -200,6 +200,13 @@ uint8_t settings_store_global_setting(int parameter, float value) { case 23: settings.homing_seek_rate = value; break; case 24: settings.homing_debounce_delay = round(value); break; case 25: settings.homing_pulloff = value; break; + case 26: case 27: case 28: + if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); } + settings.mm_soft_limit[parameter-26] = value; break; + case 29: + if (value) { settings.flags |= BITFLAG_SOFT_LIMIT_ENABLE; } + else { settings.flags &= ~BITFLAG_SOFT_LIMIT_ENABLE; } + break; default: return(STATUS_INVALID_STATEMENT); } diff --git a/settings.h b/settings.h index 221c4fb..b614fa3 100644 --- a/settings.h +++ b/settings.h @@ -37,6 +37,7 @@ #define BITFLAG_INVERT_ST_ENABLE bit(2) #define BITFLAG_HARD_LIMIT_ENABLE bit(3) #define BITFLAG_HOMING_ENABLE bit(4) +#define BITFLAG_SOFT_LIMIT_ENABLE bit(5) // Define EEPROM memory address location values for Grbl settings and parameters // NOTE: The Atmega328p has 1KB EEPROM. The upper half is reserved for parameters and @@ -74,7 +75,7 @@ typedef struct { uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable. uint8_t decimal_places; float max_velocity[N_AXIS]; -// float mm_soft_limit[N_AXIS]; + float mm_soft_limit[N_AXIS]; // uint8_t status_report_mask; // Mask to indicate desired report data. } settings_t; extern settings_t settings;