Arc mm_per_segment removed, now in terms of tolerance. Stepper ramp counter variable type corrected.

- Arc mm_per_segment parameter was removed and replaced with an
arc_tolerance parameter, which scales all arc segments automatically to
radius, such that the line segment error doesn't exceed the tolerance.
Significantly improves arc performance through larger radius arc,
because the segments are much longer and the planner buffer has more to
work with.

- Moved n_arc correction from the settings to config.h. Mathematically
this doesn't need to be a setting anymore, as the default config value
will work for all known CNC applications. The error does not accumulate
as much anymore, since the small angle approximation used by the arc
generation has been updated to a third-order approximation and how the
line segment length scale with radius and tolerance now. Left in
config.h for extraneous circumstances.

- Corrected the st.ramp_count variable (acceleration tick counter) to a
8-bit vs. 32-bit variable. Should make the stepper algorithm just a
touch faster overall.
This commit is contained in:
Sonny Jeon 2012-12-19 17:30:09 -07:00
parent a1397f61c4
commit 3dfffa622d
8 changed files with 208 additions and 128 deletions

View File

@ -105,14 +105,6 @@
#define CMD_CYCLE_START '~' #define CMD_CYCLE_START '~'
#define CMD_RESET 0x18 // ctrl-x #define CMD_RESET 0x18 // ctrl-x
// The temporal resolution of the acceleration management subsystem. Higher number give smoother
// acceleration but may impact performance. If you run at very high feedrates (>15kHz or so) and
// very high accelerations, this will reduce the error between how the planner plans the velocity
// profiles and how the stepper program actually performs them. The correct value for this parameter
// is machine dependent, so it's advised to set this only as high as needed. Approximate successful
// values can widely range from 50 to 200 or more. Cannot be greater than ISR_TICKS_PER_SECOND/2.
#define ACCELERATION_TICKS_PER_SECOND 100L
// The "Stepper Driver Interrupt" employs the Pramod Ranade inverse time algorithm to manage the // The "Stepper Driver Interrupt" employs the Pramod Ranade inverse time algorithm to manage the
// Bresenham line stepping algorithm. The value ISR_TICKS_PER_SECOND is the frequency(Hz) at which // Bresenham line stepping algorithm. The value ISR_TICKS_PER_SECOND is the frequency(Hz) at which
// the Ranade algorithm ticks at. Maximum step frequencies are limited by the Ranade frequency by // the Ranade algorithm ticks at. Maximum step frequencies are limited by the Ranade frequency by
@ -124,6 +116,17 @@
// 20kHz by performing two steps per step event, rather than just one. // 20kHz by performing two steps per step event, rather than just one.
#define ISR_TICKS_PER_SECOND 20000L // Integer (Hz) #define ISR_TICKS_PER_SECOND 20000L // Integer (Hz)
// The temporal resolution of the acceleration management subsystem. Higher number give smoother
// acceleration but may impact performance. If you run at very high feedrates (>15kHz or so) and
// very high accelerations, this will reduce the error between how the planner plans the velocity
// profiles and how the stepper program actually performs them. The correct value for this parameter
// is machine dependent, so it's advised to set this only as high as needed. Approximate successful
// values can widely range from 50 to 200 or more. Cannot be greater than ISR_TICKS_PER_SECOND/2.
#define ACCELERATION_TICKS_PER_SECOND 100L
// NOTE: Make sure this value is less than 256, when adjusting both dependent parameters.
#define INTERRUPTS_PER_ACCELERATION_TICK (ISR_TICKS_PER_SECOND/ACCELERATION_TICKS_PER_SECOND)
// The Ranade algorithm can use either floating point or long integers for its counters, but for // The Ranade algorithm can use either floating point or long integers for its counters, but for
// integers the counter values must be scaled since these values can be very small (10^-6). This // integers the counter values must be scaled since these values can be very small (10^-6). This
// multiplier value scales the floating point counter values for use in a long integer. Long integers // multiplier value scales the floating point counter values for use in a long integer. Long integers
@ -193,6 +196,13 @@
// parser state depending on user preferences. // parser state depending on user preferences.
#define N_STARTUP_LINE 2 // Integer (1-5) #define N_STARTUP_LINE 2 // Integer (1-5)
// Number of arc generation iterations by small angle approximation before exact arc trajectory
// correction. This parameter maybe decreased if there are issues with the accuracy of the arc
// generations. In general, the default value is more than enough for the intended CNC applications
// of grbl, and should be on the order or greater than the size of the buffer to help with the
// computational efficiency of generating arcs.
#define N_ARC_CORRECTION 20 // Integer (1-255)
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------
// FOR ADVANCED USERS ONLY: // FOR ADVANCED USERS ONLY:

