G54 work coordinate support (w/ G10,G92.1). Re-factored g-code parser with error checking. Minor compiler compatibility changes.

- G54 work coordinate system support. Up to 6 work coordinate systems
(G54-G59) available as a compile-time option.

- G10 command added to set work coordinate offsets from machine
position.

- G92/G92.1 position offsets and cancellation support. Properly follows
NIST standard rules with other systems.

- G53 absolute override now works correctly with new coordinate systems.

- Revamped g-code parser with robust error checking. Providing user
feedback with bad commands. Follows NIST standards.

- Planner module slightly changed to only expected position movements
in terms of machine coordinates only. This was to simplify coordinate
system handling, which is done solely by the g-code parser.

- Upon grbl system abort, machine position and work positions are
retained, while G92 offsets are reset per NIST standards.

- Compiler compatibility update for _delay_us().

- Updated README.
This commit is contained in:
Sonny Jeon 2012-02-11 11:59:35 -07:00
parent b51e902530
commit 567fbf93ed
15 changed files with 351 additions and 180 deletions

View File

@ -65,6 +65,10 @@
#define CMD_CYCLE_START '~' #define CMD_CYCLE_START '~'
#define CMD_RESET 0x18 // ctrl-x #define CMD_RESET 0x18 // ctrl-x
// Specifies the number of work coordinate systems grbl will support (G54 - G59).
// This parameter must be one or greater, currently supporting up to a value of 6.
#define N_COORDINATE_SYSTEM 1
// 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
// CNC axes don't cause the axes to drift off position. This is particularly important when manually // CNC axes don't cause the axes to drift off position. This is particularly important when manually

369
gcode.c
View File

