From 065ceceb342f1366fc61cdc900af292767a3728d Mon Sep 17 00:00:00 2001 From: Sonny Jeon Date: Sun, 21 Oct 2012 19:18:24 -0600 Subject: [PATCH] New alarm method. Re(re)organized status messages. - Installed a new 'alarm' method to centralize motion kills across alarm or reset events. Right now, this is controlled by system abort and hard limits. But, in the future, a g-code parser error may call this too as a safety feature. - Re(re)organized status messages to just print all errors, regardless from where it was called. This centralizes them into one place. - Misc messages method installed for any user feedback that is not a confirmation or error. Mainly so that there is a place to perform warnings and such. - New stuff installed and still made the flash size smaller by saving flash space from clearing out repeated '\r\n' pgmstrings. - Fixed a bug where hard limits message would print everytime a system abort was sent. --- limits.c | 10 +++--- motion_control.c | 23 +++++++++++++ motion_control.h | 3 ++ protocol.c | 90 +++++++++++++++++++++--------------------------- protocol.h | 34 ++++++++++-------- serial.c | 13 ++----- settings.c | 18 +++++----- settings.h | 4 +-- stepper.c | 2 +- 9 files changed, 103 insertions(+), 94 deletions(-) diff --git a/limits.c b/limits.c index 8e0fa56..52b88df 100755 --- a/limits.c +++ b/limits.c @@ -56,16 +56,14 @@ ISR(LIMIT_INT_vect) if (bit_isfalse(sys.execute,EXEC_ALARM)) { // Kill all processes upon hard limit event. if ((LIMIT_PIN & LIMIT_MASK) ^ LIMIT_MASK) { - st_go_idle(); // Immediately stop stepper motion - spindle_stop(); // Stop spindle - sys.auto_start = false; // Disable auto cycle start. - sys.execute |= EXEC_ALARM; - // TODO: When Grbl system status is installed, update here to indicate loss of position. + mc_alarm(); // Initiate system kill. + protocol_status_message(STATUS_HARD_LIMIT); // Print ok in interrupt since system killed. } // else { // TODO: When leaving a switch, this interrupt can be activated upon detecting a pin // change to high. If so, need to start a countdown timer to check the pin again after - // a debounce period to not falsely re-engage the alarm. + // a debounce period to not falsely re-engage the alarm. Not essential, but *could* be + // a minor annoyance. } } diff --git a/motion_control.c b/motion_control.c index 2cffcc1..bb89275 100755 --- a/motion_control.c +++ b/motion_control.c @@ -25,6 +25,8 @@ #include "config.h" #include "gcode.h" #include "motion_control.h" +#include "spindle_control.h" +#include "coolant_control.h" #include #include #include @@ -223,3 +225,24 @@ void mc_go_home() PCICR |= (1 << LIMIT_INT); // Re-enable hard limits. } } + + +// Method to immediately kill all motion and set system alarm. Used by system abort, hard limits, +// and upon g-code parser error (when installed). +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)) { + sys.execute |= EXEC_ALARM; // Set alarm to allow subsystem disable for certain settings. + sys.auto_start = false; // Disable auto cycle start. + + // TODO: When Grbl system status is installed, set position lost state if the cycle is active. + // if (sys.cycle_start) { POSITION LOST } + + // Immediately force stepper, spindle, and coolant to stop. + st_go_idle(); + spindle_stop(); + coolant_stop(); + } +} diff --git a/motion_control.h b/motion_control.h index 4f988ed..4d71848 100755 --- a/motion_control.h +++ b/motion_control.h @@ -43,4 +43,7 @@ void mc_dwell(float seconds); // Send the tool home (not implemented) void mc_go_home(); +// Kills all motion and sets system alarm +void mc_alarm(); + #endif diff --git a/protocol.c b/protocol.c index a61f254..942b22c 100755 --- a/protocol.c +++ b/protocol.c @@ -36,68 +36,54 @@ static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated. static uint8_t char_counter; // Last character counter in line variable. static uint8_t iscomment; // Comment/block delete flag for processor to ignore comment characters. -// Prints all status messages, an 'ok' or 'error', after Grbl has processed a line of incoming -// serial data, whether this was a g-code block or grbl setting command. -void protocol_status_message(int8_t status_code) +// Method to handle status messages, from an 'ok' to report any 'error' that has occurred. +// Errors can originate from the g-code parser, settings module, or a critical error, such +// as a triggered hard limit. +void protocol_status_message(uint8_t status_code) { // TODO: Compile time option to only return numeric codes for GUIs. if (status_code == 0) { // STATUS_OK printPgmString(PSTR("ok\r\n")); } else { printPgmString(PSTR("error: ")); - // All critical error codes are greater than zero. These are defined to be any error - // that may cause damage by crashing or improper g-code inputs and that are susceptible - // to Grbl's alarm mode which will stop all processes, if the user enables this option. - if (status_code > 0) { - // TODO: Install option to enter alarm mode upon any critical error. - switch(status_code) { - case STATUS_BAD_NUMBER_FORMAT: - printPgmString(PSTR("Bad number format")); break; - case STATUS_EXPECTED_COMMAND_LETTER: - printPgmString(PSTR("Expected command letter")); break; - case STATUS_UNSUPPORTED_STATEMENT: - printPgmString(PSTR("Unsupported statement")); break; - case STATUS_FLOATING_POINT_ERROR: - printPgmString(PSTR("Floating point error")); break; - case STATUS_MODAL_GROUP_VIOLATION: - printPgmString(PSTR("Modal group violation")); break; - case STATUS_INVALID_STATEMENT: - printPgmString(PSTR("Invalid gcode statement")); break; - case STATUS_SETTING_DISABLED: - printPgmString(PSTR("Grbl setting disabled")); break; - case STATUS_HARD_LIMIT: - printPgmString(PSTR("Limit triggered ")); break; - } - // All other non-critical error codes are less than zero. These are defined to be any - // error that is not susceptible to the alarm mode. Typically settings responses. - } else { - switch(status_code) { - case STATUS_SETTING_INVALID: - printPgmString(PSTR("Invalid setting statement")); break; - case STATUS_SETTING_STEPS_NEG: - printPgmString(PSTR("Steps/mm must be > 0.0")); break; - case STATUS_SETTING_STEP_PULSE_MIN: - printPgmString(PSTR("Step pulse must be >= 3 microseconds")); break; - } + switch(status_code) { + case STATUS_BAD_NUMBER_FORMAT: + printPgmString(PSTR("Bad number format")); break; + case STATUS_EXPECTED_COMMAND_LETTER: + printPgmString(PSTR("Expected command letter")); break; + case STATUS_UNSUPPORTED_STATEMENT: + printPgmString(PSTR("Unsupported statement")); break; + case STATUS_FLOATING_POINT_ERROR: + printPgmString(PSTR("Floating point error")); break; + case STATUS_MODAL_GROUP_VIOLATION: + printPgmString(PSTR("Modal group violation")); break; + case STATUS_INVALID_STATEMENT: + printPgmString(PSTR("Invalid statement")); break; + case STATUS_HARD_LIMIT: + printPgmString(PSTR(" Limit triggered")); break; + case STATUS_SETTING_DISABLED: + printPgmString(PSTR("Grbl setting disabled")); break; + case STATUS_SETTING_STEPS_NEG: + printPgmString(PSTR("Steps/mm must be > 0.0")); break; + case STATUS_SETTING_STEP_PULSE_MIN: + printPgmString(PSTR("Step pulse must be >= 3 microseconds")); break; + case STATUS_SETTING_READ_FAIL: + printPgmString(PSTR("Failed to read EEPROM settings. Using defaults")); break; } printPgmString(PSTR("\r\n")); } } -// Prints Grbl warning messages. This serves as a centralized method to provide additional -// user feedback for things that do not pass through the protocol_execute_line() function. -// This includes things like initialization checks or setup warnings when features are -// enabled. This function maybe called from anywhere in Grbl at the point of concern. -void protocol_warning_message(int8_t warning_code) +// Prints miscellaneous messages. This serves as a centralized method to provide additional +// user feedback for things that do not pass through the protocol_execute_line() function +// and are not errors or confirmations, such as setup warnings. +void protocol_misc_message(uint8_t message_code) { - // TODO: Install silence warning messages option in settings - printPgmString(PSTR("warning: ")); - switch(warning_code) { - case WARNING_HOMING_ENABLE: - printPgmString(PSTR("Install all axes limit switches before use")); break; - case WARNING_SETTING_READ_FAIL: - printPgmString(PSTR("Failed to read EEPROM settings. Using defaults")); break; + // TODO: Install silence misc messages option in settings + switch(message_code) { + case MESSAGE_HOMING_ENABLE: + printPgmString(PSTR("warning: Install all axes limit switches before use")); break; } printPgmString(PSTR("\r\n")); } @@ -181,7 +167,6 @@ void protocol_execute_runtime() // System alarm. Something has gone wrong. Disable everything until system reset. if (rt_exec & EXEC_ALARM) { - protocol_status_message(STATUS_HARD_LIMIT); while (bit_isfalse(sys.execute,EXEC_RESET)) { sleep_mode(); } bit_false(sys.execute,EXEC_ALARM); } @@ -223,7 +208,7 @@ void protocol_execute_runtime() // Executes one line of input according to protocol -int8_t protocol_execute_line(char *line) +uint8_t protocol_execute_line(char *line) { if(line[0] == '$') { @@ -255,6 +240,9 @@ int8_t protocol_execute_line(char *line) } 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. } } diff --git a/protocol.h b/protocol.h index 24a2bdd..bed6092 100755 --- a/protocol.h +++ b/protocol.h @@ -21,28 +21,31 @@ #ifndef protocol_h #define protocol_h - +// Line buffer size from the serial input stream to be executed. +// NOTE: Not a problem except for extreme cases, but the line buffer size can be too small +// and g-code blocks can get truncated. Officially, the g-code standards support up to 256 +// characters. In future versions, this will be increased, when we know how much extra +// memory space we can invest into here or we re-write the g-code parser not to have his +// buffer. #define LINE_BUFFER_SIZE 50 // Define Grbl status codes. #define STATUS_OK 0 -// Critical error codes. Greater than zero. #define STATUS_BAD_NUMBER_FORMAT 1 #define STATUS_EXPECTED_COMMAND_LETTER 2 #define STATUS_UNSUPPORTED_STATEMENT 3 #define STATUS_FLOATING_POINT_ERROR 4 #define STATUS_MODAL_GROUP_VIOLATION 5 #define STATUS_INVALID_STATEMENT 6 -#define STATUS_SETTING_DISABLED 7 -#define STATUS_HARD_LIMIT 8 -// Non-critical error codes. Less than zero. -#define STATUS_SETTING_INVALID -1 -#define STATUS_SETTING_STEPS_NEG -2 -#define STATUS_SETTING_STEP_PULSE_MIN -3 +#define STATUS_HARD_LIMIT 7 +#define STATUS_SETTING_DISABLED 8 +#define STATUS_SETTING_STEPS_NEG 9 +#define STATUS_SETTING_STEP_PULSE_MIN 10 +#define STATUS_SETTING_READ_FAIL 11 + +// Define Grbl misc message codes +#define MESSAGE_HOMING_ENABLE 1 -// Define Grbl warning message codes -#define WARNING_HOMING_ENABLE 1 -#define WARNING_SETTING_READ_FAIL 2 // Initialize the serial protocol void protocol_init(); @@ -52,12 +55,15 @@ void protocol_init(); void protocol_process(); // Executes one line of input according to protocol -int8_t protocol_execute_line(char *line); +uint8_t protocol_execute_line(char *line); // Checks and executes a runtime command at various stop points in main program void protocol_execute_runtime(); -// Prints any warning messages. -void protocol_warning_message(int8_t warning_code); +// Prints Grbl's status messages. +void protocol_status_message(uint8_t status_code); + +// Prints any misc messages. +void protocol_misc_message(uint8_t message_code); #endif diff --git a/serial.c b/serial.c index 4b431f9..a0e7916 100755 --- a/serial.c +++ b/serial.c @@ -26,8 +26,7 @@ #include #include "serial.h" #include "config.h" -#include "stepper.h" -#include "spindle_control.h" +#include "motion_control.h" #include "nuts_bolts.h" #include "protocol.h" @@ -166,16 +165,8 @@ ISR(USART_RX_vect) case CMD_CYCLE_START: sys.execute |= EXEC_CYCLE_START; break; // Set as true case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true case CMD_RESET: - sys.execute |= EXEC_ALARM; // Set alarm to allow subsystem disable for certain settings. - - // TODO: When Grbl system status is installed, set position lost state if the cycle is active. - // if (sys.cycle_start) { POSITION LOST } - // Immediately force stepper and spindle subsystem idle at an interrupt level. - if (!(sys.execute & EXEC_RESET)) { // Force stop only first time. - st_go_idle(); - spindle_stop(); - } + if (!(sys.execute & EXEC_RESET)) { mc_alarm(); } // Stop only first time. sys.execute |= EXEC_RESET; // Set as true break; default: // Write character to buffer diff --git a/settings.c b/settings.c index 7085480..175cf8d 100755 --- a/settings.c +++ b/settings.c @@ -148,7 +148,7 @@ void settings_dump() { // Parameter lines are on the form '$4=374.3' or '$' to dump current settings // NOTE: Assumes '$' already exists in line[0], which is checked by protocol.c. -int8_t settings_execute_line(char *line) { +uint8_t settings_execute_line(char *line) { uint8_t char_counter = 1; // unsigned char letter; float parameter, value; @@ -173,16 +173,16 @@ int8_t settings_execute_line(char *line) { // // } else { if(!read_float(line, &char_counter, ¶meter)) { - return(STATUS_SETTING_INVALID); + return(STATUS_BAD_NUMBER_FORMAT); } if(line[char_counter++] != '=') { - return(STATUS_SETTING_INVALID); + return(STATUS_UNSUPPORTED_STATEMENT); } if(!read_float(line, &char_counter, &value)) { - return(STATUS_SETTING_INVALID); + return(STATUS_BAD_NUMBER_FORMAT); } if(line[char_counter] != 0) { - return(STATUS_SETTING_INVALID); + return(STATUS_UNSUPPORTED_STATEMENT); } return(settings_store_setting(parameter, value)); // } @@ -247,7 +247,7 @@ int read_settings() { } // A helper method to set settings from command line -int8_t settings_store_setting(int parameter, float value) { +uint8_t settings_store_setting(int parameter, float value) { switch(parameter) { case 0: case 1: case 2: if (value <= 0.0) { return(STATUS_SETTING_STEPS_NEG); } @@ -279,7 +279,7 @@ int8_t settings_store_setting(int parameter, float value) { case 13: if (value) { settings.flags |= BITFLAG_HOMING_ENABLE; - protocol_warning_message(WARNING_HOMING_ENABLE); + protocol_misc_message(MESSAGE_HOMING_ENABLE); } else { settings.flags &= ~BITFLAG_HOMING_ENABLE; } break; case 14: settings.homing_dir_mask = trunc(value); break; @@ -293,7 +293,7 @@ int8_t settings_store_setting(int parameter, float value) { break; case 20: settings.decimal_places = round(value); break; default: - return(STATUS_SETTING_INVALID); + return(STATUS_INVALID_STATEMENT); } write_settings(); return(STATUS_OK); @@ -302,7 +302,7 @@ int8_t settings_store_setting(int parameter, float value) { // Initialize the config subsystem void settings_init() { if(!read_settings()) { - protocol_warning_message(WARNING_SETTING_READ_FAIL); + protocol_status_message(STATUS_SETTING_READ_FAIL); settings_reset(true); write_settings(); settings_dump(); diff --git a/settings.h b/settings.h index 3d2086a..635911b 100755 --- a/settings.h +++ b/settings.h @@ -66,10 +66,10 @@ void settings_init(); void settings_dump(); // Handle settings command -int8_t settings_execute_line(char *line); +uint8_t settings_execute_line(char *line); // A helper method to set new settings from command line -int8_t settings_store_setting(int parameter, float value); +uint8_t settings_store_setting(int parameter, float value); // int8_t settings_execute_startup(); diff --git a/stepper.c b/stepper.c index f96c3f4..117c7a2 100755 --- a/stepper.c +++ b/stepper.c @@ -113,7 +113,7 @@ void st_go_idle() // Force stepper dwell to lock axes for a defined amount of time to ensure the axes come to a complete // stop and not drift from residual inertial forces at the end of the last movement. delay_ms(settings.stepper_idle_lock_time); - // Disable steppers only upon system alarm activated or by user setting to keep enabled. + // Disable steppers only upon system alarm activated or by user setting to not be kept enabled. if ((settings.stepper_idle_lock_time != 0xff) || bit_istrue(sys.execute,EXEC_ALARM)) { STEPPERS_DISABLE_PORT |= (1<