View File

@ -33,7 +33,7 @@
#define DEFAULT_Y_STEPS_PER_MM 250.0 #define DEFAULT_Y_STEPS_PER_MM 250.0
#define DEFAULT_Z_STEPS_PER_MM 250.0 #define DEFAULT_Z_STEPS_PER_MM 250.0
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_MM_PER_ARC_SEGMENT 0.1 #define DEFAULT_ARC_TOLERANCE 0.005 // mm
#define DEFAULT_RAPID_FEEDRATE 500.0 // mm/min #define DEFAULT_RAPID_FEEDRATE 500.0 // mm/min
#define DEFAULT_FEEDRATE 250.0 #define DEFAULT_FEEDRATE 250.0
#define DEFAULT_ACCELERATION (10.0*60*60) // 10 mm/min^2 #define DEFAULT_ACCELERATION (10.0*60*60) // 10 mm/min^2
@ -51,7 +51,6 @@
#define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_HOMING_PULLOFF 1.0 // mm
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
#define DEFAULT_DECIMAL_PLACES 3 #define DEFAULT_DECIMAL_PLACES 3
#define DEFAULT_N_ARC_CORRECTION 25
#endif #endif
#ifdef DEFAULTS_SHERLINE_5400 #ifdef DEFAULTS_SHERLINE_5400
@ -64,7 +63,7 @@
#define DEFAULT_Y_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV) #define DEFAULT_Y_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)
#define DEFAULT_Z_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV) #define DEFAULT_Z_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_MM_PER_ARC_SEGMENT 0.1 #define DEFAULT_ARC_TOLERANCE 0.005 // mm
#define DEFAULT_RAPID_FEEDRATE 635.0 // mm/min (25ipm) #define DEFAULT_RAPID_FEEDRATE 635.0 // mm/min (25ipm)
#define DEFAULT_FEEDRATE 254.0 // mm/min (10ipm) #define DEFAULT_FEEDRATE 254.0 // mm/min (10ipm)
#define DEFAULT_ACCELERATION 50.0*60*60 // 50 mm/min^2 #define DEFAULT_ACCELERATION 50.0*60*60 // 50 mm/min^2
@ -82,7 +81,6 @@
#define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_HOMING_PULLOFF 1.0 // mm
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
#define DEFAULT_DECIMAL_PLACES 3 #define DEFAULT_DECIMAL_PLACES 3
#define DEFAULT_N_ARC_CORRECTION 25
#endif #endif
#ifdef DEFAULTS_SHAPEOKO #ifdef DEFAULTS_SHAPEOKO
@ -98,7 +96,7 @@
#define DEFAULT_Y_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY) #define DEFAULT_Y_STEPS_PER_MM (MICROSTEPS_XY*STEP_REVS_XY/MM_PER_REV_XY)
#define DEFAULT_Z_STEPS_PER_MM (MICROSTEPS_Z*STEP_REVS_Z/MM_PER_REV_Z) #define DEFAULT_Z_STEPS_PER_MM (MICROSTEPS_Z*STEP_REVS_Z/MM_PER_REV_Z)
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_MM_PER_ARC_SEGMENT 0.1 #define DEFAULT_ARC_TOLERANCE 0.005 // mm
#define DEFAULT_RAPID_FEEDRATE 1000.0 // mm/min #define DEFAULT_RAPID_FEEDRATE 1000.0 // mm/min
#define DEFAULT_FEEDRATE 250.0 #define DEFAULT_FEEDRATE 250.0
#define DEFAULT_ACCELERATION (15.0*60*60) // 15 mm/min^2 #define DEFAULT_ACCELERATION (15.0*60*60) // 15 mm/min^2
@ -116,7 +114,6 @@
#define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_HOMING_PULLOFF 1.0 // mm
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-255) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-255)
#define DEFAULT_DECIMAL_PLACES 3 #define DEFAULT_DECIMAL_PLACES 3
#define DEFAULT_N_ARC_CORRECTION 25
#endif #endif
#ifdef DEFAULTS_ZEN_TOOLWORKS_7x7 #ifdef DEFAULTS_ZEN_TOOLWORKS_7x7
@ -130,7 +127,7 @@
#define DEFAULT_Y_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV) #define DEFAULT_Y_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)
#define DEFAULT_Z_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV) #define DEFAULT_Z_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV)
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_MM_PER_ARC_SEGMENT 0.1 #define DEFAULT_ARC_TOLERANCE 0.005 // mm
#define DEFAULT_RAPID_FEEDRATE 2500.0 // mm/min #define DEFAULT_RAPID_FEEDRATE 2500.0 // mm/min
#define DEFAULT_FEEDRATE 1000.0 // mm/min #define DEFAULT_FEEDRATE 1000.0 // mm/min
#define DEFAULT_ACCELERATION 150.0*60*60 // 150 mm/min^2 #define DEFAULT_ACCELERATION 150.0*60*60 // 150 mm/min^2
@ -148,7 +145,6 @@
#define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_HOMING_PULLOFF 1.0 // mm
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255) #define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
#define DEFAULT_DECIMAL_PLACES 3 #define DEFAULT_DECIMAL_PLACES 3
#define DEFAULT_N_ARC_CORRECTION 25
#endif #endif
#endif #endif