@ -32,42 +32,53 @@
#include "errno.h" #include "errno.h"
#include "protocol.h" #include "protocol.h"
#define NEXT_ACTION_DEFAULT 0 // Define modal group internal numbers for checking multiple command violations and tracking the
#define NEXT_ACTION_DWELL 1 // type of command that is called in the block. A modal group is a group of g-code commands that are
#define NEXT_ACTION_GO_HOME 2 // mutually exclusive, or cannot exist on the same line, because they each toggle a state or execute
#define NEXT_ACTION_SET_COORDINATE_OFFSET 3 // 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_SEEK 0 // G0
#define MOTION_MODE_LINEAR 1 // G1 #define MOTION_MODE_LINEAR 1 // G1
#define MOTION_MODE_CW_ARC 2 // G2 #define MOTION_MODE_CW_ARC 2 // G2
#define MOTION_MODE_CCW_ARC 3 // G3 #define MOTION_MODE_CCW_ARC 3 // G3
#define MOTION_MODE_CANCEL 4 // G80 #define MOTION_MODE_CANCEL 4 // G80
#define PATH_CONTROL_MODE_EXACT_PATH 0
#define PATH_CONTROL_MODE_EXACT_STOP 1
#define PATH_CONTROL_MODE_CONTINOUS 2
#define PROGRAM_FLOW_RUNNING 0 #define PROGRAM_FLOW_RUNNING 0
#define PROGRAM_FLOW_PAUSED 1 #define PROGRAM_FLOW_PAUSED 1 // M0, M1
#define PROGRAM_FLOW_OPT_PAUSED 2 #define PROGRAM_FLOW_COMPLETED 2 // M2, M30
#define PROGRAM_FLOW_COMPLETED 3
#define SPINDLE_DIRECTION_CW 0 #define NON_MODAL_NONE 0
#define SPINDLE_DIRECTION_CCW 1 #define NON_MODAL_DWELL 1 // G4
#define NON_MODAL_SET_COORDINATE_DATA 2 // G10
#define NON_MODAL_GO_HOME 3 // G28,G30
#define NON_MODAL_SET_COORDINATE_OFFSET 4 // G92
#define NON_MODAL_RESET_COORDINATE_OFFSET 5 //G92.1
typedef struct { typedef struct {
uint8_t status_code; uint8_t status_code; // Parser status for current block
uint8_t motion_mode; // {G0, G1, G2, G3, G80}
uint8_t motion_mode; /* {G0, G1, G2, G3, G80} */ uint8_t inverse_feed_rate_mode; // {G93, G94}
uint8_t inverse_feed_rate_mode; /* G93, G94 */ uint8_t inches_mode; // 0 = millimeter mode, 1 = inches mode {G20, G21}
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 absolute_mode; /* 0 = relative motion, 1 = absolute motion {G90, G91} */ uint8_t program_flow; // {M0, M1, M2, M30}
uint8_t program_flow; int8_t spindle_direction; // 1 = CW, -1 = CCW, 0 = Stop {M3, M4, M5}
int8_t spindle_direction; double feed_rate, seek_rate; // Millimeters/second
double feed_rate, seek_rate; /* Millimeters/second */ double position[3]; // Where the interpreter considers the tool to be at this point in the code
double position[3]; /* Where the interpreter considers the tool to be at this point in the code */
uint8_t tool; uint8_t tool;
int16_t spindle_speed; /* RPM/100 */ int16_t spindle_speed; // RPM/100
uint8_t plane_axis_0, uint8_t plane_axis_0,
plane_axis_1, plane_axis_1,
plane_axis_2; // The axes of the selected plane plane_axis_2; // The axes of the selected plane
@ -89,12 +100,11 @@ 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;
gc.seek_rate = settings.default_seek_rate;
select_plane(X_AXIS, Y_AXIS, Z_AXIS); select_plane(X_AXIS, Y_AXIS, Z_AXIS);
gc.absolute_mode = true; gc.absolute_mode = true;
} }
// Set g-code parser position. Input in steps. // Sets g-code parser position in mm. Input in steps. Called by the system abort routine.
void gc_set_current_position(int32_t x, int32_t y, int32_t z) void gc_set_current_position(int32_t x, int32_t y, int32_t z)
{ {
gc.position[X_AXIS] = x/settings.steps_per_mm[X_AXIS]; gc.position[X_AXIS] = x/settings.steps_per_mm[X_AXIS];
@ -102,63 +112,104 @@ void gc_set_current_position(int32_t x, int32_t y, int32_t z)
gc.position[Z_AXIS] = z/settings.steps_per_mm[Z_AXIS]; gc.position[Z_AXIS] = z/settings.steps_per_mm[Z_AXIS];
} }
static float to_millimeters(double value) { static float to_millimeters(double value)
{
return(gc.inches_mode ? (value * MM_PER_INCH) : value); return(gc.inches_mode ? (value * MM_PER_INCH) : value);
} }
// Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase // Executes one line of 0-terminated G-Code. The line is assumed to contain only uppercase
// characters and signed floating point values (no whitespace). Comments and block delete // characters and signed floating point values (no whitespace). Comments and block delete
// characters have been removed. // characters have been removed. All units and positions are converted and exported to grbl's
// internal functions in terms of (mm, mm/min) and absolute machine coordinates, respectively.
uint8_t gc_execute_line(char *line) uint8_t gc_execute_line(char *line)
{ {
uint8_t char_counter = 0; uint8_t char_counter = 0;
char letter; char letter;
double value; double value;
double unit_converted_value; int int_value;
double inverse_feed_rate = -1; // negative inverse_feed_rate means no inverse_feed_rate specified
uint8_t radius_mode = false;
uint8_t absolute_override = false; /* 1 = absolute motion for this block only {G53} */ uint16_t modal_group_words = 0; // Bitflag variable to track and check modal group words in block
uint8_t next_action = NEXT_ACTION_DEFAULT; /* The action that will be taken by the parsed line */ uint8_t axis_words = 0; // Bitflag to track which XYZ(ABC) parameters exist in block
double inverse_feed_rate = -1; // negative inverse_feed_rate means no inverse_feed_rate specified
uint8_t absolute_override = false; // true(1) = absolute motion for this block only {G53}
uint8_t non_modal_action = NON_MODAL_NONE; // Tracks the actions of modal group 0 (non-modal)
double target[3], offset[3]; double target[3], offset[3];
clear_vector(target); // XYZ(ABC) axes parameters.
double p = 0, r = 0; clear_vector(offset); // IJK Arc offsets are incremental. Value of zero indicates no change.
int int_value;
gc.status_code = STATUS_OK; gc.status_code = STATUS_OK;
// Pass 1: Commands /* Pass 1: Commands and set all modes. Check for modal group violations.
NOTE: Modal group numbers are defined in Table 4 of NIST RS274-NGC v3, pg.20 */
uint8_t group_number = MODAL_GROUP_NONE;
while(next_statement(&letter, &value, line, &char_counter)) { while(next_statement(&letter, &value, line, &char_counter)) {
int_value = trunc(value); int_value = trunc(value);
switch(letter) { switch(letter) {
case 'G': case 'G':
// Set modal group values
switch(int_value) {
case 4: case 10: case 28: case 30: case 53: case 92: group_number = MODAL_GROUP_0; break;
case 0: case 1: case 2: case 3: case 80: group_number = MODAL_GROUP_1; break;
case 17: case 18: case 19: group_number = MODAL_GROUP_2; break;
case 90: case 91: group_number = MODAL_GROUP_3; break;
case 93: case 94: group_number = MODAL_GROUP_5; break;
case 20: case 21: group_number = MODAL_GROUP_6; break;
case 54: case 55: case 56: case 57: case 58: case 59: group_number = MODAL_GROUP_12; break;
}
// Set 'G' commands
switch(int_value) { switch(int_value) {
case 0: gc.motion_mode = MOTION_MODE_SEEK; break; case 0: gc.motion_mode = MOTION_MODE_SEEK; break;
case 1: gc.motion_mode = MOTION_MODE_LINEAR; break; case 1: gc.motion_mode = MOTION_MODE_LINEAR; break;
case 2: gc.motion_mode = MOTION_MODE_CW_ARC; break; case 2: gc.motion_mode = MOTION_MODE_CW_ARC; break;
case 3: gc.motion_mode = MOTION_MODE_CCW_ARC; break; case 3: gc.motion_mode = MOTION_MODE_CCW_ARC; break;
case 4: next_action = NEXT_ACTION_DWELL; break; case 4: non_modal_action = NON_MODAL_DWELL; break;
case 10: non_modal_action = NON_MODAL_SET_COORDINATE_DATA; break;
case 17: select_plane(X_AXIS, Y_AXIS, Z_AXIS); break; case 17: select_plane(X_AXIS, Y_AXIS, Z_AXIS); break;
case 18: select_plane(X_AXIS, Z_AXIS, Y_AXIS); break; case 18: select_plane(X_AXIS, Z_AXIS, Y_AXIS); break;
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;
case 28: case 30: next_action = NEXT_ACTION_GO_HOME; break; case 28: case 30: non_modal_action = NON_MODAL_GO_HOME; 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:
int_value -= 54; // Compute coordinate system row index (0=G54,1=G55,...)
if (int_value < N_COORDINATE_SYSTEM) {
sys.coord_select = int_value;
} else {
FAIL(STATUS_UNSUPPORTED_STATEMENT);
}
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;
case 91: gc.absolute_mode = false; break; case 91: gc.absolute_mode = false; break;
case 92: next_action = NEXT_ACTION_SET_COORDINATE_OFFSET; break; case 92:
int_value = trunc(10*value); // Multiply by 10 to pick up G92.1
switch(int_value) {
case 920: non_modal_action = NON_MODAL_SET_COORDINATE_OFFSET; break;
case 921: non_modal_action = NON_MODAL_RESET_COORDINATE_OFFSET; break;
default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
}
break;
case 93: gc.inverse_feed_rate_mode = true; break; case 93: gc.inverse_feed_rate_mode = true; break;
case 94: gc.inverse_feed_rate_mode = false; break; case 94: gc.inverse_feed_rate_mode = false; break;
default: FAIL(STATUS_UNSUPPORTED_STATEMENT); default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
} }
break; break;
case 'M': case 'M':
// Set modal group values
switch(int_value) { switch(int_value) {
case 0: case 60: gc.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause case 0: case 1: case 2: case 30: group_number = MODAL_GROUP_4; break;
case 1: gc.program_flow = PROGRAM_FLOW_OPT_PAUSED; break; // Program pause with optional stop on case 3: case 4: case 5: group_number = MODAL_GROUP_7; break;
}
// 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 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;
@ -166,75 +217,197 @@ uint8_t gc_execute_line(char *line)
default: FAIL(STATUS_UNSUPPORTED_STATEMENT); default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
} }
break; break;
case 'T': gc.tool = trunc(value); break;
} }
if(gc.status_code) { break; } // Check for modal group multiple command violations in the current block
if (group_number) {
if ( bit_istrue(modal_group_words,bit(group_number)) ) {
FAIL(STATUS_MODAL_GROUP_VIOLATION);
} else {
bit_true(modal_group_words,bit(group_number));
}
group_number = MODAL_GROUP_NONE; // Reset for next command.
}
} }
// If there were any errors parsing this line, we will return right away with the bad news // If there were any errors parsing this line, we will return right away with the bad news
if (gc.status_code) { return(gc.status_code); } if (gc.status_code) { return(gc.status_code); }
/* Pass 2: Parameters. All units converted according to current block commands. Position
parameters are converted and flagged to indicate a change. These can have multiple connotations
for different commands. Each will be converted to their proper value upon execution. */
double p = 0, r = 0;
uint8_t l = 0;
char_counter = 0; char_counter = 0;
clear_vector(target);
clear_vector(offset);
memcpy(target, gc.position, sizeof(target)); // i.e. target = gc.position
// Pass 2: Parameters
while(next_statement(&letter, &value, line, &char_counter)) { while(next_statement(&letter, &value, line, &char_counter)) {
int_value = trunc(value);
unit_converted_value = to_millimeters(value);
switch(letter) { switch(letter) {
case 'F': case 'F':
if (unit_converted_value <= 0) { FAIL(STATUS_BAD_NUMBER_FORMAT); } // Must be greater than zero if (value <= 0) { FAIL(STATUS_INVALID_COMMAND); } // Must be greater than zero
if (gc.inverse_feed_rate_mode) { if (gc.inverse_feed_rate_mode) {
inverse_feed_rate = unit_converted_value; // seconds per motion for this motion only inverse_feed_rate = to_millimeters(value); // seconds per motion for this motion only
} else { } else {
if (gc.motion_mode == MOTION_MODE_SEEK) { gc.feed_rate = to_millimeters(value); // millimeters per minute
gc.seek_rate = unit_converted_value;
} else {
gc.feed_rate = unit_converted_value; // millimeters per minute
}
} }
break; break;
case 'I': case 'J': case 'K': offset[letter-'I'] = unit_converted_value; break; case 'I': case 'J': case 'K': offset[letter-'I'] = to_millimeters(value); break;
case 'L': l = trunc(value); break;
case 'P': p = value; break; case 'P': p = value; break;
case 'R': r = unit_converted_value; radius_mode = true; break; case 'R': r = to_millimeters(value); break;
case 'S': gc.spindle_speed = value; break; case 'S':
case 'X': case 'Y': case 'Z': if (value < 0) { FAIL(STATUS_INVALID_COMMAND); } // Cannot be negative
if (gc.absolute_mode || absolute_override) { gc.spindle_speed = value;
target[letter - 'X'] = unit_converted_value;
} else {
target[letter - 'X'] += unit_converted_value;
}
break; break;
case 'T':
if (value < 0) { FAIL(STATUS_INVALID_COMMAND); } // Cannot be negative
gc.tool = trunc(value);
break;
case 'X': target[X_AXIS] = to_millimeters(value); bit_true(axis_words,bit(X_AXIS)); break;
case 'Y': target[Y_AXIS] = to_millimeters(value); bit_true(axis_words,bit(Y_AXIS)); break;
case 'Z': target[Z_AXIS] = to_millimeters(value); bit_true(axis_words,bit(Z_AXIS)); break;
} }
} }
// If there were any errors parsing this line, we will return right away with the bad news // If there were any errors parsing this line, we will return right away with the bad news
if (gc.status_code) { return(gc.status_code); } if (gc.status_code) { return(gc.status_code); }
// Update spindle state
/* Execute Commands: Perform by order of execution defined in NIST RS274-NGC.v3, Table 8, pg.41.
NOTE: Independent non-motion/settings parameters are set out of this order for code efficiency
and simplicity purposes, but this should not affect proper g-code execution. */
// ([M6]: Tool change execution 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);
// Perform any physical actions // ([M7,M8,M9]: Coolant state should be executed here.)
switch (next_action) {
case NEXT_ACTION_GO_HOME: mc_go_home(); clear_vector_double(target); break; // [G4,G10,G28,G30,G92,G92.1]: Perform dwell, set coordinate system data, homing, or set axis offsets.
case NEXT_ACTION_DWELL: mc_dwell(p); break; // NOTE: These commands are in the same modal group, hence are mutually exclusive. G53 is in this
case NEXT_ACTION_SET_COORDINATE_OFFSET: // modal group and do not effect these actions.
mc_set_coordinate_offset(target[X_AXIS],target[Y_AXIS],target[Z_AXIS]); switch (non_modal_action) {
case NON_MODAL_DWELL:
if (p < 0) { // Time cannot be negative.
FAIL(STATUS_INVALID_COMMAND);
} else {
mc_dwell(p);
}
break; break;
case NEXT_ACTION_DEFAULT: case NON_MODAL_SET_COORDINATE_DATA:
int_value = trunc(p); // Convert p value to int.
if (l != 2 || (int_value < 1 || int_value > N_COORDINATE_SYSTEM)) { // L2 only. P1=G54, P2=G55, ...
FAIL(STATUS_UNSUPPORTED_STATEMENT);
} else if (!axis_words) { // No axis words.
FAIL(STATUS_INVALID_COMMAND);
} else {
int_value--; // Adjust p to be inline with row array index.
// Update axes defined only in block. Always in machine coordinates. Can change non-active system.
uint8_t i;
for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
if ( bit_istrue(axis_words,bit(i)) ) { sys.coord_system[int_value][i] = target[i]; }
}
}
axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.
break;
case NON_MODAL_GO_HOME:
// Move to intermediate position before going home. Obeys current coordinate system and offsets
// and absolute and incremental modes.
if (axis_words) {
// Apply absolute mode coordinate offsets or incremental mode offsets.
uint8_t i;
for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
if ( bit_istrue(axis_words,bit(i)) ) {
if (gc.absolute_mode) {
target[i] += sys.coord_system[sys.coord_select][i] + sys.coord_offset[i];
} else {
target[i] += gc.position[i];
}
} else {
target[i] = gc.position[i];
}
}
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], settings.default_seek_rate, false);
}
mc_go_home();
clear_vector(gc.position); // Assumes home is at [0,0,0]
axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.
break;
case NON_MODAL_SET_COORDINATE_OFFSET:
if (!axis_words) { // No axis words
FAIL(STATUS_INVALID_COMMAND);
} else {
// Update axes defined only in block. Offsets current system to defined value. Does not update when
// active coordinate system is selected, but is still active unless G92.1 disables it.
uint8_t i;
for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
if (bit_istrue(axis_words,bit(i)) ) {
sys.coord_offset[i] = gc.position[i]-sys.coord_system[sys.coord_select][i]-target[i];
}
}
}
axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.
break;
case NON_MODAL_RESET_COORDINATE_OFFSET:
clear_vector(sys.coord_offset); // Disable G92 offsets by zeroing offset vector.
break;
}
// [G0,G1,G2,G3,G80]: Perform motion modes.
// NOTE: Commands G10,G28,G30,G92 lock out and prevent axis words from use in motion modes.
// Enter motion modes only if there are axis words or a motion mode command word in the block.
if ( bit_istrue(modal_group_words,bit(MODAL_GROUP_1)) || axis_words ) {
// G1,G2,G3 require F word in inverse time mode.
if ( gc.inverse_feed_rate_mode ) {
if (inverse_feed_rate < 0 && gc.motion_mode != MOTION_MODE_CANCEL) {
FAIL(STATUS_INVALID_COMMAND);
}
}
// Absolute override G53 only valid with G0 and G1 active.
if ( absolute_override && !(gc.motion_mode == MOTION_MODE_SEEK || gc.motion_mode == MOTION_MODE_LINEAR)) {
FAIL(STATUS_INVALID_COMMAND);
}
// Report any errors.
if (gc.status_code) { return(gc.status_code); }
// Convert all target position data to machine coordinates for executing motion. Apply
// absolute mode coordinate offsets or incremental mode offsets.
// NOTE: Tool offsets may be appended to these conversions when/if this feature is added.
uint8_t i;
for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used to save flash space.
if ( bit_istrue(axis_words,bit(i)) ) {
if (!absolute_override) { // Do not update target in absolute override mode
if (gc.absolute_mode) {
target[i] += sys.coord_system[sys.coord_select][i] + sys.coord_offset[i]; // Absolute mode
} else {
target[i] += gc.position[i]; // Incremental mode
}
}
} else {
target[i] = gc.position[i]; // No axis word in block. Keep same axis position.
}
}
switch (gc.motion_mode) { switch (gc.motion_mode) {
case MOTION_MODE_CANCEL: break; case MOTION_MODE_CANCEL:
if (axis_words) { FAIL(STATUS_INVALID_COMMAND); } // No axis words allowed while active.
break;
case MOTION_MODE_SEEK: case MOTION_MODE_SEEK:
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], gc.seek_rate, false); if (!axis_words) { FAIL(STATUS_INVALID_COMMAND);}
else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], settings.default_seek_rate, false); }
break; break;
case MOTION_MODE_LINEAR: case MOTION_MODE_LINEAR:
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], if (!axis_words) { FAIL(STATUS_INVALID_COMMAND);}
(gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode); else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS],
(gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode); }
break; break;
case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC:
if (radius_mode) { // Check if at least one of the axes of the selected plane has been specified. If in center
// format arc mode, also check for at least one of the IJK axes of the selected plane was sent.
if ( !( bit_false(axis_words,bit(gc.plane_axis_2)) ) ||
( !r && !offset[gc.plane_axis_0] && !offset[gc.plane_axis_1] ) ) {
FAIL(STATUS_INVALID_COMMAND);
} else {
if (r != 0) { // Arc Radius Mode
/* /*
We need to calculate the center of the circle that has the designated radius and passes We need to calculate the center of the circle that has the designated radius and passes
through both the current position and the target position. This method calculates the following through both the current position and the target position. This method calculates the following
@ -326,10 +499,8 @@ uint8_t gc_execute_line(char *line)
offset[gc.plane_axis_0] = 0.5*(x-(y*h_x2_div_d)); offset[gc.plane_axis_0] = 0.5*(x-(y*h_x2_div_d));
offset[gc.plane_axis_1] = 0.5*(y+(x*h_x2_div_d)); offset[gc.plane_axis_1] = 0.5*(y+(x*h_x2_div_d));
} else { // Offset mode specific computations } else { // Arc Center Format Offset Mode
r = hypot(offset[gc.plane_axis_0], offset[gc.plane_axis_1]); // Compute arc radius for mc_arc r = hypot(offset[gc.plane_axis_0], offset[gc.plane_axis_1]); // Compute arc radius for mc_arc
} }
// Set clockwise/counter-clockwise sign for mc_arc computations // Set clockwise/counter-clockwise sign for mc_arc computations
@ -340,29 +511,28 @@ uint8_t gc_execute_line(char *line)
mc_arc(gc.position, target, offset, gc.plane_axis_0, gc.plane_axis_1, gc.plane_axis_2, mc_arc(gc.position, target, offset, gc.plane_axis_0, gc.plane_axis_1, gc.plane_axis_2,
(gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode, (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode,
r, isclockwise); r, isclockwise);
}
break; break;
} }
}
// Report any errors.
if (gc.status_code) { return(gc.status_code); }
// As far as the parser is concerned, the position is now == target. In reality the // As far as the parser is concerned, the position is now == target. In reality the
// motion control system might still be processing the action and the real tool position // motion control system might still be processing the action and the real tool position
// in any intermediate location. // in any intermediate location.
memcpy(gc.position, target, sizeof(double)*3); // gc.position[] = target[]; memcpy(gc.position, target, sizeof(double)*3); // gc.position[] = target[];
}
// Perform non-running program flow actions. During a program pause, the buffer may refill and can // M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may
// only be resumed by the cycle start run-time command. // refill and can only be resumed by the cycle start run-time command.
// TODO: Install optional stop setting and re-factor program flow actions.
if (gc.program_flow) { if (gc.program_flow) {
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.
switch (gc.program_flow) {
case PROGRAM_FLOW_PAUSED: case PROGRAM_FLOW_OPT_PAUSED:
gc.program_flow = PROGRAM_FLOW_RUNNING; // Re-enable program flow after pause complete. gc.program_flow = PROGRAM_FLOW_RUNNING; // Re-enable program flow after pause complete.
break;
// Reset to reload defaults (G92.2,G54,G17,G90,G94,M48,G40,M5,M9) // If complete, reset to reload defaults (G92.2,G54,G17,G90,G94,M48,G40,M5,M9)
case PROGRAM_FLOW_COMPLETED: sys.abort = true; break; if (gc.program_flow == PROGRAM_FLOW_COMPLETED) { sys.abort = true; }
}
} }
return(gc.status_code); return(gc.status_code);
@ -391,21 +561,24 @@ static int next_statement(char *letter, double *double_ptr, char *line, uint8_t
} }
/* /*
Intentionally not supported: Not supported:
- Canned cycles - Canned cycles
- Tool radius compensation - Tool radius compensation
- A,B,C-axes - A,B,C-axes
- Multiple coordinate systems
- Evaluation of expressions - Evaluation of expressions
- Variables - Variables
- Multiple home locations - Multiple home locations
- Multiple coordinate systems (May be added in the future)
- Probing - Probing
- Override control - Override control
- Tool changes
group 0 = {G10, G28, G30, G92.1, G92.2, G92.3} (Non modal G-codes) group 0 = {G92.2, G92.3} (Non modal: Cancel and re-enable G92 offsets)
group 1 = {G38.2, G81 - G89} (Motion modes: straight probe, canned cycles)
group 6 = {M6} (Tool change)
group 8 = {M7, M8, M9} coolant (special case: M7 and M8 may be active at the same time) group 8 = {M7, M8, M9} coolant (special case: M7 and M8 may be active at the same time)
group 9 = {M48, M49} enable/disable feed and speed override switches group 9 = {M48, M49} enable/disable feed and speed override switches
group 12 = {G54, G55, G56, G57, G58, G59, G59.1, G59.2, G59.3} coordinate system selection 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
*/ */

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) 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

View File

@ -76,9 +76,9 @@ static void homing_cycle(bool x_axis, bool y_axis, bool z_axis, bool reverse_dir
// Check if we are done // Check if we are done
if(!(x_axis || y_axis || z_axis)) { return; } if(!(x_axis || y_axis || z_axis)) { return; }
STEPPING_PORT |= out_bits & STEP_MASK; STEPPING_PORT |= out_bits & STEP_MASK;
_delay_us(settings.pulse_microseconds); delay_us(settings.pulse_microseconds);
STEPPING_PORT ^= out_bits & STEP_MASK; STEPPING_PORT ^= out_bits & STEP_MASK;
_delay_us(step_delay); delay_us(step_delay);
} }
return; return;
} }

