Added block delete, opt stop, single block mode. New parser state and parameter feedback. Overhauled '$' command.

NOTE: Another incremental update. Likely buggy, still a ways to go
before everything is installed, such as startup blocks.

- Changed the '$' command to print help. '$$' now prints Grbl settings.
The help now instructs the user of runtime commands, switch toggling,
homing, etc. Jogging will be added to these in v0.9.

- Added switches: block delete, opt stop, and single block mode.

- Now can print the g-code parser state and persistent parameters
(coord sys) to view what Grbl has internally.

- Made the gc struct in the g-code parser global to be able to print
the states. Also moved coordinate system tracking from sys to gc struct.

- Changed up the welcome flag and updated version to v0.8c.

- Removed spindle speed from gcode parser. Not used.
This commit is contained in:
Sonny Jeon 2012-11-01 19:48:55 -06:00
parent e0a9054e32
commit 303cf59f52
11 changed files with 570 additions and 448 deletions

View File

@ -149,7 +149,7 @@
// TODO: The following options are set as compile-time options for now, until the next EEPROM // 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 // settings version has solidified. This is to prevent having to support dozens of different
// incremental settings versions. // 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. // 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 // A short delay ensures the steppers come to a complete stop and the residual inertial force in the

106
gcode.c
View File

@ -34,62 +34,8 @@
#include "protocol.h" #include "protocol.h"
#include "report.h" #include "report.h"
// Define modal group internal numbers for checking multiple command violations and tracking the // Declare gc extern struct
// type of command that is called in the block. A modal group is a group of g-code commands that are parser_state_t gc;
// 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;
#define FAIL(status) gc.status_code = status; #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() void gc_init()
{ {
memset(&gc, 0, sizeof(gc)); 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); select_plane(X_AXIS, Y_AXIS, Z_AXIS);
gc.absolute_mode = true; 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()); // 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 19: select_plane(Y_AXIS, Z_AXIS, X_AXIS); break;
case 20: gc.inches_mode = true; break; case 20: gc.inches_mode = true; break;
case 21: gc.inches_mode = false; break; case 21: gc.inches_mode = false; break;
// NOTE: G28.1, G30.1 sets home position parameters. Not currently supported.
case 28: case 30: 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) { switch(int_value) {
case 280: non_modal_action = NON_MODAL_GO_HOME_0; break; case 280: non_modal_action = NON_MODAL_GO_HOME_0; break;
case 281: non_modal_action = NON_MODAL_SET_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; break;
case 53: absolute_override = true; break; case 53: absolute_override = true; break;
case 54: case 55: case 56: case 57: case 58: case 59: 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; break;
case 80: gc.motion_mode = MOTION_MODE_CANCEL; break; case 80: gc.motion_mode = MOTION_MODE_CANCEL; break;
case 90: gc.absolute_mode = true; break; case 90: gc.absolute_mode = true; break;
@ -226,10 +176,11 @@ uint8_t gc_execute_line(char *line)
// Set 'M' commands // Set 'M' commands
switch(int_value) { switch(int_value) {
case 0: gc.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause case 0: gc.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause
case 1: // Program pause with optional stop on case 1: // Program pause with optional stop on, otherwise do nothing.
// if (sys.opt_stop) { // TODO: Add system variable for optional stop. if (bit_istrue(sys.switches,BITFLAG_OPT_STOP)) {
gc.program_flow = PROGRAM_FLOW_PAUSED; break; gc.program_flow = PROGRAM_FLOW_PAUSED;
// } }
break;
case 2: case 30: gc.program_flow = PROGRAM_FLOW_COMPLETED; break; // Program end and reset case 2: case 30: gc.program_flow = PROGRAM_FLOW_COMPLETED; break; // Program end and reset
case 3: gc.spindle_direction = 1; break; case 3: gc.spindle_direction = 1; break;
case 4: 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 'R': r = to_millimeters(value); break;
case 'S': case 'S':
if (value < 0) { FAIL(STATUS_INVALID_STATEMENT); } // Cannot be negative 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; break;
case 'T': case 'T':
if (value < 0) { FAIL(STATUS_INVALID_STATEMENT); } // Cannot be negative 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.) // ([M6]: Tool change should be executed here.)
// [M3,M4,M5]: Update spindle state // [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 // [*M7,M8,M9]: Update coolant state
coolant_run(gc.coolant_mode); coolant_run(gc.coolant_mode);
@ -312,8 +264,8 @@ uint8_t gc_execute_line(char *line)
// [G54,G55,...,G59]: Coordinate system selection // [G54,G55,...,G59]: Coordinate system selection
if ( bit_istrue(modal_group_words,bit(MODAL_GROUP_12)) ) { // Check if called in block if ( bit_istrue(modal_group_words,bit(MODAL_GROUP_12)) ) { // Check if called in block
float coord_data[N_AXIS]; float coord_data[N_AXIS];
if (!(settings_read_coord_data(sys.coord_select,coord_data))) { return(STATUS_SETTING_READ_FAIL); } if (!(settings_read_coord_data(gc.coord_select,coord_data))) { return(STATUS_SETTING_READ_FAIL); }
memcpy(sys.coord_system,coord_data,sizeof(coord_data)); 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. // [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) { if (l == 20) {
settings_write_coord_data(int_value,gc.position); settings_write_coord_data(int_value,gc.position);
// Update system coordinate system if currently active. // 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 { } else {
float coord_data[N_AXIS]; float coord_data[N_AXIS];
if (!settings_read_coord_data(int_value,coord_data)) { return(STATUS_SETTING_READ_FAIL); } 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); settings_write_coord_data(int_value,coord_data);
// Update system coordinate system if currently active. // 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. 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<N_AXIS; i++) { // Axes indices are consistent, so loop may be used. for (i=0; i<N_AXIS; i++) { // Axes indices are consistent, so loop may be used.
if ( bit_istrue(axis_words,bit(i)) ) { if ( bit_istrue(axis_words,bit(i)) ) {
if (gc.absolute_mode) { if (gc.absolute_mode) {
target[i] += sys.coord_system[i] + sys.coord_offset[i]; target[i] += gc.coord_system[i] + gc.coord_offset[i];
} else { } else {
target[i] += gc.position[i]; target[i] += gc.position[i];
} }
@ -395,14 +347,14 @@ uint8_t gc_execute_line(char *line)
uint8_t i; uint8_t i;
for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used. for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
if (bit_istrue(axis_words,bit(i)) ) { if (bit_istrue(axis_words,bit(i)) ) {
sys.coord_offset[i] = gc.position[i]-sys.coord_system[i]-target[i]; gc.coord_offset[i] = gc.position[i]-gc.coord_system[i]-target[i];
} }
} }
} }
axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags. axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.
break; break;
case NON_MODAL_RESET_COORDINATE_OFFSET: case NON_MODAL_RESET_COORDINATE_OFFSET:
clear_vector(sys.coord_offset); // Disable G92 offsets by zeroing offset vector. clear_vector(gc.coord_offset); // Disable G92 offsets by zeroing offset vector.
break; break;
} }
@ -432,7 +384,7 @@ uint8_t gc_execute_line(char *line)
if ( bit_istrue(axis_words,bit(i)) ) { if ( bit_istrue(axis_words,bit(i)) ) {
if (!absolute_override) { // Do not update target in absolute override mode if (!absolute_override) { // Do not update target in absolute override mode
if (gc.absolute_mode) { if (gc.absolute_mode) {
target[i] += sys.coord_system[i] + sys.coord_offset[i]; // Absolute mode target[i] += gc.coord_system[i] + gc.coord_offset[i]; // Absolute mode
} else { } else {
target[i] += gc.position[i]; // Incremental mode target[i] += gc.position[i]; // Incremental mode
} }
@ -585,9 +537,9 @@ uint8_t gc_execute_line(char *line)
// M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may // M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may
// refill and can only be resumed by the cycle start run-time command. // refill and can only be resumed by the cycle start run-time command.
if (gc.program_flow) { if (gc.program_flow || bit_istrue(sys.switches,BITFLAG_SINGLE_BLOCK)) {
plan_synchronize(); // Finish all remaining buffered motions. Program paused when complete. plan_synchronize(); // Finish all remaining buffered motions. Program paused when complete.
sys.auto_start = false; // Disable auto cycle start. sys.auto_start = false; // Disable auto cycle start. Forces pause until cycle start issued.
// If complete, reset to reload defaults (G92.2,G54,G17,G90,G94,M48,G40,M5,M9). Otherwise, // If complete, reset to reload defaults (G92.2,G54,G17,G90,G94,M48,G40,M5,M9). Otherwise,
// re-enable program flow after pause complete, where cycle start will resume the program. // re-enable program flow after pause complete, where cycle start will resume the program.
@ -628,7 +580,6 @@ static int next_statement(char *letter, float *float_ptr, char *line, uint8_t *c
- A,B,C-axes - A,B,C-axes
- Evaluation of expressions - Evaluation of expressions
- Variables - Variables
- Multiple home locations
- Probing - Probing
- Override control - Override control
- Tool changes - Tool changes
@ -639,6 +590,5 @@ static int next_statement(char *letter, float *float_ptr, char *line, uint8_t *c
group 6 = {M6} (Tool change) group 6 = {M6} (Tool change)
group 8 = {*M7} enable mist coolant group 8 = {*M7} enable mist coolant
group 9 = {M48, M49} enable/disable feed and speed override switches group 9 = {M48, M49} enable/disable feed and speed override switches
group 12 = {*G55, *G56, *G57, *G58, *G59, G59.1, G59.2, G59.3} coordinate system selection
group 13 = {G61, G61.1, G64} path control mode group 13 = {G61, G61.1, G64} path control mode
*/ */

64
gcode.h
View File

@ -19,10 +19,72 @@
along with Grbl. If not, see <http://www.gnu.org/licenses/>. along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef gcode_h #ifndef gcode_h
#define gcode_h #define gcode_h
#include <avr/io.h> #include <avr/io.h>
#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 // Initialize the parser
void gc_init(); void gc_init();

View File

@ -35,12 +35,12 @@
#define Y_AXIS 1 #define Y_AXIS 1
#define Z_AXIS 2 #define Z_AXIS 2
#define MM_PER_INCH (25.4) #define MM_PER_INCH (25.40)
#define INCH_PER_MM (0.03937) #define INCH_PER_MM (0.0393701)
// Useful macros // Useful macros
#define clear_vector(a) memset(a, 0, sizeof(a)) #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 max(a,b) (((a) > (b)) ? (a) : (b))
#define min(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 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 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 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. uint8_t switches; // Switches state bitflag variable. For features not governed by g-code.
int32_t position[3]; // Real-time machine (aka home) position vector in steps. // uint8_t state; // Tracks the current state of Grbl.
// NOTE: This may need to be a volatile variable, if problems arise. // 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 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. 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; } system_t;
extern system_t sys; extern system_t sys;

View File

@ -135,77 +135,80 @@ uint8_t protocol_execute_line(char *line)
uint8_t char_counter = 1; uint8_t char_counter = 1;
float parameter, value; float parameter, value;
switch( line[char_counter] ) { switch( line[char_counter] ) {
case 0 : case 0 : report_grbl_help(); break;
report_grbl_help(); case '$' : // Prints Grbl settings
return(STATUS_OK); 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; 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, &parameter)) { 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 case 'H' : // Perform homing cycle
if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) { mc_go_home(); }
mc_go_home(); else { return(STATUS_SETTING_DISABLED); }
return(STATUS_OK);
} else {
return(STATUS_SETTING_DISABLED);
}
break; break;
// // case 'J' : break; // Jogging methods // case 'J' : break; // Jogging methods
// // TODO: Here jogging can be placed for execution as a seperate subprogram. It does not need to be // 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 // 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 // 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 // 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 // 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 // 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. // 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 // 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 // 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 // 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 'P' : // Print g-code parameters and parser state // case 'N' : // Start up blocks
// if(line[char_counter] != 0) { return(STATUS_UNSUPPORTED_STATEMENT); } // if(!read_float(line, &char_counter, &parameter)) { return(STATUS_BAD_NUMBER_FORMAT); }
// // if(line[char_counter++] != '=') { return(STATUS_UNSUPPORTED_STATEMENT); }
// break; // // Extract startup block, execute, and store.
// case 'S' : // Switch methods // for (char_counter = 0; char_counter < LINE_BUFFER_SIZE-3; char_counter++) {
// // Opt stop and block delete are referred to as switches. // line[char_counter] = line[char_counter+3];
// // How to store home position and work offsets real-time?? // }
// break; // uint8_t status = gc_execute_line(line);
// // Parse $parameter=value settings // if (status) { return(status); }
default : // else { settings_store_startup_block(line); }
if(!read_float(line, &char_counter, &parameter)) { // break;
return(STATUS_BAD_NUMBER_FORMAT); case 'B' : // Toggle block delete
} if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
if(line[char_counter++] != '=') { sys.switches ^= BITFLAG_BLOCK_DELETE;
return(STATUS_UNSUPPORTED_STATEMENT); if (bit_istrue(sys.switches,BITFLAG_BLOCK_DELETE)) { report_feedback_message(MESSAGE_SWITCH_ON); }
} else { report_feedback_message(MESSAGE_SWITCH_OFF); }
if(!read_float(line, &char_counter, &value)) { break;
return(STATUS_BAD_NUMBER_FORMAT); case 'S' : // Toggle single block mode
} if ( line[++char_counter] != 0 ) { return(STATUS_UNSUPPORTED_STATEMENT); }
if(line[char_counter] != 0) { sys.switches ^= BITFLAG_SINGLE_BLOCK;
return(STATUS_UNSUPPORTED_STATEMENT); 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, &parameter)) { 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(settings_store_global_setting(parameter, value));
} }
return(STATUS_OK); // If '$' command makes it to here, then everything's ok.
} 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 // 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 // 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 the g-code doesn't perform as intended.
} }
} }
@ -246,9 +249,9 @@ void protocol_process()
// Throw away whitepace and control characters // Throw away whitepace and control characters
} else if (c == '/') { } else if (c == '/') {
// Disable block delete and throw away characters. Will ignore until EOL. // 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; iscomment = true;
#endif }
} else if (c == '(') { } else if (c == '(') {
// Enable comments flag and ignore all characters until ')' or EOL. // Enable comments flag and ignore all characters until ')' or EOL.
iscomment = true; iscomment = true;

154
report.c
View File

@ -34,6 +34,8 @@
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include "report.h" #include "report.h"
#include "protocol.h" #include "protocol.h"
#include "gcode.h"
#include "coolant_control.h"
// Handles the primary confirmation protocol response for streaming interfaces and human-feedback. // 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 // 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 // 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. // are messages such as setup warnings and how to exit alarms.
// NOTE: For interfaces, messages are always placed within parentheses. And if silent mode // NOTE: For interfaces, messages are always placed within chevrons. And if silent mode
// is installed, the message codes are less than zero. // is installed, the message number codes are less than zero.
// TODO: Install silence feedback messages option in settings // TODO: Install silence feedback messages option in settings
void report_feedback_message(int8_t message_code) void report_feedback_message(int8_t message_code)
{ {
printPgmString(PSTR("(")); printPgmString(PSTR("<"));
switch(message_code) { switch(message_code) {
case MESSAGE_SYSTEM_ALARM: case MESSAGE_SYSTEM_ALARM:
printPgmString(PSTR("ALARM: Check and reset Grbl")); break; 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; printPgmString(PSTR("warning: Position may be lost")); break;
case MESSAGE_HOMING_ENABLE: case MESSAGE_HOMING_ENABLE:
printPgmString(PSTR("'$H' to home. Ensure all limit switches are installed")); break; 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 // Welcome message
void report_init_message() void report_init_message()
{ {
// Print grbl initialization message printPgmString(PSTR("\r\nGrbl " GRBL_VERSION " ['$' for help]\r\n"));
printPgmString(PSTR("\r\nGrbl " GRBL_VERSION));
printPgmString(PSTR("\r\n'$' for help and to view settings\r\n"));
} }
void report_grbl_help() { 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("$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(" (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]); 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(" (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(" (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); printPgmString(PSTR(" (decimal places, int)\r\n$22 = ")); printInteger(settings.n_arc_correction);
// char st_line[LINE_BUFFER_SIZE]; printPgmString(PSTR(" (n arc correction, int)\r\n"));
// 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"));
} }
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<N_AXIS; i++) {
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { printFloat(coord_data[i]*INCH_PER_MM); }
else { printFloat(coord_data[i]); }
if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); }
else { printPgmString(PSTR("]\r\n")); }
}
}
printPgmString(PSTR("G92:[")); // Print G92,G92.1 which are not persistent in memory
for (i=0; i<N_AXIS; i++) {
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { printFloat(gc.coord_offset[i]*INCH_PER_MM); }
else { printFloat(gc.coord_offset[i]); }
if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); }
else { printPgmString(PSTR("]\r\n")); }
}
}
void report_gcode_modes()
{
switch (gc.motion_mode) {
case MOTION_MODE_SEEK : printPgmString(PSTR("G0")); break;
case MOTION_MODE_LINEAR : printPgmString(PSTR("G1")); break;
case MOTION_MODE_CW_ARC : printPgmString(PSTR("G2")); break;
case MOTION_MODE_CCW_ARC : printPgmString(PSTR("G3")); break;
case MOTION_MODE_CANCEL : printPgmString(PSTR("G80")); break;
}
// void report_gcode_status() printPgmString(PSTR(" G"));
// { printInteger(gc.coord_select+54);
// // Print gcode parser state
// } if (gc.plane_axis_0 == X_AXIS) {
// if (gc.plane_axis_1 == Y_AXIS) { printPgmString(PSTR(" G17")); }
// void report_gcode_parameters() else { printPgmString(PSTR(" G18")); }
// { } else { printPgmString(PSTR(" G19")); }
// // Print gcode work coordinate offsets?
// } if (gc.inches_mode) { printPgmString(PSTR(" G20")); }
else { printPgmString(PSTR(" G21")); }
if (gc.absolute_mode) { printPgmString(PSTR(" G90")); }
else { printPgmString(PSTR(" G91")); }
if (gc.inverse_feed_rate_mode) { printPgmString(PSTR(" G93")); }
else { printPgmString(PSTR(" G94")); }
// TODO: Check if G92 needs to be here. If so, how to track it.
switch (gc.program_flow) {
case PROGRAM_FLOW_RUNNING : printPgmString(PSTR(" M0")); break;
case PROGRAM_FLOW_PAUSED : printPgmString(PSTR(" M1")); break;
case PROGRAM_FLOW_COMPLETED : printPgmString(PSTR(" M2")); break;
}
switch (gc.spindle_direction) {
case 1 : printPgmString(PSTR(" M3")); break;
case -1 : printPgmString(PSTR(" M4")); break;
case 0 : printPgmString(PSTR(" M5")); break;
}
switch (gc.coolant_mode) {
case COOLANT_DISABLE : printPgmString(PSTR(" M9")); break;
case COOLANT_FLOOD_ENABLE : printPgmString(PSTR(" M8")); break;
// case COOLANT_MIST_ENABLE : printPgmString(PSTR(" M7")); break;
}
printPgmString(PSTR(" T"));
printInteger(gc.tool);
printPgmString(PSTR(" F"));
if (gc.inches_mode) { printFloat(gc.feed_rate*INCH_PER_MM); }
else { printFloat(gc.feed_rate); }
if (sys.switches) {
if (bit_istrue(sys.switches,BITFLAG_BLOCK_DELETE)) { printPgmString(PSTR(" $B")); }
if (bit_istrue(sys.switches,BITFLAG_SINGLE_BLOCK)) { printPgmString(PSTR(" $S")); }
if (bit_istrue(sys.switches,BITFLAG_OPT_STOP)) { printPgmString(PSTR(" $O")); }
}
printPgmString(PSTR("\r\n"));
}
void report_realtime_status() void report_realtime_status()
@ -198,9 +296,9 @@ void report_realtime_status()
printPgmString(PSTR(",WPos:[")); printPgmString(PSTR(",WPos:["));
for (i=0; i<= 2; i++) { for (i=0; i<= 2; i++) {
if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) { if (bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)) {
print_position[i] -= (sys.coord_system[i]+sys.coord_offset[i])*INCH_PER_MM; print_position[i] -= (gc.coord_system[i]+gc.coord_offset[i])*INCH_PER_MM;
} else { } else {
print_position[i] -= sys.coord_system[i]+sys.coord_offset[i]; print_position[i] -= gc.coord_system[i]+gc.coord_offset[i];
} }
printFloat(print_position[i]); printFloat(print_position[i]);
if (i < 2) { printPgmString(PSTR(",")); } if (i < 2) { printPgmString(PSTR(",")); }

