Tweaks and bug fixes. Increase to 3 startup blocks. Remove purge/added unlock command

- Increased the number of startup blocks to 3 for no good reason other
than it doesn't increase the flash size.

- Removed the purge buffer command and replaced with an disable homing
lock command.

- Homing now blocks all g-code commands (not system commands) until the
homing cycle has been performed or the disable homing lock is sent.
Homing is required upon startup or if Grbl loses it position. This is
for safety reasons.

- Cleaned up some of the Grbl states and re-organized it to be little
more cohesive.

- Cleaned up the feedback and status messages to not use so much flash
space, as it's a premium now.

 - Check g-code and dry run switches how are mutually exclusive and
can't be enabled when the other is. And automatically resets Grbl when
disabled.

- Some bug fixes and other minor tweaks.
This commit is contained in:
Sonny Jeon 2012-11-05 21:40:52 -07:00
parent c2b31a06ff
commit f41dd69273
9 changed files with 96 additions and 97 deletions

View File

@ -164,7 +164,7 @@
// and addresses are defined in settings.h. With the current settings, up to 5 startup blocks may // and addresses are defined in settings.h. With the current settings, up to 5 startup blocks may
// be stored and executed in order. These startup blocks would typically be used to set the g-code // be stored and executed in order. These startup blocks would typically be used to set the g-code
// parser state depending on user preferences. // parser state depending on user preferences.
#define N_STARTUP_LINE 1 // Integer (1-5) #define N_STARTUP_LINE 3 // Integer (1-5)
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
// FOR ADVANCED USERS ONLY: // FOR ADVANCED USERS ONLY:

View File

@ -410,9 +410,7 @@ uint8_t gc_execute_line(char *line)
break; break;
case MOTION_MODE_SEEK: case MOTION_MODE_SEEK:
if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);} if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);}
else { else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], gc.seek_rate, false); }
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], gc.seek_rate, false);
}
break; break;
case MOTION_MODE_LINEAR: case MOTION_MODE_LINEAR:
// TODO: Inverse time requires F-word with each statement. Need to do a check. Also need // TODO: Inverse time requires F-word with each statement. Need to do a check. Also need

17
main.c
View File