16
main.c
View File

@ -53,15 +53,17 @@ int main(void)
// reset to finish the initialization process. // reset to finish the initialization process.
if (sys.abort) { if (sys.abort) {
// Retain last known machine position. If the system abort occurred while in motion, machine // Retain last known machine position and work coordinate offset(s). If the system abort
// position is not guaranteed, since a hard stop can cause the steppers to lose steps. Always // occurred while in motion, machine position is not guaranteed, since a hard stop can cause
// perform a feedhold before an abort, if maintaining accurate machine position is required. // the steppers to lose steps. Always perform a feedhold before an abort, if maintaining
// accurate machine position is required.
// TODO: Report last position and coordinate offset to users to help relocate origins. Future // TODO: Report last position and coordinate offset to users to help relocate origins. Future
// releases will auto-reset the machine position back to [0,0,0] if an abort is used while // releases will auto-reset the machine position back to [0,0,0] if an abort is used while
// grbl is moving the machine. // grbl is moving the machine.
int32_t last_position[3]; // last_coord_offset[3]; int32_t last_position[3];
double last_coord_system[N_COORDINATE_SYSTEM][3];
memcpy(last_position, sys.position, sizeof(sys.position)); // last_position[] = sys.position[] memcpy(last_position, sys.position, sizeof(sys.position)); // last_position[] = sys.position[]
// memcpy(last_coord_offset, sys.coord_offset, sizeof(sys.coord_offset)); // last_coord_offset[] = sys.coord_offset[] memcpy(last_coord_system, sys.coord_system, sizeof(sys.coord_system)); // last_coord_system[] = sys.coord_system[]
// Reset system. // Reset system.
memset(&sys, 0, sizeof(sys)); // Clear all system variables memset(&sys, 0, sizeof(sys)); // Clear all system variables
@ -74,8 +76,9 @@ int main(void)
limits_init(); limits_init();
st_reset(); // Clear stepper subsystem variables. st_reset(); // Clear stepper subsystem variables.
// Reload last known machine position. Coordinate offsets are reset per NIST RS274-NGC protocol. // Reload last known machine position and work systems. G92 coordinate offsets are reset.
memcpy(sys.position, last_position, sizeof(last_position)); // sys.position[] = last_position[] memcpy(sys.position, last_position, sizeof(last_position)); // sys.position[] = last_position[]
memcpy(sys.coord_system, last_coord_system, sizeof(last_coord_system)); // sys.coord_system[] = last_coord_system[]
gc_set_current_position(last_position[X_AXIS],last_position[Y_AXIS],last_position[Z_AXIS]); gc_set_current_position(last_position[X_AXIS],last_position[Y_AXIS],last_position[Z_AXIS]);
plan_set_current_position(last_position[X_AXIS],last_position[Y_AXIS],last_position[Z_AXIS]); plan_set_current_position(last_position[X_AXIS],last_position[Y_AXIS],last_position[Z_AXIS]);
@ -85,6 +88,7 @@ int main(void)
#ifdef CYCLE_AUTO_START #ifdef CYCLE_AUTO_START
sys.auto_start = true; sys.auto_start = true;
#endif #endif
// TODO: Install G20/G21 unit default into settings and load appropriate settings.
} }
protocol_execute_runtime(); protocol_execute_runtime();

