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.
This commit is contained in:
Sonny Jeon 2012-10-21 19:18:24 -06:00
parent 909feb7f79
commit 065ceceb34
9 changed files with 103 additions and 94 deletions

View File

@ -56,16 +56,14 @@ ISR(LIMIT_INT_vect)
if (bit_isfalse(sys.execute,EXEC_ALARM)) { if (bit_isfalse(sys.execute,EXEC_ALARM)) {
// Kill all processes upon hard limit event. // Kill all processes upon hard limit event.
if ((LIMIT_PIN & LIMIT_MASK) ^ LIMIT_MASK) { if ((LIMIT_PIN & LIMIT_MASK) ^ LIMIT_MASK) {
st_go_idle(); // Immediately stop stepper motion mc_alarm(); // Initiate system kill.
spindle_stop(); // Stop spindle protocol_status_message(STATUS_HARD_LIMIT); // Print ok in interrupt since system killed.
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.
} }
// else { // else {
// TODO: When leaving a switch, this interrupt can be activated upon detecting a pin // 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 // 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.
} }
} }

View File

@ -25,6 +25,8 @@
#include "config.h" #include "config.h"
#include "gcode.h" #include "gcode.h"
#include "motion_control.h" #include "motion_control.h"
#include "spindle_control.h"
#include "coolant_control.h"
#include <util/delay.h> #include <util/delay.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
@ -223,3 +225,24 @@ void mc_go_home()
PCICR |= (1 << LIMIT_INT); // Re-enable hard limits. 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();
}
}

View File

@ -43,4 +43,7 @@ void mc_dwell(float seconds);
// Send the tool home (not implemented) // Send the tool home (not implemented)
void mc_go_home(); void mc_go_home();
// Kills all motion and sets system alarm
void mc_alarm();
#endif #endif

View File

@ -36,20 +36,16 @@ 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 char_counter; // Last character counter in line variable.
static uint8_t iscomment; // Comment/block delete flag for processor to ignore comment characters. 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 // Method to handle status messages, from an 'ok' to report any 'error' that has occurred.
// serial data, whether this was a g-code block or grbl setting command. // Errors can originate from the g-code parser, settings module, or a critical error, such
void protocol_status_message(int8_t status_code) // as a triggered hard limit.
void protocol_status_message(uint8_t status_code)
{ {
// TODO: Compile time option to only return numeric codes for GUIs. // TODO: Compile time option to only return numeric codes for GUIs.
if (status_code == 0) { // STATUS_OK if (status_code == 0) { // STATUS_OK
printPgmString(PSTR("ok\r\n")); printPgmString(PSTR("ok\r\n"));
} else { } else {
printPgmString(PSTR("error: ")); 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) { switch(status_code) {
case STATUS_BAD_NUMBER_FORMAT: case STATUS_BAD_NUMBER_FORMAT:
printPgmString(PSTR("Bad number format")); break; printPgmString(PSTR("Bad number format")); break;
@ -62,42 +58,32 @@ void protocol_status_message(int8_t status_code)
case STATUS_MODAL_GROUP_VIOLATION: case STATUS_MODAL_GROUP_VIOLATION:
printPgmString(PSTR("Modal group violation")); break; printPgmString(PSTR("Modal group violation")); break;
case STATUS_INVALID_STATEMENT: case STATUS_INVALID_STATEMENT:
printPgmString(PSTR("Invalid gcode statement")); break; printPgmString(PSTR("Invalid statement")); break;
case STATUS_HARD_LIMIT:
printPgmString(PSTR("<ALARM> Limit triggered")); break;
case STATUS_SETTING_DISABLED: case STATUS_SETTING_DISABLED:
printPgmString(PSTR("Grbl setting disabled")); break; printPgmString(PSTR("Grbl setting disabled")); break;
case STATUS_HARD_LIMIT:
printPgmString(PSTR("Limit triggered <Check and Reset>")); 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: case STATUS_SETTING_STEPS_NEG:
printPgmString(PSTR("Steps/mm must be > 0.0")); break; printPgmString(PSTR("Steps/mm must be > 0.0")); break;
case STATUS_SETTING_STEP_PULSE_MIN: case STATUS_SETTING_STEP_PULSE_MIN:
printPgmString(PSTR("Step pulse must be >= 3 microseconds")); break; 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")); printPgmString(PSTR("\r\n"));
} }
} }
// Prints Grbl warning messages. This serves as a centralized method to provide additional // 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. // 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 // and are not errors or confirmations, such as setup warnings.
// enabled. This function maybe called from anywhere in Grbl at the point of concern. void protocol_misc_message(uint8_t message_code)
void protocol_warning_message(int8_t warning_code)
{ {
// TODO: Install silence warning messages option in settings // TODO: Install silence misc messages option in settings
printPgmString(PSTR("warning: ")); switch(message_code) {
switch(warning_code) { case MESSAGE_HOMING_ENABLE:
case WARNING_HOMING_ENABLE: printPgmString(PSTR("warning: Install all axes limit switches before use")); break;
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;
} }
printPgmString(PSTR("\r\n")); printPgmString(PSTR("\r\n"));
} }
@ -181,7 +167,6 @@ void protocol_execute_runtime()
// System alarm. Something has gone wrong. Disable everything until system reset. // System alarm. Something has gone wrong. Disable everything until system reset.
if (rt_exec & EXEC_ALARM) { if (rt_exec & EXEC_ALARM) {
protocol_status_message(STATUS_HARD_LIMIT);
while (bit_isfalse(sys.execute,EXEC_RESET)) { sleep_mode(); } while (bit_isfalse(sys.execute,EXEC_RESET)) { sleep_mode(); }
bit_false(sys.execute,EXEC_ALARM); bit_false(sys.execute,EXEC_ALARM);
} }
@ -223,7 +208,7 @@ void protocol_execute_runtime()
// Executes one line of input according to protocol // 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] == '$') { if(line[0] == '$') {
@ -255,6 +240,9 @@ int8_t protocol_execute_line(char *line)
} else { } else {
return(gc_execute_line(line)); // Everything else is gcode 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.
} }
} }

