From 6fdb35a7dad3e4ef027260aa30aef1fb0e55c554 Mon Sep 17 00:00:00 2001 From: Robert Grzesek Date: Thu, 6 Feb 2014 15:10:27 -0800 Subject: [PATCH 1/2] Initial line number reporting --- gcode.c | 14 ++++++++------ limits.c | 2 +- motion_control.c | 12 ++++++------ motion_control.h | 5 +++-- planner.c | 3 ++- planner.h | 5 +++-- report.c | 12 ++++++++++++ 7 files changed, 35 insertions(+), 18 deletions(-) diff --git a/gcode.c b/gcode.c index 4ba45ba..a9a0dae 100644 --- a/gcode.c +++ b/gcode.c @@ -106,6 +106,7 @@ uint8_t gc_execute_line(char *line) float target[N_AXIS]; clear_vector(target); // XYZ(ABC) axes parameters. + uint32_t line_number = 0; gc.arc_radius = 0; clear_vector(gc.arc_offset); // IJK Arc offsets are incremental. Value of zero indicates no change. @@ -220,7 +221,7 @@ uint8_t gc_execute_line(char *line) char_counter = 0; while(next_statement(&letter, &value, line, &char_counter)) { switch(letter) { - case 'G': case 'M': case 'N': break; // Ignore command statements and line numbers + case 'G': case 'M': break; // Ignore command statements and line numbers case 'F': if (value <= 0) { FAIL(STATUS_INVALID_STATEMENT); } // Must be greater than zero if (gc.inverse_feed_rate_mode) { @@ -231,6 +232,7 @@ uint8_t gc_execute_line(char *line) break; case 'I': case 'J': case 'K': gc.arc_offset[letter-'I'] = to_millimeters(value); break; case 'L': l = trunc(value); break; + case 'N': line_number = trunc(value); break; case 'P': p = value; break; case 'R': gc.arc_radius = to_millimeters(value); break; case 'S': @@ -330,7 +332,7 @@ uint8_t gc_execute_line(char *line) target[idx] = gc.position[idx]; } } - mc_line(target, -1.0, false); + mc_line(target, -1.0, false, line_number); } // Retreive G28/30 go-home position data (in machine coordinates) from EEPROM float coord_data[N_AXIS]; @@ -339,7 +341,7 @@ uint8_t gc_execute_line(char *line) } else { if (!settings_read_coord_data(SETTING_INDEX_G30,coord_data)) { return(STATUS_SETTING_READ_FAIL); } } - mc_line(coord_data, -1.0, false); + mc_line(coord_data, -1.0, false, line_number); memcpy(gc.position, coord_data, sizeof(coord_data)); // gc.position[] = coord_data[]; axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags. break; @@ -410,7 +412,7 @@ uint8_t gc_execute_line(char *line) break; case MOTION_MODE_SEEK: if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);} - else { mc_line(target, -1.0, false); } + else { mc_line(target, -1.0, false, line_number); } break; case MOTION_MODE_LINEAR: // TODO: Inverse time requires F-word with each statement. Need to do a check. Also need @@ -418,7 +420,7 @@ uint8_t gc_execute_line(char *line) // and after an inverse time move and then check for non-zero feed rate each time. This // should be efficient and effective. if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);} - else { mc_line(target, (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode); } + else { mc_line(target, (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode, line_number); } break; case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC: // Check if at least one of the axes of the selected plane has been specified. If in center @@ -442,7 +444,7 @@ uint8_t gc_execute_line(char *line) // Trace the arc mc_arc(gc.position, target, gc.arc_offset, gc.plane_axis_0, gc.plane_axis_1, gc.plane_axis_2, (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode, - gc.arc_radius, isclockwise); + gc.arc_radius, isclockwise, line_number); } break; } diff --git a/limits.c b/limits.c index 169ca71..486f389 100644 --- a/limits.c +++ b/limits.c @@ -157,7 +157,7 @@ void limits_go_home(uint8_t cycle_mask, bool approach, float homing_rate) // Perform homing cycle. Planner buffer should be empty, as required to initiate the homing cycle. uint8_t limit_state; - plan_buffer_line(target, homing_rate, false); // Bypass mc_line(). Directly plan homing motion. + plan_buffer_line(target, homing_rate, false, HOMING_CYCLE_LINE_NUMBER); // Bypass mc_line(). Directly plan homing motion. st_prep_buffer(); // Prep first segment from newly planned block. st_wake_up(); // Initiate motion do { diff --git a/motion_control.c b/motion_control.c index ee1798b..e336bfd 100644 --- a/motion_control.c +++ b/motion_control.c @@ -39,7 +39,7 @@ // segments, must pass through this routine before being passed to the planner. The seperation of // mc_line and plan_buffer_line is done primarily to place non-planner-type functions from being // in the planner and to let backlash compensation or canned cycle integration simple and direct. -void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate) +void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate, uint32_t line_number) { // If enabled, check for soft limit violations. Placed here all line motions are picked up // from everywhere in Grbl. @@ -68,7 +68,7 @@ void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate) else { break; } } while (1); - plan_buffer_line(target, feed_rate, invert_feed_rate); + plan_buffer_line(target, feed_rate, invert_feed_rate, line_number); // If idle, indicate to the system there is now a planned block in the buffer ready to cycle // start. Otherwise ignore and continue on. @@ -84,7 +84,7 @@ void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate) // of each segment is configured in settings.arc_tolerance, which is defined to be the maximum normal // distance from segment to the circle when the end points both lie on the circle. void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, - uint8_t axis_linear, float feed_rate, uint8_t invert_feed_rate, float radius, uint8_t isclockwise) + uint8_t axis_linear, float feed_rate, uint8_t invert_feed_rate, float radius, uint8_t isclockwise, uint32_t line_number) { float center_axis0 = position[axis_0] + offset[axis_0]; float center_axis1 = position[axis_1] + offset[axis_1]; @@ -180,14 +180,14 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8 arc_target[axis_0] = center_axis0 + r_axis0; arc_target[axis_1] = center_axis1 + r_axis1; arc_target[axis_linear] += linear_per_segment; - mc_line(arc_target, feed_rate, invert_feed_rate); + mc_line(arc_target, feed_rate, invert_feed_rate, line_number); // Bail mid-circle on system abort. Runtime command check already performed by mc_line. if (sys.abort) { return; } } } // Ensure last segment arrives at target location. - mc_line(target, feed_rate, invert_feed_rate); + mc_line(target, feed_rate, invert_feed_rate, line_number); } @@ -273,7 +273,7 @@ void mc_homing_cycle() sys.state = STATE_IDLE; // Set system state to IDLE to complete motion and indicate homed. - mc_line(pulloff_target, settings.homing_seek_rate, false); + mc_line(pulloff_target, settings.homing_seek_rate, false, HOMING_CYCLE_LINE_NUMBER); st_cycle_start(); // Move it. Nothing should be in the buffer except this motion. plan_synchronize(); // Make sure the motion completes. // NOTE: Stepper idle lock resumes normal functionality after cycle. diff --git a/motion_control.h b/motion_control.h index b17e168..0fe2960 100644 --- a/motion_control.h +++ b/motion_control.h @@ -22,18 +22,19 @@ #ifndef motion_control_h #define motion_control_h +#define HOMING_CYCLE_LINE_NUMBER 1000000000 // Execute linear motion in absolute millimeter coordinates. Feed rate given in millimeters/second // unless invert_feed_rate is true. Then the feed_rate means that the motion should be completed in // (1 minute)/feed_rate time. -void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate); +void mc_line(float *target, float feed_rate, uint8_t invert_feed_rate, uint32_t line_number); // Execute an arc in offset mode format. position == current xyz, target == target xyz, // offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is // the direction of helical travel, radius == circle radius, isclockwise boolean. Used // for vector transformation direction. void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1, - uint8_t axis_linear, float feed_rate, uint8_t invert_feed_rate, float radius, uint8_t isclockwise); + uint8_t axis_linear, float feed_rate, uint8_t invert_feed_rate, float radius, uint8_t isclockwise, uint32_t line_number); // Dwell for a specific number of seconds void mc_dwell(float seconds); diff --git a/planner.c b/planner.c index 9e435c7..f167522 100644 --- a/planner.c +++ b/planner.c @@ -272,7 +272,7 @@ void plan_synchronize() is used in three ways: as a normal feed rate if invert_feed_rate is false, as inverse time if invert_feed_rate is true, or as seek/rapids rate if the feed_rate value is negative (and invert_feed_rate always false). */ -void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate) +void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate, uint32_t line_number) { // Prepare and initialize new block plan_block_t *block = &block_buffer[block_buffer_head]; @@ -280,6 +280,7 @@ void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate) block->millimeters = 0; block->direction_bits = 0; block->acceleration = SOME_LARGE_VALUE; // Scaled down to maximum acceleration later + block->line_number = line_number; // Compute and store initial move distance data. // TODO: After this for-loop, we don't touch the stepper algorithm data. Might be a good idea diff --git a/planner.h b/planner.h index 99298ed..e7ae716 100644 --- a/planner.h +++ b/planner.h @@ -26,7 +26,7 @@ // The number of linear motions that can be in the plan at any give time #ifndef BLOCK_BUFFER_SIZE - #define BLOCK_BUFFER_SIZE 18 + #define BLOCK_BUFFER_SIZE 16 #endif // This struct stores a linear movement of a g-code block motion with its critical "nominal" values @@ -47,6 +47,7 @@ typedef struct { float acceleration; // Axis-limit adjusted line acceleration in (mm/min^2) float millimeters; // The remaining distance for this block to be executed in (mm) // uint8_t max_override; // Maximum override value based on axis speed limits + uint32_t line_number; } plan_block_t; @@ -56,7 +57,7 @@ void plan_reset(); // Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position // in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed // rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. -void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate); +void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate, uint32_t line_number); // Called when the current block is no longer needed. Discards the block and makes the memory // availible for new blocks. diff --git a/report.c b/report.c index ee4de61..d62ed49 100644 --- a/report.c +++ b/report.c @@ -32,6 +32,7 @@ #include "settings.h" #include "gcode.h" #include "coolant_control.h" +#include "planner.h" // Handles the primary confirmation protocol response for streaming interfaces and human-feedback. @@ -348,6 +349,17 @@ void report_realtime_status() printFloat(print_position[i]); if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); } } + + // Report current line number + printPgmString(PSTR(",")); + printPgmString(PSTR("Ln:")); + uint32_t ln=0; + plan_block_t * pb = plan_get_current_block(); + if(pb != NULL) { + ln = pb->line_number; + } + printInteger(ln); + printPgmString(PSTR(">\r\n")); } From cd71a90ce8a770e0030ed6c9bac805b89724e275 Mon Sep 17 00:00:00 2001 From: Robert Grzesek Date: Thu, 6 Feb 2014 15:19:30 -0800 Subject: [PATCH 2/2] Made line number reporting optional via config.h --- config.h | 4 ++++ planner.c | 3 ++- planner.h | 8 +++++++- report.c | 3 ++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/config.h b/config.h index dbf37e3..ddaddcb 100644 --- a/config.h +++ b/config.h @@ -28,6 +28,10 @@ #ifndef config_h #define config_h +// Allows GRBL to tranck and report gcode line numbers. Enabling this means that the planning buffer +// goes from 18 or 16 to make room for the additional line number data in the plan_block_t struct +#define USE_LINE_NUMBERS + // Default settings. Used when resetting EEPROM. Change to desired name in defaults.h #define DEFAULTS_SHERLINE_5400 diff --git a/planner.c b/planner.c index f167522..dfc56db 100644 --- a/planner.c +++ b/planner.c @@ -280,8 +280,9 @@ void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate, block->millimeters = 0; block->direction_bits = 0; block->acceleration = SOME_LARGE_VALUE; // Scaled down to maximum acceleration later +#ifdef USE_LINE_NUMBERS block->line_number = line_number; - +#endif // Compute and store initial move distance data. // TODO: After this for-loop, we don't touch the stepper algorithm data. Might be a good idea // to try to keep these types of things completely separate from the planner for portability. diff --git a/planner.h b/planner.h index e7ae716..7a255be 100644 --- a/planner.h +++ b/planner.h @@ -26,7 +26,11 @@ // The number of linear motions that can be in the plan at any give time #ifndef BLOCK_BUFFER_SIZE - #define BLOCK_BUFFER_SIZE 16 + #ifdef USE_LINE_NUMBERS + #define BLOCK_BUFFER_SIZE 16 + #else + #define BLOCK_BUFFER_SIZE 18 + #endif #endif // This struct stores a linear movement of a g-code block motion with its critical "nominal" values @@ -47,7 +51,9 @@ typedef struct { float acceleration; // Axis-limit adjusted line acceleration in (mm/min^2) float millimeters; // The remaining distance for this block to be executed in (mm) // uint8_t max_override; // Maximum override value based on axis speed limits +#ifdef USE_LINE_NUMBERS uint32_t line_number; +#endif } plan_block_t; diff --git a/report.c b/report.c index d62ed49..5b97dc1 100644 --- a/report.c +++ b/report.c @@ -350,6 +350,7 @@ void report_realtime_status() if (i < (N_AXIS-1)) { printPgmString(PSTR(",")); } } +#ifdef USE_LINE_NUMBERS // Report current line number printPgmString(PSTR(",")); printPgmString(PSTR("Ln:")); @@ -359,7 +360,7 @@ void report_realtime_status() ln = pb->line_number; } printInteger(ln); - +#endif printPgmString(PSTR(">\r\n")); }