View File

@ -91,8 +91,9 @@ void mc_line(float x, float y, float z, float feed_rate, uint8_t invert_feed_rat
// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is // 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 // the direction of helical travel, radius == circle radius, isclockwise boolean. Used
// for vector transformation direction. // for vector transformation direction.
// The arc is approximated by generating a huge number of tiny, linear segments. The length of each // The arc is approximated by generating a huge number of tiny, linear segments. The chordal tolerance
// segment is configured in settings.mm_per_arc_segment. // 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, 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)
{ {
@ -112,9 +113,16 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
if (angular_travel <= 0) { angular_travel += 2*M_PI; } if (angular_travel <= 0) { angular_travel += 2*M_PI; }
} }
// NOTE: Segment end points are on the arc, which can lead to the arc diameter being smaller by up to
// (2x) settings.arc_tolerance. For 99% of users, this is just fine. If a different arc segment fit
// is desired, i.e. least-squares, midpoint on arc, just change the mm_per_arc_segment calculation.
// Computes: mm_per_arc_segment = sqrt(4*arc_tolerance*(2*radius-arc_tolerance)),
// segments = millimeters_of_travel/mm_per_arc_segment
float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel)); float millimeters_of_travel = hypot(angular_travel*radius, fabs(linear_travel));
if (millimeters_of_travel == 0.0) { return; } uint16_t segments = floor(millimeters_of_travel/
uint16_t segments = floor(millimeters_of_travel/settings.mm_per_arc_segment); sqrt(4*settings.arc_tolerance*(2*radius - settings.arc_tolerance)) );
if (segments) {
// Multiply inverse feed_rate to compensate for the fact that this movement is approximated // Multiply inverse feed_rate to compensate for the fact that this movement is approximated
// by a number of discrete segments. The inverse feed_rate should be correct for the sum of // by a number of discrete segments. The inverse feed_rate should be correct for the sum of
// all segments. // all segments.
@ -130,29 +138,28 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
For arc generation, the center of the circle is the axis of rotation and the radius vector is For arc generation, the center of the circle is the axis of rotation and the radius vector is
defined from the circle center to the initial position. Each line segment is formed by successive defined from the circle center to the initial position. Each line segment is formed by successive
vector rotations. This requires only two cos() and sin() computations to form the rotation vector rotations. Single precision values can accumulate error greater than tool precision in some
matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since cases. So, exact arc path correction is implemented. This approach avoids the problem of too many very
all double numbers are single precision on the Arduino. (True double precision will not have expensive trig operations [sin(),cos(),tan()] which can take 100-200 usec each to compute.
round off issues for CNC applications.) Single precision error can accumulate to be greater than
tool precision in some cases. Therefore, arc path correction is implemented.
Small angle approximation may be used to reduce computation overhead further. This approximation Small angle approximation may be used to reduce computation overhead further. A third-order approximation
holds for everything, but very small circles and large mm_per_arc_segment values. In other words, (second order sin() has too much error) holds for nearly all CNC applications, except for possibly very
theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large small radii (~0.5mm). In other words, theta_per_segment would need to be greater than 0.25 rad(14 deg)
to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for and N_ARC_CORRECTION would need to be large to cause an appreciable drift error (>5% of radius, for very
numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an small radii this is very, very small). N_ARC_CORRECTION~=20 should be more than small enough to correct
issue for CNC machines with the single precision Arduino calculations. for numerical drift error.
This approximation also allows mc_arc to immediately insert a line segment into the planner This approximation also allows mc_arc to immediately insert a line segment into the planner
without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied without the initial overhead of computing cos() or sin(). By the time the arc needs to be applied
a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead. a correction, the planner should have caught up to the lag caused by the initial mc_arc overhead.
This is important when there are successive arc motions. This is important when there are successive arc motions.
*/ */
// Vector rotation matrix values // Computes: cos_T = 1 - theta_per_segment^2/2, sin_T = theta_per_segment - theta_per_segment^3/6) in ~52usec
float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation float cos_T = 2 - theta_per_segment*theta_per_segment;
float sin_T = theta_per_segment; float sin_T = theta_per_segment*0.1666667*(cos_T + 4);
cos_T *= 0.5;
float arc_target[3]; float arc_target[N_AXIS];
float sin_Ti; float sin_Ti;
float cos_Ti; float cos_Ti;
float r_axisi; float r_axisi;
@ -164,14 +171,14 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
for (i = 1; i<segments; i++) { // Increment (segments-1) for (i = 1; i<segments; i++) { // Increment (segments-1)
if (count < settings.n_arc_correction) { if (count < N_ARC_CORRECTION) {
// Apply vector rotation matrix // Apply vector rotation matrix. ~40 usec
r_axisi = r_axis0*sin_T + r_axis1*cos_T; r_axisi = r_axis0*sin_T + r_axis1*cos_T;
r_axis0 = r_axis0*cos_T - r_axis1*sin_T; r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
r_axis1 = r_axisi; r_axis1 = r_axisi;
count++; count++;
} else { } else {
// Arc correction to radius vector. Computed only every n_arc_correction increments. // Arc correction to radius vector. Computed only every N_ARC_CORRECTION increments. ~375 usec
// Compute exact location by applying transformation matrix from initial radius vector(=-offset). // Compute exact location by applying transformation matrix from initial radius vector(=-offset).
cos_Ti = cos(i*theta_per_segment); cos_Ti = cos(i*theta_per_segment);
sin_Ti = sin(i*theta_per_segment); sin_Ti = sin(i*theta_per_segment);
@ -189,6 +196,7 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
// Bail mid-circle on system abort. Runtime command check already performed by mc_line. // Bail mid-circle on system abort. Runtime command check already performed by mc_line.
if (sys.abort) { return; } if (sys.abort) { return; }
} }
}
// Ensure last segment arrives at target location. // Ensure last segment arrives at target location.
mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], feed_rate, invert_feed_rate); mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], feed_rate, invert_feed_rate);
} }

