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
// be stored and executed in order. These startup blocks would typically be used to set the g-code
// 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:

View File

@ -410,9 +410,7 @@ uint8_t gc_execute_line(char *line)
break;
case MOTION_MODE_SEEK:
if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);}
else {
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], gc.seek_rate, false);
}
else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], gc.seek_rate, false); }
break;
case MOTION_MODE_LINEAR:
// 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
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(;;) {
@ -59,11 +59,6 @@ int main(void)
// Once here, it is safe to re-initialize the system. At startup, the system will automatically
// reset to finish the initialization process.
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.
serial_reset_read_buffer(); // Clear serial read buffer
@ -84,11 +79,15 @@ int main(void)
// resume.
sys_sync_current_position();
// Reset system variables
// Reset system variables.
sys.abort = false;
sys.execute = 0;
if (sys.state == STATE_LOST && bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) {
report_feedback_message(MESSAGE_POSITION_LOST);
if (sys.state == STATE_ALARM && bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) {
// 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 {
sys.state = STATE_IDLE;
}

View File

@ -215,7 +215,7 @@ void mc_go_home()
limits_go_home(); // Perform homing routine.
if (sys.abort) {
sys.state = STATE_LOST; // Homing routine did not complete.
sys.state = STATE_ALARM; // Homing routine did not complete.
return;
}
@ -253,7 +253,8 @@ void mc_alarm()
// Only this function can set the system alarm. This is done to prevent multiple kill calls
// by different processes.
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;
// Immediately force stepper, spindle, and coolant to stop.
st_go_idle();

View File

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

View File

@ -102,22 +102,25 @@ void protocol_execute_runtime()
if (sys.execute) { // Enter only if any bit flag is true
uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times
// System alarm. Something has gone wrong. Disable everything by entering an infinite
// loop until system reset/abort.
// System alarm. Everything has shutdown by either something that has gone wrong or issuing
// 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) {
// Report the cause of the alarm here in the main program.
if (sys.state == STATE_LIMIT) { report_status_message(STATUS_HARD_LIMIT); }
if (sys.state == STATE_CYCLE) { // Pick up abort during active cycle.
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)) {
// Limit switch critical event. Lock out Grbl until reset.
if (sys.state == STATE_LIMIT) {
report_status_message(STATUS_HARD_LIMIT);
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(); }
}
// 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);
}
@ -193,8 +196,8 @@ uint8_t protocol_execute_line(char *line)
case 'H' : // Perform homing cycle
if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) {
// Only perform homing if Grbl is idle or lost.
if ( sys.state==STATE_IDLE || sys.state==STATE_LOST ) { mc_go_home(); }
else { return(STATUS_HOMING_ERROR); }
if ( sys.state==STATE_IDLE || sys.state==STATE_ALARM ) { mc_go_home(); }
else { return(STATUS_IDLE_ERROR); }
} else { return(STATUS_SETTING_DISABLED); }
break;
// 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
// on its own carefully. This approach could be effective and possibly size/memory efficient.
case 'S' : // Switch modes
if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
// Set helper_var as switch bitmask or clearing flag
switch (line[++char_counter]) {
case '0' :
helper_var = BITFLAG_CHECK_GCODE;
// 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 '0' : helper_var = BITFLAG_CHECK_GCODE; break;
case '1' : helper_var = BITFLAG_DRY_RUN; break;
case '2' : helper_var = BITFLAG_BLOCK_DELETE; break;
case '3' : helper_var = BITFLAG_SINGLE_BLOCK; break;
case '4' : helper_var = BITFLAG_OPT_STOP; break;
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 (sys.state == STATE_CYCLE) { return(STATUS_PURGE_CYCLE); } // Also prevents position error
plan_reset_buffer();
if (sys.state == STATE_LOST) {
report_feedback_message(MESSAGE_PURGE_AXES_LOCK);
sys_sync_current_position(); // Any motion commands during a lock can unsync position vectors.
if ( helper_var & (BITFLAG_CHECK_GCODE | BITFLAG_DRY_RUN) ) {
if ( bit_istrue(gc.switches,helper_var) ) {
// Perform reset and check for cycle when toggling off. If disabled while in cycle,
// immediately stop everything and notify user that stopping mid-cycle and likely
// 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;
case 'N' : // Startup lines.
if ( line[++char_counter] == 0 ) { // Print startup lines
for (helper_var=0; helper_var < N_STARTUP_LINE; helper_var++) {
if (!(settings_read_startup_line(helper_var, line))) {
report_status_message(STATUS_SETTING_READ_FAIL);
report_status_message(STATUS_SETTING_READ_FAIL);
} else {
report_startup_line(helper_var,line);
}
@ -287,12 +288,17 @@ uint8_t protocol_execute_line(char *line)
return(STATUS_OK); // If '$' command makes it to here, then everything's ok.
} else {
return(gc_execute_line(line)); // Everything else is gcode
// 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.
// If homing is enabled and position is lost, lock out all g-code commands.
if (sys.state != STATE_ALARM) {
return(gc_execute_line(line)); // Everything else is gcode
// 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:
printPgmString(PSTR("Invalid statement")); break;
case STATUS_HARD_LIMIT:
printPgmString(PSTR("Limit triggered")); break;
printPgmString(PSTR("Limit triggered. MPos lost?")); break;
case STATUS_SETTING_DISABLED:
printPgmString(PSTR("Setting disabled")); break;
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;
case STATUS_SETTING_READ_FAIL:
printPgmString(PSTR("Failed to read EEPROM settings. Using defaults")); break;
case STATUS_HOMING_ERROR:
printPgmString(PSTR("Must be idle to home")); break;
case STATUS_IDLE_ERROR:
printPgmString(PSTR("Must be idle to execute")); break;
case STATUS_ABORT_CYCLE:
printPgmString(PSTR("Abort during cycle. Position maybe lost")); break;
case STATUS_PURGE_CYCLE:
printPgmString(PSTR("Can't purge buffer during cycle")); break;
printPgmString(PSTR("Abort during cycle. MPos lost?")); break;
case STATUS_HOMING_LOCK:
printPgmString(PSTR("Locked until homed")); break;
}
printPgmString(PSTR("\r\n"));
}
@ -94,18 +94,16 @@ void report_feedback_message(int8_t message_code)
{
printPgmString(PSTR("["));
switch(message_code) {
case MESSAGE_SYSTEM_ALARM:
printPgmString(PSTR("ALARM: Check and reset Grbl")); break;
case MESSAGE_POSITION_LOST:
printPgmString(PSTR("'$H' to home and enable axes")); break;
case MESSAGE_HOMING_ENABLE:
printPgmString(PSTR("WARNING: All limit switches must be installed before homing")); break;
case MESSAGE_SWITCH_ON:
printPgmString(PSTR("Switch enabled")); break;
case MESSAGE_SWITCH_OFF:
printPgmString(PSTR("Switch disabled")); break;
case MESSAGE_PURGE_AXES_LOCK:
printPgmString(PSTR("WARNING: Motion lock disabled. Position unknown.")); break;
case MESSAGE_CRITICAL_EVENT:
printPgmString(PSTR("ALARM: Check and reset")); break;
case MESSAGE_HOMING_ALARM:
printPgmString(PSTR("'$H' to home and unlock")); break;
case MESSAGE_ENABLED:
printPgmString(PSTR("Enabled")); break;
case MESSAGE_DISABLED:
printPgmString(PSTR("Disabled")); break;
case MESSAGE_HOMING_UNLOCK:
printPgmString(PSTR("Unlocked. MPos lost?")); break;
}
printPgmString(PSTR("]\r\n"));
}
@ -131,7 +129,7 @@ void report_grbl_help() {
"$S2 (toggle block delete)\r\n"
"$S3 (toggle single block)\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"
"~ (cycle start)\r\n"
"! (feed hold)\r\n"

View File

@ -34,17 +34,16 @@
#define STATUS_SETTING_VALUE_NEG 9
#define STATUS_SETTING_STEP_PULSE_MIN 10
#define STATUS_SETTING_READ_FAIL 11
#define STATUS_HOMING_ERROR 12
#define STATUS_IDLE_ERROR 12
#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 MESSAGE_SYSTEM_ALARM -1
#define MESSAGE_POSITION_LOST -2
#define MESSAGE_HOMING_ENABLE -3
#define MESSAGE_SWITCH_ON -4
#define MESSAGE_SWITCH_OFF -5
#define MESSAGE_PURGE_AXES_LOCK -6
#define MESSAGE_CRITICAL_EVENT -1
#define MESSAGE_HOMING_ALARM -2
#define MESSAGE_ENABLED -3
#define MESSAGE_DISABLED -4
#define MESSAGE_HOMING_UNLOCK -5
// Prints system status messages.
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:
if (value) {
settings.flags |= BITFLAG_HOMING_ENABLE;
sys.state = STATE_LOST;
report_feedback_message(MESSAGE_POSITION_LOST);
report_feedback_message(MESSAGE_HOMING_ENABLE);
sys.state = STATE_ALARM;
report_feedback_message(MESSAGE_HOMING_ALARM);
} else { settings.flags &= ~BITFLAG_HOMING_ENABLE; }
break;
case 15: settings.homing_dir_mask = trunc(value); break;