View File

@ -21,28 +21,31 @@
#ifndef protocol_h #ifndef protocol_h
#define 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 LINE_BUFFER_SIZE 50
// Define Grbl status codes. // Define Grbl status codes.
#define STATUS_OK 0 #define STATUS_OK 0
// Critical error codes. Greater than zero.
#define STATUS_BAD_NUMBER_FORMAT 1 #define STATUS_BAD_NUMBER_FORMAT 1
#define STATUS_EXPECTED_COMMAND_LETTER 2 #define STATUS_EXPECTED_COMMAND_LETTER 2
#define STATUS_UNSUPPORTED_STATEMENT 3 #define STATUS_UNSUPPORTED_STATEMENT 3
#define STATUS_FLOATING_POINT_ERROR 4 #define STATUS_FLOATING_POINT_ERROR 4
#define STATUS_MODAL_GROUP_VIOLATION 5 #define STATUS_MODAL_GROUP_VIOLATION 5
#define STATUS_INVALID_STATEMENT 6 #define STATUS_INVALID_STATEMENT 6
#define STATUS_SETTING_DISABLED 7 #define STATUS_HARD_LIMIT 7
#define STATUS_HARD_LIMIT 8 #define STATUS_SETTING_DISABLED 8
// Non-critical error codes. Less than zero. #define STATUS_SETTING_STEPS_NEG 9
#define STATUS_SETTING_INVALID -1 #define STATUS_SETTING_STEP_PULSE_MIN 10
#define STATUS_SETTING_STEPS_NEG -2 #define STATUS_SETTING_READ_FAIL 11
#define STATUS_SETTING_STEP_PULSE_MIN -3
// 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 // Initialize the serial protocol
void protocol_init(); void protocol_init();
@ -52,12 +55,15 @@ void protocol_init();
void protocol_process(); void protocol_process();
// Executes one line of input according to protocol // 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 // Checks and executes a runtime command at various stop points in main program
void protocol_execute_runtime(); void protocol_execute_runtime();
// Prints any warning messages. // Prints Grbl's status messages.
void protocol_warning_message(int8_t warning_code); void protocol_status_message(uint8_t status_code);
// Prints any misc messages.
void protocol_misc_message(uint8_t message_code);
#endif #endif

View File

