v1.1b: Tweaked Bf reports, jogging doc, saved another 160 bytes, minor bug fixes
- Increment to v1.1b due to status report tweak. - Tweaked the buffer state status reports to show bytes and blocks available, rather than in use. This does not require knowing the buffer sizes beforehand. It’s implicit. - Also, since buffer states are not used by most devs (after inquiries), it is no longer enabled by default and a status mask option was added for this. - Fixed some typos and updated for the report tweak in the documentation. - Wrote a joystick implementation concept in the jogging markdown document. Outlines how to get a low-latency feel to a joystick (and other input devices). - Removed XON/XOFF support. It’s not used by anyone because of its inherent problems. Remains in older versions for reference. - Added a compile option on how to handle the probe position during a check mode. - Fixed a jogging bug. If G93 is the modal state before a jogging motion, the feed rate did not get calculated correctly. Fixed the issue. - Refactored some code to save another 160+ bytes. Included an improved float vector comparison macro and reducing a few large and repetitive function calls. - Fixed a probing bug (existing in v0.9 too) where the target positions were not set correct and error handling was improper.
This commit is contained in:
@ -254,10 +254,10 @@
|
||||
// NOTE: This feature is new and experimental. Make sure the GUI you are using supports this mode.
|
||||
#define REPORT_GUI_MODE // Default enabled. Comment to disable.
|
||||
|
||||
// The status report change for Grbl v1.0 and after also removed the ability to disable/enable data fields
|
||||
// from the report. This caused issues for GUI developers, who've had to manage several scenarios and
|
||||
// configurations. The increased efficiency of the new reporting style allows for all data fields to be
|
||||
// sent without potential performance issues.
|
||||
// The status report change for Grbl v1.0 and after also removed the ability to disable/enable most data
|
||||
// fields from the report. This caused issues for GUI developers, who've had to manage several scenarios
|
||||
// and configurations. The increased efficiency of the new reporting style allows for all data fields to
|
||||
// be sent without potential performance issues.
|
||||
// NOTE: The options below are here only provide a way to disable certain data fields if a unique
|
||||
// situation demands it, but be aware GUIs may depend on this data. If disabled, it may not be compatible.
|
||||
#define REPORT_FIELD_BUFFER_STATE // Default enabled. Comment to disable.
|
||||
@ -453,16 +453,6 @@
|
||||
// #define RX_BUFFER_SIZE 128 // (1-254) Uncomment to override defaults in serial.h
|
||||
// #define TX_BUFFER_SIZE 90 // (1-254)
|
||||
|
||||
// Toggles XON/XOFF software flow control for serial communications. Not officially supported
|
||||
// due to problems involving the Atmega8U2 USB-to-serial chips on current Arduinos. The firmware
|
||||
// on these chips do not support XON/XOFF flow control characters and the intermediate buffer
|
||||
// in the chips cause latency and overflow problems with standard terminal programs. However,
|
||||
// using specifically-programmed UI's to manage this latency problem has been confirmed to work.
|
||||
// As well as, older FTDI FT232RL-based Arduinos(Duemilanove) are known to work with standard
|
||||
// terminal programs since their firmware correctly manage these XON/XOFF characters. In any
|
||||
// case, please report any successes to grbl administrators!
|
||||
// #define ENABLE_XONXOFF // Default disabled. Uncomment to enable.
|
||||
|
||||
// A simple software debouncing feature for hard limit switches. When enabled, the interrupt
|
||||
// monitoring the hard limit switch pins will enable the Arduino's watchdog timer to re-check
|
||||
// the limit pin state after a delay of about 32msec. This can help with CNC machines with
|
||||
@ -472,6 +462,10 @@
|
||||
// work well and are cheap to find) and wire in a low-pass circuit into each limit pin.
|
||||
// #define ENABLE_SOFTWARE_DEBOUNCE // Default disabled. Uncomment to enable.
|
||||
|
||||
// Configures the position after a probing cycle during Grbl's check mode. Disabled sets
|
||||
// the position to the probe target, when enabled sets the position to the start position.
|
||||
// #define SET_CHECK_MODE_PROBE_TO_START // Default disabled. Uncomment to enable.
|
||||
|
||||
// Force Grbl to check the state of the hard limit switches when the processor detects a pin
|
||||
// change inside the hard limit ISR routine. By default, Grbl will trigger the hard limits
|
||||
// alarm upon any pin change, since bouncing switches can cause a state check like this to
|
||||
|
@ -47,7 +47,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK 0
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // false
|
||||
@ -89,7 +89,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_AXIS)|(1<<Z_AXIS))
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // true
|
||||
@ -134,7 +134,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_AXIS)|(1<<Z_AXIS))
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // false
|
||||
@ -179,7 +179,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<X_AXIS)|(1<<Z_AXIS))
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // false
|
||||
@ -223,7 +223,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<X_AXIS)|(1<<Z_AXIS))
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.01 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // false
|
||||
@ -268,7 +268,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<X_AXIS)|(1<<Y_AXIS))
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // false
|
||||
@ -313,7 +313,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<X_AXIS)|(1<<Y_AXIS))
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // false
|
||||
@ -356,7 +356,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK ((1<<Y_AXIS))
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // false
|
||||
@ -395,7 +395,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK 0
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // false
|
||||
@ -434,7 +434,7 @@
|
||||
#define DEFAULT_STEPPING_INVERT_MASK 0
|
||||
#define DEFAULT_DIRECTION_INVERT_MASK 0
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-254, 255 keeps steppers enabled)
|
||||
#define DEFAULT_STATUS_REPORT_MASK 255 // All enabled
|
||||
#define DEFAULT_STATUS_REPORT_MASK 1 // MPos enabled
|
||||
#define DEFAULT_JUNCTION_DEVIATION 0.01 // mm
|
||||
#define DEFAULT_ARC_TOLERANCE 0.002 // mm
|
||||
#define DEFAULT_REPORT_INCHES 0 // false
|
||||
|
134
grbl/gcode.c
134
grbl/gcode.c
@ -57,15 +57,6 @@ void gc_sync_position()
|
||||
}
|
||||
|
||||
|
||||
static uint8_t gc_check_same_position(float *pos_a, float *pos_b)
|
||||
{
|
||||
uint8_t idx;
|
||||
for (idx=0; idx<N_AXIS; idx++) {
|
||||
if (pos_a[idx] != pos_b[idx]) { return(false); }
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
// 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. In this function, all units and positions are converted and
|
||||
@ -430,35 +421,40 @@ 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
|
||||
// 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_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]
|
||||
// NOTE: For jogging, ignore prior feed rate mode. Enforce G94 and check for required F word.
|
||||
if (is_jog_motion) {
|
||||
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; }
|
||||
} else {
|
||||
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_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]
|
||||
}
|
||||
}
|
||||
}
|
||||
// NOTE: It seems redundant to check for an F word to be passed after switching from G94 to G93. We would
|
||||
// accomplish the exact same thing if the feed rate value is always reset to zero and undefined after each
|
||||
// inverse time block, since the commands that use this value already perform undefined checks. This would
|
||||
// also allow other commands, following this switch, to execute and not error out needlessly. This code is
|
||||
// combined with the above feed rate mode and the below set feed rate error-checking.
|
||||
// NOTE: It seems redundant to check for an F word to be passed after switching from G94 to G93. We would
|
||||
// accomplish the exact same thing if the feed rate value is always reset to zero and undefined after each
|
||||
// inverse time block, since the commands that use this value already perform undefined checks. This would
|
||||
// also allow other commands, following this switch, to execute and not error out needlessly. This code is
|
||||
// combined with the above feed rate mode and the below set feed rate error-checking.
|
||||
|
||||
// [3. Set feed rate ]: F is negative (done.)
|
||||
// - In inverse time mode: Always implicitly zero the feed rate value before and after block completion.
|
||||
// NOTE: If in G93 mode or switched into it from G94, just keep F value as initialized zero or passed F word
|
||||
// value in the block. If no F word is passed with a motion command that requires a feed rate, this will error
|
||||
// out in the motion modes error-checking. However, if no F word is passed with NO motion command that requires
|
||||
// a feed rate, we simply move on and the state feed rate value gets updated to zero and remains undefined.
|
||||
} else { // = G94
|
||||
// - In units per mm mode: If F word passed, ensure value is in mm/min, otherwise push last state value.
|
||||
if (gc_state.modal.feed_rate == FEED_RATE_MODE_UNITS_PER_MIN) { // Last state is also G94
|
||||
if (bit_istrue(value_words,bit(WORD_F))) {
|
||||
if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; }
|
||||
} else {
|
||||
// NOTE: Jogging mode does not pass modal feed rate and requires unique values for each command.
|
||||
if (!is_jog_motion) { gc_block.values.f = gc_state.feed_rate; } // Push last state feed rate
|
||||
}
|
||||
} // Else, switching to G94 from G93, so don't push last state feed rate. Its undefined or the passed F word value.
|
||||
// [3. Set feed rate ]: F is negative (done.)
|
||||
// - In inverse time mode: Always implicitly zero the feed rate value before and after block completion.
|
||||
// NOTE: If in G93 mode or switched into it from G94, just keep F value as initialized zero or passed F word
|
||||
// value in the block. If no F word is passed with a motion command that requires a feed rate, this will error
|
||||
// out in the motion modes error-checking. However, if no F word is passed with NO motion command that requires
|
||||
// a feed rate, we simply move on and the state feed rate value gets updated to zero and remains undefined.
|
||||
} else { // = G94
|
||||
// - In units per mm mode: If F word passed, ensure value is in mm/min, otherwise push last state value.
|
||||
if (gc_state.modal.feed_rate == FEED_RATE_MODE_UNITS_PER_MIN) { // Last state is also G94
|
||||
if (bit_istrue(value_words,bit(WORD_F))) {
|
||||
if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.f *= MM_PER_INCH; }
|
||||
} else {
|
||||
gc_block.values.f = gc_state.feed_rate; // Push last state feed rate
|
||||
}
|
||||
} // Else, switching to G94 from G93, so don't push last state feed rate. Its undefined or the passed F word value.
|
||||
}
|
||||
}
|
||||
// bit_false(value_words,bit(WORD_F)); // NOTE: Single-meaning value word. Set at end of error-checking.
|
||||
|
||||
@ -712,7 +708,7 @@ uint8_t gc_execute_line(char *line)
|
||||
|
||||
if (value_words & bit(WORD_R)) { // Arc Radius Mode
|
||||
bit_false(value_words,bit(WORD_R));
|
||||
if (gc_check_same_position(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]
|
||||
if (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]
|
||||
|
||||
// Convert radius value to proper units.
|
||||
if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.r *= MM_PER_INCH; }
|
||||
@ -836,7 +832,7 @@ uint8_t gc_execute_line(char *line)
|
||||
// an error, it issues an alarm to prevent further motion to the probe. It's also done there to
|
||||
// allow the planner buffer to empty and move off the probe trigger before another probing cycle.
|
||||
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 (isequal_position_vector(gc_state.position, gc_block.values.xyz)) { FAIL(STATUS_GCODE_INVALID_TARGET); } // [Invalid target]
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1021,42 +1017,38 @@ uint8_t gc_execute_line(char *line)
|
||||
gc_state.modal.motion = gc_block.modal.motion;
|
||||
if (gc_state.modal.motion != MOTION_MODE_NONE) {
|
||||
if (axis_command == AXIS_COMMAND_MOTION_MODE) {
|
||||
switch (gc_state.modal.motion) {
|
||||
case MOTION_MODE_SEEK:
|
||||
pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag.
|
||||
mc_line(gc_block.values.xyz, pl_data);
|
||||
break;
|
||||
case MOTION_MODE_LINEAR:
|
||||
mc_line(gc_block.values.xyz, pl_data);
|
||||
break;
|
||||
case MOTION_MODE_CW_ARC:
|
||||
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, true);
|
||||
break;
|
||||
case MOTION_MODE_CCW_ARC:
|
||||
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, false);
|
||||
break;
|
||||
case MOTION_MODE_PROBE_TOWARD:
|
||||
// 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.
|
||||
mc_probe_cycle(gc_block.values.xyz, pl_data, false, false);
|
||||
break;
|
||||
case MOTION_MODE_PROBE_TOWARD_NO_ERROR:
|
||||
mc_probe_cycle(gc_block.values.xyz, pl_data, false, true);
|
||||
break;
|
||||
case MOTION_MODE_PROBE_AWAY:
|
||||
mc_probe_cycle(gc_block.values.xyz, pl_data, true, false);
|
||||
break;
|
||||
case MOTION_MODE_PROBE_AWAY_NO_ERROR:
|
||||
mc_probe_cycle(gc_block.values.xyz, pl_data, true, true);
|
||||
}
|
||||
|
||||
uint8_t gc_update_pos = GC_UPDATE_POS_TARGET;
|
||||
if (gc_state.modal.motion == MOTION_MODE_LINEAR) {
|
||||
mc_line(gc_block.values.xyz, pl_data);
|
||||
} else if (gc_state.modal.motion == MOTION_MODE_SEEK) {
|
||||
pl_data->condition |= PL_COND_FLAG_RAPID_MOTION; // Set rapid motion condition flag.
|
||||
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)) {
|
||||
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,
|
||||
axis_0, axis_1, axis_linear, is_clockwise_arc);
|
||||
} else {
|
||||
// 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.
|
||||
uint8_t is_probe_away = false;
|
||||
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
|
||||
// motion control system might still be processing the action and the real tool position
|
||||
// in any intermediate location.
|
||||
memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[]
|
||||
}
|
||||
if (gc_update_pos == GC_UPDATE_POS_TARGET) {
|
||||
memcpy(gc_state.position, gc_block.values.xyz, sizeof(gc_block.values.xyz)); // gc_state.position[] = gc_block.values.xyz[]
|
||||
} else if (gc_update_pos == GC_UPDATE_POS_SYSTEM) {
|
||||
gc_sync_position(); // gc_state.position[] = sys_position
|
||||
} // == GC_UPDATE_POS_NONE
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// [21. Program flow ]:
|
||||
|
18
grbl/gcode.h
18
grbl/gcode.h
@ -123,7 +123,6 @@
|
||||
// Modal Group G12: Active work coordinate system
|
||||
// N/A: Stores coordinate system value (54-59) to change to.
|
||||
|
||||
|
||||
// Define parameter word mapping.
|
||||
#define WORD_F 0
|
||||
#define WORD_I 1
|
||||
@ -139,6 +138,23 @@
|
||||
#define WORD_Y 11
|
||||
#define WORD_Z 12
|
||||
|
||||
// Define g-code parser position updating flags
|
||||
#define GC_UPDATE_POS_TARGET 0
|
||||
#define GC_UPDATE_POS_SYSTEM 1
|
||||
#define GC_UPDATE_POS_NONE 2
|
||||
|
||||
// Define probe cycle exit states and assign proper position updating.
|
||||
#define GC_PROBE_FOUND GC_UPDATE_POS_SYSTEM
|
||||
#define GC_PROBE_ABORT GC_UPDATE_POS_NONE
|
||||
#define GC_PROBE_FAIL_INIT GC_UPDATE_POS_NONE
|
||||
#define GC_PROBE_FAIL_END GC_UPDATE_POS_TARGET
|
||||
#ifdef SET_CHECK_MODE_PROBE_TO_START
|
||||
#define GC_PROBE_CHECK_MODE GC_UPDATE_POS_NONE
|
||||
#else
|
||||
#define GC_PROBE_CHECK_MODE GC_UPDATE_POS_TARGET
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// NOTE: When this struct is zeroed, the above defines set the defaults for the system.
|
||||
typedef struct {
|
||||
|
@ -22,8 +22,8 @@
|
||||
#define grbl_h
|
||||
|
||||
// Grbl versioning system
|
||||
#define GRBL_VERSION "1.1a"
|
||||
#define GRBL_VERSION_BUILD "20160925"
|
||||
#define GRBL_VERSION "1.1b"
|
||||
#define GRBL_VERSION_BUILD "20160926"
|
||||
|
||||
// Define standard libraries used by Grbl.
|
||||
#include <avr/io.h>
|
||||
|
@ -237,13 +237,14 @@ void mc_homing_cycle()
|
||||
|
||||
// Perform tool length probe cycle. Requires probe switch.
|
||||
// NOTE: Upon probe failure, the program will be stopped and placed into ALARM state.
|
||||
void 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 is_probe_away, uint8_t is_no_error)
|
||||
{
|
||||
// TODO: Need to update this cycle so it obeys a non-auto cycle start.
|
||||
if (sys.state == STATE_CHECK_MODE) { return; }
|
||||
if (sys.state == STATE_CHECK_MODE) { return(GC_PROBE_CHECK_MODE); }
|
||||
|
||||
// Finish all queued commands and empty planner buffer before starting probe cycle.
|
||||
protocol_buffer_synchronize();
|
||||
if (sys.abort) { return(GC_PROBE_ABORT); } // Return if system reset has been issued.
|
||||
|
||||
// Initialize probing control variables
|
||||
sys.probe_succeeded = false; // Re-initialize probe history before beginning cycle.
|
||||
@ -254,8 +255,9 @@ void mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t is_probe_a
|
||||
if ( probe_get_state() ) { // Check probe pin state.
|
||||
system_set_exec_alarm(EXEC_ALARM_PROBE_FAIL_INITIAL);
|
||||
protocol_execute_realtime();
|
||||
probe_configure_invert_mask(false); // Re-initialize invert mask before returning.
|
||||
return(GC_PROBE_FAIL_INIT); // Nothing else to do but bail.
|
||||
}
|
||||
if (sys.abort) { return; } // Return if system reset has been issued.
|
||||
|
||||
// Setup and queue probing motion. Auto cycle-start should not start the cycle.
|
||||
mc_line(target, pl_data);
|
||||
@ -267,7 +269,7 @@ void mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t is_probe_a
|
||||
system_set_exec_state_flag(EXEC_CYCLE_START);
|
||||
do {
|
||||
protocol_execute_realtime();
|
||||
if (sys.abort) { return; } // Check for system abort
|
||||
if (sys.abort) { return(GC_PROBE_ABORT); } // Check for system abort
|
||||
} while (sys.state != STATE_IDLE);
|
||||
|
||||
// Probing cycle complete!
|
||||
@ -280,8 +282,8 @@ void mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t is_probe_a
|
||||
sys.probe_succeeded = true; // Indicate to system the probing cycle completed successfully.
|
||||
}
|
||||
sys_probe_state = PROBE_OFF; // Ensure probe state monitor is disabled.
|
||||
probe_configure_invert_mask(false); // Re-initialize invert mask.
|
||||
protocol_execute_realtime(); // Check and execute run-time commands
|
||||
if (sys.abort) { return; } // Check for system abort
|
||||
|
||||
// Reset the stepper and planner buffers to remove the remainder of the probe motion.
|
||||
st_reset(); // Reset step segment buffer.
|
||||
@ -290,12 +292,21 @@ void mc_probe_cycle(float *target, plan_line_data_t *pl_data, uint8_t is_probe_a
|
||||
|
||||
// TODO: Update the g-code parser code to not require this target calculation but uses a gc_sync_position() call.
|
||||
// NOTE: The target[] variable updated here will be sent back and synced with the g-code parser.
|
||||
system_convert_array_steps_to_mpos(target, sys_position);
|
||||
|
||||
//!!! This is the problem. Need to set the g-code parser to update the position appropriately.
|
||||
// - Probe initialization fail: Retain current position.
|
||||
// - Probe successful: Update new positions across everything, since held before the target.
|
||||
// - Probe did not contact (alarm or not): Copy original target position as normal
|
||||
|
||||
// system_convert_array_steps_to_mpos(target, sys_position);
|
||||
|
||||
#ifdef MESSAGE_PROBE_COORDINATES
|
||||
// All done! Output the probe position as message.
|
||||
report_probe_parameters();
|
||||
#endif
|
||||
|
||||
if (sys.probe_succeeded) { return(GC_PROBE_FOUND); } // Successful probe cycle.
|
||||
else { return(GC_PROBE_FAIL_END); } // Failed to trigger probe within travel. With or without error.
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,7 +46,7 @@ void mc_dwell(float seconds);
|
||||
void mc_homing_cycle();
|
||||
|
||||
// Perform tool length probe cycle. Requires probe switch.
|
||||
void 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 is_probe_away, uint8_t is_no_error);
|
||||
|
||||
// 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);
|
||||
|
@ -55,6 +55,7 @@
|
||||
// #define clear_vector_long(a) memset(a, 0.0, sizeof(long)*N_AXIS)
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
#define isequal_position_vector(a,b) !(memcmp(a, b, sizeof(float)*N_AXIS))
|
||||
|
||||
// Bit field and masking macros
|
||||
#define bit(n) (1 << n)
|
||||
|
@ -487,7 +487,16 @@ void plan_sync_position()
|
||||
}
|
||||
|
||||
|
||||
// Returns the number of available blocks are in the planner buffer.
|
||||
uint8_t plan_get_block_buffer_available()
|
||||
{
|
||||
if (block_buffer_head >= block_buffer_tail) { return((BLOCK_BUFFER_SIZE-1)-(block_buffer_head-block_buffer_tail)); }
|
||||
return((block_buffer_tail-block_buffer_head-1));
|
||||
}
|
||||
|
||||
|
||||
// Returns the number of active blocks are in the planner buffer.
|
||||
// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h
|
||||
uint8_t plan_get_block_buffer_count()
|
||||
{
|
||||
if (block_buffer_head >= block_buffer_tail) { return(block_buffer_head-block_buffer_tail); }
|
||||
|
@ -131,7 +131,11 @@ void plan_sync_position();
|
||||
// Reinitialize plan with a partially completed block
|
||||
void plan_cycle_reinitialize();
|
||||
|
||||
// Returns the number of available blocks are in the planner buffer.
|
||||
uint8_t plan_get_block_buffer_available();
|
||||
|
||||
// Returns the number of active blocks are in the planner buffer.
|
||||
// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h
|
||||
uint8_t plan_get_block_buffer_count();
|
||||
|
||||
// Returns the status of the block ring buffer. True, if buffer is full.
|
||||
|
@ -725,10 +725,12 @@ void report_realtime_status()
|
||||
|
||||
// Returns planner and serial read buffer states.
|
||||
#ifdef REPORT_FIELD_BUFFER_STATE
|
||||
printPgmString(PSTR("|Bf:"));
|
||||
print_uint8_base10(plan_get_block_buffer_count());
|
||||
serial_write(',');
|
||||
print_uint8_base10(serial_get_rx_buffer_count());
|
||||
if (bit_istrue(settings.status_report_mask,BITFLAG_RT_STATUS_BUFFER_STATE)) {
|
||||
printPgmString(PSTR("|Bf:"));
|
||||
print_uint8_base10(plan_get_block_buffer_available());
|
||||
serial_write(',');
|
||||
print_uint8_base10(serial_get_rx_buffer_available());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_LINE_NUMBERS
|
||||
|
@ -33,12 +33,17 @@ uint8_t serial_tx_buffer_head = 0;
|
||||
volatile uint8_t serial_tx_buffer_tail = 0;
|
||||
|
||||
|
||||
#ifdef ENABLE_XONXOFF
|
||||
volatile uint8_t flow_ctrl = XON_SENT; // Flow control state variable
|
||||
#endif
|
||||
// Returns the number of bytes available in the RX serial buffer.
|
||||
uint8_t serial_get_rx_buffer_available()
|
||||
{
|
||||
uint8_t rtail = serial_rx_buffer_tail; // Copy to limit multiple calls to volatile
|
||||
if (serial_rx_buffer_head >= rtail) { return(RX_BUFFER_SIZE - (serial_rx_buffer_head-rtail)); }
|
||||
return((rtail-serial_rx_buffer_head-1));
|
||||
}
|
||||
|
||||
|
||||
// Returns the number of bytes used in the RX serial buffer.
|
||||
// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h.
|
||||
uint8_t serial_get_rx_buffer_count()
|
||||
{
|
||||
uint8_t rtail = serial_rx_buffer_tail; // Copy to limit multiple calls to volatile
|
||||
@ -104,25 +109,14 @@ ISR(SERIAL_UDRE)
|
||||
{
|
||||
uint8_t tail = serial_tx_buffer_tail; // Temporary serial_tx_buffer_tail (to optimize for volatile)
|
||||
|
||||
#ifdef ENABLE_XONXOFF
|
||||
if (flow_ctrl == SEND_XOFF) {
|
||||
UDR0 = XOFF_CHAR;
|
||||
flow_ctrl = XOFF_SENT;
|
||||
} else if (flow_ctrl == SEND_XON) {
|
||||
UDR0 = XON_CHAR;
|
||||
flow_ctrl = XON_SENT;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// Send a byte from the buffer
|
||||
UDR0 = serial_tx_buffer[tail];
|
||||
// Send a byte from the buffer
|
||||
UDR0 = serial_tx_buffer[tail];
|
||||
|
||||
// Update tail position
|
||||
tail++;
|
||||
if (tail == TX_RING_BUFFER) { tail = 0; }
|
||||
// Update tail position
|
||||
tail++;
|
||||
if (tail == TX_RING_BUFFER) { tail = 0; }
|
||||
|
||||
serial_tx_buffer_tail = tail;
|
||||
}
|
||||
serial_tx_buffer_tail = tail;
|
||||
|
||||
// Turn off Data Register Empty Interrupt to stop tx-streaming if this concludes the transfer
|
||||
if (tail == serial_tx_buffer_head) { UCSR0B &= ~(1 << UDRIE0); }
|
||||
@ -142,13 +136,6 @@ uint8_t serial_read()
|
||||
if (tail == RX_RING_BUFFER) { tail = 0; }
|
||||
serial_rx_buffer_tail = tail;
|
||||
|
||||
#ifdef ENABLE_XONXOFF
|
||||
if ((serial_get_rx_buffer_count() < RX_BUFFER_LOW) && flow_ctrl == XOFF_SENT) {
|
||||
flow_ctrl = SEND_XON;
|
||||
UCSR0B |= (1 << UDRIE0); // Force TX
|
||||
}
|
||||
#endif
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -201,14 +188,6 @@ ISR(SERIAL_RX)
|
||||
if (next_head != serial_rx_buffer_tail) {
|
||||
serial_rx_buffer[serial_rx_buffer_head] = data;
|
||||
serial_rx_buffer_head = next_head;
|
||||
|
||||
#ifdef ENABLE_XONXOFF
|
||||
if ((serial_get_rx_buffer_count() >= RX_BUFFER_FULL) && flow_ctrl == XON_SENT) {
|
||||
flow_ctrl = SEND_XOFF;
|
||||
UCSR0B |= (1 << UDRIE0); // Force TX
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -218,8 +197,4 @@ ISR(SERIAL_RX)
|
||||
void serial_reset_read_buffer()
|
||||
{
|
||||
serial_rx_buffer_tail = serial_rx_buffer_head;
|
||||
|
||||
#ifdef ENABLE_XONXOFF
|
||||
flow_ctrl = XON_SENT;
|
||||
#endif
|
||||
}
|
||||
|
@ -36,16 +36,6 @@
|
||||
|
||||
#define SERIAL_NO_DATA 0xff
|
||||
|
||||
#ifdef ENABLE_XONXOFF
|
||||
#define RX_BUFFER_FULL 96 // XOFF high watermark
|
||||
#define RX_BUFFER_LOW 64 // XON low watermark
|
||||
#define SEND_XOFF 1
|
||||
#define SEND_XON 2
|
||||
#define XOFF_SENT 3
|
||||
#define XON_SENT 4
|
||||
#define XOFF_CHAR 0x13
|
||||
#define XON_CHAR 0x11
|
||||
#endif
|
||||
|
||||
void serial_init();
|
||||
|
||||
@ -58,7 +48,11 @@ uint8_t serial_read();
|
||||
// Reset and empty data in read buffer. Used by e-stop and reset.
|
||||
void serial_reset_read_buffer();
|
||||
|
||||
// Returns the number of bytes available in the RX serial buffer.
|
||||
uint8_t serial_get_rx_buffer_available();
|
||||
|
||||
// Returns the number of bytes used in the RX serial buffer.
|
||||
// NOTE: Deprecated. Not used unless classic status reports are enabled in config.h.
|
||||
uint8_t serial_get_rx_buffer_count();
|
||||
|
||||
// Returns the number of bytes used in the TX serial buffer.
|
||||
|
@ -51,6 +51,7 @@
|
||||
#define BITFLAG_RT_STATUS_OVERRIDES bit(7)
|
||||
#else
|
||||
#define BITFLAG_RT_STATUS_POSITION_TYPE bit(0)
|
||||
#define BITFLAG_RT_STATUS_BUFFER_STATE bit(1)
|
||||
#endif
|
||||
|
||||
// Define settings restore bitflags.
|
||||
|
Reference in New Issue
Block a user