G-code parser G0/G1 bug fix.
- Although stated as invalid in the NIST g-code standard, most g-code parsers, including linuxcnc, allow G0 and G1 to be commanded without axis words present. For example, something like ‘G1 F100.0’ to preset the motion mode and feed rate without a motion commanded. Older CNC controllers actually required this for feed rate settings. This update should now allow this type of behavior.
This commit is contained in:
parent
1ef5a45479
commit
92d6c2bca5
70
gcode.c
70
gcode.c
@ -92,7 +92,7 @@ uint8_t gc_execute_line(char *line)
|
||||
|
||||
memset(&gc_block, 0, sizeof(gc_block)); // Initialize the parser block struct.
|
||||
memcpy(&gc_block.modal,&gc_state.modal,sizeof(gc_modal_t)); // Copy current modes
|
||||
uint8_t axis_explicit = AXIS_COMMAND_NONE;
|
||||
uint8_t axis_command = AXIS_COMMAND_NONE;
|
||||
uint8_t axis_0, axis_1, axis_linear;
|
||||
float coordinate_data[N_AXIS]; // Multi-use variable to store coordinate data for execution
|
||||
float parameter_data[N_AXIS]; // Multi-use variable to store parameter data for execution
|
||||
@ -149,8 +149,8 @@ uint8_t gc_execute_line(char *line)
|
||||
case 10: case 28: case 30: case 92:
|
||||
// Check for G10/28/30/92 being called with G0/1/2/3/38 on same block.
|
||||
if (mantissa == 0) { // Ignore G28.1, G30.1, and G92.1
|
||||
if (axis_explicit) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
|
||||
axis_explicit = AXIS_COMMAND_NON_MODAL;
|
||||
if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
|
||||
axis_command = AXIS_COMMAND_NON_MODAL;
|
||||
}
|
||||
// No break. Continues to next line.
|
||||
case 4: case 53:
|
||||
@ -187,8 +187,8 @@ uint8_t gc_execute_line(char *line)
|
||||
break;
|
||||
case 0: case 1: case 2: case 3: case 38:
|
||||
// Check for G0/1/2/3/38 being called with G10/28/30/92 on same block.
|
||||
if (axis_explicit) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
|
||||
axis_explicit = AXIS_COMMAND_MOTION_MODE;
|
||||
if (axis_command) { FAIL(STATUS_GCODE_AXIS_COMMAND_CONFLICT); } // [Axis word/command conflict]
|
||||
axis_command = AXIS_COMMAND_MOTION_MODE;
|
||||
// No break. Continues to next line.
|
||||
case 80:
|
||||
word_bit = MODAL_GROUP_G1;
|
||||
@ -363,21 +363,10 @@ uint8_t gc_execute_line(char *line)
|
||||
|
||||
// [0. Non-specific/common error-checks and miscellaneous setup]:
|
||||
|
||||
// Determine how axis words are used and error-check it. Apply implicit conditions and exceptions.
|
||||
if (axis_explicit) { // Either a non-modal or motion mode axis-explicit command has been passed.
|
||||
// Axis-words are required (with exceptions) with axis-explicit commands.
|
||||
// NOTE: G28/30 reserve any axis words as an intermediate motion, but are not required. G2/3 full
|
||||
// circle arcs don't require axis words, but this aren't supported.
|
||||
if (!axis_words) {
|
||||
if ((gc_block.non_modal_command == NON_MODAL_GO_HOME_0) || (gc_block.non_modal_command == NON_MODAL_GO_HOME_1)) {
|
||||
axis_explicit = AXIS_COMMAND_NONE; // No axis words passed for G28/30.
|
||||
} else {
|
||||
FAIL(STATUS_GCODE_NO_AXIS_WORDS); // [No axis words]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If no axis-explicit commands in the block, axis words implicitly activate the current motion mode.
|
||||
if (axis_words) { axis_explicit = AXIS_COMMAND_MOTION_MODE; } // Assign implicit motion-mode
|
||||
// Determine implicit axis command conditions. Axis words have been passed, but no explicit axis
|
||||
// command has been sent. If so, set axis command to current motion mode.
|
||||
if (axis_words) {
|
||||
if (!axis_command) { axis_command = AXIS_COMMAND_MOTION_MODE; } // Assign implicit motion-mode
|
||||
}
|
||||
|
||||
// Check for valid line number N value.
|
||||
@ -391,7 +380,7 @@ uint8_t gc_execute_line(char *line)
|
||||
// NOTE: Single-meaning value words are removed all at once at the end of error-checking, because
|
||||
// they are always used when present. This was done to save a few bytes of flash. For clarity, the
|
||||
// single-meaning value words may be removed as they are used. Also, axis words are treated in the
|
||||
// same way. If there is an axis explicit/implicit command, XYZ words are always used and are
|
||||
// same way. If there is an explicit/implicit axis command, XYZ words are always used and are
|
||||
// are removed at the end of error-checking.
|
||||
|
||||
// [1. Comments ]: MSG's NOT SUPPORTED. Comment handling performed by protocol.
|
||||
@ -400,7 +389,7 @@ uint8_t gc_execute_line(char *line)
|
||||
// is not defined after switching to G94 from G93.
|
||||
if (gc_block.modal.feed_rate == FEED_RATE_MODE_INVERSE_TIME) { // = G93
|
||||
// NOTE: G38 can also operate in inverse time, but is undefined as an error. Missing F word check added here.
|
||||
if (axis_explicit == AXIS_COMMAND_MOTION_MODE) {
|
||||
if (axis_command == AXIS_COMMAND_MOTION_MODE) {
|
||||
if ((gc_block.modal.motion != MOTION_MODE_NONE) || (gc_block.modal.motion != MOTION_MODE_SEEK)) {
|
||||
if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } // [F word missing]
|
||||
}
|
||||
@ -497,15 +486,16 @@ uint8_t gc_execute_line(char *line)
|
||||
// [18. Set retract mode ]: NOT SUPPORTED.
|
||||
|
||||
// [19. Remaining non-modal actions ]: Check go to predefined position, set G10, or set axis offsets.
|
||||
// NOTE: We need to separate the non-modal commands that are axis-explicit (G10/G28/G30/G92), as these
|
||||
// NOTE: We need to separate the non-modal commands that are axis word-using (G10/G28/G30/G92), as these
|
||||
// commands all treat axis words differently. G10 as absolute offsets or computes current position as
|
||||
// the axis value, G92 similarly to G10 L20, and G28/30 as an intermediate target position that observes
|
||||
// all the current coordinate system and G92 offsets.
|
||||
switch (gc_block.non_modal_command) {
|
||||
case NON_MODAL_SET_COORDINATE_DATA:
|
||||
// [G10 Errors]: L missing and is not 2 or 20. P word missing. (Negative P value done.)
|
||||
// [G10 L2 Errors]: R word NOT SUPPORTED. P value not 0 to nCoordSys(max 9). Axis words missing (done.)
|
||||
// [G10 L20 Errors]: P must be 0 to nCoordSys(max 9). Axis words missing (done.)
|
||||
// [G10 L2 Errors]: R word NOT SUPPORTED. P value not 0 to nCoordSys(max 9). Axis words missing.
|
||||
// [G10 L20 Errors]: P must be 0 to nCoordSys(max 9). Axis words missing.
|
||||
if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS) }; // [No axis words]
|
||||
if (bit_isfalse(value_words,((1<<WORD_P)|(1<<WORD_L)))) { FAIL(STATUS_GCODE_VALUE_WORD_MISSING); } // [P/L word missing]
|
||||
int_value = trunc(gc_block.values.p); // Convert p value to int.
|
||||
if (int_value > N_COORDINATE_SYSTEM) { FAIL(STATUS_GCODE_UNSUPPORTED_COORD_SYS); } // [Greater than N sys]
|
||||
@ -533,7 +523,8 @@ uint8_t gc_execute_line(char *line)
|
||||
}
|
||||
break;
|
||||
case NON_MODAL_SET_COORDINATE_OFFSET:
|
||||
// [G92 Errors]: No axis words (done.)
|
||||
// [G92 Errors]: No axis words.
|
||||
if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]
|
||||
|
||||
// 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.
|
||||
@ -548,7 +539,7 @@ uint8_t gc_execute_line(char *line)
|
||||
|
||||
default:
|
||||
|
||||
// At this point, the rest of the axis-explicit commands treat the axis values as the traditional
|
||||
// At this point, the rest of the explicit axis commands treat the axis values as the traditional
|
||||
// target position with the coordinate system offsets, G92 offsets, absolute override, and distance
|
||||
// modes applied. This includes the motion mode commands. We can now pre-compute the target position.
|
||||
// NOTE: Tool offsets may be appended to these conversions when/if this feature is added.
|
||||
@ -603,26 +594,31 @@ uint8_t gc_execute_line(char *line)
|
||||
// [20. Motion modes ]:
|
||||
if (gc_block.modal.motion == MOTION_MODE_NONE) {
|
||||
// [G80 Errors]: Axis word exist and are not used by a non-modal command.
|
||||
if ((axis_words) && (axis_explicit != AXIS_COMMAND_NON_MODAL)) {
|
||||
if ((axis_words) && (axis_command != AXIS_COMMAND_NON_MODAL)) {
|
||||
FAIL(STATUS_GCODE_AXIS_WORDS_EXIST); // [No axis words allowed]
|
||||
}
|
||||
|
||||
// Check remaining motion modes, if axis word are implicit (exist and not used by G10/28/30/92), or
|
||||
// was explicitly commanded in the g-code block.
|
||||
} else if ( axis_explicit == AXIS_COMMAND_MOTION_MODE ) {
|
||||
} else if ( axis_command == AXIS_COMMAND_MOTION_MODE ) {
|
||||
|
||||
// [G0 Errors]: (All done!) No axis words. Axis letter not configured or without real value.
|
||||
if (gc_block.modal.motion == MOTION_MODE_SEEK) {
|
||||
// [G0 Errors]: Axis letter not configured or without real value (done.)
|
||||
// Axis words are optional. If missing, set axis command flag to ignore execution.
|
||||
if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }
|
||||
|
||||
// All remaining motion modes (all but G0 and G80), require a valid feed rate value. In units per mm mode,
|
||||
// the value must be positive. In inverse time mode, a positive value must be passed with each block.
|
||||
if (gc_block.modal.motion != MOTION_MODE_SEEK) {
|
||||
|
||||
} else {
|
||||
// Check if feed rate is defined for the motion modes that require it.
|
||||
if (gc_block.values.f == 0.0) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); } // [Feed rate undefined]
|
||||
|
||||
switch (gc_block.modal.motion) {
|
||||
case MOTION_MODE_LINEAR:
|
||||
// [G1 Errors]: (All done!) No axis words and feed rate undefined. Axis letter not configured or without real value.
|
||||
// [G1 Errors]: Feed rate undefined. Axis letter not configured or without real value.
|
||||
// Axis words are optional. If missing, set axis command flag to ignore execution.
|
||||
if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }
|
||||
|
||||
break;
|
||||
case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC:
|
||||
// [G2/3 Errors All-Modes]: Feed rate undefined.
|
||||
@ -632,6 +628,7 @@ uint8_t gc_execute_line(char *line)
|
||||
// [G2/3 Full-Circle-Mode Errors]: NOT SUPPORTED. Axis words exist. No offsets programmed. P must be an integer.
|
||||
// NOTE: Both radius and offsets are required for arc tracing and are pre-computed with the error-checking.
|
||||
|
||||
if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]
|
||||
if (!(axis_words & (bit(axis_0)|bit(axis_1)))) { FAIL(STATUS_GCODE_NO_AXIS_WORDS_IN_PLANE); } // [No axis words in plane]
|
||||
|
||||
// Calculate the change in position along each selected axis
|
||||
@ -760,6 +757,7 @@ uint8_t gc_execute_line(char *line)
|
||||
case MOTION_MODE_PROBE:
|
||||
// [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate
|
||||
// is undefined. Probe is triggered.
|
||||
if (!axis_words) { FAIL(STATUS_GCODE_NO_AXIS_WORDS); } // [No axis words]
|
||||
if (gc_check_same_position(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]
|
||||
if (probe_get_state()) { FAIL(STATUS_GCODE_PROBE_TRIGGERED); } // [Probe triggered]
|
||||
break;
|
||||
@ -772,7 +770,7 @@ uint8_t gc_execute_line(char *line)
|
||||
// [0. Non-specific error-checks]: Complete unused value words check, i.e. IJK used when in arc
|
||||
// radius mode, or axis words that aren't used in the block.
|
||||
bit_false(value_words,(bit(WORD_N)|bit(WORD_F)|bit(WORD_S)|bit(WORD_T))); // Remove single-meaning value words.
|
||||
if (axis_explicit) { bit_false(value_words,(bit(WORD_X)|bit(WORD_Y)|bit(WORD_Z))); } // Remove axis words.
|
||||
if (axis_command) { bit_false(value_words,(bit(WORD_X)|bit(WORD_Y)|bit(WORD_Z))); } // Remove axis words.
|
||||
if (value_words) { FAIL(STATUS_GCODE_UNUSED_WORDS); } // [Unused words]
|
||||
|
||||
|
||||
@ -859,7 +857,7 @@ uint8_t gc_execute_line(char *line)
|
||||
case NON_MODAL_GO_HOME_0: case NON_MODAL_GO_HOME_1:
|
||||
// Move to intermediate position before going home. Obeys current coordinate system and offsets
|
||||
// and absolute and incremental modes.
|
||||
if (axis_explicit) {
|
||||
if (axis_command) {
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
mc_line(gc_block.values.xyz, -1.0, false, gc_block.values.n);
|
||||
#else
|
||||
@ -893,7 +891,7 @@ uint8_t gc_execute_line(char *line)
|
||||
// Enter motion modes only if there are axis words or a motion mode command word in the block.
|
||||
gc_state.modal.motion = gc_block.modal.motion;
|
||||
if (gc_state.modal.motion != MOTION_MODE_NONE) {
|
||||
if (axis_explicit == AXIS_COMMAND_MOTION_MODE) {
|
||||
if (axis_command == AXIS_COMMAND_MOTION_MODE) {
|
||||
switch (gc_state.modal.motion) {
|
||||
case MOTION_MODE_SEEK:
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
|
Loading…
Reference in New Issue
Block a user