v1.1e: New laser features. G-code parser refactoring. CoreXY homing fix.
- Increment to v1.1e due to new laser features. - After several discussions with some prominent laser people, a few tweaks to the new laser mode has been installed. - LASER: M3 behaves in a constant power mode. - LASER: M4 behaves in a dynamic power mode, where the laser power is automatically adjusted based on how fast Grbl is moving relative to the programmed feed rate. This is the same as the CONSTANT_POWER_PER_RATE config.h option in the last version. NOTE: When not in motion in M4, Grbl automatically turns off the laser. Again, it only operates while moving! - LASER: Only G1, G2, and G3 motion modes will turn on the laser. So, this means that G0, G80 motion modes will always keep the laser disabled. No matter if M3/M4 are active! - LASER: A spindle stop override is automatically invoked when a laser is put in a feed hold. This behavior may be disabled by a config.h option. - Lots of little tweaks to the g-code parser to help streamline it a bit. It should no effect how it operates. Generally just added a parser flag to track and execute certain scenarios a little more clearly. - Jog motions now allow line numbers to be passed to it and will be displayed in the status reports. - Fixed a CoreXY homing bug. - Fixed an issue when $13 is changed, WCO isn’t sent immediately. - Altered how spindle PWM is set in the stepper ISR. Updated on a step segment basis now. May need to change this back if there are any oddities from doing this. - Updated some documentation. Clarified why M0 no longer showing up in $G and why a `1.` floating point values are shown with no decimals, like so `1`.
This commit is contained in:
parent
998f23b9ce
commit
b753c542c7
@ -1,3 +1,18 @@
|
|||||||
|
----------------
|
||||||
|
Date: 2016-11-12
|
||||||
|
Author: Sonny Jeon
|
||||||
|
Subject: PWM calculation correction.
|
||||||
|
|
||||||
|
- The PWM calculation was a little bit off and has been corrected.
|
||||||
|
|
||||||
|
- Edited the unused settings strings to be smaller and just show what
|
||||||
|
the settings are, rather than include units. May include this in the
|
||||||
|
master build, if it fits.
|
||||||
|
|
||||||
|
- The minimum spindle PWM define in config.h needed to be update for
|
||||||
|
cpu map compatibilty.
|
||||||
|
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
Date: 2016-11-04
|
Date: 2016-11-04
|
||||||
Author: Sonny Jeon
|
Author: Sonny Jeon
|
||||||
|
@ -37,6 +37,11 @@ Grbl v1.1's interface protocol has been tweaked in the attempt to make GUI devel
|
|||||||
|
|
||||||
In addition, all `$x=val` settings, `error:`, and `ALARM:` messages no longer contain human-readable strings, but rather codes that are defined in other documents. The `$` help message is also reduced to just showing the available commands. Doing this saves incredible amounts of flash space. Otherwise, the new overrides features would not have fit.
|
In addition, all `$x=val` settings, `error:`, and `ALARM:` messages no longer contain human-readable strings, but rather codes that are defined in other documents. The `$` help message is also reduced to just showing the available commands. Doing this saves incredible amounts of flash space. Otherwise, the new overrides features would not have fit.
|
||||||
|
|
||||||
|
Other minor changes and bug fixes that may effect GUI parsing include:
|
||||||
|
|
||||||
|
- Floating point values printed with zero precision do not show a decimal, or look like an integer. This includes spindle speed RPM and feed rate in mm mode.
|
||||||
|
- `$G` reports fixed a long time bug with program modal state. It always showed `M0` program pause when running. Now during a normal program run, no program modal state is given until an `M0`, `M2`, or `M30` is active and then the appropriate state will be shown.
|
||||||
|
|
||||||
On a final note, these interface tweaks came about out of necessity, because more data is being sent back from Grbl, it is capable of doing many more things, and flash space is at a premium. It's not intended to be altered again in the near future, if at all. This is likely the only and last major change to this. If you have any comments or suggestions before Grbl v1.1 goes to master, please do immediately so we can all vet the new alteration before its installed.
|
On a final note, these interface tweaks came about out of necessity, because more data is being sent back from Grbl, it is capable of doing many more things, and flash space is at a premium. It's not intended to be altered again in the near future, if at all. This is likely the only and last major change to this. If you have any comments or suggestions before Grbl v1.1 goes to master, please do immediately so we can all vet the new alteration before its installed.
|
||||||
|
|
||||||
----
|
----
|
||||||
|
@ -255,13 +255,18 @@ Feedback messages provide non-critical information on what Grbl is doing, what i
|
|||||||
|
|
||||||
- **Queried Feedback Messages:**
|
- **Queried Feedback Messages:**
|
||||||
|
|
||||||
- `[GC:]` G-code Parser State Message
|
- `[GC:]` G-code Parser State Message
|
||||||
- Initiated by the user via a `$G` command. Grbl replies as follows, where the `[GC:` denotes the message type and is followed by a separate `ok` to confirm the `$G` was executed.
|
```
|
||||||
```
|
[GC:G0 G54 G17 G21 G90 G94 M5 M9 T0 F0.0 S0]
|
||||||
[GC:G0 G54 G17 G21 G90 G94 M0 M5 M9 T0 F0. S0.]
|
|
||||||
ok
|
ok
|
||||||
```
|
```
|
||||||
- The shown g-code are the current modal states of Grbl's g-code parser. This may not correlate to what is executing since there are usually several motions queued in the planner buffer.
|
- Initiated by the user via a `$G` command. Grbl replies as follows, where the `[GC:` denotes the message type and is followed by a separate `ok` to confirm the `$G` was executed.
|
||||||
|
|
||||||
|
- The shown g-code are the current modal states of Grbl's g-code parser. This may not correlate to what is executing since there are usually several motions queued in the planner buffer.
|
||||||
|
|
||||||
|
- NOTE: Program modal state has been fixed and will show `M0`, `M2`, or `M30` when they are active. During a run state, nothing will appear for program modal state.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- `[HLP:]` : Initiated by the user via a `$` print help command. The help message is shown below with a separate `ok` to confirm the `$` was executed.
|
- `[HLP:]` : Initiated by the user via a `$` print help command. The help message is shown below with a separate `ok` to confirm the `$` was executed.
|
||||||
```
|
```
|
||||||
@ -589,4 +594,11 @@ Grbl v1.1's interface protocol has been tweaked in the attempt to make GUI devel
|
|||||||
|
|
||||||
- `>G54G20:ok` : The open chevron indicates startup line execution. The `:ok` suffix shows it executed correctly without adding an unmatched `ok` response on a new line.
|
- `>G54G20:ok` : The open chevron indicates startup line execution. The `:ok` suffix shows it executed correctly without adding an unmatched `ok` response on a new line.
|
||||||
|
|
||||||
|
In addition, all `$x=val` settings, `error:`, and `ALARM:` messages no longer contain human-readable strings, but rather codes that are defined in other documents. The `$` help message is also reduced to just showing the available commands. Doing this saves incredible amounts of flash space. Otherwise, the new overrides features would not have fit.
|
||||||
|
|
||||||
|
Other minor changes and bug fixes that may effect GUI parsing include:
|
||||||
|
|
||||||
|
- Floating point values printed with zero precision do not show a decimal, or look like an integer. This includes spindle speed RPM and feed rate in mm mode.
|
||||||
|
- `$G` reports fixed a long time bug with program modal state. It always showed `M0` program pause when running. Now during a normal program run, no program modal state is given until an `M0`, `M2`, or `M30` is active and then the appropriate state will be shown.
|
||||||
|
|
||||||
On a final note, this interface tweak came about out of necessity, as more data is being sent back from Grbl and it is capable of doing many more things. It's not intended to be altered again in the near future, if at all. This is likely the only and last major change to this. If you have any comments or suggestions before Grbl v1.1 goes to master, please do immediately so we can all vet the new alteration before its installed.
|
On a final note, this interface tweak came about out of necessity, as more data is being sent back from Grbl and it is capable of doing many more things. It's not intended to be altered again in the near future, if at all. This is likely the only and last major change to this. If you have any comments or suggestions before Grbl v1.1 goes to master, please do immediately so we can all vet the new alteration before its installed.
|
||||||
|
@ -13,7 +13,8 @@ Executing a jog requires a specific command structure, as described below:
|
|||||||
- G20 or G21 - Inch and millimeter mode
|
- G20 or G21 - Inch and millimeter mode
|
||||||
- G90 or G91 - Absolute and incremental distances
|
- G90 or G91 - Absolute and incremental distances
|
||||||
- G53 - Move in machine coordinates
|
- G53 - Move in machine coordinates
|
||||||
- All other g-codes, m-codes, and value words are not accepted in the jog command.
|
- N line numbers are valid. Will show in reports, if enabled, but is otherwise ignored.
|
||||||
|
- All other g-codes, m-codes, and value words (including S and T) are not accepted in the jog command.
|
||||||
- Spaces and comments are allowed in the command. These are removed by the pre-parser.
|
- Spaces and comments are allowed in the command. These are removed by the pre-parser.
|
||||||
|
|
||||||
- Example: G21 and G90 are active modal states prior to jogging. These are sequential commands.
|
- Example: G21 and G90 are active modal states prior to jogging. These are sequential commands.
|
||||||
|
@ -570,11 +570,11 @@
|
|||||||
#define PARKING_PULLOUT_INCREMENT 5.0 // Spindle pull-out and plunge distance in mm. Incremental distance.
|
#define PARKING_PULLOUT_INCREMENT 5.0 // Spindle pull-out and plunge distance in mm. Incremental distance.
|
||||||
// Must be positive value or equal to zero.
|
// Must be positive value or equal to zero.
|
||||||
|
|
||||||
// Experimental feature that adjusts laser power (PWM output) based on current running speed of the
|
// This option will automatically disable the laser during a feed hold by invoking a spindle stop
|
||||||
// machine. When laser mode is enabled, Grbl will turn off the spindle PWM pin whenever it is not
|
// override immediately after coming to a stop. However, this also means that the laser still may
|
||||||
// moving, which may be confusing to some users to why their laser is not on. This behavior may change
|
// be reenabled by disabling the spindle stop override, if needed. This is purely a safety feature
|
||||||
// in future iterations of this feature, where it will turn on to the minimum rpm value when active.
|
// to ensure the laser doesn't inadvertently remain powered while at a stop and cause a fire.
|
||||||
// #define LASER_CONSTANT_POWER_PER_RATE
|
#define DISABLE_LASER_DURING_HOLD // Default enabled. Comment to disable.
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------------------
|
||||||
OEM Single File Configuration Option
|
OEM Single File Configuration Option
|
||||||
|
161
grbl/gcode.c
161
grbl/gcode.c
@ -82,17 +82,20 @@ uint8_t gc_execute_line(char *line)
|
|||||||
uint8_t axis_words = 0; // XYZ tracking
|
uint8_t axis_words = 0; // XYZ tracking
|
||||||
uint8_t ijk_words = 0; // IJK tracking
|
uint8_t ijk_words = 0; // IJK tracking
|
||||||
|
|
||||||
// Initialize command and value words variables. Tracks words contained in this block.
|
// Initialize command and value words and parser flags variables.
|
||||||
uint16_t command_words = 0; // G and M command words. Also used for modal group violations.
|
uint16_t command_words = 0; // Tracks G and M command words. Also used for modal group violations.
|
||||||
uint16_t value_words = 0; // Value words.
|
uint16_t value_words = 0; // Tracks value words.
|
||||||
|
uint8_t gc_parser_flags = GC_PARSER_NONE;
|
||||||
|
|
||||||
// Determine if the line is a jogging motion or a normal g-code block.
|
// Determine if the line is a jogging motion or a normal g-code block.
|
||||||
uint8_t is_jog_motion = false;
|
|
||||||
if (line[0] == '$') { // NOTE: `$J=` already parsed when passed to this function.
|
if (line[0] == '$') { // NOTE: `$J=` already parsed when passed to this function.
|
||||||
// Set G1 and G94 enforced modes to ensure accurate error checks.
|
// Set G1 and G94 enforced modes to ensure accurate error checks.
|
||||||
is_jog_motion = true;
|
gc_parser_flags |= GC_PARSER_JOG_MOTION;
|
||||||
gc_block.modal.motion = MOTION_MODE_LINEAR;
|
gc_block.modal.motion = MOTION_MODE_LINEAR;
|
||||||
gc_block.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN;
|
gc_block.modal.feed_rate = FEED_RATE_MODE_UNITS_PER_MIN;
|
||||||
|
#ifdef USE_LINE_NUMBERS
|
||||||
|
gc_block.values.n = JOG_LINE_NUMBER; // Initialize default line number reported during jog.
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------
|
||||||
@ -107,7 +110,7 @@ uint8_t gc_execute_line(char *line)
|
|||||||
float value;
|
float value;
|
||||||
uint8_t int_value = 0;
|
uint8_t int_value = 0;
|
||||||
uint16_t mantissa = 0;
|
uint16_t mantissa = 0;
|
||||||
if (is_jog_motion) { char_counter = 3; } // Start parsing after `$J=`
|
if (gc_parser_flags & GC_PARSER_JOG_MOTION) { char_counter = 3; } // Start parsing after `$J=`
|
||||||
else { char_counter = 0; }
|
else { char_counter = 0; }
|
||||||
|
|
||||||
while (line[char_counter] != 0) { // Loop until no more g-code words in line.
|
while (line[char_counter] != 0) { // Loop until no more g-code words in line.
|
||||||
@ -127,7 +130,7 @@ uint8_t gc_execute_line(char *line)
|
|||||||
// Maybe update this later.
|
// Maybe update this later.
|
||||||
int_value = trunc(value);
|
int_value = trunc(value);
|
||||||
mantissa = round(100*(value - int_value)); // Compute mantissa for Gxx.x commands.
|
mantissa = round(100*(value - int_value)); // Compute mantissa for Gxx.x commands.
|
||||||
// NOTE: Rounding must be used to catch small floating point errors.
|
// NOTE: Rounding must be used to catch small floating point errors.
|
||||||
|
|
||||||
// Check if the g-code word is supported or errors due to modal group violations or has
|
// Check if the g-code word is supported or errors due to modal group violations or has
|
||||||
// been repeated in the g-code block. If ok, update the command or record its value.
|
// been repeated in the g-code block. If ok, update the command or record its value.
|
||||||
@ -381,7 +384,7 @@ uint8_t gc_execute_line(char *line)
|
|||||||
// [2. Set feed rate mode ]: G93 F word missing with G1,G2/3 active, implicitly or explicitly. Feed rate
|
// [2. Set feed rate mode ]: G93 F word missing with G1,G2/3 active, implicitly or explicitly. Feed rate
|
||||||
// is not defined after switching to G94 from G93.
|
// is not defined after switching to G94 from G93.
|
||||||
// NOTE: For jogging, ignore prior feed rate mode. Enforce G94 and check for required F word.
|
// NOTE: For jogging, ignore prior feed rate mode. Enforce G94 and check for required F word.
|
||||||
if (is_jog_motion) {
|
if (gc_parser_flags & GC_PARSER_JOG_MOTION) {
|
||||||
if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); }
|
if (bit_isfalse(value_words,bit(WORD_F))) { FAIL(STATUS_GCODE_UNDEFINED_FEED_RATE); }
|
||||||
if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; }
|
if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; }
|
||||||
} else {
|
} else {
|
||||||
@ -653,9 +656,10 @@ uint8_t gc_execute_line(char *line)
|
|||||||
// [G1 Errors]: 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.
|
// Axis words are optional. If missing, set axis command flag to ignore execution.
|
||||||
if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }
|
if (!axis_words) { axis_command = AXIS_COMMAND_NONE; }
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC:
|
case MOTION_MODE_CW_ARC:
|
||||||
|
gc_parser_flags |= GC_PARSER_ARC_IS_CLOCKWISE; // No break intentional.
|
||||||
|
case MOTION_MODE_CCW_ARC:
|
||||||
// [G2/3 Errors All-Modes]: Feed rate undefined.
|
// [G2/3 Errors All-Modes]: Feed rate undefined.
|
||||||
// [G2/3 Radius-Mode Errors]: No axis words in selected plane. Target point is same as current.
|
// [G2/3 Radius-Mode Errors]: No axis words in selected plane. Target point is same as current.
|
||||||
// [G2/3 Offset-Mode Errors]: No axis words and/or offsets in selected plane. The radius to the current
|
// [G2/3 Offset-Mode Errors]: No axis words and/or offsets in selected plane. The radius to the current
|
||||||
@ -790,8 +794,11 @@ uint8_t gc_execute_line(char *line)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MOTION_MODE_PROBE_TOWARD: case MOTION_MODE_PROBE_TOWARD_NO_ERROR:
|
case MOTION_MODE_PROBE_TOWARD_NO_ERROR: case MOTION_MODE_PROBE_AWAY_NO_ERROR:
|
||||||
case MOTION_MODE_PROBE_AWAY: case MOTION_MODE_PROBE_AWAY_NO_ERROR:
|
gc_parser_flags |= GC_PARSER_PROBE_IS_NO_ERROR; // No break intentional.
|
||||||
|
case MOTION_MODE_PROBE_TOWARD: case MOTION_MODE_PROBE_AWAY:
|
||||||
|
if ((gc_block.modal.motion == MOTION_MODE_PROBE_AWAY) ||
|
||||||
|
(gc_block.modal.motion == MOTION_MODE_PROBE_AWAY_NO_ERROR)) { gc_parser_flags |= GC_PARSER_PROBE_IS_AWAY; }
|
||||||
// [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate
|
// [G38 Errors]: Target is same current. No axis words. Cutter compensation is enabled. Feed rate
|
||||||
// is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning
|
// is undefined. Probe is triggered. NOTE: Probe check moved to probe cycle. Instead of returning
|
||||||
// an error, it issues an alarm to prevent further motion to the probe. It's also done there to
|
// an error, it issues an alarm to prevent further motion to the probe. It's also done there to
|
||||||
@ -807,29 +814,15 @@ uint8_t gc_execute_line(char *line)
|
|||||||
|
|
||||||
// [0. Non-specific error-checks]: Complete unused value words check, i.e. IJK used when in arc
|
// [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.
|
// 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 (gc_parser_flags & GC_PARSER_JOG_MOTION) {
|
||||||
|
// Jogging only uses the F feed rate and XYZ value words. N is valid, but S and T are invalid.
|
||||||
|
bit_false(value_words,(bit(WORD_N)|bit(WORD_F)));
|
||||||
|
} else {
|
||||||
|
bit_false(value_words,(bit(WORD_N)|bit(WORD_F)|bit(WORD_S)|bit(WORD_T))); // Remove single-meaning value words.
|
||||||
|
}
|
||||||
if (axis_command) { 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]
|
if (value_words) { FAIL(STATUS_GCODE_UNUSED_WORDS); } // [Unused words]
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------
|
|
||||||
STEP 3.5ish : EXECUTE JOG!!
|
|
||||||
Intercept jog commands and complete error checking for valid jog commands and execute.
|
|
||||||
NOTE: G-code parser state is not updated, except the position to ensure sequential jog
|
|
||||||
targets are computed correctly. The final parser position after a jog is updated in
|
|
||||||
protocol_execute_realtime() when jogging completes or is canceled.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (is_jog_motion) {
|
|
||||||
// Only distance and unit modal commands and G53 absolute override command are allowed.
|
|
||||||
if (command_words & ~(bit(MODAL_GROUP_G3) | bit(MODAL_GROUP_G6 | bit(MODAL_GROUP_G0))) ) { FAIL(STATUS_INVALID_JOG_COMMAND) };
|
|
||||||
if (!(gc_block.non_modal_command == NON_MODAL_ABSOLUTE_OVERRIDE || gc_block.non_modal_command == NON_MODAL_NO_ACTION)) { FAIL(STATUS_INVALID_JOG_COMMAND); }
|
|
||||||
// NOTE: Feed rate word and axis word checks have already been performed in STEP 3.
|
|
||||||
uint8_t status = jog_execute(&gc_block);
|
|
||||||
if (status == STATUS_OK) { memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); }
|
|
||||||
return(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------------------
|
/* -------------------------------------------------------------------------------------
|
||||||
STEP 4: EXECUTE!!
|
STEP 4: EXECUTE!!
|
||||||
Assumes that all error-checking has been completed and no failure modes exist. We just
|
Assumes that all error-checking has been completed and no failure modes exist. We just
|
||||||
@ -841,6 +834,60 @@ uint8_t gc_execute_line(char *line)
|
|||||||
plan_line_data_t *pl_data = &plan_data;
|
plan_line_data_t *pl_data = &plan_data;
|
||||||
memset(pl_data,0,sizeof(plan_line_data_t)); // Zero pl_data struct
|
memset(pl_data,0,sizeof(plan_line_data_t)); // Zero pl_data struct
|
||||||
|
|
||||||
|
// Intercept jog commands and complete error checking for valid jog commands and execute.
|
||||||
|
// NOTE: G-code parser state is not updated, except the position to ensure sequential jog
|
||||||
|
// targets are computed correctly. The final parser position after a jog is updated in
|
||||||
|
// protocol_execute_realtime() when jogging completes or is canceled.
|
||||||
|
if (gc_parser_flags & GC_PARSER_JOG_MOTION) {
|
||||||
|
// Only distance and unit modal commands and G53 absolute override command are allowed.
|
||||||
|
// NOTE: Feed rate word and axis word checks have already been performed in STEP 3.
|
||||||
|
if (command_words & ~(bit(MODAL_GROUP_G3) | bit(MODAL_GROUP_G6 | bit(MODAL_GROUP_G0))) ) { FAIL(STATUS_INVALID_JOG_COMMAND) };
|
||||||
|
if (!(gc_block.non_modal_command == NON_MODAL_ABSOLUTE_OVERRIDE || gc_block.non_modal_command == NON_MODAL_NO_ACTION)) { FAIL(STATUS_INVALID_JOG_COMMAND); }
|
||||||
|
|
||||||
|
// Initialize planner data to current spindle and coolant modal state.
|
||||||
|
pl_data->spindle_speed = gc_state.spindle_speed;
|
||||||
|
plan_data.condition = (gc_state.modal.spindle | gc_state.modal.coolant);
|
||||||
|
|
||||||
|
uint8_t status = jog_execute(&plan_data, &gc_block);
|
||||||
|
if (status == STATUS_OK) { memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); }
|
||||||
|
return(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If in laser mode, setup laser power based on current and past parser conditions.
|
||||||
|
if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) {
|
||||||
|
if ( !((gc_block.modal.motion == MOTION_MODE_LINEAR) || (gc_block.modal.motion == MOTION_MODE_CW_ARC)
|
||||||
|
|| (gc_block.modal.motion == MOTION_MODE_CCW_ARC)) ) {
|
||||||
|
gc_parser_flags |= GC_PARSER_LASER_DISABLE;
|
||||||
|
}
|
||||||
|
// M3 constant power laser requires planner syncs to update the laser in certain conditions.
|
||||||
|
// certain conditions.
|
||||||
|
if (gc_state.modal.spindle == SPINDLE_ENABLE_CW) {
|
||||||
|
if ((gc_state.modal.motion == MOTION_MODE_LINEAR) || (gc_state.modal.motion == MOTION_MODE_CW_ARC)
|
||||||
|
|| (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) {
|
||||||
|
if (gc_parser_flags & GC_PARSER_LASER_DISABLE) {
|
||||||
|
gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC; // Change from G1/2/3 motion mode.
|
||||||
|
} else {
|
||||||
|
// Any non-motion block with M3 enabled and G1/2/3 modal state requires a sync when
|
||||||
|
// the spindle speed changes. It is otherwise passed onto the planner.
|
||||||
|
if (gc_state.spindle_speed != gc_block.values.s) {
|
||||||
|
// NOTE: A G1/2/3 motion will always have axis words and be in AXIS_COMMAND_MOTION_MODE.
|
||||||
|
// A non-motion G1 or any non-modal command using axis words will alter axis_command.
|
||||||
|
if (!(axis_words) || (axis_command != AXIS_COMMAND_MOTION_MODE )) {
|
||||||
|
gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// When changing to a G1 motion mode without axis words from a non-G1/2/3 motion mode.
|
||||||
|
if (bit_isfalse(gc_parser_flags,GC_PARSER_LASER_DISABLE)) {
|
||||||
|
if (!(axis_words) || (axis_command != AXIS_COMMAND_MOTION_MODE )) {
|
||||||
|
gc_parser_flags |= GC_PARSER_LASER_FORCE_SYNC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// [0. Non-specific/common error-checks and miscellaneous setup]:
|
// [0. Non-specific/common error-checks and miscellaneous setup]:
|
||||||
// NOTE: If no line number is present, the value is zero.
|
// NOTE: If no line number is present, the value is zero.
|
||||||
gc_state.line_number = gc_block.values.n;
|
gc_state.line_number = gc_block.values.n;
|
||||||
@ -859,24 +906,22 @@ uint8_t gc_execute_line(char *line)
|
|||||||
pl_data->feed_rate = gc_state.feed_rate; // Record data for planner use.
|
pl_data->feed_rate = gc_state.feed_rate; // Record data for planner use.
|
||||||
|
|
||||||
// [4. Set spindle speed ]:
|
// [4. Set spindle speed ]:
|
||||||
if (gc_state.spindle_speed != gc_block.values.s) {
|
if ((gc_state.spindle_speed != gc_block.values.s) || bit_istrue(gc_parser_flags,GC_PARSER_LASER_FORCE_SYNC)) {
|
||||||
#ifdef VARIABLE_SPINDLE
|
if (gc_state.modal.spindle != SPINDLE_DISABLE) {
|
||||||
if (gc_state.modal.spindle != SPINDLE_DISABLE) {
|
#ifdef VARIABLE_SPINDLE
|
||||||
if ( bit_istrue(settings.flags, BITFLAG_LASER_MODE) ) {
|
if (bit_istrue(gc_parser_flags,GC_PARSER_LASER_DISABLE)) {
|
||||||
// Do not stop motion if in laser mode and a G1, G2, or G3 motion is being executed.
|
spindle_sync(gc_state.modal.spindle, 0.0);
|
||||||
if (!( (axis_command == AXIS_COMMAND_MOTION_MODE) && ((gc_block.modal.motion == MOTION_MODE_LINEAR ) || (gc_block.modal.motion == MOTION_MODE_CW_ARC) || (gc_block.modal.motion == MOTION_MODE_CCW_ARC)) ) ) {
|
} else { spindle_sync(gc_state.modal.spindle, gc_block.values.s); }
|
||||||
spindle_sync(gc_state.modal.spindle, gc_block.values.s);
|
#else
|
||||||
}
|
spindle_sync(gc_state.modal.spindle, 0.0);
|
||||||
} else {
|
#endif
|
||||||
spindle_sync(gc_state.modal.spindle, gc_block.values.s);
|
}
|
||||||
}
|
gc_state.spindle_speed = gc_block.values.s; // Update spindle speed state.
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (gc_state.modal.spindle != SPINDLE_DISABLE) { spindle_sync(gc_state.modal.spindle, 0.0); }
|
|
||||||
#endif
|
|
||||||
gc_state.spindle_speed = gc_block.values.s;
|
|
||||||
}
|
}
|
||||||
pl_data->spindle_speed = gc_state.spindle_speed; // Record data for planner use.
|
// NOTE: Pass zero spindle speed for all restricted laser motions.
|
||||||
|
if (bit_isfalse(gc_parser_flags,GC_PARSER_LASER_DISABLE)) {
|
||||||
|
pl_data->spindle_speed = gc_state.spindle_speed; // Record data for planner use.
|
||||||
|
} // else { pl_data->spindle_speed = 0.0; } // Initialized as zero already.
|
||||||
|
|
||||||
// [5. Select tool ]: NOT SUPPORTED. Only tracks tool value.
|
// [5. Select tool ]: NOT SUPPORTED. Only tracks tool value.
|
||||||
gc_state.tool = gc_block.values.t;
|
gc_state.tool = gc_block.values.t;
|
||||||
@ -886,7 +931,9 @@ uint8_t gc_execute_line(char *line)
|
|||||||
// [7. Spindle control ]:
|
// [7. Spindle control ]:
|
||||||
if (gc_state.modal.spindle != gc_block.modal.spindle) {
|
if (gc_state.modal.spindle != gc_block.modal.spindle) {
|
||||||
// Update spindle control and apply spindle speed when enabling it in this block.
|
// Update spindle control and apply spindle speed when enabling it in this block.
|
||||||
spindle_sync(gc_block.modal.spindle, gc_state.spindle_speed);
|
// NOTE: All spindle state changes are synced, even in laser mode. Also, pl_data,
|
||||||
|
// rather than gc_state, is used to manage laser state for non-laser motions.
|
||||||
|
spindle_sync(gc_block.modal.spindle, pl_data->spindle_speed);
|
||||||
gc_state.modal.spindle = gc_block.modal.spindle;
|
gc_state.modal.spindle = gc_block.modal.spindle;
|
||||||
}
|
}
|
||||||
pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use.
|
pl_data->condition |= gc_state.modal.spindle; // Set condition flag for planner use.
|
||||||
@ -993,23 +1040,16 @@ uint8_t gc_execute_line(char *line)
|
|||||||
pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag.
|
pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag.
|
||||||
mc_line(gc_block.values.xyz, pl_data);
|
mc_line(gc_block.values.xyz, pl_data);
|
||||||
} else if ((gc_state.modal.motion == MOTION_MODE_CW_ARC) || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) {
|
} else if ((gc_state.modal.motion == MOTION_MODE_CW_ARC) || (gc_state.modal.motion == MOTION_MODE_CCW_ARC)) {
|
||||||
uint8_t is_clockwise_arc;
|
|
||||||
if (gc_state.modal.motion == MOTION_MODE_CW_ARC) { is_clockwise_arc = true; }
|
|
||||||
else { is_clockwise_arc = false; }
|
|
||||||
mc_arc(gc_block.values.xyz, pl_data, gc_state.position, gc_block.values.ijk, gc_block.values.r,
|
mc_arc(gc_block.values.xyz, pl_data, gc_state.position, gc_block.values.ijk, gc_block.values.r,
|
||||||
axis_0, axis_1, axis_linear, is_clockwise_arc);
|
axis_0, axis_1, axis_linear, bit_istrue(gc_parser_flags,GC_PARSER_ARC_IS_CLOCKWISE));
|
||||||
} else {
|
} else {
|
||||||
// NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So
|
// NOTE: gc_block.values.xyz is returned from mc_probe_cycle with the updated position value. So
|
||||||
// upon a successful probing cycle, the machine position and the returned value should be the same.
|
// upon a successful probing cycle, the machine position and the returned value should be the same.
|
||||||
#ifndef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES
|
#ifndef ALLOW_FEED_OVERRIDE_DURING_PROBE_CYCLES
|
||||||
pl_data->condition |= PL_COND_FLAG_NO_FEED_OVERRIDE;
|
pl_data->condition |= PL_COND_FLAG_NO_FEED_OVERRIDE;
|
||||||
#endif
|
#endif
|
||||||
uint8_t is_probe_away = false;
|
gc_update_pos = mc_probe_cycle(gc_block.values.xyz, pl_data, gc_parser_flags);
|
||||||
uint8_t is_no_error = false;
|
}
|
||||||
if ((gc_state.modal.motion == MOTION_MODE_PROBE_AWAY) || (gc_state.modal.motion == MOTION_MODE_PROBE_AWAY_NO_ERROR)) { is_probe_away = true; }
|
|
||||||
if ((gc_state.modal.motion == MOTION_MODE_PROBE_TOWARD_NO_ERROR) || (gc_state.modal.motion == MOTION_MODE_PROBE_AWAY_NO_ERROR)) { is_no_error = true; }
|
|
||||||
gc_update_pos = mc_probe_cycle(gc_block.values.xyz, pl_data, is_probe_away, is_no_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
@ -1020,7 +1060,6 @@ uint8_t gc_execute_line(char *line)
|
|||||||
gc_sync_position(); // gc_state.position[] = sys_position
|
gc_sync_position(); // gc_state.position[] = sys_position
|
||||||
} // == GC_UPDATE_POS_NONE
|
} // == GC_UPDATE_POS_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// [21. Program flow ]:
|
// [21. Program flow ]:
|
||||||
|
11
grbl/gcode.h
11
grbl/gcode.h
@ -145,7 +145,7 @@
|
|||||||
#define WORD_Z 12
|
#define WORD_Z 12
|
||||||
|
|
||||||
// Define g-code parser position updating flags
|
// Define g-code parser position updating flags
|
||||||
#define GC_UPDATE_POS_TARGET 0
|
#define GC_UPDATE_POS_TARGET 0 // Must be zero
|
||||||
#define GC_UPDATE_POS_SYSTEM 1
|
#define GC_UPDATE_POS_SYSTEM 1
|
||||||
#define GC_UPDATE_POS_NONE 2
|
#define GC_UPDATE_POS_NONE 2
|
||||||
|
|
||||||
@ -160,6 +160,15 @@
|
|||||||
#define GC_PROBE_CHECK_MODE GC_UPDATE_POS_TARGET
|
#define GC_PROBE_CHECK_MODE GC_UPDATE_POS_TARGET
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Define gcode parser flags for handling special cases.
|
||||||
|
#define GC_PARSER_NONE 0 // Must be zero.
|
||||||
|
#define GC_PARSER_JOG_MOTION bit(0)
|
||||||
|
#define GC_PARSER_CHECK_MANTISSA bit(1)
|
||||||
|
#define GC_PARSER_ARC_IS_CLOCKWISE bit(2)
|
||||||
|
#define GC_PARSER_PROBE_IS_AWAY bit(3)
|
||||||
|
#define GC_PARSER_PROBE_IS_NO_ERROR bit(4)
|
||||||
|
#define GC_PARSER_LASER_FORCE_SYNC bit(5)
|
||||||
|
#define GC_PARSER_LASER_DISABLE bit(6)
|
||||||
|
|
||||||
|
|
||||||
// NOTE: When this struct is zeroed, the above defines set the defaults for the system.
|
// NOTE: When this struct is zeroed, the above defines set the defaults for the system.
|
||||||
|
@ -22,8 +22,8 @@
|
|||||||
#define grbl_h
|
#define grbl_h
|
||||||
|
|
||||||
// Grbl versioning system
|
// Grbl versioning system
|
||||||
#define GRBL_VERSION "1.1d"
|
#define GRBL_VERSION "1.1e"
|
||||||
#define GRBL_VERSION_BUILD "20161112"
|
#define GRBL_VERSION_BUILD "20161203"
|
||||||
|
|
||||||
// Define standard libraries used by Grbl.
|
// Define standard libraries used by Grbl.
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
|
12
grbl/jog.c
12
grbl/jog.c
@ -22,18 +22,14 @@
|
|||||||
|
|
||||||
|
|
||||||
// Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog.
|
// Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog.
|
||||||
uint8_t jog_execute(parser_block_t *gc_block)
|
uint8_t jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block)
|
||||||
{
|
{
|
||||||
// Initialize planner data struct for motion blocks.
|
// Initialize planner data struct for jogging motions.
|
||||||
// NOTE: Spindle and coolant are allowed to fully function with overrides during a jog.
|
// NOTE: Spindle and coolant are allowed to fully function with overrides during a jog.
|
||||||
plan_line_data_t plan_data;
|
|
||||||
plan_line_data_t *pl_data = &plan_data;
|
|
||||||
memset(pl_data,0,sizeof(plan_line_data_t)); // Zero pl_data struct
|
|
||||||
pl_data->feed_rate = gc_block->values.f;
|
pl_data->feed_rate = gc_block->values.f;
|
||||||
pl_data->spindle_speed = gc_block->values.s; // Continue current spindle and coolant condition.
|
pl_data->condition |= PL_COND_FLAG_NO_FEED_OVERRIDE;
|
||||||
plan_data.condition = (PL_COND_FLAG_NO_FEED_OVERRIDE | gc_block->modal.spindle | gc_block->modal.coolant);
|
|
||||||
#ifdef USE_LINE_NUMBERS
|
#ifdef USE_LINE_NUMBERS
|
||||||
pl_data->line_number = JOG_LINE_NUMBER;
|
pl_data->line_number = gc_block.values.n;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) {
|
if (bit_istrue(settings.flags,BITFLAG_SOFT_LIMIT_ENABLE)) {
|
||||||
|
@ -27,6 +27,6 @@
|
|||||||
#define JOG_LINE_NUMBER 0
|
#define JOG_LINE_NUMBER 0
|
||||||
|
|
||||||
// Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog.
|
// Sets up valid jog motion received from g-code parser, checks for soft-limits, and executes the jog.
|
||||||
uint8_t jog_execute(parser_block_t *gc_block);
|
uint8_t jog_execute(plan_line_data_t *pl_data, parser_block_t *gc_block);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -246,7 +246,7 @@ void mc_homing_cycle(uint8_t cycle_mask)
|
|||||||
|
|
||||||
// Perform tool length probe cycle. Requires probe switch.
|
// Perform tool length probe cycle. Requires probe switch.
|
||||||
// NOTE: Upon probe failure, the program will be stopped and placed into ALARM state.
|
// NOTE: Upon probe failure, the program will be stopped and placed into ALARM state.
|
||||||
uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t is_probe_away, uint8_t is_no_error)
|
uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t parser_flags)
|
||||||
{
|
{
|
||||||
// TODO: Need to update this cycle so it obeys a non-auto cycle start.
|
// TODO: Need to update this cycle so it obeys a non-auto cycle start.
|
||||||
if (sys.state == STATE_CHECK_MODE) { return(GC_PROBE_CHECK_MODE); }
|
if (sys.state == STATE_CHECK_MODE) { return(GC_PROBE_CHECK_MODE); }
|
||||||
@ -256,6 +256,8 @@ uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t is_prob
|
|||||||
if (sys.abort) { return(GC_PROBE_ABORT); } // Return if system reset has been issued.
|
if (sys.abort) { return(GC_PROBE_ABORT); } // Return if system reset has been issued.
|
||||||
|
|
||||||
// Initialize probing control variables
|
// Initialize probing control variables
|
||||||
|
uint8_t is_probe_away = bit_istrue(parser_flags,GC_PARSER_PROBE_IS_AWAY);
|
||||||
|
uint8_t is_no_error = bit_istrue(parser_flags,GC_PARSER_PROBE_IS_NO_ERROR);
|
||||||
sys.probe_succeeded = false; // Re-initialize probe history before beginning cycle.
|
sys.probe_succeeded = false; // Re-initialize probe history before beginning cycle.
|
||||||
probe_configure_invert_mask(is_probe_away);
|
probe_configure_invert_mask(is_probe_away);
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ void mc_dwell(float seconds);
|
|||||||
void mc_homing_cycle(uint8_t cycle_mask);
|
void mc_homing_cycle(uint8_t cycle_mask);
|
||||||
|
|
||||||
// Perform tool length probe cycle. Requires probe switch.
|
// Perform tool length probe cycle. Requires probe switch.
|
||||||
uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t is_probe_away, uint8_t is_no_error);
|
uint8_t mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t parser_flags);
|
||||||
|
|
||||||
// Plans and executes the single special motion case for parking. Independent of main planner buffer.
|
// Plans and executes the single special motion case for parking. Independent of main planner buffer.
|
||||||
void mc_parking_motion(float *parking_target, plan_line_data_t *pl_data);
|
void mc_parking_motion(float *parking_target, plan_line_data_t *pl_data);
|
||||||
|
@ -331,8 +331,15 @@ uint8_t plan_buffer_line(float *target, plan_line_data_t *pl_data)
|
|||||||
uint8_t idx;
|
uint8_t idx;
|
||||||
|
|
||||||
// Copy position data based on type of motion being planned.
|
// Copy position data based on type of motion being planned.
|
||||||
if (block->condition & PL_COND_FLAG_SYSTEM_MOTION) { memcpy(position_steps, sys_position, sizeof(sys_position)); }
|
if (block->condition & PL_COND_FLAG_SYSTEM_MOTION) {
|
||||||
else { memcpy(position_steps, pl.position, sizeof(pl.position)); }
|
#ifdef COREXY
|
||||||
|
position_steps[X_AXIS] = system_convert_corexy_to_x_axis_steps(sys_position);
|
||||||
|
position_steps[Y_AXIS] = system_convert_corexy_to_y_axis_steps(sys_position);
|
||||||
|
position_steps[Z_AXIS] = sys_position[Z_AXIS];
|
||||||
|
#else
|
||||||
|
memcpy(position_steps, sys_position, sizeof(sys_position));
|
||||||
|
#endif
|
||||||
|
} else { memcpy(position_steps, pl.position, sizeof(pl.position)); }
|
||||||
|
|
||||||
#ifdef COREXY
|
#ifdef COREXY
|
||||||
target_steps[A_MOTOR] = lround(target[A_MOTOR]*settings.steps_per_mm[A_MOTOR]);
|
target_steps[A_MOTOR] = lround(target[A_MOTOR]*settings.steps_per_mm[A_MOTOR]);
|
||||||
|
@ -530,6 +530,11 @@ static void protocol_exec_rt_suspend()
|
|||||||
restore_condition = block->condition;
|
restore_condition = block->condition;
|
||||||
restore_spindle_speed = block->spindle_speed;
|
restore_spindle_speed = block->spindle_speed;
|
||||||
}
|
}
|
||||||
|
#ifdef DISABLE_LASER_DURING_HOLD
|
||||||
|
if (bit_istrue(settings.flags,BITFLAG_LASER_MODE)) {
|
||||||
|
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
if (block == NULL) { restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant); }
|
if (block == NULL) { restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant); }
|
||||||
else { restore_condition = block->condition; }
|
else { restore_condition = block->condition; }
|
||||||
|
@ -295,7 +295,7 @@ void report_grbl_settings() {
|
|||||||
printPgmString(PSTR(" (soft limits, bool)\r\n$21=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
|
printPgmString(PSTR(" (soft limits, bool)\r\n$21=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
|
||||||
printPgmString(PSTR(" (hard limits, bool)\r\n$22=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
|
printPgmString(PSTR(" (hard limits, bool)\r\n$22=")); print_uint8_base10(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
|
||||||
printPgmString(PSTR(" (homing cycle, bool)\r\n$23=")); print_uint8_base10(settings.homing_dir_mask);
|
printPgmString(PSTR(" (homing cycle, bool)\r\n$23=")); print_uint8_base10(settings.homing_dir_mask);
|
||||||
printPgmString(PSTR(" (homing dir invert mask\r\n$24=")); printFloat(settings.homing_feed_rate,N_DECIMAL_SETTINGVALUE);
|
printPgmString(PSTR(" (homing dir invert mask)\r\n$24=")); printFloat(settings.homing_feed_rate,N_DECIMAL_SETTINGVALUE);
|
||||||
printPgmString(PSTR(" (homing feed, mm/min)\r\n$25=")); printFloat(settings.homing_seek_rate,N_DECIMAL_SETTINGVALUE);
|
printPgmString(PSTR(" (homing feed, mm/min)\r\n$25=")); printFloat(settings.homing_seek_rate,N_DECIMAL_SETTINGVALUE);
|
||||||
printPgmString(PSTR(" (homing seek, mm/min)\r\n$26=")); print_uint8_base10(settings.homing_debounce_delay);
|
printPgmString(PSTR(" (homing seek, mm/min)\r\n$26=")); print_uint8_base10(settings.homing_debounce_delay);
|
||||||
printPgmString(PSTR(" (homing debounce, msec)\r\n$27=")); printFloat(settings.homing_pulloff,N_DECIMAL_SETTINGVALUE);
|
printPgmString(PSTR(" (homing debounce, msec)\r\n$27=")); printFloat(settings.homing_pulloff,N_DECIMAL_SETTINGVALUE);
|
||||||
|
@ -262,6 +262,7 @@ uint8_t settings_store_global_setting(uint8_t parameter, float value) {
|
|||||||
case 13:
|
case 13:
|
||||||
if (int_value) { settings.flags |= BITFLAG_REPORT_INCHES; }
|
if (int_value) { settings.flags |= BITFLAG_REPORT_INCHES; }
|
||||||
else { settings.flags &= ~BITFLAG_REPORT_INCHES; }
|
else { settings.flags &= ~BITFLAG_REPORT_INCHES; }
|
||||||
|
system_flag_wco_change(); // Make sure WCO is immediately updated.
|
||||||
break;
|
break;
|
||||||
case 20:
|
case 20:
|
||||||
if (int_value) {
|
if (int_value) {
|
||||||
|
@ -189,10 +189,10 @@ void spindle_stop()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef VARIABLE_SPINDLE
|
#ifdef VARIABLE_SPINDLE
|
||||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
// NOTE: Assumes all calls to this function is when Grbl is not moving or must remain off.
|
||||||
// NOTE: Assumes all calls to this function is when Grbl is not moving or must remain off.
|
if (settings.flags & BITFLAG_LASER_MODE) {
|
||||||
if (settings.flags & BITFLAG_LASER_MODE) { rpm = 0.0; } // TODO: May need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE);
|
if (state == SPINDLE_ENABLE_CCW) { rpm = 0.0; } // TODO: May need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE);
|
||||||
#endif
|
}
|
||||||
spindle_set_speed(spindle_compute_pwm_value(rpm));
|
spindle_set_speed(spindle_compute_pwm_value(rpm));
|
||||||
#else
|
#else
|
||||||
// NOTE: Without variable spindle, the enable bit should just turn on or off, regardless
|
// NOTE: Without variable spindle, the enable bit should just turn on or off, regardless
|
||||||
|
@ -62,11 +62,7 @@ typedef struct {
|
|||||||
uint32_t step_event_count;
|
uint32_t step_event_count;
|
||||||
uint8_t direction_bits;
|
uint8_t direction_bits;
|
||||||
#ifdef VARIABLE_SPINDLE
|
#ifdef VARIABLE_SPINDLE
|
||||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
uint8_t is_pwm_rate_adjusted; // Tracks motions that require constant laser power/rate
|
||||||
uint8_t is_pwm_rate_adjusted; // Tracks motions that require constant laser power/rate
|
|
||||||
#else
|
|
||||||
uint8_t spindle_pwm;
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
} st_block_t;
|
} st_block_t;
|
||||||
static st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE-1];
|
static st_block_t st_block_buffer[SEGMENT_BUFFER_SIZE-1];
|
||||||
@ -84,8 +80,8 @@ typedef struct {
|
|||||||
#else
|
#else
|
||||||
uint8_t prescaler; // Without AMASS, a prescaler is required to adjust for slow timing.
|
uint8_t prescaler; // Without AMASS, a prescaler is required to adjust for slow timing.
|
||||||
#endif
|
#endif
|
||||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
#ifdef VARIABLE_SPINDLE
|
||||||
uint8_t rate_adjusted_pwm;
|
uint8_t spindle_pwm;
|
||||||
#endif
|
#endif
|
||||||
} segment_t;
|
} segment_t;
|
||||||
static segment_t segment_buffer[SEGMENT_BUFFER_SIZE];
|
static segment_t segment_buffer[SEGMENT_BUFFER_SIZE];
|
||||||
@ -159,8 +155,9 @@ typedef struct {
|
|||||||
float accelerate_until; // Acceleration ramp end measured from end of block (mm)
|
float accelerate_until; // Acceleration ramp end measured from end of block (mm)
|
||||||
float decelerate_after; // Deceleration ramp start measured from end of block (mm)
|
float decelerate_after; // Deceleration ramp start measured from end of block (mm)
|
||||||
|
|
||||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
#ifdef VARIABLE_SPINDLE
|
||||||
float inv_rate; // Used by PWM laser mode to speed up segment calculations.
|
float inv_rate; // Used by PWM laser mode to speed up segment calculations.
|
||||||
|
uint8_t current_spindle_pwm;
|
||||||
#endif
|
#endif
|
||||||
} st_prep_t;
|
} st_prep_t;
|
||||||
static st_prep_t prep;
|
static st_prep_t prep;
|
||||||
@ -360,20 +357,14 @@ ISR(TIMER1_COMPA_vect)
|
|||||||
|
|
||||||
#ifdef VARIABLE_SPINDLE
|
#ifdef VARIABLE_SPINDLE
|
||||||
// Set real-time spindle output as segment is loaded, just prior to the first step.
|
// Set real-time spindle output as segment is loaded, just prior to the first step.
|
||||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
spindle_set_speed(st.exec_segment->spindle_pwm);
|
||||||
spindle_set_speed(st.exec_segment->rate_adjusted_pwm);
|
|
||||||
#else
|
|
||||||
spindle_set_speed(st.exec_block->spindle_pwm);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Segment buffer empty. Shutdown.
|
// Segment buffer empty. Shutdown.
|
||||||
st_go_idle();
|
st_go_idle();
|
||||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
// Ensure pwm is set properly upon completion of rate-controlled motion.
|
||||||
// Ensure pwm is set properly upon completion of rate-controlled motion.
|
if (st.exec_block->is_pwm_rate_adjusted) { spindle_set_speed(SPINDLE_PWM_OFF_VALUE); }
|
||||||
if (st.exec_block->is_pwm_rate_adjusted) { spindle_set_speed(SPINDLE_PWM_OFF_VALUE); }
|
|
||||||
#endif
|
|
||||||
system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end
|
system_set_exec_state_flag(EXEC_CYCLE_STOP); // Flag main program for cycle end
|
||||||
return; // Nothing to do but exit.
|
return; // Nothing to do but exit.
|
||||||
}
|
}
|
||||||
@ -664,16 +655,16 @@ void st_prep_buffer()
|
|||||||
prep.current_speed = sqrt(pl_block->entry_speed_sqr);
|
prep.current_speed = sqrt(pl_block->entry_speed_sqr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
// Setup laser mode variables. PWM rate adjusted motions will always complete a motion with the
|
||||||
// Setup laser mode variables. PWM rate adjusted motions will always complete a motion with the
|
// spindle off.
|
||||||
// spindle off.
|
st_prep_block->is_pwm_rate_adjusted = false;
|
||||||
st_prep_block->is_pwm_rate_adjusted = false;
|
if (settings.flags & BITFLAG_LASER_MODE) {
|
||||||
if (settings.flags & BITFLAG_LASER_MODE) {
|
if (pl_block->condition & PL_COND_FLAG_SPINDLE_CCW) {
|
||||||
// Pre-compute inverse programmed rate to speed up PWM updating per step segment.
|
// Pre-compute inverse programmed rate to speed up PWM updating per step segment.
|
||||||
prep.inv_rate = 1.0/pl_block->programmed_rate;
|
prep.inv_rate = 1.0/pl_block->programmed_rate;
|
||||||
if (!(pl_block->condition & PL_COND_MOTION_MASK)) { st_prep_block->is_pwm_rate_adjusted = true; }
|
st_prep_block->is_pwm_rate_adjusted = true;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------------
|
||||||
@ -881,32 +872,23 @@ void st_prep_buffer()
|
|||||||
/* -----------------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------------
|
||||||
Compute spindle speed PWM output for step segment
|
Compute spindle speed PWM output for step segment
|
||||||
*/
|
*/
|
||||||
#ifdef LASER_CONSTANT_POWER_PER_RATE
|
|
||||||
if (st_prep_block->is_pwm_rate_adjusted || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM)) {
|
if (st_prep_block->is_pwm_rate_adjusted || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM)) {
|
||||||
if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) {
|
if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) {
|
||||||
float rpm = pl_block->spindle_speed;
|
float rpm = pl_block->spindle_speed;
|
||||||
// NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate.
|
// NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate.
|
||||||
if (st_prep_block->is_pwm_rate_adjusted) { rpm *= (prep.current_speed * prep.inv_rate); }
|
if (st_prep_block->is_pwm_rate_adjusted) { rpm *= (prep.current_speed * prep.inv_rate); }
|
||||||
// If current_speed is zero, then may need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE)
|
// If current_speed is zero, then may need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE)
|
||||||
// but this would be instantaneous only and during a motion. May not matter at all.
|
// but this would be instantaneous only and during a motion. May not matter at all.
|
||||||
prep_segment->rate_adjusted_pwm = spindle_compute_pwm_value(rpm);
|
prep.current_spindle_pwm = spindle_compute_pwm_value(rpm);
|
||||||
} else {
|
} else {
|
||||||
sys.spindle_speed = 0.0;
|
sys.spindle_speed = 0.0;
|
||||||
prep_segment->rate_adjusted_pwm = SPINDLE_PWM_OFF_VALUE;
|
prep.current_spindle_pwm = SPINDLE_PWM_OFF_VALUE;
|
||||||
}
|
|
||||||
bit_false(sys.step_control,STEP_CONTROL_UPDATE_SPINDLE_PWM);
|
|
||||||
}
|
}
|
||||||
#else
|
bit_false(sys.step_control,STEP_CONTROL_UPDATE_SPINDLE_PWM);
|
||||||
if (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_PWM) {
|
}
|
||||||
if (pl_block->condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)) {
|
prep_segment->spindle_pwm = prep.current_spindle_pwm; // Reload segment PWM value
|
||||||
st_prep_block->spindle_pwm = spindle_compute_pwm_value(pl_block->spindle_speed);
|
|
||||||
} else {
|
|
||||||
sys.spindle_speed = 0.0;
|
|
||||||
st_prep_block->spindle_pwm = SPINDLE_PWM_OFF_VALUE;
|
|
||||||
}
|
|
||||||
bit_false(sys.step_control,STEP_CONTROL_UPDATE_SPINDLE_PWM);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* -----------------------------------------------------------------------------------
|
/* -----------------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user