View File

@ -38,6 +38,7 @@ static block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion ins
static volatile uint8_t block_buffer_head; // Index of the next block to be pushed static volatile uint8_t block_buffer_head; // Index of the next block to be pushed
static volatile uint8_t block_buffer_tail; // Index of the block to process now static volatile uint8_t block_buffer_tail; // Index of the block to process now
static uint8_t next_buffer_head; // Index of the next buffer head static uint8_t next_buffer_head; // Index of the next buffer head
// static *block_t block_buffer_planned;
// Define planner variables // Define planner variables
typedef struct { typedef struct {
@ -190,12 +191,82 @@ static void calculate_trapezoid_for_block(block_t *block, float entry_speed_sqr,
*/ */
static void planner_recalculate() static void planner_recalculate()
{ {
// float entry_speed_sqr;
// uint8_t block_index = block_buffer_head;
// block_t *previous = NULL;
// block_t *current = NULL;
// block_t *next;
// while (block_index != block_buffer_tail) {
// block_index = prev_block_index( block_index );
// next = current;
// current = previous;
// previous = &block_buffer[block_index];
//
// if (next && current) {
// if (next != block_buffer_planned) {
// if (previous == block_buffer_tail) { block_buffer_planned = next; }
// else {
//
// if (current->entry_speed_sqr != current->max_entry_speed_sqr) {
// current->recalculate_flag = true; // Almost always changes. So force recalculate.
// entry_speed_sqr = next->entry_speed_sqr + 2*current->acceleration*current->millimeters;
// if (entry_speed_sqr < current->max_entry_speed_sqr) {
// current->entry_speed_sqr = entry_speed_sqr;
// } else {
// current->entry_speed_sqr = current->max_entry_speed_sqr;
// }
// } else {
// block_buffer_planned = current;
// }
// }
// } else {
// break;
// }
// }
// }
//
// block_index = block_buffer_planned;
// next = &block_buffer[block_index];
// current = prev_block_index(block_index);
// while (block_index != block_buffer_head) {
//
// // If the current block is an acceleration block, but it is not long enough to complete the
// // full speed change within the block, we need to adjust the exit speed accordingly. Entry
// // speeds have already been reset, maximized, and reverse planned by reverse planner.
// if (current->entry_speed_sqr < next->entry_speed_sqr) {
// // Compute block exit speed based on the current block speed and distance
// // Computes: v_exit^2 = v_entry^2 + 2*acceleration*distance
// entry_speed_sqr = current->entry_speed_sqr + 2*current->acceleration*current->millimeters;
//
// // If it's less than the stored value, update the exit speed and set recalculate flag.
// if (entry_speed_sqr < next->entry_speed_sqr) {
// next->entry_speed_sqr = entry_speed_sqr;
// next->recalculate_flag = true;
// }
// }
//
// // Recalculate if current block entry or exit junction speed has changed.
// if (current->recalculate_flag || next->recalculate_flag) {
// // NOTE: Entry and exit factors always > 0 by all previous logic operations.
// calculate_trapezoid_for_block(current, current->entry_speed_sqr, next->entry_speed_sqr);
// current->recalculate_flag = false; // Reset current only to ensure next trapezoid is computed
// }
//
// current = next;
// next = &block_buffer[block_index];
// block_index = next_block_index( block_index );
// }
//
// // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated.
// calculate_trapezoid_for_block(next, next->entry_speed_sqr, MINIMUM_PLANNER_SPEED*MINIMUM_PLANNER_SPEED);
// next->recalculate_flag = false;
// TODO: No over-write protection exists for the executing block. For most cases this has proven to be ok, but // TODO: No over-write protection exists for the executing block. For most cases this has proven to be ok, but
// for feed-rate overrides, something like this is essential. Place a request here to the stepper driver to // for feed-rate overrides, something like this is essential. Place a request here to the stepper driver to
// find out where in the planner buffer is the a safe place to begin re-planning from. // find out where in the planner buffer is the a safe place to begin re-planning from.
// if (block_buffer_head != block_buffer_tail) { // if (block_buffer_head != block_buffer_tail) {
float entry_speed_sqr; float entry_speed_sqr;
// Perform reverse planner pass. Skip the head(end) block since it is already initialized, and skip the // Perform reverse planner pass. Skip the head(end) block since it is already initialized, and skip the
@ -268,7 +339,6 @@ static void planner_recalculate()
// Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated. // Last/newest block in buffer. Exit speed is set with MINIMUM_PLANNER_SPEED. Always recalculated.
calculate_trapezoid_for_block(next, next->entry_speed_sqr, MINIMUM_PLANNER_SPEED*MINIMUM_PLANNER_SPEED); calculate_trapezoid_for_block(next, next->entry_speed_sqr, MINIMUM_PLANNER_SPEED*MINIMUM_PLANNER_SPEED);
next->recalculate_flag = false; next->recalculate_flag = false;
// } // }
} }
@ -276,6 +346,7 @@ void plan_reset_buffer()
{ {
block_buffer_tail = block_buffer_head; block_buffer_tail = block_buffer_head;
next_buffer_head = next_block_index(block_buffer_head); next_buffer_head = next_block_index(block_buffer_head);
// block_buffer_planned = block_buffer_head;
} }
inline void plan_discard_current_block() inline void plan_discard_current_block()

View File

@ -158,20 +158,19 @@ void report_grbl_settings() {
printPgmString(PSTR(" (step port invert mask, int:")); print_uint8_base2(settings.invert_mask); printPgmString(PSTR(" (step port invert mask, int:")); print_uint8_base2(settings.invert_mask);
printPgmString(PSTR(")\r\n$12=")); printInteger(settings.stepper_idle_lock_time); printPgmString(PSTR(")\r\n$12=")); printInteger(settings.stepper_idle_lock_time);
printPgmString(PSTR(" (step idle delay, msec)\r\n$13=")); printFloat(settings.junction_deviation); printPgmString(PSTR(" (step idle delay, msec)\r\n$13=")); printFloat(settings.junction_deviation);
printPgmString(PSTR(" (junction deviation, mm)\r\n$14=")); printFloat(settings.mm_per_arc_segment); printPgmString(PSTR(" (junction deviation, mm)\r\n$14=")); printFloat(settings.arc_tolerance);
printPgmString(PSTR(" (arc, mm/segment)\r\n$15=")); printInteger(settings.n_arc_correction); printPgmString(PSTR(" (arc tolerance, mm)\r\n$15=")); printInteger(settings.decimal_places);
printPgmString(PSTR(" (n-arc correction, int)\r\n$16=")); printInteger(settings.decimal_places); printPgmString(PSTR(" (n-decimals, int)\r\n$16=")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
printPgmString(PSTR(" (n-decimals, int)\r\n$17=")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES)); printPgmString(PSTR(" (report inches, bool)\r\n$17=")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START));
printPgmString(PSTR(" (report inches, bool)\r\n$18=")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START)); printPgmString(PSTR(" (auto start, bool)\r\n$18=")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE));
printPgmString(PSTR(" (auto start, bool)\r\n$19=")); printInteger(bit_istrue(settings.flags,BITFLAG_INVERT_ST_ENABLE)); printPgmString(PSTR(" (invert step enable, bool)\r\n$19=")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
printPgmString(PSTR(" (invert step enable, bool)\r\n$20=")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE)); printPgmString(PSTR(" (hard limits, bool)\r\n$20=")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
printPgmString(PSTR(" (hard limits, bool)\r\n$21=")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)); printPgmString(PSTR(" (homing cycle, bool)\r\n$21=")); printInteger(settings.homing_dir_mask);
printPgmString(PSTR(" (homing cycle, bool)\r\n$22=")); printInteger(settings.homing_dir_mask);
printPgmString(PSTR(" (homing dir invert mask, int:")); print_uint8_base2(settings.homing_dir_mask); printPgmString(PSTR(" (homing dir invert mask, int:")); print_uint8_base2(settings.homing_dir_mask);
printPgmString(PSTR(")\r\n$23=")); printFloat(settings.homing_feed_rate); printPgmString(PSTR(")\r\n$22=")); printFloat(settings.homing_feed_rate);
printPgmString(PSTR(" (homing feed, mm/min)\r\n$24=")); printFloat(settings.homing_seek_rate); printPgmString(PSTR(" (homing feed, mm/min)\r\n$23=")); printFloat(settings.homing_seek_rate);
printPgmString(PSTR(" (homing seek, mm/min)\r\n$25=")); printInteger(settings.homing_debounce_delay); printPgmString(PSTR(" (homing seek, mm/min)\r\n$24=")); printInteger(settings.homing_debounce_delay);
printPgmString(PSTR(" (homing debounce, msec)\r\n$26=")); printFloat(settings.homing_pulloff); printPgmString(PSTR(" (homing debounce, msec)\r\n$25=")); printFloat(settings.homing_pulloff);
printPgmString(PSTR(" (homing pull-off, mm)\r\n")); printPgmString(PSTR(" (homing pull-off, mm)\r\n"));
} }