View File

@ -25,10 +25,6 @@
#include <avr/io.h> #include <avr/io.h>
#include "planner.h" #include "planner.h"
// NOTE: Although the following function structurally belongs in this module, there is nothing to do but
// to forward the request to the planner.
#define mc_set_coordinate_offset(x, y, z) plan_set_coordinate_offset(x, y, z)
// Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second // Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second
// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in // unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in
// (1 minute)/feed_rate time. // (1 minute)/feed_rate time.

View File

@ -44,3 +44,10 @@ void delay_ms(uint16_t ms)
{ {
while ( ms-- ) { _delay_ms(1); } while ( ms-- ) { _delay_ms(1); }
} }
// Delays variable defined microseconds. Compiler compatibility fix for _delay_us(),
// which only accepts constants in future compiler releases.
void delay_us(uint16_t us)
{
while ( us-- ) { _delay_us(1); }
}

View File

@ -21,6 +21,7 @@
#ifndef nuts_bolts_h #ifndef nuts_bolts_h
#define nuts_bolts_h #define nuts_bolts_h
#include <config.h>
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
@ -70,8 +71,13 @@ typedef struct {
int32_t position[3]; // Real-time machine (aka home) position vector in steps. 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. // NOTE: This may need to be a volatile variable, if problems arise.
int32_t coord_offset[3]; // Retains the G92 coordinate offset (work coordinates) relative to
// machine zero in steps. uint8_t coord_select; // Active work coordinate system number. Default: 0=G54.
double coord_system[N_COORDINATE_SYSTEM][3]; // Work coordinate systems (G54+). Stores offset from
// absolute machine position in mm.
// Rows: Work system number (0=G54,1=G55,...5=G59), Columns: XYZ Offsets
double coord_offset[3]; // 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.
@ -86,4 +92,7 @@ int read_double(char *line, uint8_t *char_counter, double *double_ptr);
// Delays variable-defined milliseconds. Compiler compatibility fix for _delay_ms(). // Delays variable-defined milliseconds. Compiler compatibility fix for _delay_ms().
void delay_ms(uint16_t ms); void delay_ms(uint16_t ms);
// Delays variable-defined microseconds. Compiler compatibility fix for _delay_us().
void delay_us(uint16_t us);
#endif #endif

View File

@ -344,6 +344,8 @@ void plan_synchronize()
// Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in // Add a new linear movement to the buffer. x, y and z is the signed, absolute target position in
// millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed // millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed
// rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. // rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes.
// All position data passed to the planner must be in terms of machine position to keep the planner
// independent of any coordinate system changes and offsets, which are handled by the g-code parser.
// NOTE: Assumes buffer is available. Buffer checks are handled at a higher level by motion_control. // NOTE: Assumes buffer is available. Buffer checks are handled at a higher level by motion_control.
void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t invert_feed_rate) void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t invert_feed_rate)
{ {
@ -471,36 +473,7 @@ void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t in
planner_recalculate(); planner_recalculate();
} }
// Apply G92 coordinate offsets and update planner position vector. // Reset the planner position vector (in steps). Called by the system abort routine.
void plan_set_coordinate_offset(double x, double y, double z)
{
// To correlate status reporting work position correctly, the planner must force the steppers to
// empty the block buffer and synchronize with the planner, as the real-time machine position and
// the planner position at the end of the buffer can be and are usually different. This function is
// only called with a G92, which typically is used only at the beginning of a g-code program or
// between different operations.
// TODO: Find a robust way to avoid a planner synchronize, but this may require a bit of ingenuity.
plan_synchronize();
// Update the system coordinate offsets from machine zero
sys.coord_offset[X_AXIS] += pl.position[X_AXIS];
sys.coord_offset[Y_AXIS] += pl.position[Y_AXIS];
sys.coord_offset[Z_AXIS] += pl.position[Z_AXIS];
memset(&pl, 0, sizeof(pl)); // Clear planner variables. Assume start from rest.
// Update planner position and coordinate offset vectors
int32_t new_position[3];
new_position[X_AXIS] = lround(x*settings.steps_per_mm[X_AXIS]);
new_position[Y_AXIS] = lround(y*settings.steps_per_mm[Y_AXIS]);
new_position[Z_AXIS] = lround(z*settings.steps_per_mm[Z_AXIS]);
plan_set_current_position(new_position[X_AXIS],new_position[Y_AXIS],new_position[Z_AXIS]);
sys.coord_offset[X_AXIS] -= pl.position[X_AXIS];
sys.coord_offset[Y_AXIS] -= pl.position[Y_AXIS];
sys.coord_offset[Z_AXIS] -= pl.position[Z_AXIS];
}
// Reset the planner position vector (in steps)
void plan_set_current_position(int32_t x, int32_t y, int32_t z) void plan_set_current_position(int32_t x, int32_t y, int32_t z)
{ {
pl.position[X_AXIS] = x; pl.position[X_AXIS] = x;

View File

@ -69,9 +69,6 @@ block_t *plan_get_current_block();
// Reset the planner position vector (in steps) // Reset the planner position vector (in steps)
void plan_set_current_position(int32_t x, int32_t y, int32_t z); void plan_set_current_position(int32_t x, int32_t y, int32_t z);
// Apply G92 coordinate offsets and update planner position vector. Called by g-code parser.
void plan_set_coordinate_offset(double x, double y, double z);
// Reinitialize plan with a partially completed block // Reinitialize plan with a partially completed block
void plan_cycle_reinitialize(int32_t step_events_remaining); void plan_cycle_reinitialize(int32_t step_events_remaining);

View File

@ -53,6 +53,10 @@ static void status_message(int status_code)
printPgmString(PSTR("Unsupported statement\r\n")); break; printPgmString(PSTR("Unsupported statement\r\n")); break;
case STATUS_FLOATING_POINT_ERROR: case STATUS_FLOATING_POINT_ERROR:
printPgmString(PSTR("Floating point error\r\n")); break; printPgmString(PSTR("Floating point error\r\n")); break;
case STATUS_MODAL_GROUP_VIOLATION:
printPgmString(PSTR("Modal group violation\r\n")); break;
case STATUS_INVALID_COMMAND:
printPgmString(PSTR("Invalid command\r\n")); break;
default: default:
printInteger(status_code); printInteger(status_code);
printPgmString(PSTR("\r\n")); printPgmString(PSTR("\r\n"));
@ -74,7 +78,7 @@ void protocol_status_report()
// short line segments and interface setups that require real-time status reports (5-20Hz). // short line segments and interface setups that require real-time status reports (5-20Hz).
// **Under construction** Bare-bones status report. Provides real-time machine position relative to // **Under construction** Bare-bones status report. Provides real-time machine position relative to
// the system power on location (0,0,0) and work coordinate position, updatable by the G92 command. // the system power on location (0,0,0) and work coordinate position (G54 and G92 applied).
// The following are still needed: user setting of output units (mm|inch), compressed (non-human // The following are still needed: user setting of output units (mm|inch), compressed (non-human
// readable) data for interfaces?, save last known position in EEPROM?, code optimizations, solidify // readable) data for interfaces?, save last known position in EEPROM?, code optimizations, solidify
// the reporting schemes, move to a separate .c file for easy user accessibility, and setting the // the reporting schemes, move to a separate .c file for easy user accessibility, and setting the
@ -87,16 +91,16 @@ void protocol_status_report()
printString("MPos:["); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS]*MM_PER_INCH)); printString("MPos:["); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS]*MM_PER_INCH));
printString(","); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]*MM_PER_INCH)); printString(","); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]*MM_PER_INCH));
printString(","); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]*MM_PER_INCH)); printString(","); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]*MM_PER_INCH));
printString("],WPos:["); printFloat((print_position[X_AXIS]-sys.coord_offset[X_AXIS])/(settings.steps_per_mm[X_AXIS]*MM_PER_INCH)); printString("],WPos:["); printFloat((print_position[X_AXIS]/settings.steps_per_mm[X_AXIS]-sys.coord_system[sys.coord_select][X_AXIS]-sys.coord_offset[X_AXIS])/MM_PER_INCH);
printString(","); printFloat((print_position[Y_AXIS]-sys.coord_offset[Y_AXIS])/(settings.steps_per_mm[Y_AXIS]*MM_PER_INCH)); printString(","); printFloat((print_position[Y_AXIS]/settings.steps_per_mm[Y_AXIS]-sys.coord_system[sys.coord_select][Y_AXIS]-sys.coord_offset[Y_AXIS])/MM_PER_INCH);
printString(","); printFloat((print_position[Z_AXIS]-sys.coord_offset[Z_AXIS])/(settings.steps_per_mm[Z_AXIS]*MM_PER_INCH)); printString(","); printFloat((print_position[Z_AXIS]/settings.steps_per_mm[Z_AXIS]-sys.coord_system[sys.coord_select][Z_AXIS]-sys.coord_offset[Z_AXIS])/MM_PER_INCH);
#else #else
printString("MPos:["); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS])); printString("MPos:["); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS]));
printString(","); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS])); printString(","); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]));
printString(","); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS])); printString(","); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]));
printString("],WPos:["); printFloat((print_position[X_AXIS]-sys.coord_offset[X_AXIS])/(settings.steps_per_mm[X_AXIS])); printString("],WPos:["); printFloat(print_position[X_AXIS]/settings.steps_per_mm[X_AXIS]-sys.coord_system[sys.coord_select][X_AXIS]-sys.coord_offset[X_AXIS]);
printString(","); printFloat((print_position[Y_AXIS]-sys.coord_offset[Y_AXIS])/(settings.steps_per_mm[Y_AXIS])); printString(","); printFloat(print_position[Y_AXIS]/settings.steps_per_mm[Y_AXIS]-sys.coord_system[sys.coord_select][Y_AXIS]-sys.coord_offset[Y_AXIS]);
printString(","); printFloat((print_position[Z_AXIS]-sys.coord_offset[Z_AXIS])/(settings.steps_per_mm[Z_AXIS])); printString(","); printFloat(print_position[Z_AXIS]/settings.steps_per_mm[Z_AXIS]-sys.coord_system[sys.coord_select][Z_AXIS]-sys.coord_offset[Z_AXIS]);
#endif #endif
printString("]\r\n"); printString("]\r\n");
} }