@ -26,8 +26,7 @@
#include <avr/sleep.h> #include <avr/sleep.h>
#include "serial.h" #include "serial.h"
#include "config.h" #include "config.h"
#include "stepper.h" #include "motion_control.h"
#include "spindle_control.h"
#include "nuts_bolts.h" #include "nuts_bolts.h"
#include "protocol.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_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_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true
case CMD_RESET: 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. // Immediately force stepper and spindle subsystem idle at an interrupt level.
if (!(sys.execute & EXEC_RESET)) { // Force stop only first time. if (!(sys.execute & EXEC_RESET)) { mc_alarm(); } // Stop only first time.
st_go_idle();
spindle_stop();
}
sys.execute |= EXEC_RESET; // Set as true sys.execute |= EXEC_RESET; // Set as true
break; break;
default: // Write character to buffer default: // Write character to buffer

View File

@ -148,7 +148,7 @@ void settings_dump() {
// Parameter lines are on the form '$4=374.3' or '$' to dump current settings // 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. // 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; uint8_t char_counter = 1;
// unsigned char letter; // unsigned char letter;
float parameter, value; float parameter, value;
@ -173,16 +173,16 @@ int8_t settings_execute_line(char *line) {
// //
// } else { // } else {
if(!read_float(line, &char_counter, &parameter)) { if(!read_float(line, &char_counter, &parameter)) {
return(STATUS_SETTING_INVALID); return(STATUS_BAD_NUMBER_FORMAT);
} }
if(line[char_counter++] != '=') { if(line[char_counter++] != '=') {
return(STATUS_SETTING_INVALID); return(STATUS_UNSUPPORTED_STATEMENT);
} }
if(!read_float(line, &char_counter, &value)) { if(!read_float(line, &char_counter, &value)) {
return(STATUS_SETTING_INVALID); return(STATUS_BAD_NUMBER_FORMAT);
} }
if(line[char_counter] != 0) { if(line[char_counter] != 0) {
return(STATUS_SETTING_INVALID); return(STATUS_UNSUPPORTED_STATEMENT);
} }
return(settings_store_setting(parameter, value)); return(settings_store_setting(parameter, value));
// } // }
@ -247,7 +247,7 @@ int read_settings() {
} }
// A helper method to set settings from command line // 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) { switch(parameter) {
case 0: case 1: case 2: case 0: case 1: case 2:
if (value <= 0.0) { return(STATUS_SETTING_STEPS_NEG); } if (value <= 0.0) { return(STATUS_SETTING_STEPS_NEG); }
@ -279,7 +279,7 @@ int8_t settings_store_setting(int parameter, float value) {
case 13: case 13:
if (value) { if (value) {
settings.flags |= BITFLAG_HOMING_ENABLE; settings.flags |= BITFLAG_HOMING_ENABLE;
protocol_warning_message(WARNING_HOMING_ENABLE); protocol_misc_message(MESSAGE_HOMING_ENABLE);
} else { settings.flags &= ~BITFLAG_HOMING_ENABLE; } } else { settings.flags &= ~BITFLAG_HOMING_ENABLE; }
break; break;
case 14: settings.homing_dir_mask = trunc(value); break; case 14: settings.homing_dir_mask = trunc(value); break;
@ -293,7 +293,7 @@ int8_t settings_store_setting(int parameter, float value) {
break; break;
case 20: settings.decimal_places = round(value); break; case 20: settings.decimal_places = round(value); break;
default: default:
return(STATUS_SETTING_INVALID); return(STATUS_INVALID_STATEMENT);
} }
write_settings(); write_settings();
return(STATUS_OK); return(STATUS_OK);
@ -302,7 +302,7 @@ int8_t settings_store_setting(int parameter, float value) {
// Initialize the config subsystem // Initialize the config subsystem
void settings_init() { void settings_init() {
if(!read_settings()) { if(!read_settings()) {
protocol_warning_message(WARNING_SETTING_READ_FAIL); protocol_status_message(STATUS_SETTING_READ_FAIL);
settings_reset(true); settings_reset(true);
write_settings(); write_settings();
settings_dump(); settings_dump();

View File

@ -66,10 +66,10 @@ void settings_init();
void settings_dump(); void settings_dump();
// Handle settings command // 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 // 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(); // int8_t settings_execute_startup();

View File

@ -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 // 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. // stop and not drift from residual inertial forces at the end of the last movement.
delay_ms(settings.stepper_idle_lock_time); 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)) { if ((settings.stepper_idle_lock_time != 0xff) || bit_istrue(sys.execute,EXEC_ALARM)) {
STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT); STEPPERS_DISABLE_PORT |= (1<<STEPPERS_DISABLE_BIT);
} }