View File

@ -79,7 +79,7 @@ void settings_reset(bool reset_all) {
settings.acceleration[X_AXIS] = DEFAULT_ACCELERATION; settings.acceleration[X_AXIS] = DEFAULT_ACCELERATION;
settings.acceleration[Y_AXIS] = DEFAULT_ACCELERATION; settings.acceleration[Y_AXIS] = DEFAULT_ACCELERATION;
settings.acceleration[Z_AXIS] = DEFAULT_ACCELERATION; settings.acceleration[Z_AXIS] = DEFAULT_ACCELERATION;
settings.mm_per_arc_segment = DEFAULT_MM_PER_ARC_SEGMENT; settings.arc_tolerance = DEFAULT_ARC_TOLERANCE;
settings.invert_mask = DEFAULT_STEPPING_INVERT_MASK; settings.invert_mask = DEFAULT_STEPPING_INVERT_MASK;
settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION; settings.junction_deviation = DEFAULT_JUNCTION_DEVIATION;
} }
@ -97,7 +97,6 @@ void settings_reset(bool reset_all) {
settings.homing_pulloff = DEFAULT_HOMING_PULLOFF; settings.homing_pulloff = DEFAULT_HOMING_PULLOFF;
settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME; settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;
settings.decimal_places = DEFAULT_DECIMAL_PLACES; settings.decimal_places = DEFAULT_DECIMAL_PLACES;
settings.n_arc_correction = DEFAULT_N_ARC_CORRECTION;
write_global_settings(); write_global_settings();
} }
@ -173,35 +172,34 @@ uint8_t settings_store_global_setting(int parameter, float value) {
case 11: settings.invert_mask = trunc(value); break; case 11: settings.invert_mask = trunc(value); break;
case 12: settings.stepper_idle_lock_time = round(value); break; case 12: settings.stepper_idle_lock_time = round(value); break;
case 13: settings.junction_deviation = fabs(value); break; case 13: settings.junction_deviation = fabs(value); break;
case 14: settings.mm_per_arc_segment = value; break; case 14: settings.arc_tolerance = value; break;
case 15: settings.n_arc_correction = round(value); break; case 15: settings.decimal_places = round(value); break;
case 16: settings.decimal_places = round(value); break; case 16:
case 17:
if (value) { settings.flags |= BITFLAG_REPORT_INCHES; } if (value) { settings.flags |= BITFLAG_REPORT_INCHES; }
else { settings.flags &= ~BITFLAG_REPORT_INCHES; } else { settings.flags &= ~BITFLAG_REPORT_INCHES; }
break; break;
case 18: // Reset to ensure change. Immediate re-init may cause problems. case 17: // Reset to ensure change. Immediate re-init may cause problems.
if (value) { settings.flags |= BITFLAG_AUTO_START; } if (value) { settings.flags |= BITFLAG_AUTO_START; }
else { settings.flags &= ~BITFLAG_AUTO_START; } else { settings.flags &= ~BITFLAG_AUTO_START; }
break; break;
case 19: // Reset to ensure change. Immediate re-init may cause problems. case 18: // Reset to ensure change. Immediate re-init may cause problems.
if (value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; } if (value) { settings.flags |= BITFLAG_INVERT_ST_ENABLE; }
else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; } else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; }
break; break;
case 20: case 19:
if (value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; } if (value) { settings.flags |= BITFLAG_HARD_LIMIT_ENABLE; }
else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; } else { settings.flags &= ~BITFLAG_HARD_LIMIT_ENABLE; }
limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later. limits_init(); // Re-init to immediately change. NOTE: Nice to have but could be problematic later.
break; break;
case 21: case 20:
if (value) { settings.flags |= BITFLAG_HOMING_ENABLE; } if (value) { settings.flags |= BITFLAG_HOMING_ENABLE; }
else { settings.flags &= ~BITFLAG_HOMING_ENABLE; } else { settings.flags &= ~BITFLAG_HOMING_ENABLE; }
break; break;
case 22: settings.homing_dir_mask = trunc(value); break; case 21: settings.homing_dir_mask = trunc(value); break;
case 23: settings.homing_feed_rate = value; break; case 22: settings.homing_feed_rate = value; break;
case 24: settings.homing_seek_rate = value; break; case 23: settings.homing_seek_rate = value; break;
case 25: settings.homing_debounce_delay = round(value); break; case 24: settings.homing_debounce_delay = round(value); break;
case 26: settings.homing_pulloff = value; break; case 25: settings.homing_pulloff = value; break;
default: default:
return(STATUS_INVALID_STATEMENT); return(STATUS_INVALID_STATEMENT);
} }