View File

@ -26,6 +26,8 @@
#define STATUS_EXPECTED_COMMAND_LETTER 2 #define STATUS_EXPECTED_COMMAND_LETTER 2
#define STATUS_UNSUPPORTED_STATEMENT 3 #define STATUS_UNSUPPORTED_STATEMENT 3
#define STATUS_FLOATING_POINT_ERROR 4 #define STATUS_FLOATING_POINT_ERROR 4
#define STATUS_MODAL_GROUP_VIOLATION 5
#define STATUS_INVALID_COMMAND 6
// Initialize the serial protocol // Initialize the serial protocol
void protocol_init(); void protocol_init();

View File

@ -14,9 +14,10 @@ Grbl includes full acceleration management with look ahead. That means the contr
- New run-time command control: Feed hold (pause), Cycle start (resume), Reset (abort), Status reporting - New run-time command control: Feed hold (pause), Cycle start (resume), Reset (abort), Status reporting
- Controlled feed hold with deceleration to ensure no skipped steps and loss of location. - Controlled feed hold with deceleration to ensure no skipped steps and loss of location.
- After feed hold, cycle accelerations are re-planned and may be resumed. - After feed hold, cycle accelerations are re-planned and may be resumed.
- Work offset(G92) and machine coordinate system support. - Re-factored g-code parser with robust error-checking.
- Program stop(M0,M1*,M2,M30) initial support. Pallet shuttle not supported. - Work coordinate system (G54), offsets(G92), and machine coordinate system support. G10 work coordinate settings support. (Up to 6 work coordinate systems(G54-G59) available as a compile-time option.)
- System reset re-initializes grbl without resetting the Arduino and retains machine/home position. - Program stop(M0,M1*,M2,M30) initial support. Optional stop to do.
- System reset re-initializes grbl without resetting the Arduino and retains machine/home position and work coordinates.
- Restructured planner and stepper modules to become independent and ready for future features. - Restructured planner and stepper modules to become independent and ready for future features.
- Planned features: Jog mode, status reporting, runtime settings such as toggling block delete, XON/XOFF flow control. - Planned features: Jog mode, status reporting, runtime settings such as toggling block delete, XON/XOFF flow control.
- Reduce serial read buffer to 128 characters and increased write buffer to 64 characters. - Reduce serial read buffer to 128 characters and increased write buffer to 64 characters.

View File

@ -3,7 +3,7 @@
Part of Grbl Part of Grbl
Copyright (c) 2009-2011 Simen Svale Skogsrud Copyright (c) 2009-2011 Simen Svale Skogsrud
Copyright (c) 2011 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

View File

@ -24,7 +24,7 @@
#include "config.h" #include "config.h"
#include "planner.h" #include "planner.h"
#include <avr/io.h> #include <stdint.h>
// TODO: Deprecated. Need to update for new version. // TODO: Deprecated. Need to update for new version.