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:
parent
a1397f61c4
commit
3dfffa622d
26
config.h
26
config.h
@ -105,14 +105,6 @@
|
||||
#define CMD_CYCLE_START '~'
|
||||
#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
|
||||
// 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
|
||||
@ -124,6 +116,17 @@
|
||||
// 20kHz by performing two steps per step event, rather than just one.
|
||||
#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
|
||||
// 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
|
||||
@ -193,6 +196,13 @@
|
||||
// parser state depending on user preferences.
|
||||
#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:
|
||||
|
||||
|
12
defaults.h
12
defaults.h
@ -33,7 +33,7 @@
|
||||
#define DEFAULT_Y_STEPS_PER_MM 250.0
|
||||
#define DEFAULT_Z_STEPS_PER_MM 250.0
|
||||
#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_FEEDRATE 250.0
|
||||
#define DEFAULT_ACCELERATION (10.0*60*60) // 10 mm/min^2
|
||||
@ -51,7 +51,6 @@
|
||||
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
|
||||
#define DEFAULT_DECIMAL_PLACES 3
|
||||
#define DEFAULT_N_ARC_CORRECTION 25
|
||||
#endif
|
||||
|
||||
#ifdef DEFAULTS_SHERLINE_5400
|
||||
@ -64,7 +63,7 @@
|
||||
#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_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_FEEDRATE 254.0 // mm/min (10ipm)
|
||||
#define DEFAULT_ACCELERATION 50.0*60*60 // 50 mm/min^2
|
||||
@ -82,7 +81,6 @@
|
||||
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
|
||||
#define DEFAULT_DECIMAL_PLACES 3
|
||||
#define DEFAULT_N_ARC_CORRECTION 25
|
||||
#endif
|
||||
|
||||
#ifdef DEFAULTS_SHAPEOKO
|
||||
@ -98,7 +96,7 @@
|
||||
#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_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_FEEDRATE 250.0
|
||||
#define DEFAULT_ACCELERATION (15.0*60*60) // 15 mm/min^2
|
||||
@ -116,7 +114,6 @@
|
||||
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-255)
|
||||
#define DEFAULT_DECIMAL_PLACES 3
|
||||
#define DEFAULT_N_ARC_CORRECTION 25
|
||||
#endif
|
||||
|
||||
#ifdef DEFAULTS_ZEN_TOOLWORKS_7x7
|
||||
@ -130,7 +127,7 @@
|
||||
#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_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_FEEDRATE 1000.0 // mm/min
|
||||
#define DEFAULT_ACCELERATION 150.0*60*60 // 150 mm/min^2
|
||||
@ -148,7 +145,6 @@
|
||||
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
|
||||
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 25 // msec (0-255)
|
||||
#define DEFAULT_DECIMAL_PLACES 3
|
||||
#define DEFAULT_N_ARC_CORRECTION 25
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
158
motion_control.c
158
motion_control.c
@ -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
|
||||
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
|
||||
// for vector transformation direction.
|
||||
// The arc is approximated by generating a huge number of tiny, linear segments. The length of each
|
||||
// segment is configured in settings.mm_per_arc_segment.
|
||||
// The arc is approximated by generating a huge number of tiny, linear segments. The chordal tolerance
|
||||
// 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)
|
||||
{
|
||||
@ -111,83 +112,90 @@ void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8
|
||||
} else {
|
||||
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));
|
||||
if (millimeters_of_travel == 0.0) { return; }
|
||||
uint16_t segments = floor(millimeters_of_travel/settings.mm_per_arc_segment);
|
||||
// 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
|
||||
// all segments.
|
||||
if (invert_feed_rate) { feed_rate *= segments; }
|
||||
|
||||
float theta_per_segment = angular_travel/segments;
|
||||
float linear_per_segment = linear_travel/segments;
|
||||
uint16_t segments = floor(millimeters_of_travel/
|
||||
sqrt(4*settings.arc_tolerance*(2*radius - settings.arc_tolerance)) );
|
||||
|
||||
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
||||
and phi is the angle of rotation. Solution approach by Jens Geisler.
|
||||
r_T = [cos(phi) -sin(phi);
|
||||
sin(phi) cos(phi] * r ;
|
||||
|
||||
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
|
||||
vector rotations. This requires only two cos() and sin() computations to form the rotation
|
||||
matrix for the duration of the entire arc. Error may accumulate from numerical round-off, since
|
||||
all double numbers are single precision on the Arduino. (True double precision will not have
|
||||
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
|
||||
holds for everything, but very small circles and large mm_per_arc_segment values. In other words,
|
||||
theta_per_segment would need to be greater than 0.1 rad and N_ARC_CORRECTION would need to be large
|
||||
to cause an appreciable drift error. N_ARC_CORRECTION~=25 is more than small enough to correct for
|
||||
numerical drift error. N_ARC_CORRECTION may be on the order a hundred(s) before error becomes an
|
||||
issue for CNC machines with the single precision Arduino calculations.
|
||||
|
||||
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
|
||||
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.
|
||||
*/
|
||||
// Vector rotation matrix values
|
||||
float cos_T = 1-0.5*theta_per_segment*theta_per_segment; // Small angle approximation
|
||||
float sin_T = theta_per_segment;
|
||||
|
||||
float arc_target[3];
|
||||
float sin_Ti;
|
||||
float cos_Ti;
|
||||
float r_axisi;
|
||||
uint16_t i;
|
||||
int8_t count = 0;
|
||||
|
||||
// Initialize the linear axis
|
||||
arc_target[axis_linear] = position[axis_linear];
|
||||
|
||||
for (i = 1; i<segments; i++) { // Increment (segments-1)
|
||||
if (segments) {
|
||||
// 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
|
||||
// all segments.
|
||||
if (invert_feed_rate) { feed_rate *= segments; }
|
||||
|
||||
float theta_per_segment = angular_travel/segments;
|
||||
float linear_per_segment = linear_travel/segments;
|
||||
|
||||
if (count < settings.n_arc_correction) {
|
||||
// Apply vector rotation matrix
|
||||
r_axisi = r_axis0*sin_T + r_axis1*cos_T;
|
||||
r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
|
||||
r_axis1 = r_axisi;
|
||||
count++;
|
||||
} else {
|
||||
// Arc correction to radius vector. Computed only every n_arc_correction increments.
|
||||
// Compute exact location by applying transformation matrix from initial radius vector(=-offset).
|
||||
cos_Ti = cos(i*theta_per_segment);
|
||||
sin_Ti = sin(i*theta_per_segment);
|
||||
r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;
|
||||
r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;
|
||||
count = 0;
|
||||
/* Vector rotation by transformation matrix: r is the original vector, r_T is the rotated vector,
|
||||
and phi is the angle of rotation. Solution approach by Jens Geisler.
|
||||
r_T = [cos(phi) -sin(phi);
|
||||
sin(phi) cos(phi] * r ;
|
||||
|
||||
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
|
||||
vector rotations. Single precision values can accumulate error greater than tool precision in some
|
||||
cases. So, exact arc path correction is implemented. This approach avoids the problem of too many very
|
||||
expensive trig operations [sin(),cos(),tan()] which can take 100-200 usec each to compute.
|
||||
|
||||
Small angle approximation may be used to reduce computation overhead further. A third-order approximation
|
||||
(second order sin() has too much error) holds for nearly all CNC applications, except for possibly very
|
||||
small radii (~0.5mm). In other words, theta_per_segment would need to be greater than 0.25 rad(14 deg)
|
||||
and N_ARC_CORRECTION would need to be large to cause an appreciable drift error (>5% of radius, for very
|
||||
small radii this is very, very small). N_ARC_CORRECTION~=20 should be more than small enough to correct
|
||||
for numerical drift error.
|
||||
|
||||
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
|
||||
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.
|
||||
*/
|
||||
// Computes: cos_T = 1 - theta_per_segment^2/2, sin_T = theta_per_segment - theta_per_segment^3/6) in ~52usec
|
||||
float cos_T = 2 - theta_per_segment*theta_per_segment;
|
||||
float sin_T = theta_per_segment*0.1666667*(cos_T + 4);
|
||||
cos_T *= 0.5;
|
||||
|
||||
float arc_target[N_AXIS];
|
||||
float sin_Ti;
|
||||
float cos_Ti;
|
||||
float r_axisi;
|
||||
uint16_t i;
|
||||
int8_t count = 0;
|
||||
|
||||
// Initialize the linear axis
|
||||
arc_target[axis_linear] = position[axis_linear];
|
||||
|
||||
for (i = 1; i<segments; i++) { // Increment (segments-1)
|
||||
|
||||
if (count < N_ARC_CORRECTION) {
|
||||
// Apply vector rotation matrix. ~40 usec
|
||||
r_axisi = r_axis0*sin_T + r_axis1*cos_T;
|
||||
r_axis0 = r_axis0*cos_T - r_axis1*sin_T;
|
||||
r_axis1 = r_axisi;
|
||||
count++;
|
||||
} else {
|
||||
// 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).
|
||||
cos_Ti = cos(i*theta_per_segment);
|
||||
sin_Ti = sin(i*theta_per_segment);
|
||||
r_axis0 = -offset[axis_0]*cos_Ti + offset[axis_1]*sin_Ti;
|
||||
r_axis1 = -offset[axis_0]*sin_Ti - offset[axis_1]*cos_Ti;
|
||||
count = 0;
|
||||
}
|
||||
|
||||
// Update arc_target location
|
||||
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[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], feed_rate, invert_feed_rate);
|
||||
|
||||
// Bail mid-circle on system abort. Runtime command check already performed by mc_line.
|
||||
if (sys.abort) { return; }
|
||||
}
|
||||
|
||||
// Update arc_target location
|
||||
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[X_AXIS], arc_target[Y_AXIS], arc_target[Z_AXIS], feed_rate, invert_feed_rate);
|
||||
|
||||
// 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[X_AXIS], target[Y_AXIS], target[Z_AXIS], feed_rate, invert_feed_rate);
|
||||
|
77
planner.c
77
planner.c
@ -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_tail; // Index of the block to process now
|
||||
static uint8_t next_buffer_head; // Index of the next buffer head
|
||||
// static *block_t block_buffer_planned;
|
||||
|
||||
// Define planner variables
|
||||
typedef struct {
|
||||
@ -190,12 +191,82 @@ static void calculate_trapezoid_for_block(block_t *block, float entry_speed_sqr,
|
||||
*/
|
||||
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
|
||||
// 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.
|
||||
|
||||
// if (block_buffer_head != block_buffer_tail) {
|
||||
|
||||
// if (block_buffer_head != block_buffer_tail) {
|
||||
float entry_speed_sqr;
|
||||
|
||||
// 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.
|
||||
calculate_trapezoid_for_block(next, next->entry_speed_sqr, MINIMUM_PLANNER_SPEED*MINIMUM_PLANNER_SPEED);
|
||||
next->recalculate_flag = false;
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
@ -276,6 +346,7 @@ void plan_reset_buffer()
|
||||
{
|
||||
block_buffer_tail = block_buffer_head;
|
||||
next_buffer_head = next_block_index(block_buffer_head);
|
||||
// block_buffer_planned = block_buffer_head;
|
||||
}
|
||||
|
||||
inline void plan_discard_current_block()
|
||||
|
25
report.c
25
report.c
@ -158,20 +158,19 @@ void report_grbl_settings() {
|
||||
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(" (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(" (arc, mm/segment)\r\n$15=")); printInteger(settings.n_arc_correction);
|
||||
printPgmString(PSTR(" (n-arc correction, int)\r\n$16=")); printInteger(settings.decimal_places);
|
||||
printPgmString(PSTR(" (n-decimals, int)\r\n$17=")); printInteger(bit_istrue(settings.flags,BITFLAG_REPORT_INCHES));
|
||||
printPgmString(PSTR(" (report inches, bool)\r\n$18=")); printInteger(bit_istrue(settings.flags,BITFLAG_AUTO_START));
|
||||
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$20=")); printInteger(bit_istrue(settings.flags,BITFLAG_HARD_LIMIT_ENABLE));
|
||||
printPgmString(PSTR(" (hard limits, bool)\r\n$21=")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
|
||||
printPgmString(PSTR(" (homing cycle, bool)\r\n$22=")); printInteger(settings.homing_dir_mask);
|
||||
printPgmString(PSTR(" (junction deviation, mm)\r\n$14=")); printFloat(settings.arc_tolerance);
|
||||
printPgmString(PSTR(" (arc tolerance, mm)\r\n$15=")); printInteger(settings.decimal_places);
|
||||
printPgmString(PSTR(" (n-decimals, int)\r\n$16=")); 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(" (auto start, bool)\r\n$18=")); 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(" (hard limits, bool)\r\n$20=")); printInteger(bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE));
|
||||
printPgmString(PSTR(" (homing cycle, bool)\r\n$21=")); printInteger(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(" (homing feed, mm/min)\r\n$24=")); printFloat(settings.homing_seek_rate);
|
||||
printPgmString(PSTR(" (homing seek, mm/min)\r\n$25=")); printInteger(settings.homing_debounce_delay);
|
||||
printPgmString(PSTR(" (homing debounce, msec)\r\n$26=")); printFloat(settings.homing_pulloff);
|
||||
printPgmString(PSTR(")\r\n$22=")); printFloat(settings.homing_feed_rate);
|
||||
printPgmString(PSTR(" (homing feed, mm/min)\r\n$23=")); printFloat(settings.homing_seek_rate);
|
||||
printPgmString(PSTR(" (homing seek, mm/min)\r\n$24=")); printInteger(settings.homing_debounce_delay);
|
||||
printPgmString(PSTR(" (homing debounce, msec)\r\n$25=")); printFloat(settings.homing_pulloff);
|
||||
printPgmString(PSTR(" (homing pull-off, mm)\r\n"));
|
||||
}
|
||||
|
||||
|
28
settings.c
28
settings.c
@ -79,7 +79,7 @@ void settings_reset(bool reset_all) {
|
||||
settings.acceleration[X_AXIS] = DEFAULT_ACCELERATION;
|
||||
settings.acceleration[Y_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.junction_deviation = DEFAULT_JUNCTION_DEVIATION;
|
||||
}
|
||||
@ -97,7 +97,6 @@ void settings_reset(bool reset_all) {
|
||||
settings.homing_pulloff = DEFAULT_HOMING_PULLOFF;
|
||||
settings.stepper_idle_lock_time = DEFAULT_STEPPER_IDLE_LOCK_TIME;
|
||||
settings.decimal_places = DEFAULT_DECIMAL_PLACES;
|
||||
settings.n_arc_correction = DEFAULT_N_ARC_CORRECTION;
|
||||
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 12: settings.stepper_idle_lock_time = round(value); break;
|
||||
case 13: settings.junction_deviation = fabs(value); break;
|
||||
case 14: settings.mm_per_arc_segment = value; break;
|
||||
case 15: settings.n_arc_correction = round(value); break;
|
||||
case 16: settings.decimal_places = round(value); break;
|
||||
case 17:
|
||||
case 14: settings.arc_tolerance = value; break;
|
||||
case 15: settings.decimal_places = round(value); break;
|
||||
case 16:
|
||||
if (value) { settings.flags |= BITFLAG_REPORT_INCHES; }
|
||||
else { settings.flags &= ~BITFLAG_REPORT_INCHES; }
|
||||
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; }
|
||||
else { settings.flags &= ~BITFLAG_AUTO_START; }
|
||||
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; }
|
||||
else { settings.flags &= ~BITFLAG_INVERT_ST_ENABLE; }
|
||||
break;
|
||||
case 20:
|
||||
case 19:
|
||||
if (value) { 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.
|
||||
break;
|
||||
case 21:
|
||||
case 20:
|
||||
if (value) { settings.flags |= BITFLAG_HOMING_ENABLE; }
|
||||
else { settings.flags &= ~BITFLAG_HOMING_ENABLE; }
|
||||
break;
|
||||
case 22: settings.homing_dir_mask = trunc(value); break;
|
||||
case 23: settings.homing_feed_rate = value; break;
|
||||
case 24: settings.homing_seek_rate = value; break;
|
||||
case 25: settings.homing_debounce_delay = round(value); break;
|
||||
case 26: settings.homing_pulloff = value; break;
|
||||
case 21: settings.homing_dir_mask = trunc(value); break;
|
||||
case 22: settings.homing_feed_rate = value; break;
|
||||
case 23: settings.homing_seek_rate = value; break;
|
||||
case 24: settings.homing_debounce_delay = round(value); break;
|
||||
case 25: settings.homing_pulloff = value; break;
|
||||
default:
|
||||
return(STATUS_INVALID_STATEMENT);
|
||||
}
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
// 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
|
||||
#define SETTINGS_VERSION 51
|
||||
#define SETTINGS_VERSION 52
|
||||
|
||||
// Define bit flag masks for the boolean settings in settings.flag.
|
||||
#define BITFLAG_REPORT_INCHES bit(0)
|
||||
@ -62,7 +62,7 @@ typedef struct {
|
||||
float default_feed_rate;
|
||||
float default_seek_rate;
|
||||
uint8_t invert_mask;
|
||||
float mm_per_arc_segment;
|
||||
float arc_tolerance;
|
||||
float acceleration[N_AXIS];
|
||||
float junction_deviation;
|
||||
uint8_t flags; // Contains default boolean settings
|
||||
@ -73,9 +73,8 @@ typedef struct {
|
||||
float homing_pulloff;
|
||||
uint8_t stepper_idle_lock_time; // If max value 255, steppers do not disable.
|
||||
uint8_t decimal_places;
|
||||
uint8_t n_arc_correction;
|
||||
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.
|
||||
} settings_t;
|
||||
extern settings_t settings;
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
// Some useful constants
|
||||
#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 ACCEL_RAMP 1
|
||||
#define DECEL_RAMP 2
|
||||
@ -47,7 +46,7 @@ typedef struct {
|
||||
// Used by Pramod Ranade inverse time algorithm
|
||||
int32_t delta_d; // Ranade distance traveled per interrupt tick
|
||||
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 execute_step; // Flags step execution for each interrupt.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user