@ -51,7 +51,7 @@ int main(void)
memset(&sys, 0, sizeof(sys)); // Clear all system variables memset(&sys, 0, sizeof(sys)); // Clear all system variables
sys.abort = true; // Set abort to complete initialization sys.abort = true; // Set abort to complete initialization
sys.state = STATE_LOST; // Set state to indicate unknown initial position sys.state = STATE_ALARM; // Set alarm state to indicate unknown initial position
for(;;) { for(;;) {
@ -59,11 +59,6 @@ int main(void)
// Once here, it is safe to re-initialize the system. At startup, the system will automatically // Once here, it is safe to re-initialize the system. At startup, the system will automatically
// reset to finish the initialization process. // reset to finish the initialization process.
if (sys.abort) { if (sys.abort) {
// If a critical event has occurred, set the position lost system state. For example, a
// hard limit event can cause the stepper to lose steps and position due to an immediate
// stop, not with a controlled deceleration. Or, if an abort was issued while a cycle
// was active, the immediate stop can also cause lost steps.
if (sys.state == STATE_ALARM) { sys.state = STATE_LOST; }
// Reset system. // Reset system.
serial_reset_read_buffer(); // Clear serial read buffer serial_reset_read_buffer(); // Clear serial read buffer
@ -84,11 +79,15 @@ int main(void)
// resume. // resume.
sys_sync_current_position(); sys_sync_current_position();
// Reset system variables // Reset system variables.
sys.abort = false; sys.abort = false;
sys.execute = 0; sys.execute = 0;
if (sys.state == STATE_LOST && bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { if (sys.state == STATE_ALARM && bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) {
report_feedback_message(MESSAGE_POSITION_LOST); // If a critical event has occurred, set the position lost system state. For example, a
// hard limit event can cause the stepper to lose steps and position due to an immediate
// stop, not with a controlled deceleration. Or, if an abort was issued while a cycle
// was active, the immediate stop can also cause lost steps.
report_feedback_message(MESSAGE_HOMING_ALARM);
} else { } else {
sys.state = STATE_IDLE; sys.state = STATE_IDLE;
} }

View File

@ -215,7 +215,7 @@ void mc_go_home()
limits_go_home(); // Perform homing routine. limits_go_home(); // Perform homing routine.
if (sys.abort) { if (sys.abort) {
sys.state = STATE_LOST; // Homing routine did not complete. sys.state = STATE_ALARM; // Homing routine did not complete.
return; return;
} }
@ -253,7 +253,8 @@ void mc_alarm()
// Only this function can set the system alarm. This is done to prevent multiple kill calls // Only this function can set the system alarm. This is done to prevent multiple kill calls
// by different processes. // by different processes.
if (bit_isfalse(sys.execute, EXEC_ALARM)) { if (bit_isfalse(sys.execute, EXEC_ALARM)) {
// Set system alarm flag. // Set system alarm flag to have the main program check for anything wrong with shutting
// down the system.
sys.execute |= EXEC_ALARM; sys.execute |= EXEC_ALARM;
// Immediately force stepper, spindle, and coolant to stop. // Immediately force stepper, spindle, and coolant to stop.
st_go_idle(); st_go_idle();

View File

@ -75,9 +75,8 @@
#define STATE_HOLD 3 // Executing feed hold #define STATE_HOLD 3 // Executing feed hold
#define STATE_HOMING 4 // Performing homing cycle #define STATE_HOMING 4 // Performing homing cycle
#define STATE_JOG 5 // Jogging mode is unique like homing. #define STATE_JOG 5 // Jogging mode is unique like homing.
#define STATE_ALARM 6 // In alarm state. Locks out all but reset #define STATE_ALARM 6 // In alarm state. Locks out all g-code processes and messages position lost
#define STATE_LOST 7 // Used to message position may be lost upon startup or event #define STATE_LIMIT 7 // Used to message hard limit triggered.
#define STATE_LIMIT 8 // Used to message hard limit triggered.
// Define global system variables // Define global system variables
typedef struct { typedef struct {

View File

@ -102,22 +102,25 @@ void protocol_execute_runtime()
if (sys.execute) { // Enter only if any bit flag is true if (sys.execute) { // Enter only if any bit flag is true
uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times
// System alarm. Something has gone wrong. Disable everything by entering an infinite // System alarm. Everything has shutdown by either something that has gone wrong or issuing
// loop until system reset/abort. // the Grbl soft-reset/abort. Check the system states to report any critical error found.
// If critical, disable Grbl by entering an infinite loop until system reset/abort.
// NOTE: The system alarm state is also used to set
if (rt_exec & EXEC_ALARM) { if (rt_exec & EXEC_ALARM) {
// Report the cause of the alarm here in the main program. // Limit switch critical event. Lock out Grbl until reset.
if (sys.state == STATE_LIMIT) { report_status_message(STATUS_HARD_LIMIT); } if (sys.state == STATE_LIMIT) {
if (sys.state == STATE_CYCLE) { // Pick up abort during active cycle. report_status_message(STATUS_HARD_LIMIT);
report_status_message(STATUS_ABORT_CYCLE);
sys.state = STATE_LOST;
}
// Ignore loop if reset is already issued. In other words, a normal system abort/reset
// will not enter this loop, only a critical event not controlled by the user will.
if (bit_isfalse(rt_exec,EXEC_RESET)) {
sys.state = STATE_ALARM; sys.state = STATE_ALARM;
report_feedback_message(MESSAGE_SYSTEM_ALARM); report_feedback_message(MESSAGE_CRITICAL_EVENT);
while (bit_isfalse(sys.execute,EXEC_RESET)) { sleep_mode(); } while (bit_isfalse(sys.execute,EXEC_RESET)) { sleep_mode(); }
} }
// Check if a runtime abort command was issued during a cycle. If so, message the user
// that position may have been lost and set alarm state to force re-homing, if enabled.
if (sys.state == STATE_CYCLE) {
report_status_message(STATUS_ABORT_CYCLE);
sys.state = STATE_ALARM;
}
bit_false(sys.execute,EXEC_ALARM); bit_false(sys.execute,EXEC_ALARM);
} }
@ -193,8 +196,8 @@ uint8_t protocol_execute_line(char *line)
case 'H' : // Perform homing cycle case 'H' : // Perform homing cycle
if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) {
// Only perform homing if Grbl is idle or lost. // Only perform homing if Grbl is idle or lost.
if ( sys.state==STATE_IDLE || sys.state==STATE_LOST ) { mc_go_home(); } if ( sys.state==STATE_IDLE || sys.state==STATE_ALARM ) { mc_go_home(); }
else { return(STATUS_HOMING_ERROR); } else { return(STATUS_IDLE_ERROR); }
} else { return(STATUS_SETTING_DISABLED); } } else { return(STATUS_SETTING_DISABLED); }
break; break;
// case 'J' : break; // Jogging methods // case 'J' : break; // Jogging methods
@ -210,49 +213,47 @@ uint8_t protocol_execute_line(char *line)
// block buffer without having the planner plan them. It would need to manage de/ac-celerations // block buffer without having the planner plan them. It would need to manage de/ac-celerations
// on its own carefully. This approach could be effective and possibly size/memory efficient. // on its own carefully. This approach could be effective and possibly size/memory efficient.
case 'S' : // Switch modes case 'S' : // Switch modes
if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
// Set helper_var as switch bitmask or clearing flag // Set helper_var as switch bitmask or clearing flag
switch (line[++char_counter]) { switch (line[++char_counter]) {
case '0' : case '0' : helper_var = BITFLAG_CHECK_GCODE; break;
helper_var = BITFLAG_CHECK_GCODE; case '1' : helper_var = BITFLAG_DRY_RUN; break;
// If check mode is being disabled, automatically soft reset Grbl to ensure the user starts
// fresh with the g-code modes in their default, known state.
if (bit_istrue(gc.switches,helper_var)) { sys.execute |= EXEC_RESET; }
break;
case '1' :
helper_var = BITFLAG_DRY_RUN;
// If dry run is being disabled, automatically soft reset Grbl as with check g-code mode
if (bit_istrue(gc.switches,helper_var)) {
// If disabled while in cycle, immediately stop everything and notify user that stopping
// mid-cycle likely lost position.
if (bit_istrue(sys.state,STATE_CYCLE)) { mc_alarm(); }
sys.execute |= EXEC_RESET; // Soft-reset Grbl.
}
break;
case '2' : helper_var = BITFLAG_BLOCK_DELETE; break; case '2' : helper_var = BITFLAG_BLOCK_DELETE; break;
case '3' : helper_var = BITFLAG_SINGLE_BLOCK; break; case '3' : helper_var = BITFLAG_SINGLE_BLOCK; break;
case '4' : helper_var = BITFLAG_OPT_STOP; break; case '4' : helper_var = BITFLAG_OPT_STOP; break;
default : return(STATUS_INVALID_STATEMENT); default : return(STATUS_INVALID_STATEMENT);
} }
gc.switches ^= helper_var;
if (bit_istrue(gc.switches,helper_var)) { report_feedback_message(MESSAGE_SWITCH_ON); }
else { report_feedback_message(MESSAGE_SWITCH_OFF); }
break;
case 'P' : // Purge system
if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
if (sys.state == STATE_CYCLE) { return(STATUS_PURGE_CYCLE); } // Also prevents position error if ( helper_var & (BITFLAG_CHECK_GCODE | BITFLAG_DRY_RUN) ) {
plan_reset_buffer(); if ( bit_istrue(gc.switches,helper_var) ) {
if (sys.state == STATE_LOST) { // Perform reset and check for cycle when toggling off. If disabled while in cycle,
report_feedback_message(MESSAGE_PURGE_AXES_LOCK); // immediately stop everything and notify user that stopping mid-cycle and likely
sys_sync_current_position(); // Any motion commands during a lock can unsync position vectors. // lost position. In check g-code mode, there is never a cycle.
if (sys.state == STATE_CYCLE) { mc_alarm(); }
sys.execute |= EXEC_RESET; // Soft-reset Grbl.
} else {
// Check if Grbl is idle and ready or if the other mode is enabled.
if (sys.state) { return(STATUS_IDLE_ERROR); }
if ((gc.switches & (BITFLAG_CHECK_GCODE | BITFLAG_DRY_RUN)) & ~(helper_var)) { return(STATUS_INVALID_STATEMENT); }
}
}
gc.switches ^= helper_var;
if (bit_istrue(gc.switches,helper_var)) { report_feedback_message(MESSAGE_ENABLED); }
else { report_feedback_message(MESSAGE_DISABLED); }
break;
case 'U' : // Disable homing lock
if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
if (sys.state == STATE_ALARM) {
report_feedback_message(MESSAGE_HOMING_UNLOCK);
sys.state = STATE_IDLE;
} else {
return(STATUS_SETTING_DISABLED);
} }
sys.state = STATE_IDLE;
break; break;
case 'N' : // Startup lines. case 'N' : // Startup lines.
if ( line[++char_counter] == 0 ) { // Print startup lines if ( line[++char_counter] == 0 ) { // Print startup lines
for (helper_var=0; helper_var < N_STARTUP_LINE; helper_var++) { for (helper_var=0; helper_var < N_STARTUP_LINE; helper_var++) {
if (!(settings_read_startup_line(helper_var, line))) { if (!(settings_read_startup_line(helper_var, line))) {
report_status_message(STATUS_SETTING_READ_FAIL); report_status_message(STATUS_SETTING_READ_FAIL);
} else { } else {
report_startup_line(helper_var,line); report_startup_line(helper_var,line);
} }
@ -288,10 +289,15 @@ uint8_t protocol_execute_line(char *line)
} else { } else {
return(gc_execute_line(line)); // Everything else is gcode // If homing is enabled and position is lost, lock out all g-code commands.
// TODO: Install option to set system alarm upon any error code received back from the if (sys.state != STATE_ALARM) {
// the g-code parser. This is a common safety feature on CNCs to help prevent crashes return(gc_execute_line(line)); // Everything else is gcode
// if the g-code doesn't perform as intended. // TODO: Install option to set system alarm upon any error code received back from the
// the g-code parser. This is a common safety feature on CNCs to help prevent crashes
// if the g-code doesn't perform as intended.
} else {
return(STATUS_HOMING_LOCK);
}
} }
} }

View File

@ -63,7 +63,7 @@ void report_status_message(uint8_t status_code)
case STATUS_INVALID_STATEMENT: case STATUS_INVALID_STATEMENT:
printPgmString(PSTR("Invalid statement")); break; printPgmString(PSTR("Invalid statement")); break;
case STATUS_HARD_LIMIT: case STATUS_HARD_LIMIT:
printPgmString(PSTR("Limit triggered")); break; printPgmString(PSTR("Limit triggered. MPos lost?")); break;
case STATUS_SETTING_DISABLED: case STATUS_SETTING_DISABLED:
printPgmString(PSTR("Setting disabled")); break; printPgmString(PSTR("Setting disabled")); break;
case STATUS_SETTING_VALUE_NEG: case STATUS_SETTING_VALUE_NEG:
@ -72,12 +72,12 @@ void report_status_message(uint8_t status_code)
printPgmString(PSTR("Step pulse must be >= 3 microseconds")); break; printPgmString(PSTR("Step pulse must be >= 3 microseconds")); break;
case STATUS_SETTING_READ_FAIL: case STATUS_SETTING_READ_FAIL:
printPgmString(PSTR("Failed to read EEPROM settings. Using defaults")); break; printPgmString(PSTR("Failed to read EEPROM settings. Using defaults")); break;
case STATUS_HOMING_ERROR: case STATUS_IDLE_ERROR:
printPgmString(PSTR("Must be idle to home")); break; printPgmString(PSTR("Must be idle to execute")); break;
case STATUS_ABORT_CYCLE: case STATUS_ABORT_CYCLE:
printPgmString(PSTR("Abort during cycle. Position maybe lost")); break; printPgmString(PSTR("Abort during cycle. MPos lost?")); break;
case STATUS_PURGE_CYCLE: case STATUS_HOMING_LOCK:
printPgmString(PSTR("Can't purge buffer during cycle")); break; printPgmString(PSTR("Locked until homed")); break;
} }
printPgmString(PSTR("\r\n")); printPgmString(PSTR("\r\n"));
} }
@ -94,18 +94,16 @@ void report_feedback_message(int8_t message_code)
{ {
printPgmString(PSTR("[")); printPgmString(PSTR("["));
switch(message_code) { switch(message_code) {
case MESSAGE_SYSTEM_ALARM: case MESSAGE_CRITICAL_EVENT:
printPgmString(PSTR("ALARM: Check and reset Grbl")); break; printPgmString(PSTR("ALARM: Check and reset")); break;
case MESSAGE_POSITION_LOST: case MESSAGE_HOMING_ALARM:
printPgmString(PSTR("'$H' to home and enable axes")); break; printPgmString(PSTR("'$H' to home and unlock")); break;
case MESSAGE_HOMING_ENABLE: case MESSAGE_ENABLED:
printPgmString(PSTR("WARNING: All limit switches must be installed before homing")); break; printPgmString(PSTR("Enabled")); break;
case MESSAGE_SWITCH_ON: case MESSAGE_DISABLED:
printPgmString(PSTR("Switch enabled")); break; printPgmString(PSTR("Disabled")); break;
case MESSAGE_SWITCH_OFF: case MESSAGE_HOMING_UNLOCK:
printPgmString(PSTR("Switch disabled")); break; printPgmString(PSTR("Unlocked. MPos lost?")); break;
case MESSAGE_PURGE_AXES_LOCK:
printPgmString(PSTR("WARNING: Motion lock disabled. Position unknown.")); break;
} }
printPgmString(PSTR("]\r\n")); printPgmString(PSTR("]\r\n"));
} }
@ -131,7 +129,7 @@ void report_grbl_help() {
"$S2 (toggle block delete)\r\n" "$S2 (toggle block delete)\r\n"
"$S3 (toggle single block)\r\n" "$S3 (toggle single block)\r\n"
"$S4 (toggle optional stop)\r\n" "$S4 (toggle optional stop)\r\n"
"$P (purge buffer and locks)\r\n" "$U (disable homing lock)\r\n"
"$H (perform homing cycle)\r\n" "$H (perform homing cycle)\r\n"
"~ (cycle start)\r\n" "~ (cycle start)\r\n"
"! (feed hold)\r\n" "! (feed hold)\r\n"

View File

@ -34,17 +34,16 @@
#define STATUS_SETTING_VALUE_NEG 9 #define STATUS_SETTING_VALUE_NEG 9
#define STATUS_SETTING_STEP_PULSE_MIN 10 #define STATUS_SETTING_STEP_PULSE_MIN 10
#define STATUS_SETTING_READ_FAIL 11 #define STATUS_SETTING_READ_FAIL 11
#define STATUS_HOMING_ERROR 12 #define STATUS_IDLE_ERROR 12
#define STATUS_ABORT_CYCLE 13 #define STATUS_ABORT_CYCLE 13
#define STATUS_PURGE_CYCLE 14 #define STATUS_HOMING_LOCK 14
// Define Grbl feedback message codes. Less than zero to distinguish message from error. // Define Grbl feedback message codes. Less than zero to distinguish message from error.
#define MESSAGE_SYSTEM_ALARM -1 #define MESSAGE_CRITICAL_EVENT -1
#define MESSAGE_POSITION_LOST -2 #define MESSAGE_HOMING_ALARM -2
#define MESSAGE_HOMING_ENABLE -3 #define MESSAGE_ENABLED -3
#define MESSAGE_SWITCH_ON -4 #define MESSAGE_DISABLED -4
#define MESSAGE_SWITCH_OFF -5 #define MESSAGE_HOMING_UNLOCK -5
#define MESSAGE_PURGE_AXES_LOCK -6
// Prints system status messages. // Prints system status messages.
void report_status_message(uint8_t status_code); void report_status_message(uint8_t status_code);

View File

@ -202,9 +202,8 @@ uint8_t settings_store_global_setting(int parameter, float value) {
case 14: case 14:
if (value) { if (value) {
settings.flags |= BITFLAG_HOMING_ENABLE; settings.flags |= BITFLAG_HOMING_ENABLE;
sys.state = STATE_LOST; sys.state = STATE_ALARM;
report_feedback_message(MESSAGE_POSITION_LOST); report_feedback_message(MESSAGE_HOMING_ALARM);
report_feedback_message(MESSAGE_HOMING_ENABLE);
} else { settings.flags &= ~BITFLAG_HOMING_ENABLE; } } else { settings.flags &= ~BITFLAG_HOMING_ENABLE; }
break; break;
case 15: settings.homing_dir_mask = trunc(value); break; case 15: settings.homing_dir_mask = trunc(value); break;