Program stop support (M0,M1*,M2,M30*), proper position retainment upon reset, misc minor updates.

- Program stop support (M0,M1*,M2,M30*). *Optional stop to be done.
*Pallet shuttle not supported.

- Work position is set equal to machine position upon reset, as
according to NIST RS274-NGC guidelines. G92 is disabled.

- Renamed mc_set_current_position() to mc_set_coordinate_offset().

- Fixed bug in plan_synchronize(). Would exit right before last step is
finished and caused issues with program stops. Now fixed.

- Spindle now stops upon a run-time abort command.

- Updated readme and misc upkeeping.
This commit is contained in:
Sonny Jeon 2012-01-28 20:41:08 -07:00
parent 0f0d5a6138
commit b51e902530
17 changed files with 282 additions and 232 deletions

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by

376
gcode.c
View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by
@ -49,7 +49,8 @@
#define PROGRAM_FLOW_RUNNING 0
#define PROGRAM_FLOW_PAUSED 1
#define PROGRAM_FLOW_COMPLETED 2
#define PROGRAM_FLOW_OPT_PAUSED 2
#define PROGRAM_FLOW_COMPLETED 3
#define SPINDLE_DIRECTION_CW 0
#define SPINDLE_DIRECTION_CCW 1
@ -84,7 +85,8 @@ static void select_plane(uint8_t axis_0, uint8_t axis_1, uint8_t axis_2)
gc.plane_axis_2 = axis_2;
}
void gc_init() {
void gc_init()
{
memset(&gc, 0, sizeof(gc));
gc.feed_rate = settings.default_feed_rate;
gc.seek_rate = settings.default_seek_rate;
@ -92,6 +94,14 @@ void gc_init() {
gc.absolute_mode = true;
}
// Set g-code parser position. Input in steps.
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[Y_AXIS] = y/settings.steps_per_mm[Y_AXIS];
gc.position[Z_AXIS] = z/settings.steps_per_mm[Z_AXIS];
}
static float to_millimeters(double value) {
return(gc.inches_mode ? (value * MM_PER_INCH) : value);
}
@ -99,7 +109,8 @@ static float to_millimeters(double value) {
// 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 have been removed.
uint8_t gc_execute_line(char *line) {
uint8_t gc_execute_line(char *line)
{
uint8_t char_counter = 0;
char letter;
double value;
@ -122,39 +133,39 @@ uint8_t gc_execute_line(char *line) {
int_value = trunc(value);
switch(letter) {
case 'G':
switch(int_value) {
case 0: gc.motion_mode = MOTION_MODE_SEEK; break;
case 1: gc.motion_mode = MOTION_MODE_LINEAR; break;
case 2: gc.motion_mode = MOTION_MODE_CW_ARC; break;
case 3: gc.motion_mode = MOTION_MODE_CCW_ARC; break;
case 4: next_action = NEXT_ACTION_DWELL; break;
case 17: select_plane(X_AXIS, Y_AXIS, Z_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 20: gc.inches_mode = true; break;
case 21: gc.inches_mode = false; break;
case 28: case 30: next_action = NEXT_ACTION_GO_HOME; break;
case 53: absolute_override = true; break;
case 80: gc.motion_mode = MOTION_MODE_CANCEL; break;
case 90: gc.absolute_mode = true; break;
case 91: gc.absolute_mode = false; break;
case 92: next_action = NEXT_ACTION_SET_COORDINATE_OFFSET; break;
case 93: gc.inverse_feed_rate_mode = true; break;
case 94: gc.inverse_feed_rate_mode = false; break;
default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
}
break;
switch(int_value) {
case 0: gc.motion_mode = MOTION_MODE_SEEK; break;
case 1: gc.motion_mode = MOTION_MODE_LINEAR; break;
case 2: gc.motion_mode = MOTION_MODE_CW_ARC; break;
case 3: gc.motion_mode = MOTION_MODE_CCW_ARC; break;
case 4: next_action = NEXT_ACTION_DWELL; break;
case 17: select_plane(X_AXIS, Y_AXIS, Z_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 20: gc.inches_mode = true; break;
case 21: gc.inches_mode = false; break;
case 28: case 30: next_action = NEXT_ACTION_GO_HOME; break;
case 53: absolute_override = true; break;
case 80: gc.motion_mode = MOTION_MODE_CANCEL; break;
case 90: gc.absolute_mode = true; break;
case 91: gc.absolute_mode = false; break;
case 92: next_action = NEXT_ACTION_SET_COORDINATE_OFFSET; break;
case 93: gc.inverse_feed_rate_mode = true; break;
case 94: gc.inverse_feed_rate_mode = false; break;
default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
}
break;
case 'M':
switch(int_value) {
case 0: case 1: gc.program_flow = PROGRAM_FLOW_PAUSED; break;
case 2: case 30: case 60: gc.program_flow = PROGRAM_FLOW_COMPLETED; break;
case 3: gc.spindle_direction = 1; break;
case 4: gc.spindle_direction = -1; break;
case 5: gc.spindle_direction = 0; break;
default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
}
break;
switch(int_value) {
case 0: case 60: gc.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause
case 1: gc.program_flow = PROGRAM_FLOW_OPT_PAUSED; break; // Program pause with optional stop on
case 2: case 30: gc.program_flow = PROGRAM_FLOW_COMPLETED; break; // Program end and reset
case 3: gc.spindle_direction = 1; break;
case 4: gc.spindle_direction = -1; break;
case 5: gc.spindle_direction = 0; break;
default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
}
break;
case 'T': gc.tool = trunc(value); break;
}
if(gc.status_code) { break; }
@ -174,28 +185,28 @@ uint8_t gc_execute_line(char *line) {
unit_converted_value = to_millimeters(value);
switch(letter) {
case 'F':
if (unit_converted_value <= 0) { FAIL(STATUS_BAD_NUMBER_FORMAT); } // Must be greater than zero
if (gc.inverse_feed_rate_mode) {
inverse_feed_rate = unit_converted_value; // seconds per motion for this motion only
} else {
if (gc.motion_mode == MOTION_MODE_SEEK) {
gc.seek_rate = unit_converted_value;
} else {
gc.feed_rate = unit_converted_value; // millimeters per minute
if (unit_converted_value <= 0) { FAIL(STATUS_BAD_NUMBER_FORMAT); } // Must be greater than zero
if (gc.inverse_feed_rate_mode) {
inverse_feed_rate = unit_converted_value; // seconds per motion for this motion only
} else {
if (gc.motion_mode == MOTION_MODE_SEEK) {
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 'P': p = value; break;
case 'R': r = unit_converted_value; radius_mode = true; break;
case 'S': gc.spindle_speed = value; break;
case 'X': case 'Y': case 'Z':
if (gc.absolute_mode || absolute_override) {
target[letter - 'X'] = unit_converted_value;
} else {
target[letter - 'X'] += unit_converted_value;
}
break;
if (gc.absolute_mode || absolute_override) {
target[letter - 'X'] = unit_converted_value;
} else {
target[letter - 'X'] += unit_converted_value;
}
break;
}
}
@ -207,144 +218,161 @@ uint8_t gc_execute_line(char *line) {
// Perform any physical actions
switch (next_action) {
case NEXT_ACTION_GO_HOME: mc_go_home(); clear_vector(target); break;
case NEXT_ACTION_GO_HOME: mc_go_home(); clear_vector_double(target); break;
case NEXT_ACTION_DWELL: mc_dwell(p); break;
case NEXT_ACTION_SET_COORDINATE_OFFSET:
mc_set_current_position(target[X_AXIS], target[Y_AXIS], target[Z_AXIS]);
break;
mc_set_coordinate_offset(target[X_AXIS],target[Y_AXIS],target[Z_AXIS]);
break;
case NEXT_ACTION_DEFAULT:
switch (gc.motion_mode) {
case MOTION_MODE_CANCEL: break;
case MOTION_MODE_SEEK:
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], gc.seek_rate, false);
break;
case MOTION_MODE_LINEAR:
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;
case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC:
if (radius_mode) {
/*
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
set of equations where [x,y] is the vector from current to target position, d == magnitude of
that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to
the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the
length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point
[i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc.
d^2 == x^2 + y^2
h^2 == r^2 - (d/2)^2
i == x/2 - y/d*h
j == y/2 + x/d*h
O <- [i,j]
- |
r - |
- |
- | h
- |
[0,0] -> C -----------------+--------------- T <- [x,y]
| <------ d/2 ---->|
switch (gc.motion_mode) {
case MOTION_MODE_CANCEL: break;
case MOTION_MODE_SEEK:
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], gc.seek_rate, false);
break;
case MOTION_MODE_LINEAR:
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;
case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC:
if (radius_mode) {
/*
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
set of equations where [x,y] is the vector from current to target position, d == magnitude of
that vector, h == hypotenuse of the triangle formed by the radius of the circle, the distance to
the center of the travel vector. A vector perpendicular to the travel vector [-y,x] is scaled to the
length of h [-y/d*h, x/d*h] and added to the center of the travel vector [x/2,y/2] to form the new point
[i,j] at [x/2-y/d*h, y/2+x/d*h] which will be the center of our arc.
d^2 == x^2 + y^2
h^2 == r^2 - (d/2)^2
i == x/2 - y/d*h
j == y/2 + x/d*h
O <- [i,j]
- |
r - |
- |
- | h
- |
[0,0] -> C -----------------+--------------- T <- [x,y]
| <------ d/2 ---->|
C - Current position
T - Target position
O - center of circle that pass through both C and T
d - distance from C to T
r - designated radius
h - distance from center of CT to O
Expanding the equations:
d -> sqrt(x^2 + y^2)
h -> sqrt(4 * r^2 - x^2 - y^2)/2
i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2
j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2
Which can be written:
i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2
j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2
Which we for size and speed reasons optimize to:
h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2)
i = (x - (y * h_x2_div_d))/2
j = (y + (x * h_x2_div_d))/2
*/
// Calculate the change in position along each selected axis
double x = target[gc.plane_axis_0]-gc.position[gc.plane_axis_0];
double y = target[gc.plane_axis_1]-gc.position[gc.plane_axis_1];
clear_vector(offset);
double h_x2_div_d = -sqrt(4 * r*r - x*x - y*y)/hypot(x,y); // == -(h * 2 / d)
// If r is smaller than d, the arc is now traversing the complex plane beyond the reach of any
// real CNC, and thus - for practical reasons - we will terminate promptly:
if(isnan(h_x2_div_d)) { FAIL(STATUS_FLOATING_POINT_ERROR); return(gc.status_code); }
// Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below)
if (gc.motion_mode == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; }
/* The counter clockwise circle lies to the left of the target direction. When offset is positive,
the left hand circle will be generated - when it is negative the right hand circle is generated.
T <-- Target position
^
Clockwise circles with this center | Clockwise circles with this center will have
will have > 180 deg of angular travel | < 180 deg of angular travel, which is a good thing!
\ | /
center of arc when h_x2_div_d is positive -> x <----- | -----> x <- center of arc when h_x2_div_d is negative
|
|
C <-- Current position */
C - Current position
T - Target position
O - center of circle that pass through both C and T
d - distance from C to T
r - designated radius
h - distance from center of CT to O
// Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!),
// even though it is advised against ever generating such circles in a single line of g-code. By
// inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of
// travel and thus we get the unadvisably long arcs as prescribed.
if (r < 0) {
h_x2_div_d = -h_x2_div_d;
r = -r; // Finished with r. Set to positive for mc_arc
}
// Complete the operation by calculating the actual center of the arc
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));
} else { // Offset mode specific computations
r = hypot(offset[gc.plane_axis_0], offset[gc.plane_axis_1]); // Compute arc radius for mc_arc
}
Expanding the equations:
d -> sqrt(x^2 + y^2)
h -> sqrt(4 * r^2 - x^2 - y^2)/2
i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2
j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2)) / sqrt(x^2 + y^2)) / 2
Which can be written:
i -> (x - (y * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2
j -> (y + (x * sqrt(4 * r^2 - x^2 - y^2))/sqrt(x^2 + y^2))/2
Which we for size and speed reasons optimize to:
h_x2_div_d = sqrt(4 * r^2 - x^2 - y^2)/sqrt(x^2 + y^2)
i = (x - (y * h_x2_div_d))/2
j = (y + (x * h_x2_div_d))/2
*/
// Calculate the change in position along each selected axis
double x = target[gc.plane_axis_0]-gc.position[gc.plane_axis_0];
double y = target[gc.plane_axis_1]-gc.position[gc.plane_axis_1];
clear_vector(offset);
double h_x2_div_d = -sqrt(4 * r*r - x*x - y*y)/hypot(x,y); // == -(h * 2 / d)
// If r is smaller than d, the arc is now traversing the complex plane beyond the reach of any
// real CNC, and thus - for practical reasons - we will terminate promptly:
if(isnan(h_x2_div_d)) { FAIL(STATUS_FLOATING_POINT_ERROR); return(gc.status_code); }
// Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below)
if (gc.motion_mode == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; }
/* The counter clockwise circle lies to the left of the target direction. When offset is positive,
the left hand circle will be generated - when it is negative the right hand circle is generated.
T <-- Target position
^
Clockwise circles with this center | Clockwise circles with this center will have
will have > 180 deg of angular travel | < 180 deg of angular travel, which is a good thing!
\ | /
center of arc when h_x2_div_d is positive -> x <----- | -----> x <- center of arc when h_x2_div_d is negative
|
|
C <-- Current position */
// Negative R is g-code-alese for "I want a circle with more than 180 degrees of travel" (go figure!),
// even though it is advised against ever generating such circles in a single line of g-code. By
// inverting the sign of h_x2_div_d the center of the circles is placed on the opposite side of the line of
// travel and thus we get the unadvisably long arcs as prescribed.
if (r < 0) {
h_x2_div_d = -h_x2_div_d;
r = -r; // Finished with r. Set to positive for mc_arc
}
// Complete the operation by calculating the actual center of the arc
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));
} else { // Offset mode specific computations
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
uint8_t isclockwise = false;
if (gc.motion_mode == MOTION_MODE_CW_ARC) { isclockwise = true; }
// Trace the arc
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,
r, isclockwise);
break;
}
// Set clockwise/counter-clockwise sign for mc_arc computations
uint8_t isclockwise = false;
if (gc.motion_mode == MOTION_MODE_CW_ARC) { isclockwise = true; }
// Trace the arc
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,
r, isclockwise);
break;
}
}
// 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
// in any intermediate location.
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
// 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) {
plan_synchronize(); // Finish all remaining buffered motions. Program paused when complete.
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.
break;
// Reset to reload defaults (G92.2,G54,G17,G90,G94,M48,G40,M5,M9)
case PROGRAM_FLOW_COMPLETED: sys.abort = true; break;
}
}
return(gc.status_code);
}
// Parses the next statement and leaves the counter on the first character following
// the statement. Returns 1 if there was a statements, 0 if end of string was reached
// or there was an error (check state.status_code).
static int next_statement(char *letter, double *double_ptr, char *line, uint8_t *char_counter) {
static int next_statement(char *letter, double *double_ptr, char *line, uint8_t *char_counter)
{
if (line[*char_counter] == 0) {
return(0); // No more statements
}
@ -375,7 +403,7 @@ static int next_statement(char *letter, double *double_ptr, char *line, uint8_t
- Probing
- Override control
group 0 = {G10, G28, G30, G92, G92.1, G92.2, G92.3} (Non modal G-codes)
group 0 = {G10, G28, G30, G92.1, G92.2, G92.3} (Non modal G-codes)
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 12 = {G54, G55, G56, G57, G58, G59, G59.1, G59.2, G59.3} coordinate system selection

View File

@ -29,4 +29,7 @@ void gc_init();
// Execute one block of rs275/ngc/g-code
uint8_t gc_execute_line(char *line);
// Set g-code parser position. Input in steps.
void gc_set_current_position(int32_t x, int32_t y, int32_t z);
#endif

26
main.c
View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by
@ -46,7 +46,7 @@ int main(void)
memset(&sys, 0, sizeof(sys)); // Clear all system variables
sys.abort = true; // Set abort to complete initialization
while(1) {
for(;;) {
// Execute system reset upon a system abort, where the main program will return to this loop.
// Once here, it is safe to re-initialize the system. At startup, the system will automatically
@ -56,18 +56,15 @@ int main(void)
// Retain last known machine position. If the system abort occurred while in motion, machine
// position is not guaranteed, since a hard stop can cause the steppers to lose steps. Always
// perform a feedhold before an abort, if maintaining accurate machine position is required.
int32_t last_position[3];
// 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
// grbl is moving the machine.
int32_t last_position[3]; // last_coord_offset[3];
memcpy(last_position, sys.position, sizeof(sys.position)); // last_position[] = sys.position[]
// Clear all system variables
memset(&sys, 0, sizeof(sys));
// Update last known machine position. Set the post-abort work position as the origin [0,0,0],
// which corresponds to the g-code parser and planner positions after re-initialization.
memcpy(sys.position, last_position, sizeof(last_position)); // sys.position[] = last_position[]
memcpy(sys.coord_offset, last_position, sizeof(last_position)); // sys.coord_offset[] = last_position[]
// memcpy(last_coord_offset, sys.coord_offset, sizeof(sys.coord_offset)); // last_coord_offset[] = sys.coord_offset[]
// Reset system.
memset(&sys, 0, sizeof(sys)); // Clear all system variables
serial_reset_read_buffer(); // Clear serial read buffer
settings_init(); // Load grbl settings from EEPROM
protocol_init(); // Clear incoming line data
@ -77,6 +74,11 @@ int main(void)
limits_init();
st_reset(); // Clear stepper subsystem variables.
// Reload last known machine position. Coordinate offsets are reset per NIST RS274-NGC protocol.
memcpy(sys.position, last_position, sizeof(last_position)); // sys.position[] = last_position[]
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]);
// Set system runtime defaults
// TODO: Eventual move to EEPROM from config.h when all of the new settings are worked out.
// Mainly to avoid having to maintain several different versions.

View File

@ -3,7 +3,7 @@
Part of Grbl
Copyright (c) 2009-2011 Simen Svale Skogsrud
Copyright (c) 2011 Sungeun K. Jeon
Copyright (c) 2011-2012 Sungeun K. Jeon
Copyright (c) 2011 Jens Geisler
Grbl is free software: you can redistribute it and/or modify
@ -183,12 +183,11 @@ void mc_dwell(double seconds)
uint16_t i = floor(1000/DWELL_TIME_STEP*seconds);
plan_synchronize();
delay_ms(floor(1000*seconds-i*DWELL_TIME_STEP)); // Delay millisecond remainder
while (i > 0) {
while (i-- > 0) {
// NOTE: Check and execute runtime commands during dwell every <= DWELL_TIME_STEP milliseconds.
protocol_execute_runtime();
if (sys.abort) { return; }
_delay_ms(DWELL_TIME_STEP); // Delay DWELL_TIME_STEP increment
i--;
}
}

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by
@ -27,7 +27,7 @@
// 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_current_position(x, y, z) plan_set_current_position(x, y, z)
#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
// unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in

View File

@ -3,6 +3,7 @@
Part of Grbl
Copyright (c) 2009-2011 Simen Svale Skogsrud
Copyright (c) 2011-2012 Sungeun K. Jeon
Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -37,10 +38,9 @@ int read_double(char *line, uint8_t *char_counter, double *double_ptr)
return(true);
}
// Delays variable defined milliseconds. Compiler compatibility fix for _delay_ms(),
// which only accepts constants in future compiler releases.
void delay_ms(uint16_t ms)
{
while ( ms-- ) { _delay_ms(1); }
}
}

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
Part of Grbl
Copyright (c) 2009-2011 Simen Svale Skogsrud
Copyright (c) 2011 Sungeun K. Jeon
Copyright (c) 2011-2012 Sungeun K. Jeon
Copyright (c) 2011 Jens Geisler
Grbl is free software: you can redistribute it and/or modify
@ -312,14 +312,14 @@ void plan_init()
memset(&pl, 0, sizeof(pl)); // Clear planner struct
}
void plan_discard_current_block()
inline void plan_discard_current_block()
{
if (block_buffer_head != block_buffer_tail) {
block_buffer_tail = next_block_index( block_buffer_tail );
}
}
block_t *plan_get_current_block()
inline block_t *plan_get_current_block()
{
if (block_buffer_head == block_buffer_tail) { return(NULL); }
return(&block_buffer[block_buffer_tail]);
@ -335,7 +335,7 @@ uint8_t plan_check_full_buffer()
// Block until all buffered steps are executed.
void plan_synchronize()
{
while(plan_get_current_block()) {
while (plan_get_current_block() || sys.cycle_start) {
protocol_execute_runtime(); // Check and execute run-time commands
if (sys.abort) { return; } // Check for system abort
}
@ -471,8 +471,8 @@ void plan_buffer_line(double x, double y, double z, double feed_rate, uint8_t in
planner_recalculate();
}
// Reset the planner position vector and planner speed
void plan_set_current_position(double x, double y, double z)
// Apply G92 coordinate offsets and update planner position vector.
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
@ -489,14 +489,25 @@ void plan_set_current_position(double x, double y, double z)
memset(&pl, 0, sizeof(pl)); // Clear planner variables. Assume start from rest.
pl.position[X_AXIS] = lround(x*settings.steps_per_mm[X_AXIS]); // Update planner position
pl.position[Y_AXIS] = lround(y*settings.steps_per_mm[Y_AXIS]);
pl.position[Z_AXIS] = lround(z*settings.steps_per_mm[Z_AXIS]);
// 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)
{
pl.position[X_AXIS] = x;
pl.position[Y_AXIS] = y;
pl.position[Z_AXIS] = z;
}
// Re-initialize buffer plan with a partially completed block, assumed to exist at the buffer tail.
// Called after a steppers have come to a complete stop for a feed hold and the cycle is stopped.
void plan_cycle_reinitialize(int32_t step_events_remaining)

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by
@ -66,8 +66,11 @@ void plan_discard_current_block();
// Gets the current block. Returns NULL if buffer empty
block_t *plan_get_current_block();
// Reset the position vector
void plan_set_current_position(double x, double y, double z);
// Reset the planner position vector (in steps)
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
void plan_cycle_reinitialize(int32_t step_events_remaining);

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by
@ -84,21 +84,21 @@ void protocol_status_report()
int32_t print_position[3];
memcpy(print_position,sys.position,sizeof(sys.position));
#if REPORT_INCH_MODE
printString("MPos: x"); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS]*MM_PER_INCH));
printString(",y"); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]*MM_PER_INCH));
printString(",z"); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]*MM_PER_INCH));
printString(" WPos: x"); printFloat((print_position[X_AXIS]-sys.coord_offset[X_AXIS])/(settings.steps_per_mm[X_AXIS]*MM_PER_INCH));
printString(",y"); printFloat((print_position[Y_AXIS]-sys.coord_offset[Y_AXIS])/(settings.steps_per_mm[Y_AXIS]*MM_PER_INCH));
printString(",z"); printFloat((print_position[Z_AXIS]-sys.coord_offset[Z_AXIS])/(settings.steps_per_mm[Z_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[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(","); printFloat((print_position[Y_AXIS]-sys.coord_offset[Y_AXIS])/(settings.steps_per_mm[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));
#else
printString("MPos: x"); printFloat(print_position[X_AXIS]/(settings.steps_per_mm[X_AXIS]));
printString(",y"); printFloat(print_position[Y_AXIS]/(settings.steps_per_mm[Y_AXIS]));
printString(",z"); printFloat(print_position[Z_AXIS]/(settings.steps_per_mm[Z_AXIS]));
printString(" WPos: x"); printFloat((print_position[X_AXIS]-sys.coord_offset[X_AXIS])/(settings.steps_per_mm[X_AXIS]));
printString(",y"); printFloat((print_position[Y_AXIS]-sys.coord_offset[Y_AXIS])/(settings.steps_per_mm[Y_AXIS]));
printString(",z"); printFloat((print_position[Z_AXIS]-sys.coord_offset[Z_AXIS])/(settings.steps_per_mm[Z_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[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(","); printFloat((print_position[Y_AXIS]-sys.coord_offset[Y_AXIS])/(settings.steps_per_mm[Y_AXIS]));
printString(","); printFloat((print_position[Z_AXIS]-sys.coord_offset[Z_AXIS])/(settings.steps_per_mm[Z_AXIS]));
#endif
printString("\r\n");
printString("]\r\n");
}

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by

View File

@ -6,17 +6,19 @@ The controller is written in highly optimized C utilizing every clever feature o
It accepts standards-compliant G-code and has been tested with the output of several CAM tools with no problems. Arcs, circles and helical motion are fully supported, as well as, other basic functional g-code commands. Functions and variables are not currently supported, but may be included in future releases in a form of a pre-processor.
Grbl includes full acceleration management with look ahead. That means the controller will look up to 20 motions into the future and plan its velocities ahead to deliver smooth acceleration and jerk-free cornering.
Grbl includes full acceleration management with look ahead. That means the controller will look up to 18 motions into the future and plan its velocities ahead to deliver smooth acceleration and jerk-free cornering.
*Changelog for v0.8 from v0.7:*
- *ALPHA STATUS*: Major structural overhaul to allow for multi-tasking events and new feature sets
- *ALPHA status: _Under heavy development. Code state may significantly change with each push as new features are integrated._*
- Major structural overhaul to allow for multi-tasking events and new feature sets
- 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.
- After feed hold, cycle accelerations are re-planned and may be resumed.
- Work(G92) and machine coordinate system support.
- Work offset(G92) and machine coordinate system support.
- Program stop(M0,M1*,M2,M30) initial support. Pallet shuttle not supported.
- System reset re-initializes grbl without resetting the Arduino and retains machine/home position.
- 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.
- 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.
- Misc bug fixes and removed deprecated acceleration enabled code.

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by
@ -27,6 +27,7 @@
#include "serial.h"
#include "config.h"
#include "stepper.h"
#include "spindle_control.h"
#include "nuts_bolts.h"
#include "protocol.h"
@ -127,9 +128,10 @@ ISR(USART_RX_vect)
case CMD_CYCLE_START: sys.execute |= EXEC_CYCLE_START; break; // Set as true
case CMD_FEED_HOLD: sys.execute |= EXEC_FEED_HOLD; break; // Set as true
case CMD_RESET:
// Immediately force stepper subsystem idle at an interrupt level.
// Immediately force stepper and spindle subsystem idle at an interrupt level.
if (!(sys.execute & EXEC_RESET)) { // Force stop only first time.
st_go_idle();
spindle_stop();
}
sys.execute |= EXEC_RESET; // Set as true
break;

View File

@ -3,7 +3,7 @@
Part of Grbl
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
it under the terms of the GNU General Public License as published by
@ -115,7 +115,7 @@ void st_go_idle()
// This function determines an acceleration velocity change every CYCLES_PER_ACCELERATION_TICK by
// keeping track of the number of elapsed cycles during a de/ac-celeration. The code assumes that
// step_events occur significantly more often than the acceleration velocity iterations.
static uint8_t iterate_trapezoid_cycle_counter()
inline static uint8_t iterate_trapezoid_cycle_counter()
{
st.trapezoid_tick_cycle_counter += st.cycles_per_step_event;
if(st.trapezoid_tick_cycle_counter > CYCLES_PER_ACCELERATION_TICK) {