View File

@ -39,7 +39,8 @@
#define MESSAGE_SYSTEM_ALARM -1 #define MESSAGE_SYSTEM_ALARM -1
#define MESSAGE_POSITION_LOST -2 #define MESSAGE_POSITION_LOST -2
#define MESSAGE_HOMING_ENABLE -3 #define MESSAGE_HOMING_ENABLE -3
#define MESSAGE_SWITCH_ON -4
#define MESSAGE_SWITCH_OFF -5
// Prints system status messages. // Prints system status messages.
void report_status_message(uint8_t status_code); void report_status_message(uint8_t status_code);
@ -53,7 +54,14 @@ void report_init_message();
// Prints Grbl help and current global settings // Prints Grbl help and current global settings
void report_grbl_help(); void report_grbl_help();
void report_grbl_settings();
// Prints realtime status report // Prints realtime status report
void report_realtime_status(); void report_realtime_status();
// Prints Grbl persistent coordinate parameters
void report_gcode_parameters();
void report_gcode_modes();
#endif #endif

View File

@ -1,256 +1,256 @@
/* /*
settings.c - eeprom configuration handling settings.c - eeprom configuration handling
Part of Grbl Part of Grbl
Copyright (c) 2009-2011 Simen Svale Skogsrud Copyright (c) 2009-2011 Simen Svale Skogsrud
Copyright (c) 2011-2012 Sungeun K. Jeon Copyright (c) 2011-2012 Sungeun K. Jeon
Grbl is free software: you can redistribute it and/or modify Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (at your option) any later version.
Grbl is distributed in the hope that it will be useful, Grbl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Grbl. If not, see <http://www.gnu.org/licenses/>. along with Grbl. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <avr/io.h> #include <avr/io.h>
#include <math.h> #include <math.h>
#include "nuts_bolts.h" #include "nuts_bolts.h"
#include "settings.h" #include "settings.h"
#include "eeprom.h" #include "eeprom.h"
#include "print.h" #include "print.h"
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#include "protocol.h" #include "protocol.h"
#include "config.h" #include "config.h"
#include "report.h" #include "report.h"
settings_t settings; settings_t settings;
// Version 4 outdated settings record // Version 4 outdated settings record
typedef struct { typedef struct {
float steps_per_mm[3]; float steps_per_mm[3];
uint8_t microsteps; uint8_t microsteps;
uint8_t pulse_microseconds; uint8_t pulse_microseconds;
float default_feed_rate; float default_feed_rate;
float default_seek_rate; float default_seek_rate;
uint8_t invert_mask; uint8_t invert_mask;
float mm_per_arc_segment; float mm_per_arc_segment;
float acceleration; float acceleration;
float junction_deviation; float junction_deviation;
} settings_v4_t; } settings_v4_t;
// Default settings (used when resetting eeprom-settings) // Default settings (used when resetting eeprom-settings)
#define MICROSTEPS 8 #define MICROSTEPS 8
#define DEFAULT_X_STEPS_PER_MM (94.488188976378*MICROSTEPS) #define DEFAULT_X_STEPS_PER_MM (94.488188976378*MICROSTEPS)
#define DEFAULT_Y_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_Z_STEPS_PER_MM (94.488188976378*MICROSTEPS)
#define DEFAULT_STEP_PULSE_MICROSECONDS 30 #define DEFAULT_STEP_PULSE_MICROSECONDS 30
#define DEFAULT_MM_PER_ARC_SEGMENT 0.1 #define DEFAULT_MM_PER_ARC_SEGMENT 0.1
#define DEFAULT_RAPID_FEEDRATE 500.0 // mm/min #define DEFAULT_RAPID_FEEDRATE 500.0 // mm/min
#define DEFAULT_FEEDRATE 500.0 #define DEFAULT_FEEDRATE 500.0
#define DEFAULT_ACCELERATION (DEFAULT_FEEDRATE*60*60/10.0) // mm/min^2 #define DEFAULT_ACCELERATION (DEFAULT_FEEDRATE*60*60/10.0) // mm/min^2
#define DEFAULT_JUNCTION_DEVIATION 0.05 // mm #define DEFAULT_JUNCTION_DEVIATION 0.05 // mm
#define DEFAULT_STEPPING_INVERT_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)) #define DEFAULT_STEPPING_INVERT_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT))
// Developmental default settings // Developmental default settings
#define DEFAULT_REPORT_INCHES 0 // false #define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_AUTO_START 1 // true #define DEFAULT_AUTO_START 1 // true
#define DEFAULT_INVERT_ST_ENABLE 0 // false #define DEFAULT_INVERT_ST_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false #define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 0 // false #define DEFAULT_HOMING_ENABLE 0 // false
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
#define DEFAULT_HOMING_RAPID_FEEDRATE 250.0 // mm/min #define DEFAULT_HOMING_RAPID_FEEDRATE 250.0 // mm/min
#define DEFAULT_HOMING_FEEDRATE 50 // mm/min #define DEFAULT_HOMING_FEEDRATE 50 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 100 // msec (0-65k) #define DEFAULT_HOMING_DEBOUNCE_DELAY 100 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1 // mm #define DEFAULT_HOMING_PULLOFF 1 // mm
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
#define DEFAULT_DECIMAL_PLACES 3 #define DEFAULT_DECIMAL_PLACES 3
#define DEFAULT_N_ARC_CORRECTION 25 #define DEFAULT_N_ARC_CORRECTION 25
void settings_write_coord_data(uint8_t coord_select, float *coord_data) void settings_write_coord_data(uint8_t coord_select, float *coord_data)
{ {
uint16_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS; uint16_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;
memcpy_to_eeprom_with_checksum(addr,(char*)coord_data, sizeof(float)*N_AXIS); memcpy_to_eeprom_with_checksum(addr,(char*)coord_data, sizeof(float)*N_AXIS);
} }
void write_global_settings() void write_global_settings()
{ {
eeprom_put_char(0, SETTINGS_VERSION); eeprom_put_char(0, SETTINGS_VERSION);
memcpy_to_eeprom_with_checksum(EEPROM_ADDR_GLOBAL, (char*)&settings, sizeof(settings_t)); memcpy_to_eeprom_with_checksum(EEPROM_ADDR_GLOBAL, (char*)&settings, sizeof(settings_t));
} }
void settings_reset(bool reset_all) { void settings_reset(bool reset_all) {
// Reset all settings or only the migration settings to the new version. // Reset all settings or only the migration settings to the new version.
if (reset_all) { if (reset_all) {
settings.steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM; settings.steps_per_mm[X_AXIS] = DEFAULT_X_STEPS_PER_MM;
settings.steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM; settings.steps_per_mm[Y_AXIS] = DEFAULT_Y_STEPS_PER_MM;
settings.steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM; settings.steps_per_mm[Z_AXIS] = DEFAULT_Z_STEPS_PER_MM;
settings.pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS; settings.pulse_microseconds = DEFAULT_STEP_PULSE_MICROSECONDS;
settings.default_feed_rate = DEFAULT_FEEDRATE; settings.default_feed_rate = DEFAULT_FEEDRATE;
settings.default_seek_rate = DEFAULT_RAPID_FEEDRATE; settings.default_seek_rate = DEFAULT_RAPID_FEEDRATE;
settings.acceleration = DEFAULT_ACCELERATION; settings.acceleration = DEFAULT_ACCELERATION;
settings.mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT; settings.mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT;
settings.invert_mask = DEFAULT_STEPPING_INVERT_MASK; settings.invert_mask = DEFAULT_STEPPING_INVERT_MASK;
settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION; settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION;
} }
// New settings since last version // New settings since last version
settings.flags = 0; settings.flags = 0;
if (DEFAULT_REPORT_INCHES) { settings.flags |= BITFLAG_REPORT_INCHES; } if (DEFAULT_REPORT_INCHES) { settings.flags |= BITFLAG_REPORT_INCHES; }
if (DEFAULT_AUTO_START) { settings.flags |= BITFLAG_AUTO_START; } if (DEFAULT_AUTO_START) { settings.flags |= BITFLAG_AUTO_START; }
if (DEFAULT_INVERT_ST_ENABLE) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; } if (DEFAULT_INVERT_ST_ENABLE) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; }
if (DEFAULT_HARD_LIMIT_ENABLE) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } if (DEFAULT_HARD_LIMIT_ENABLE) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }
if (DEFAULT_HOMING_ENABLE) { settings.flags |= BITFLAG_HOMING_ENABLE; } if (DEFAULT_HOMING_ENABLE) { settings.flags |= BITFLAG_HOMING_ENABLE; }
settings.homing_dir_mask = DEFAULT_HOMING_DIR_MASK; settings.homing_dir_mask = DEFAULT_HOMING_DIR_MASK;
settings.homing_feed_rate = DEFAULT_HOMING_FEEDRATE; settings.homing_feed_rate = DEFAULT_HOMING_FEEDRATE;
settings.homing_seek_rate = DEFAULT_HOMING_RAPID_FEEDRATE; settings.homing_seek_rate = DEFAULT_HOMING_RAPID_FEEDRATE;
settings.homing_debounce_delay = DEFAULT_HOMING_DEBOUNCE_DELAY; settings.homing_debounce_delay = DEFAULT_HOMING_DEBOUNCE_DELAY;
settings.homing_pulloff = DEFAULT_HOMING_PULLOFF; settings.homing_pulloff = DEFAULT_HOMING_PULLOFF;
settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME; settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;
settings.decimal_places = DEFAULT_DECIMAL_PLACES; settings.decimal_places = DEFAULT_DECIMAL_PLACES;
settings.n_arc_correction = DEFAULT_N_ARC_CORRECTION; settings.n_arc_correction = DEFAULT_N_ARC_CORRECTION;
write_global_settings(); write_global_settings();
// Zero all coordinate parameter data. // Zero all coordinate parameter data.
float coord_data[N_AXIS]; float coord_data[N_AXIS];
clear_vector_float(coord_data); clear_vector_float(coord_data);
uint8_t i = 0; uint8_t i = 0;
for (i=0; i<=SETTING_INDEX_NCOORD; i++) { for (i=0; i<=SETTING_INDEX_NCOORD; i++) {
settings_write_coord_data(i,coord_data); settings_write_coord_data(i,coord_data);
} }
} }
// Read selected coordinate data from EEPROM. Updates pointed coord_data value. // Read selected coordinate data from EEPROM. Updates pointed coord_data value.
uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data) uint8_t settings_read_coord_data(uint8_t coord_select, float *coord_data)
{ {
uint16_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS; uint16_t addr = coord_select*(sizeof(float)*N_AXIS+1) + EEPROM_ADDR_PARAMETERS;
if ((!memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float)*N_AXIS))) { if ((!memcpy_from_eeprom_with_checksum((char*)coord_data, addr, sizeof(float)*N_AXIS))) {
clear_vector_float(coord_data); // Default zero vector clear_vector_float(coord_data); // Default zero vector
settings_write_coord_data(coord_select,coord_data); settings_write_coord_data(coord_select,coord_data);
return(false); return(false);
} else { } else {
return(true); return(true);
} }
} }
uint8_t read_global_settings() { uint8_t read_global_settings() {
// Check version-byte of eeprom // Check version-byte of eeprom
uint8_t version = eeprom_get_char(0); uint8_t version = eeprom_get_char(0);
if (version == SETTINGS_VERSION) { if (version == SETTINGS_VERSION) {
// Read settings-record and check checksum // Read settings-record and check checksum
if (!(memcpy_from_eeprom_with_checksum((char*)&settings, EEPROM_ADDR_GLOBAL, sizeof(settings_t)))) { if (!(memcpy_from_eeprom_with_checksum((char*)&settings, EEPROM_ADDR_GLOBAL, sizeof(settings_t)))) {
return(false); return(false);
} }
} else { } else {
if (version <= 4) { if (version <= 4) {
// Migrate from settings version 4 to current version. // Migrate from settings version 4 to current version.
if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v4_t)))) { if (!(memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v4_t)))) {
return(false); return(false);
} }
settings_reset(false); settings_reset(false);
} else if (version >= 50) { } else if (version >= 50) {
// Developmental settings. Version numbers greater than or equal to 50 are temporary. // 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 // 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. // should be re-written to the default value, if the developmental version number changed.
// Grab settings regardless of error. // Grab settings regardless of error.
memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_v4_t)); memcpy_from_eeprom_with_checksum((char*)&settings, 1, sizeof(settings_t));
settings_reset(false); settings_reset(false);
} else { } else {
return(false); return(false);
} }
} }
return(true); return(true);
} }
// A helper method to set settings from command line // A helper method to set settings from command line
uint8_t settings_store_global_setting(int parameter, float value) { uint8_t settings_store_global_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_VALUE_NEG); } if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); }
settings.steps_per_mm[parameter] = value; break; settings.steps_per_mm[parameter] = value; break;
case 3: case 3:
if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); } if (value < 3) { return(STATUS_SETTING_STEP_PULSE_MIN); }
settings.pulse_microseconds = round(value); break; settings.pulse_microseconds = round(value); break;
case 4: settings.default_feed_rate = value; break; case 4: settings.default_feed_rate = value; break;
case 5: settings.default_seek_rate = value; break; case 5: settings.default_seek_rate = value; break;
case 6: settings.mm_per_arc_segment = value; break; case 6: settings.mm_per_arc_segment = value; break;
case 7: settings.invert_mask = trunc(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 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 9: settings.junction_deviation = fabs(value); break;
case 10: case 10:
if (value) { if (value) {
settings.flags |= BITFLAG_REPORT_INCHES; settings.flags |= BITFLAG_REPORT_INCHES;
} else { settings.flags &= ~BITFLAG_REPORT_INCHES; } } else { settings.flags &= ~BITFLAG_REPORT_INCHES; }
break; break;
case 11: case 11:
if (value) { if (value) {
settings.flags |= BITFLAG_AUTO_START; settings.flags |= BITFLAG_AUTO_START;
} else { settings.flags &= ~BITFLAG_AUTO_START; } } else { settings.flags &= ~BITFLAG_AUTO_START; }
break; break;
case 12: case 12:
if (value) { if (value) {
settings.flags |= BITFLAG_INVERT_ST_ENABLE; settings.flags |= BITFLAG_INVERT_ST_ENABLE;
} else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; } } else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; }
break; break;
case 13: case 13:
if (value) { if (value) {
settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; settings.flags |= BITFLAG_HARD_LIMIT_ENABLE;
} else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } } else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; }
break; break;
case 14: case 14:
if (value) { if (value) {
settings.flags |= BITFLAG_HOMING_ENABLE; settings.flags |= BITFLAG_HOMING_ENABLE;
report_feedback_message(MESSAGE_HOMING_ENABLE); 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;
case 16: settings.homing_feed_rate = value; break; case 16: settings.homing_feed_rate = value; break;
case 17: settings.homing_seek_rate = value; break; case 17: settings.homing_seek_rate = value; break;
case 18: settings.homing_debounce_delay = round(value); break; case 18: settings.homing_debounce_delay = round(value); break;
case 19: case 19:
if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); } if (value <= 0.0) { return(STATUS_SETTING_VALUE_NEG); }
settings.homing_pulloff = value; break; settings.homing_pulloff = value; break;
case 20: case 20:
settings.stepper_idle_lock_time = round(value); settings.stepper_idle_lock_time = round(value);
// TODO: Immediately check and toggle steppers from always enable or disable? // TODO: Immediately check and toggle steppers from always enable or disable?
break; break;
case 21: settings.decimal_places = round(value); break; case 21: settings.decimal_places = round(value); break;
case 22: settings.n_arc_correction = round(value); break; case 22: settings.n_arc_correction = round(value); break;
default: default:
return(STATUS_INVALID_STATEMENT); return(STATUS_INVALID_STATEMENT);
} }
write_global_settings(); write_global_settings();
return(STATUS_OK); return(STATUS_OK);
} }
// Initialize the config subsystem // Initialize the config subsystem
void settings_init() { void settings_init() {
if(!read_global_settings()) { if(!read_global_settings()) {
report_status_message(STATUS_SETTING_READ_FAIL); report_status_message(STATUS_SETTING_READ_FAIL);
settings_reset(true); settings_reset(true);
report_grbl_help(); report_grbl_help();
} }
} }
// int8_t settings_execute_startup() { // int8_t settings_execute_startup() {
// //
// char buf[4]; // char buf[4];
// settings_startup_string((char *)buf); // settings_startup_string((char *)buf);
// uint8_t i = 0; // uint8_t i = 0;
// while (i < 4) { // while (i < 4) {
// serial_write(buf[i++]); // serial_write(buf[i++]);
// } // }
// return(gc_execute_line(buf)); // return(gc_execute_line(buf));
// } // }

View File

@ -26,7 +26,7 @@
#include <inttypes.h> #include <inttypes.h>
#include "nuts_bolts.h" #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 // 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 // when firmware is upgraded. Always stored in byte 0 of eeprom
@ -39,18 +39,21 @@
#define BITFLAG_HARD_LIMIT_ENABLE bit(3) #define BITFLAG_HARD_LIMIT_ENABLE bit(3)
#define BITFLAG_HOMING_ENABLE bit(4) #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_GLOBAL 1
#define EEPROM_ADDR_PARAMETERS 512 #define EEPROM_ADDR_PARAMETERS 512
#define EEPROM_ADDR_STARTUP_SCRIPT 768 #define EEPROM_ADDR_STARTUP_SCRIPT 768
// Define EEPROM address indexing for coordinate parameters // Define EEPROM address indexing for coordinate parameters
#define N_COORDINATE_SYSTEM 6 // Number of supported work coordinate systems (from index 1) #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) // NOTE: Work coordinate indices are (0=G54, 1=G55, ... , 6=G59)
#define SETTING_INDEX_G28 N_COORDINATE_SYSTEM // Home position 1 #define SETTING_INDEX_G28 N_COORDINATE_SYSTEM // Home position 1
#define SETTING_INDEX_G30 N_COORDINATE_SYSTEM+1 // Home position 2 #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) // Global persistent settings (Stored from byte EEPROM_ADDR_GLOBAL onwards)
typedef struct { typedef struct {
@ -72,6 +75,7 @@ typedef struct {
uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable. uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable.
uint8_t decimal_places; uint8_t decimal_places;
uint8_t n_arc_correction; uint8_t n_arc_correction;
// uint8_t status_report_mask; // Mask to indicate desired report data.
} settings_t; } settings_t;
extern settings_t settings; extern settings_t settings;

View File

@ -43,7 +43,7 @@ void spindle_stop()
SPINDLE_ENABLE_PORT &= ~(1<<SPINDLE_ENABLE_BIT); SPINDLE_ENABLE_PORT &= ~(1<<SPINDLE_ENABLE_BIT);
} }
void spindle_run(int8_t direction, uint16_t rpm) void spindle_run(int8_t direction) //, uint16_t rpm)
{ {
if (direction != current_direction) { if (direction != current_direction) {
plan_synchronize(); plan_synchronize();

View File

@ -3,6 +3,7 @@
Part of Grbl Part of Grbl
Copyright (c) 2009-2011 Simen Svale Skogsrud Copyright (c) 2009-2011 Simen Svale Skogsrud
Copyright (c) 2012 Sungeun K. Jeon
Grbl is free software: you can redistribute it and/or modify Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@ -24,7 +25,7 @@
#include <avr/io.h> #include <avr/io.h>
void spindle_init(); void spindle_init();
void spindle_run(int8_t direction, uint16_t rpm); void spindle_run(int8_t direction); //, uint16_t rpm);
void spindle_stop(); void spindle_stop();
#endif #endif