View File

@ -29,7 +29,7 @@
// Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl // Version of the EEPROM data. Will be used to migrate existing data from older versions of Grbl
// when firmware is upgraded. Always stored in byte 0 of eeprom // when firmware is upgraded. Always stored in byte 0 of eeprom
#define SETTINGS_VERSION 51 #define SETTINGS_VERSION 52
// Define bit flag masks for the boolean settings in settings.flag. // Define bit flag masks for the boolean settings in settings.flag.
#define BITFLAG_REPORT_INCHES bit(0) #define BITFLAG_REPORT_INCHES bit(0)
@ -62,7 +62,7 @@ typedef struct {
float default_feed_rate; float default_feed_rate;
float default_seek_rate; float default_seek_rate;
uint8_t invert_mask; uint8_t invert_mask;
float mm_per_arc_segment; float arc_tolerance;
float acceleration[N_AXIS]; float acceleration[N_AXIS];
float junction_deviation; float junction_deviation;
uint8_t flags; // Contains default boolean settings uint8_t flags; // Contains default boolean settings
@ -73,7 +73,6 @@ typedef struct {
float homing_pulloff; float homing_pulloff;
uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable. uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable.
uint8_t decimal_places; uint8_t decimal_places;
uint8_t n_arc_correction;
float max_velocity[N_AXIS]; float max_velocity[N_AXIS];
// float mm_soft_limit[N_AXIS]; // float mm_soft_limit[N_AXIS];
// uint8_t status_report_mask; // Mask to indicate desired report data. // uint8_t status_report_mask; // Mask to indicate desired report data.

View File

@ -30,7 +30,6 @@
// Some useful constants // Some useful constants
#define TICKS_PER_MICROSECOND (F_CPU/1000000) #define TICKS_PER_MICROSECOND (F_CPU/1000000)
#define INTERRUPTS_PER_ACCELERATION_TICK (ISR_TICKS_PER_SECOND/ACCELERATION_TICKS_PER_SECOND)
#define CRUISE_RAMP 0 #define CRUISE_RAMP 0
#define ACCEL_RAMP 1 #define ACCEL_RAMP 1
#define DECEL_RAMP 2 #define DECEL_RAMP 2
@ -47,7 +46,7 @@ typedef struct {
// Used by Pramod Ranade inverse time algorithm // Used by Pramod Ranade inverse time algorithm
int32_t delta_d; // Ranade distance traveled per interrupt tick int32_t delta_d; // Ranade distance traveled per interrupt tick
int32_t d_counter; // Ranade distance traveled since last step event int32_t d_counter; // Ranade distance traveled since last step event
uint32_t ramp_count; // Acceleration interrupt tick counter. uint8_t ramp_count; // Acceleration interrupt tick counter.
uint8_t ramp_type; // Ramp type variable. uint8_t ramp_type; // Ramp type variable.
uint8_t execute_step; // Flags step execution for each interrupt. uint8_t execute_step; // Flags step execution for each interrupt.