diff --git a/config.h b/config.h index a598b5c..6e96453 100755 --- a/config.h +++ b/config.h @@ -149,7 +149,7 @@ // TODO: The following options are set as compile-time options for now, until the next EEPROM // settings version has solidified. This is to prevent having to support dozens of different // incremental settings versions. -#define BLOCK_DELETE_ENABLE 0 // Block delete enable/disable flag during g-code parsing +// -> NOW CODED INTO SETTINGS #define BLOCK_DELETE_ENABLE 0 // Block delete enable/disable flag during g-code parsing // This parameter sets the delay time before disabling the steppers after the final block of movement. // A short delay ensures the steppers come to a complete stop and the residual inertial force in the diff --git a/gcode.c b/gcode.c index cbda3df..2ba47c0 100755 --- a/gcode.c +++ b/gcode.c @@ -34,62 +34,8 @@ #include "protocol.h" #include "report.h" -// Define modal group internal numbers for checking multiple command violations and tracking the -// type of command that is called in the block. A modal group is a group of g-code commands that are -// mutually exclusive, or cannot exist on the same line, because they each toggle a state or execute -// a unique motion. These are defined in the NIST RS274-NGC v3 g-code standard, available online, -// and are similar/identical to other g-code interpreters by manufacturers (Haas,Fanuc,Mazak,etc). -#define MODAL_GROUP_NONE 0 -#define MODAL_GROUP_0 1 // [G4,G10,G28,G30,G53,G92,G92.1] Non-modal -#define MODAL_GROUP_1 2 // [G0,G1,G2,G3,G80] Motion -#define MODAL_GROUP_2 3 // [G17,G18,G19] Plane selection -#define MODAL_GROUP_3 4 // [G90,G91] Distance mode -#define MODAL_GROUP_4 5 // [M0,M1,M2,M30] Stopping -#define MODAL_GROUP_5 6 // [G93,G94] Feed rate mode -#define MODAL_GROUP_6 7 // [G20,G21] Units -#define MODAL_GROUP_7 8 // [M3,M4,M5] Spindle turning -#define MODAL_GROUP_12 9 // [G54,G55,G56,G57,G58,G59] Coordinate system selection - -// Define command actions for within execution-type modal groups (motion, stopping, non-modal). Used -// internally by the parser to know which command to execute. -#define MOTION_MODE_SEEK 0 // G0 -#define MOTION_MODE_LINEAR 1 // G1 -#define MOTION_MODE_CW_ARC 2 // G2 -#define MOTION_MODE_CCW_ARC 3 // G3 -#define MOTION_MODE_CANCEL 4 // G80 - -#define PROGRAM_FLOW_RUNNING 0 -#define PROGRAM_FLOW_PAUSED 1 // M0, M1 -#define PROGRAM_FLOW_COMPLETED 2 // M2, M30 - -#define NON_MODAL_NONE 0 -#define NON_MODAL_DWELL 1 // G4 -#define NON_MODAL_SET_COORDINATE_DATA 2 // G10 -#define NON_MODAL_GO_HOME_0 3 // G28 -#define NON_MODAL_SET_HOME_0 4 // G28.1 -#define NON_MODAL_GO_HOME_1 5 // G30 -#define NON_MODAL_SET_HOME_1 6 // G30.1 -#define NON_MODAL_SET_COORDINATE_OFFSET 7 // G92 -#define NON_MODAL_RESET_COORDINATE_OFFSET 8 //G92.1 - -typedef struct { - uint8_t status_code; // Parser status for current block - uint8_t motion_mode; // {G0, G1, G2, G3, G80} - uint8_t inverse_feed_rate_mode; // {G93, G94} - uint8_t inches_mode; // 0 = millimeter mode, 1 = inches mode {G20, G21} - uint8_t absolute_mode; // 0 = relative motion, 1 = absolute motion {G90, G91} - uint8_t program_flow; // {M0, M1, M2, M30} - int8_t spindle_direction; // 1 = CW, -1 = CCW, 0 = Stop {M3, M4, M5} - uint8_t coolant_mode; // 0 = Disable, 1 = Flood Enable {M8, M9} - float feed_rate, seek_rate; // Millimeters/second - float position[3]; // Where the interpreter considers the tool to be at this point in the code - uint8_t tool; - uint16_t spindle_speed; // RPM/100 - uint8_t plane_axis_0, - plane_axis_1, - plane_axis_2; // The axes of the selected plane -} parser_state_t; -static parser_state_t gc; +// Declare gc extern struct +parser_state_t gc; #define FAIL(status) gc.status_code = status; @@ -105,10 +51,15 @@ static void select_plane(uint8_t axis_0, uint8_t axis_1, uint8_t axis_2) void gc_init() { memset(&gc, 0, sizeof(gc)); - gc.feed_rate = settings.default_feed_rate; + gc.feed_rate = settings.default_feed_rate; // Should be zero at initialization. select_plane(X_AXIS, Y_AXIS, Z_AXIS); gc.absolute_mode = true; + // Load default G54 coordinate system. + if (!(settings_read_coord_data(gc.coord_select,gc.coord_system))) { + report_status_message(STATUS_SETTING_READ_FAIL); + } + // protocol_status_message(settings_execute_startup()); } @@ -186,9 +137,8 @@ uint8_t gc_execute_line(char *line) case 19: select_plane(Y_AXIS, Z_AXIS, X_AXIS); break; case 20: gc.inches_mode = true; break; case 21: gc.inches_mode = false; break; - // NOTE: G28.1, G30.1 sets home position parameters. Not currently supported. case 28: case 30: - int_value = trunc(10*value); // Multiply by 10 to pick up G92.1 + int_value = trunc(10*value); // Multiply by 10 to pick up Gxx.1 switch(int_value) { case 280: non_modal_action = NON_MODAL_GO_HOME_0; break; case 281: non_modal_action = NON_MODAL_SET_HOME_0; break; @@ -199,7 +149,7 @@ uint8_t gc_execute_line(char *line) break; case 53: absolute_override = true; break; case 54: case 55: case 56: case 57: case 58: case 59: - sys.coord_select = int_value-54; + gc.coord_select = int_value-54; break; case 80: gc.motion_mode = MOTION_MODE_CANCEL; break; case 90: gc.absolute_mode = true; break; @@ -226,10 +176,11 @@ uint8_t gc_execute_line(char *line) // Set 'M' commands switch(int_value) { case 0: gc.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause - case 1: // Program pause with optional stop on - // if (sys.opt_stop) { // TODO: Add system variable for optional stop. - gc.program_flow = PROGRAM_FLOW_PAUSED; break; - // } + case 1: // Program pause with optional stop on, otherwise do nothing. + if (bit_istrue(sys.switches,BITFLAG_OPT_STOP)) { + gc.program_flow = PROGRAM_FLOW_PAUSED; + } + break; case 2: case 30: gc.program_flow = PROGRAM_FLOW_COMPLETED; break; // Program end and reset case 3: gc.spindle_direction = 1; break; case 4: gc.spindle_direction = -1; break; @@ -280,7 +231,8 @@ uint8_t gc_execute_line(char *line) case 'R': r = to_millimeters(value); break; case 'S': if (value < 0) { FAIL(STATUS_INVALID_STATEMENT); } // Cannot be negative - gc.spindle_speed = value; + // TBD: Spindle speed not supported due to PWM issues, but may come back once resolved. + // gc.spindle_speed = value; break; case 'T': if (value < 0) { FAIL(STATUS_INVALID_STATEMENT); } // Cannot be negative @@ -304,7 +256,7 @@ uint8_t gc_execute_line(char *line) // ([M6]: Tool change should be executed here.) // [M3,M4,M5]: Update spindle state - spindle_run(gc.spindle_direction, gc.spindle_speed); + spindle_run(gc.spindle_direction); //, gc.spindle_speed); // [*M7,M8,M9]: Update coolant state coolant_run(gc.coolant_mode); @@ -312,8 +264,8 @@ uint8_t gc_execute_line(char *line) // [G54,G55,...,G59]: Coordinate system selection if ( bit_istrue(modal_group_words,bit(MODAL_GROUP_12)) ) { // Check if called in block float coord_data[N_AXIS]; - if (!(settings_read_coord_data(sys.coord_select,coord_data))) { return(STATUS_SETTING_READ_FAIL); } - memcpy(sys.coord_system,coord_data,sizeof(coord_data)); + if (!(settings_read_coord_data(gc.coord_select,coord_data))) { return(STATUS_SETTING_READ_FAIL); } + memcpy(gc.coord_system,coord_data,sizeof(coord_data)); } // [G4,G10,G28,G30,G92,G92.1]: Perform dwell, set coordinate system data, homing, or set axis offsets. @@ -338,7 +290,7 @@ uint8_t gc_execute_line(char *line) if (l == 20) { settings_write_coord_data(int_value,gc.position); // Update system coordinate system if currently active. - if (sys.coord_select == int_value) { memcpy(sys.coord_system,gc.position,sizeof(gc.position)); } + if (gc.coord_select == int_value) { memcpy(gc.coord_system,gc.position,sizeof(gc.position)); } } else { float coord_data[N_AXIS]; if (!settings_read_coord_data(int_value,coord_data)) { return(STATUS_SETTING_READ_FAIL); } @@ -349,7 +301,7 @@ uint8_t gc_execute_line(char *line) } settings_write_coord_data(int_value,coord_data); // Update system coordinate system if currently active. - if (sys.coord_select == int_value) { memcpy(sys.coord_system,coord_data,sizeof(coord_data)); } + if (gc.coord_select == int_value) { memcpy(gc.coord_system,coord_data,sizeof(coord_data)); } } } axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags. @@ -363,7 +315,7 @@ uint8_t gc_execute_line(char *line) for (i=0; i. */ - #ifndef gcode_h #define gcode_h #include +#include "nuts_bolts.h" + +// Define modal group internal numbers for checking multiple command violations and tracking the +// type of command that is called in the block. A modal group is a group of g-code commands that are +// mutually exclusive, or cannot exist on the same line, because they each toggle a state or execute +// a unique motion. These are defined in the NIST RS274-NGC v3 g-code standard, available online, +// and are similar/identical to other g-code interpreters by manufacturers (Haas,Fanuc,Mazak,etc). +#define MODAL_GROUP_NONE 0 +#define MODAL_GROUP_0 1 // [G4,G10,G28,G30,G53,G92,G92.1] Non-modal +#define MODAL_GROUP_1 2 // [G0,G1,G2,G3,G80] Motion +#define MODAL_GROUP_2 3 // [G17,G18,G19] Plane selection +#define MODAL_GROUP_3 4 // [G90,G91] Distance mode +#define MODAL_GROUP_4 5 // [M0,M1,M2,M30] Stopping +#define MODAL_GROUP_5 6 // [G93,G94] Feed rate mode +#define MODAL_GROUP_6 7 // [G20,G21] Units +#define MODAL_GROUP_7 8 // [M3,M4,M5] Spindle turning +#define MODAL_GROUP_12 9 // [G54,G55,G56,G57,G58,G59] Coordinate system selection + +// Define command actions for within execution-type modal groups (motion, stopping, non-modal). Used +// internally by the parser to know which command to execute. +#define MOTION_MODE_SEEK 0 // G0 +#define MOTION_MODE_LINEAR 1 // G1 +#define MOTION_MODE_CW_ARC 2 // G2 +#define MOTION_MODE_CCW_ARC 3 // G3 +#define MOTION_MODE_CANCEL 4 // G80 + +#define PROGRAM_FLOW_RUNNING 0 +#define PROGRAM_FLOW_PAUSED 1 // M0, M1 +#define PROGRAM_FLOW_COMPLETED 2 // M2, M30 + +#define NON_MODAL_NONE 0 +#define NON_MODAL_DWELL 1 // G4 +#define NON_MODAL_SET_COORDINATE_DATA 2 // G10 +#define NON_MODAL_GO_HOME_0 3 // G28 +#define NON_MODAL_SET_HOME_0 4 // G28.1 +#define NON_MODAL_GO_HOME_1 5 // G30 +#define NON_MODAL_SET_HOME_1 6 // G30.1 +#define NON_MODAL_SET_COORDINATE_OFFSET 7 // G92 +#define NON_MODAL_RESET_COORDINATE_OFFSET 8 //G92.1 + +typedef struct { + uint8_t status_code; // Parser status for current block + uint8_t motion_mode; // {G0, G1, G2, G3, G80} + uint8_t inverse_feed_rate_mode; // {G93, G94} + uint8_t inches_mode; // 0 = millimeter mode, 1 = inches mode {G20, G21} + uint8_t absolute_mode; // 0 = relative motion, 1 = absolute motion {G90, G91} + uint8_t program_flow; // {M0, M1, M2, M30} + int8_t spindle_direction; // 1 = CW, -1 = CCW, 0 = Stop {M3, M4, M5} + uint8_t coolant_mode; // 0 = Disable, 1 = Flood Enable {M8, M9} + float feed_rate; // Millimeters/min + float position[3]; // Where the interpreter considers the tool to be at this point in the code + uint8_t tool; +// uint16_t spindle_speed; // RPM/100 + uint8_t plane_axis_0, + plane_axis_1, + plane_axis_2; // The axes of the selected plane + uint8_t coord_select; // Active work coordinate system number. Default: 0=G54. + float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine + // position in mm. Loaded from EEPROM when called. + float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to + // machine zero in mm. Non-persistent. Cleared upon reset and boot. +} parser_state_t; +extern parser_state_t gc; // Initialize the parser void gc_init(); diff --git a/nuts_bolts.h b/nuts_bolts.h index 981bb50..2eb0525 100755 --- a/nuts_bolts.h +++ b/nuts_bolts.h @@ -35,12 +35,12 @@ #define Y_AXIS 1 #define Z_AXIS 2 -#define MM_PER_INCH (25.4) -#define INCH_PER_MM (0.03937) +#define MM_PER_INCH (25.40) +#define INCH_PER_MM (0.0393701) // Useful macros #define clear_vector(a) memset(a, 0, sizeof(a)) -#define clear_vector_float(a) memset(a, 0.0, sizeof(float)*3) +#define clear_vector_float(a) memset(a, 0.0, sizeof(float)*N_AXIS) #define max(a,b) (((a) > (b)) ? (a) : (b)) #define min(a,b) (((a) < (b)) ? (a) : (b)) @@ -86,20 +86,16 @@ typedef struct { uint8_t abort; // System abort flag. Forces exit back to main loop for reset. uint8_t feed_hold; // Feed hold flag. Held true during feed hold. Released when ready to resume. uint8_t auto_start; // Planner auto-start flag. Toggled off during feed hold. Defaulted by settings. -// uint8_t switches; // Switches state bitflag variable. For settings not governed by g-code. - - int32_t position[3]; // Real-time machine (aka home) position vector in steps. - // NOTE: This may need to be a volatile variable, if problems arise. + uint8_t switches; // Switches state bitflag variable. For features not governed by g-code. + +// uint8_t state; // Tracks the current state of Grbl. +// TODO: This may replace the functionality of the feed_hold and cycle_start variables. Need to +// make sure that overall processes don't change. - uint8_t coord_select; // Active work coordinate system number. Default: 0=G54. - float coord_system[N_AXIS]; // Current work coordinate system (G54+). Stores offset from absolute machine - // position in mm. Loaded from EEPROM when called. - float coord_offset[N_AXIS]; // Retains the G92 coordinate offset (work coordinates) relative to - // machine zero in mm. - volatile uint8_t cycle_start; // Cycle start flag. Set by stepper subsystem or main program. volatile uint8_t execute; // Global system runtime executor bitflag variable. See EXEC bitmasks. - + int32_t position[3]; // Real-time machine (aka home) position vector in steps. + // NOTE: This may need to be a volatile variable, if problems arise. } system_t; extern system_t sys; diff --git a/protocol.c b/protocol.c index 439b148..864351e 100755 --- a/protocol.c +++ b/protocol.c @@ -135,77 +135,80 @@ uint8_t protocol_execute_line(char *line) uint8_t char_counter = 1; float parameter, value; switch( line[char_counter] ) { - case 0 : - report_grbl_help(); - return(STATUS_OK); + case 0 : report_grbl_help(); break; + case '$' : // Prints Grbl settings + if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } + else { report_grbl_settings(); } + break; + case '#' : // Print gcode parameters + if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } + else { report_gcode_parameters(); } + break; + case 'G' : // Prints gcode parser state + if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } + else { report_gcode_modes(); } break; -// case '#' : -// if ( line[++char_counter] == 0 ) { -// // Print all parameters -// return(STATUS_OK); -// } else { -// return(STATUS_UNSUPPORTED_STATEMENT); -// } -// case 'G' : // Start up blocks -// if(!read_float(line, &char_counter, ¶meter)) { return(STATUS_BAD_NUMBER_FORMAT); } -// if(line[char_counter++] != '=') { return(STATUS_UNSUPPORTED_STATEMENT); } -// // Extract startup block, execute, and store. -// for (char_counter = 0; char_counter < LINE_BUFFER_SIZE-3; char_counter++) { -// line[char_counter] = line[char_counter+3]; -// } -// uint8_t status = gc_execute_line(line); -// if (status) { return(status); } -// else { settings_store_startup_block(line); } -// break; case 'H' : // Perform homing cycle - if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { - mc_go_home(); - return(STATUS_OK); - } else { - return(STATUS_SETTING_DISABLED); - } + if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { mc_go_home(); } + else { return(STATUS_SETTING_DISABLED); } break; -// // case 'J' : break; // Jogging methods -// // TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be -// // susceptible to other runtime commands except for e-stop. The jogging function is intended to -// // be a basic toggle on/off with controlled acceleration and deceleration to prevent skipped -// // steps. The user would supply the desired feedrate, axis to move, and direction. Toggle on would -// // start motion and toggle off would initiate a deceleration to stop. One could 'feather' the -// // motion by repeatedly toggling to slow the motion to the desired location. Location data would -// // need to be updated real-time and supplied to the user through status queries. -// // More controlled exact motions can be taken care of by inputting G0 or G1 commands, which are -// // handled by the planner. It would be possible for the jog subprogram to insert blocks into the -// // 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 'P' : // Print g-code parameters and parser state -// if(line[char_counter] != 0) { return(STATUS_UNSUPPORTED_STATEMENT); } -// -// break; -// case 'S' : // Switch methods -// // Opt stop and block delete are referred to as switches. -// // How to store home position and work offsets real-time?? -// break; -// // Parse $parameter=value settings - default : - if(!read_float(line, &char_counter, ¶meter)) { - return(STATUS_BAD_NUMBER_FORMAT); - } - if(line[char_counter++] != '=') { - return(STATUS_UNSUPPORTED_STATEMENT); - } - if(!read_float(line, &char_counter, &value)) { - return(STATUS_BAD_NUMBER_FORMAT); - } - if(line[char_counter] != 0) { - return(STATUS_UNSUPPORTED_STATEMENT); - } +// case 'J' : break; // Jogging methods + // TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be + // susceptible to other runtime commands except for e-stop. The jogging function is intended to + // be a basic toggle on/off with controlled acceleration and deceleration to prevent skipped + // steps. The user would supply the desired feedrate, axis to move, and direction. Toggle on would + // start motion and toggle off would initiate a deceleration to stop. One could 'feather' the + // motion by repeatedly toggling to slow the motion to the desired location. Location data would + // need to be updated real-time and supplied to the user through status queries. + // More controlled exact motions can be taken care of by inputting G0 or G1 commands, which are + // handled by the planner. It would be possible for the jog subprogram to insert blocks into the + // 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 'N' : // Start up blocks +// if(!read_float(line, &char_counter, ¶meter)) { return(STATUS_BAD_NUMBER_FORMAT); } +// if(line[char_counter++] != '=') { return(STATUS_UNSUPPORTED_STATEMENT); } +// // Extract startup block, execute, and store. +// for (char_counter = 0; char_counter < LINE_BUFFER_SIZE-3; char_counter++) { +// line[char_counter] = line[char_counter+3]; +// } +// uint8_t status = gc_execute_line(line); +// if (status) { return(status); } +// else { settings_store_startup_block(line); } +// break; + case 'B' : // Toggle block delete + if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } + sys.switches ^= BITFLAG_BLOCK_DELETE; + if (bit_istrue(sys.switches,BITFLAG_BLOCK_DELETE)) { report_feedback_message(MESSAGE_SWITCH_ON); } + else { report_feedback_message(MESSAGE_SWITCH_OFF); } + break; + case 'S' : // Toggle single block mode + if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } + sys.switches ^= BITFLAG_SINGLE_BLOCK; + if (bit_istrue(sys.switches,BITFLAG_SINGLE_BLOCK)) { report_feedback_message(MESSAGE_SWITCH_ON); } + else { report_feedback_message(MESSAGE_SWITCH_OFF); } + break; + case 'O' : // Toggle optional stop + if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); } + sys.switches ^= BITFLAG_OPT_STOP; + if (bit_istrue(sys.switches,BITFLAG_OPT_STOP)) { report_feedback_message(MESSAGE_SWITCH_ON); } + else { report_feedback_message(MESSAGE_SWITCH_OFF); } + break; + default : // Store global setting + if(!read_float(line, &char_counter, ¶meter)) { return(STATUS_BAD_NUMBER_FORMAT); } + if(line[char_counter++] != '=') { return(STATUS_UNSUPPORTED_STATEMENT); } + if(!read_float(line, &char_counter, &value)) { return(STATUS_BAD_NUMBER_FORMAT); } + if(line[char_counter] != 0) { return(STATUS_UNSUPPORTED_STATEMENT); } return(settings_store_global_setting(parameter, value)); } + 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. + } } @@ -246,9 +249,9 @@ void protocol_process() // Throw away whitepace and control characters } else if (c == '/') { // Disable block delete and throw away characters. Will ignore until EOL. - #if BLOCK_DELETE_ENABLE + if (bit_istrue(sys.switches,BITFLAG_BLOCK_DELETE)) { iscomment = true; - #endif + } } else if (c == '(') { // Enable comments flag and ignore all characters until ')' or EOL. iscomment = true; diff --git a/report.c b/report.c index 9bb3522..2383695 100644 --- a/report.c +++ b/report.c @@ -34,6 +34,8 @@ #include #include "report.h" #include "protocol.h" +#include "gcode.h" +#include "coolant_control.h" // Handles the primary confirmation protocol response for streaming interfaces and human-feedback. @@ -82,12 +84,12 @@ void report_status_message(uint8_t status_code) // Prints feedback messages. This serves as a centralized method to provide additional // user feedback for things that are not of the status message response protocol. These // are messages such as setup warnings and how to exit alarms. -// NOTE: For interfaces, messages are always placed within parentheses. And if silent mode -// is installed, the message codes are less than zero. +// NOTE: For interfaces, messages are always placed within chevrons. And if silent mode +// is installed, the message number codes are less than zero. // TODO: Install silence feedback messages option in settings void report_feedback_message(int8_t message_code) { - printPgmString(PSTR("(")); + printPgmString(PSTR("<")); switch(message_code) { case MESSAGE_SYSTEM_ALARM: printPgmString(PSTR("ALARM: Check and reset Grbl")); break; @@ -95,20 +97,37 @@ void report_feedback_message(int8_t message_code) printPgmString(PSTR("warning: Position may be lost")); break; case MESSAGE_HOMING_ENABLE: printPgmString(PSTR("'$H' to home. Ensure all limit switches are installed")); break; + case MESSAGE_SWITCH_ON: + printPgmString(PSTR("Switch enabled")); break; + case MESSAGE_SWITCH_OFF: + printPgmString(PSTR("Switch disabled")); break; } - printPgmString(PSTR(")\r\n")); + printPgmString(PSTR(">\r\n")); } // Welcome message void report_init_message() { - // Print grbl initialization message - printPgmString(PSTR("\r\nGrbl " GRBL_VERSION)); - printPgmString(PSTR("\r\n'$' for help and to view settings\r\n")); + printPgmString(PSTR("\r\nGrbl " GRBL_VERSION " ['$' for help]\r\n")); } void report_grbl_help() { +// char st_line[LINE_BUFFER_SIZE]; +// printPgmString(PSTR("\r\n\r\n Startup\r\n$100 = ")); printString(settings_read_startup(st_line,0)); +// printPgmString(PSTR("\r\n$101 = ")); printString(settings_read_startup(st_line,1)); + +// char buf[4]; +// settings_startup_string((char *)buf); +// printPgmString(PSTR("\r\n Startup: ")); printString(buf); + + printPgmString(PSTR("$ (help)\r\n$$ (print Grbl settings)\r\n$# (print gcode parameters)\r\n$G (print gcode parser state)")); + printPgmString(PSTR("\r\n$x=value (store Grbl setting)\r\n$Nx=line (store startup block)\r\n$H (run homing cycle, if enabled)")); + printPgmString(PSTR("\r\n$B (toggle block delete)\r\n$S (toggle single block mode)\r\n$O (toggle opt stop)")); + printPgmString(PSTR("\r\n~ (cycle start)\r\n! (feed hold)\r\n? (current position)\r\n^x (reset Grbl)\r\n")); +} + +void report_grbl_settings() { printPgmString(PSTR("$0 = ")); printFloat(settings.steps_per_mm[X_AXIS]); printPgmString(PSTR(" (x axis, steps/mm)\r\n$1 = ")); printFloat(settings.steps_per_mm[Y_AXIS]); printPgmString(PSTR(" (y axis, steps/mm)\r\n$2 = ")); printFloat(settings.steps_per_mm[Z_AXIS]); @@ -134,29 +153,108 @@ void report_grbl_help() { printPgmString(PSTR(" (homing pull-off travel, mm)\r\n$20 = ")); printInteger(settings.stepper_idle_lock_time); printPgmString(PSTR(" (stepper idle lock time, msec)\r\n$21 = ")); printInteger(settings.decimal_places); printPgmString(PSTR(" (decimal places, int)\r\n$22 = ")); printInteger(settings.n_arc_correction); -// char st_line[LINE_BUFFER_SIZE]; -// printPgmString(PSTR("\r\n\r\n Startup\r\n$100 = ")); printString(settings_read_startup(st_line,0)); -// printPgmString(PSTR("\r\n$101 = ")); printString(settings_read_startup(st_line,1)); - -// char buf[4]; -// settings_startup_string((char *)buf); -// printPgmString(PSTR("\r\n Startup: ")); printString(buf); - - printPgmString(PSTR("\r\n'$x=value' to store setting")); -// printPgmString(PSTR("\r\n'$Sx' to toggle switch\r\n")); + printPgmString(PSTR(" (n arc correction, int)\r\n")); } +void report_gcode_parameters() +{ + float coord_data[N_AXIS]; + uint8_t coord_select, i; + for (coord_select = 0; coord_select <= SETTING_INDEX_NCOORD; coord_select++) { + if (!(settings_read_coord_data(coord_select,coord_data))) { + report_status_message(STATUS_SETTING_READ_FAIL); + return; + } + switch (coord_select) { + case 0: printPgmString(PSTR("G54")); break; + case 1: printPgmString(PSTR("G55")); break; + case 2: printPgmString(PSTR("G56")); break; + case 3: printPgmString(PSTR("G57")); break; + case 4: printPgmString(PSTR("G58")); break; + case 5: printPgmString(PSTR("G59")); break; + case 6: printPgmString(PSTR("G28")); break; + case 7: printPgmString(PSTR("G30")); break; + // case 8: printPgmString(PSTR("G92")); break; // G92.2, G92.3 currently not supported. + } + printPgmString(PSTR(":[")); + for (i=0; i. -*/ - -#include -#include -#include "nuts_bolts.h" -#include "settings.h" -#include "eeprom.h" -#include "print.h" -#include -#include "protocol.h" -#include "config.h" -#include "report.h" - -settings_t settings; - -// Version 4 outdated settings record -typedef struct { - float steps_per_mm[3]; - uint8_t microsteps; - uint8_t pulse_microseconds; - float default_feed_rate; - float default_seek_rate; - uint8_t invert_mask; - float mm_per_arc_segment; - float acceleration; - float junction_deviation; -} settings_v4_t; - -// Default settings (used when resetting eeprom-settings) -#define MICROSTEPS 8 -#define DEFAULT_X_STEPS_PER_MM (94.488188976378*MICROSTEPS) -#define DEFAULT_Y_STEPS_PER_MM (94.488188976378*MICROSTEPS) -#define DEFAULT_Z_STEPS_PER_MM (94.488188976378*MICROSTEPS) -#define DEFAULT_STEP_PULSE_MICROSECONDS 30 -#define DEFAULT_MM_PER_ARC_SEGMENT 0.1 -#define DEFAULT_RAPID_FEEDRATE 500.0 // mm/min -#define DEFAULT_FEEDRATE 500.0 -#define DEFAULT_ACCELERATION (DEFAULT_FEEDRATE*60*60/10.0) // mm/min^2 -#define DEFAULT_JUNCTION_DEVIATION 0.05 // mm -#define DEFAULT_STEPPING_INVERT_MASK ((1<= 50) { - // Developmental settings. Version numbers greater than or equal to 50 are temporary. - // Currently, this will update the user settings to v4 and the remainder of the settings - // should be re-written to the default value, if the developmental version number changed. - - // Grab settings regardless of error. - memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v4_t)); - settings_reset(false); - } else { - return(false); - } - } - return(true); -} - - -// A helper method to set settings from command line -uint8_t settings_store_global_setting(int parameter, float value) { - switch(parameter) { - case 0: case 1: case 2: - if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); } - settings.steps_per_mm[parameter] = value; break; - case 3: - if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); } - settings.pulse_microseconds = round(value); break; - case 4: settings.default_feed_rate = value; break; - case 5: settings.default_seek_rate = value; break; - case 6: settings.mm_per_arc_segment = value; break; - case 7: settings.invert_mask = trunc(value); break; - case 8: settings.acceleration = value*60*60; break; // Convert to mm/min^2 for grbl internal use. - case 9: settings.junction_deviation = fabs(value); break; - case 10: - if (value) { - settings.flags |= BITFLAG_REPORT_INCHES; - } else { settings.flags &= ~BITFLAG_REPORT_INCHES; } - break; - case 11: - if (value) { - settings.flags |= BITFLAG_AUTO_START; - } else { settings.flags &= ~BITFLAG_AUTO_START; } - break; - case 12: - if (value) { - settings.flags |= BITFLAG_INVERT_ST_ENABLE; - } else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; } - break; - case 13: - if (value) { - settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; - } else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } - break; - case 14: - if (value) { - settings.flags |= BITFLAG_HOMING_ENABLE; - report_feedback_message(MESSAGE_HOMING_ENABLE); - } else { settings.flags &= ~BITFLAG_HOMING_ENABLE; } - break; - case 15: settings.homing_dir_mask = trunc(value); break; - case 16: settings.homing_feed_rate = value; break; - case 17: settings.homing_seek_rate = value; break; - case 18: settings.homing_debounce_delay = round(value); break; - case 19: - if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); } - settings.homing_pulloff = value; break; - case 20: - settings.stepper_idle_lock_time = round(value); - // TODO: Immediately check and toggle steppers from always enable or disable? - break; - case 21: settings.decimal_places = round(value); break; - case 22: settings.n_arc_correction = round(value); break; - default: - return(STATUS_INVALID_STATEMENT); - } - write_global_settings(); - return(STATUS_OK); -} - -// Initialize the config subsystem -void settings_init() { - if(!read_global_settings()) { - report_status_message(STATUS_SETTING_READ_FAIL); - settings_reset(true); - report_grbl_help(); - } -} - -// int8_t settings_execute_startup() { -// -// char buf[4]; -// settings_startup_string((char *)buf); -// uint8_t i = 0; -// while (i < 4) { -// serial_write(buf[i++]); -// } -// return(gc_execute_line(buf)); -// } +/* + settings.c - eeprom configuration handling + Part of Grbl + + Copyright (c) 2009-2011 Simen Svale Skogsrud + Copyright (c) 2011-2012 Sungeun K. Jeon + + Grbl is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Grbl is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Grbl. If not, see . +*/ + +#include +#include +#include "nuts_bolts.h" +#include "settings.h" +#include "eeprom.h" +#include "print.h" +#include +#include "protocol.h" +#include "config.h" +#include "report.h" + +settings_t settings; + +// Version 4 outdated settings record +typedef struct { + float steps_per_mm[3]; + uint8_t microsteps; + uint8_t pulse_microseconds; + float default_feed_rate; + float default_seek_rate; + uint8_t invert_mask; + float mm_per_arc_segment; + float acceleration; + float junction_deviation; +} settings_v4_t; + +// Default settings (used when resetting eeprom-settings) +#define MICROSTEPS 8 +#define DEFAULT_X_STEPS_PER_MM (94.488188976378*MICROSTEPS) +#define DEFAULT_Y_STEPS_PER_MM (94.488188976378*MICROSTEPS) +#define DEFAULT_Z_STEPS_PER_MM (94.488188976378*MICROSTEPS) +#define DEFAULT_STEP_PULSE_MICROSECONDS 30 +#define DEFAULT_MM_PER_ARC_SEGMENT 0.1 +#define DEFAULT_RAPID_FEEDRATE 500.0 // mm/min +#define DEFAULT_FEEDRATE 500.0 +#define DEFAULT_ACCELERATION (DEFAULT_FEEDRATE*60*60/10.0) // mm/min^2 +#define DEFAULT_JUNCTION_DEVIATION 0.05 // mm +#define DEFAULT_STEPPING_INVERT_MASK ((1<= 50) { + // Developmental settings. Version numbers greater than or equal to 50 are temporary. + // Currently, this will update the user settings to v4 and the remainder of the settings + // should be re-written to the default value, if the developmental version number changed. + + // Grab settings regardless of error. + memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_t)); + settings_reset(false); + } else { + return(false); + } + } + return(true); +} + + +// A helper method to set settings from command line +uint8_t settings_store_global_setting(int parameter, float value) { + switch(parameter) { + case 0: case 1: case 2: + if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); } + settings.steps_per_mm[parameter] = value; break; + case 3: + if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); } + settings.pulse_microseconds = round(value); break; + case 4: settings.default_feed_rate = value; break; + case 5: settings.default_seek_rate = value; break; + case 6: settings.mm_per_arc_segment = value; break; + case 7: settings.invert_mask = trunc(value); break; + case 8: settings.acceleration = value*60*60; break; // Convert to mm/min^2 for grbl internal use. + case 9: settings.junction_deviation = fabs(value); break; + case 10: + if (value) { + settings.flags |= BITFLAG_REPORT_INCHES; + } else { settings.flags &= ~BITFLAG_REPORT_INCHES; } + break; + case 11: + if (value) { + settings.flags |= BITFLAG_AUTO_START; + } else { settings.flags &= ~BITFLAG_AUTO_START; } + break; + case 12: + if (value) { + settings.flags |= BITFLAG_INVERT_ST_ENABLE; + } else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; } + break; + case 13: + if (value) { + settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; + } else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } + break; + case 14: + if (value) { + settings.flags |= BITFLAG_HOMING_ENABLE; + report_feedback_message(MESSAGE_HOMING_ENABLE); + } else { settings.flags &= ~BITFLAG_HOMING_ENABLE; } + break; + case 15: settings.homing_dir_mask = trunc(value); break; + case 16: settings.homing_feed_rate = value; break; + case 17: settings.homing_seek_rate = value; break; + case 18: settings.homing_debounce_delay = round(value); break; + case 19: + if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); } + settings.homing_pulloff = value; break; + case 20: + settings.stepper_idle_lock_time = round(value); + // TODO: Immediately check and toggle steppers from always enable or disable? + break; + case 21: settings.decimal_places = round(value); break; + case 22: settings.n_arc_correction = round(value); break; + default: + return(STATUS_INVALID_STATEMENT); + } + write_global_settings(); + return(STATUS_OK); +} + +// Initialize the config subsystem +void settings_init() { + if(!read_global_settings()) { + report_status_message(STATUS_SETTING_READ_FAIL); + settings_reset(true); + report_grbl_help(); + } +} + +// int8_t settings_execute_startup() { +// +// char buf[4]; +// settings_startup_string((char *)buf); +// uint8_t i = 0; +// while (i < 4) { +// serial_write(buf[i++]); +// } +// return(gc_execute_line(buf)); +// } diff --git a/settings.h b/settings.h index 3af5ba5..3abf350 100755 --- a/settings.h +++ b/settings.h @@ -26,7 +26,7 @@ #include #include "nuts_bolts.h" -#define GRBL_VERSION "0.8b" +#define GRBL_VERSION "0.8c" // Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl // when firmware is upgraded. Always stored in byte 0 of eeprom @@ -39,18 +39,21 @@ #define BITFLAG_HARD_LIMIT_ENABLE bit(3) #define BITFLAG_HOMING_ENABLE bit(4) -// Define EEPROM memory address location values for on-demand settings and parameters +// 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 +// the startup script. The lower half contains the global settings and space for future +// developments. #define EEPROM_ADDR_GLOBAL 1 #define EEPROM_ADDR_PARAMETERS 512 #define EEPROM_ADDR_STARTUP_SCRIPT 768 // Define EEPROM address indexing for coordinate parameters #define N_COORDINATE_SYSTEM 6 // Number of supported work coordinate systems (from index 1) -#define SETTING_INDEX_NCOORD N_COORDINATE_SYSTEM+2 // Total number of system stored (from index 0) +#define SETTING_INDEX_NCOORD N_COORDINATE_SYSTEM+1 // Total number of system stored (from index 0) // NOTE: Work coordinate indices are (0=G54, 1=G55, ... , 6=G59) #define SETTING_INDEX_G28 N_COORDINATE_SYSTEM // Home position 1 #define SETTING_INDEX_G30 N_COORDINATE_SYSTEM+1 // Home position 2 -#define SETTING_INDEX_G92 N_COORDINATE_SYSTEM+2 // Coordinate offset +// #define SETTING_INDEX_G92 N_COORDINATE_SYSTEM+2 // Coordinate offset (G92.2,G92.3 not supported) // Global persistent settings (Stored from byte EEPROM_ADDR_GLOBAL onwards) typedef struct { @@ -72,6 +75,7 @@ typedef struct { uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable. uint8_t decimal_places; uint8_t n_arc_correction; +// uint8_t status_report_mask; // Mask to indicate desired report data. } settings_t; extern settings_t settings; diff --git a/spindle_control.c b/spindle_control.c index abc67e2..1d65f41 100755 --- a/spindle_control.c +++ b/spindle_control.c @@ -43,7 +43,7 @@ void spindle_stop() SPINDLE_ENABLE_PORT &= ~(1< void spindle_init(); -void spindle_run(int8_t direction, uint16_t rpm); +void spindle_run(int8_t direction); //, uint16_t rpm); void spindle_stop(); #endif