Revamped homing cycle. Axis limits and max travel bug fixes. Build info. Refactored config.h.

- Revamped and improved homing cycle. Now tied directly into the main
planner and stepper code, which enables much faster homing seek rates.
Also dropped the compiled flash size by almost 1KB, meaning 1KB more
for other features.

- Refactored config.h. Removed obsolete defines and configuration
options. Moved lots of “advanced” options into the advanced area of the
file.

- Updated defaults.h with the new homing cycle. Also updated the
Sherline 5400 defaults and added the ShapeOko2 defaults per user
submissions.

- Fixed a bug where the individual axes limits on velocity and
acceleration were not working correctly. Caused by abs() returning a
int, rather than a float. Corrected with fabs(). Duh.

- Added build version/date to the Grbl welcome message to help indicate
which version a user is operating on.

- Max travel settings were not being defaulted into the settings EEPROM
correctly. Fixed.

- To stop a single axis during a multi-axes homing move, the stepper
algorithm now has a simple axis lock mask which inhibits the desired
axes from moving. Meaning, if one of the limit switches engages before
the other, we stop that one axes and keep moving the other.
This commit is contained in:
Sonny Jeon 2013-12-10 22:33:06 -07:00
parent b562845d9d
commit 3054b2df77
10 changed files with 188 additions and 251 deletions

117
config.h
View File

@ -29,7 +29,7 @@
#define config_h #define config_h
// Default settings. Used when resetting EEPROM. Change to desired name in defaults.h // Default settings. Used when resetting EEPROM. Change to desired name in defaults.h
#define DEFAULTS_ZEN_TOOLWORKS_7x7 #define DEFAULTS_SHERLINE_5400
// Serial baud rate // Serial baud rate
#define BAUD_RATE 115200 #define BAUD_RATE 115200
@ -49,76 +49,17 @@
#define CMD_CYCLE_START '~' #define CMD_CYCLE_START '~'
#define CMD_RESET 0x18 // ctrl-x #define CMD_RESET 0x18 // ctrl-x
// The "Stepper Driver Interrupt" employs an inverse time algorithm to manage the Bresenham line // Uncomment the following define if you are using hardware that drives high when your limits
// stepping algorithm. The value ISR_TICKS_PER_SECOND is the frequency(Hz) at which the inverse time // are reached. You will need to ensure that you have appropriate pull-down resistors on the
// algorithm ticks at. Recommended step frequencies are limited by the inverse time frequency by // limit switch input pins, or that your hardware drives the pins low when they are open (non-
// approximately 0.75-0.9 * ISR_TICK_PER_SECOND. Meaning for 30kHz, the max step frequency is roughly // triggered).
// 22.5-27kHz, but 30kHz is still possible, just not optimal. An Arduino can safely complete a single // #define LIMIT_SWITCHES_ACTIVE_HIGH
// interrupt of the current stepper driver algorithm theoretically up to a frequency of 35-40kHz, but
// CPU overhead increases exponentially as this frequency goes up. So there will be little left for
// other processes like arcs.
#define ISR_TICKS_PER_SECOND 30000L // 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.
// NOTE: Ramp count variable type in stepper module may need to be updated if changed.
#define ACCELERATION_TICKS_PER_SECOND 120L
// NOTE: Make sure this value is less than 256, when adjusting both dependent parameters.
#define ISR_TICKS_PER_ACCELERATION_TICK (ISR_TICKS_PER_SECOND/ACCELERATION_TICKS_PER_SECOND)
// The inverse time algorithm can use either floating point or long integers for its counters (usually
// very small values ~10^-6), but with integers, the counter values must be scaled to be greater than
// one. This multiplier value scales the floating point counter values for use in a long integer, which
// are significantly faster to compute with a slightly higher precision ceiling than floats. Long
// integers are finite so select the multiplier value high enough to avoid any numerical round-off
// issues and still have enough range to account for all motion types. However, in most all imaginable
// CNC applications, the following multiplier value will work more than well enough. If you do have
// happened to weird stepper motion issues, try modifying this value by adding or subtracting a
// zero and report it to the Grbl administrators.
#define INV_TIME_MULTIPLIER 100000
// Minimum stepper rate for the "Stepper Driver Interrupt". Sets the absolute minimum stepper rate
// in the stepper program and never runs slower than this value. If the INVE_TIME_MULTIPLIER value
// changes, it will affect how this value works. So, if a zero is add/subtracted from the
// INV_TIME_MULTIPLIER value, do the same to this value if you want to same response.
// NOTE: Compute by (desired_step_rate/60) * INV_TIME_MULTIPLIER/ISR_TICKS_PER_SECOND. (mm/min)
// #define MINIMUM_STEP_RATE 1000L // Integer (mult*mm/isr_tic)
// Minimum stepper rate. Only used by homing at this point. May be removed in later releases.
#define MINIMUM_STEPS_PER_MINUTE 800 // (steps/min) - Integer value only
// Minimum planner junction speed. Sets the default minimum junction speed the planner plans to at
// every buffer block junction, except for starting from rest and end of the buffer, which are always
// zero. This value controls how fast the machine moves through junctions with no regard for acceleration
// limits or angle between neighboring block line move directions. This is useful for machines that can't
// tolerate the tool dwelling for a split second, i.e. 3d printers or laser cutters. If used, this value
// should not be much greater than zero or to the minimum value necessary for the machine to work.
#define MINIMUM_JUNCTION_SPEED 0.0 // (mm/min)
// Time delay increments performed during a dwell. The default value is set at 50ms, which provides
// a maximum time delay of roughly 55 minutes, more than enough for most any application. Increasing
// this delay will increase the maximum dwell time linearly, but also reduces the responsiveness of
// run-time command executions, like status reports, since these are performed between each dwell
// time step. Also, keep in mind that the Arduino delay timer is not very accurate for long delays.
#define DWELL_TIME_STEP 50 // Integer (1-255) (milliseconds)
// If homing is enabled, homing init lock sets Grbl into an alarm state upon power up. This forces // If homing is enabled, homing init lock sets Grbl into an alarm state upon power up. This forces
// the user to perform the homing cycle (or override the locks) before doing anything else. This is // the user to perform the homing cycle (or override the locks) before doing anything else. This is
// mainly a safety feature to remind the user to home, since position is unknown to Grbl. // mainly a safety feature to remind the user to home, since position is unknown to Grbl.
#define HOMING_INIT_LOCK // Comment to disable #define HOMING_INIT_LOCK // Comment to disable
// The homing cycle seek and feed rates will adjust so all axes independently move at the homing
// seek and feed rates regardless of how many axes are in motion simultaneously. If disabled, rates
// are point-to-point rates, as done in normal operation. For example in an XY diagonal motion, the
// diagonal motion moves at the intended rate, but the individual axes move at 70% speed. This option
// just moves them all at 100% speed.
#define HOMING_RATE_ADJUST // Comment to disable
// Define the homing cycle search patterns with bitmasks. The homing cycle first performs a search // Define the homing cycle search patterns with bitmasks. The homing cycle first performs a search
// to engage the limit switches. HOMING_SEARCH_CYCLE_x are executed in order starting with suffix 0 // to engage the limit switches. HOMING_SEARCH_CYCLE_x are executed in order starting with suffix 0
// and searches the enabled axes in the bitmask. This allows for users with non-standard cartesian // and searches the enabled axes in the bitmask. This allows for users with non-standard cartesian
@ -144,6 +85,39 @@
// 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)
// ---------------------------------------------------------------------------------------
// ADVANCED CONFIGURATION OPTIONS:
// The "Stepper Driver Interrupt" employs an inverse time algorithm to manage the Bresenham line
// stepping algorithm. The value ISR_TICKS_PER_SECOND is the frequency(Hz) at which the inverse time
// algorithm ticks at. Recommended step frequencies are limited by the inverse time frequency by
// approximately 0.75-0.9 * ISR_TICK_PER_SECOND. Meaning for 30kHz, the max step frequency is roughly
// 22.5-27kHz, but 30kHz is still possible, just not optimal. An Arduino can safely complete a single
// interrupt of the current stepper driver algorithm theoretically up to a frequency of 35-40kHz, but
// CPU overhead increases exponentially as this frequency goes up. So there will be little left for
// other processes like arcs.
#define ISR_TICKS_PER_SECOND 30000L // 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.
// NOTE: Ramp count variable type in stepper module may need to be updated if changed.
#define ACCELERATION_TICKS_PER_SECOND 120L
// NOTE: Make sure this value is less than 256, when adjusting both dependent parameters.
#define ISR_TICKS_PER_ACCELERATION_TICK (ISR_TICKS_PER_SECOND/ACCELERATION_TICKS_PER_SECOND)
// Minimum planner junction speed. Sets the default minimum junction speed the planner plans to at
// every buffer block junction, except for starting from rest and end of the buffer, which are always
// zero. This value controls how fast the machine moves through junctions with no regard for acceleration
// limits or angle between neighboring block line move directions. This is useful for machines that can't
// tolerate the tool dwelling for a split second, i.e. 3d printers or laser cutters. If used, this value
// should not be much greater than zero or to the minimum value necessary for the machine to work.
#define MINIMUM_JUNCTION_SPEED 0.0 // (mm/min)
// Number of arc generation iterations by small angle approximation before exact arc trajectory // 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 // 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 // generations. In general, the default value is more than enough for the intended CNC applications
@ -151,8 +125,12 @@
// computational efficiency of generating arcs. // computational efficiency of generating arcs.
#define N_ARC_CORRECTION 20 // Integer (1-255) #define N_ARC_CORRECTION 20 // Integer (1-255)
// --------------------------------------------------------------------------------------- // Time delay increments performed during a dwell. The default value is set at 50ms, which provides
// FOR ADVANCED USERS ONLY: // a maximum time delay of roughly 55 minutes, more than enough for most any application. Increasing
// this delay will increase the maximum dwell time linearly, but also reduces the responsiveness of
// run-time command executions, like status reports, since these are performed between each dwell
// time step. Also, keep in mind that the Arduino delay timer is not very accurate for long delays.
#define DWELL_TIME_STEP 50 // Integer (1-255) (milliseconds)
// The number of linear motions in the planner buffer to be planned at any give time. The vast // The number of linear motions in the planner buffer to be planned at any give time. The vast
// majority of RAM that Grbl uses is based on this buffer size. Only increase if there is extra // majority of RAM that Grbl uses is based on this buffer size. Only increase if there is extra
@ -198,11 +176,6 @@
// case, please report any successes to grbl administrators! // case, please report any successes to grbl administrators!
// #define ENABLE_XONXOFF // Default disabled. Uncomment to enable. // #define ENABLE_XONXOFF // Default disabled. Uncomment to enable.
// Uncomment the following define if you are using hardware that drives high when your limits
// are reached. You will need to ensure that you have appropriate pull-down resistors on the
// limit switch input pins, or that your hardware drives the pins low when they are open (non-
// triggered).
// #define LIMIT_SWITCHES_ACTIVE_HIGH
// --------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------

View File

@ -56,8 +56,8 @@
#define DEFAULT_HOMING_ENABLE 0 // false #define DEFAULT_HOMING_ENABLE 0 // false
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
#define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min #define DEFAULT_HOMING_SEEK_RATE 500.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 100 // msec (0-65k) #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_HOMING_PULLOFF 1.0 // mm
#endif #endif
@ -76,9 +76,9 @@
#define DEFAULT_X_ACCELERATION (50.0*60*60) // 10 mm/min^2 #define DEFAULT_X_ACCELERATION (50.0*60*60) // 10 mm/min^2
#define DEFAULT_Y_ACCELERATION (50.0*60*60) // 10 mm/min^2 #define DEFAULT_Y_ACCELERATION (50.0*60*60) // 10 mm/min^2
#define DEFAULT_Z_ACCELERATION (50.0*60*60) // 10 mm/min^2 #define DEFAULT_Z_ACCELERATION (50.0*60*60) // 10 mm/min^2
#define DEFAULT_X_MAX_TRAVEL 200.0 // mm #define DEFAULT_X_MAX_TRAVEL 225.0 // mm
#define DEFAULT_Y_MAX_TRAVEL 200.0 // mm #define DEFAULT_Y_MAX_TRAVEL 125.0 // mm
#define DEFAULT_Z_MAX_TRAVEL 200.0 // mm #define DEFAULT_Z_MAX_TRAVEL 170.0 // mm
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_FEEDRATE 254.0 // mm/min (10 ipm) #define DEFAULT_FEEDRATE 254.0 // mm/min (10 ipm)
#define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) #define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
@ -86,16 +86,16 @@
#define DEFAULT_JUNCTION_DEVIATION 0.02 // mm #define DEFAULT_JUNCTION_DEVIATION 0.02 // mm
#define DEFAULT_ARC_TOLERANCE 0.005 // mm #define DEFAULT_ARC_TOLERANCE 0.005 // mm
#define DEFAULT_DECIMAL_PLACES 3 #define DEFAULT_DECIMAL_PLACES 3
#define DEFAULT_REPORT_INCHES 1 // true #define DEFAULT_REPORT_INCHES 0 // true
#define DEFAULT_AUTO_START 1 // true #define DEFAULT_AUTO_START 1 // true
#define DEFAULT_INVERT_ST_ENABLE 0 // false #define DEFAULT_INVERT_ST_ENABLE 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false #define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false #define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 0 // false #define DEFAULT_HOMING_ENABLE 0 // false
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
#define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min #define DEFAULT_HOMING_FEED_RATE 50.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min #define DEFAULT_HOMING_SEEK_RATE 500.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 100 // msec (0-65k) #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_HOMING_PULLOFF 1.0 // mm
#endif #endif
@ -136,7 +136,48 @@
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
#define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min #define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 100 // msec (0-65k) #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1.0 // mm
#endif
#ifdef DEFAULTS_SHAPEOKO_2
// Description: Shapeoko CNC mill with three NEMA 17 stepper motors, driven by Synthetos
// grblShield with a 24V, 4.2A power supply.
#define MICROSTEPS_XY 8
#define STEP_REVS_XY 200
#define MM_PER_REV_XY (2.0*20) // 2mm belt pitch, 20 pulley teeth
#define MICROSTEPS_Z 2
#define STEP_REVS_Z 200
#define MM_PER_REV_Z 1.250 // 1.25 mm/rev leadscrew
#define DEFAULT_X_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_X_MAX_RATE 800.0 // mm/min
#define DEFAULT_Y_MAX_RATE 800.0 // mm/min
#define DEFAULT_Z_MAX_RATE 800.0 // mm/min
#define DEFAULT_X_ACCELERATION (15.0*60*60) // 10 mm/min^2
#define DEFAULT_Y_ACCELERATION (15.0*60*60) // 10 mm/min^2
#define DEFAULT_Z_ACCELERATION (15.0*60*60) // 10 mm/min^2
#define DEFAULT_X_MAX_TRAVEL 200.0 // mm
#define DEFAULT_Y_MAX_TRAVEL 200.0 // mm
#define DEFAULT_Z_MAX_TRAVEL 200.0 // mm
#define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_FEEDRATE 250.0
#define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT))
#define DEFAULT_STEPPER_IDLE_LOCK_TIME 255 // msec (0-254, 255 keeps steppers enabled)
#define DEFAULT_JUNCTION_DEVIATION 0.05 // mm
#define DEFAULT_ARC_TOLERANCE 0.005 // mm
#define DEFAULT_DECIMAL_PLACES 3
#define DEFAULT_REPORT_INCHES 0 // false
#define DEFAULT_AUTO_START 1 // true
#define DEFAULT_INVERT_ST_ENABLE 0 // false
#define DEFAULT_SOFT_LIMIT_ENABLE 0 // false
#define DEFAULT_HARD_LIMIT_ENABLE 0 // false
#define DEFAULT_HOMING_ENABLE 0 // false
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
#define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_HOMING_PULLOFF 1.0 // mm
#endif #endif
@ -150,15 +191,15 @@
#define DEFAULT_X_STEPS_PER_MM (STEPS_PER_REV*MICROSTEPS/MM_PER_REV) #define DEFAULT_X_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_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_X_MAX_RATE 7000.0 // mm/min #define DEFAULT_X_MAX_RATE 6000.0 // mm/min
#define DEFAULT_Y_MAX_RATE 7000.0 // mm/min #define DEFAULT_Y_MAX_RATE 6000.0 // mm/min
#define DEFAULT_Z_MAX_RATE 7000.0 // mm/min #define DEFAULT_Z_MAX_RATE 6000.0 // mm/min
#define DEFAULT_X_ACCELERATION (600.0*60*60) // 10 mm/min^2 #define DEFAULT_X_ACCELERATION (600.0*60*60) // 10 mm/min^2
#define DEFAULT_Y_ACCELERATION (600.0*60*60) // 10 mm/min^2 #define DEFAULT_Y_ACCELERATION (600.0*60*60) // 10 mm/min^2
#define DEFAULT_Z_ACCELERATION (600.0*60*60) // 10 mm/min^2 #define DEFAULT_Z_ACCELERATION (600.0*60*60) // 10 mm/min^2
#define DEFAULT_X_MAX_TRAVEL 200.0 // mm #define DEFAULT_X_MAX_TRAVEL 190.0 // mm
#define DEFAULT_Y_MAX_TRAVEL 200.0 // mm #define DEFAULT_Y_MAX_TRAVEL 180.0 // mm
#define DEFAULT_Z_MAX_TRAVEL 200.0 // mm #define DEFAULT_Z_MAX_TRAVEL 150.0 // mm
#define DEFAULT_STEP_PULSE_MICROSECONDS 10 #define DEFAULT_STEP_PULSE_MICROSECONDS 10
#define DEFAULT_FEEDRATE 1000.0 // mm/min #define DEFAULT_FEEDRATE 1000.0 // mm/min
#define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT)) #define DEFAULT_STEPPING_INVERT_MASK ((1<<Y_DIRECTION_BIT))
@ -175,7 +216,7 @@
#define DEFAULT_HOMING_DIR_MASK 0 // move positive dir #define DEFAULT_HOMING_DIR_MASK 0 // move positive dir
#define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min #define DEFAULT_HOMING_FEED_RATE 25.0 // mm/min
#define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min #define DEFAULT_HOMING_SEEK_RATE 250.0 // mm/min
#define DEFAULT_HOMING_DEBOUNCE_DELAY 100 // msec (0-65k) #define DEFAULT_HOMING_DEBOUNCE_DELAY 250 // msec (0-65k)
#define DEFAULT_HOMING_PULLOFF 1.0 // mm #define DEFAULT_HOMING_PULLOFF 1.0 // mm
#endif #endif

173
limits.c
View File

@ -33,8 +33,6 @@
#include "limits.h" #include "limits.h"
#include "report.h" #include "report.h"
#define MICROSECONDS_PER_ACCELERATION_TICK (1000000/ACCELERATION_TICKS_PER_SECOND)
void limits_init() void limits_init()
{ {
@ -89,147 +87,63 @@ ISR(LIMIT_INT_vect)
// algorithm is written here. This also lets users hack and tune this code freely for // algorithm is written here. This also lets users hack and tune this code freely for
// their own particular needs without affecting the rest of Grbl. // their own particular needs without affecting the rest of Grbl.
// NOTE: Only the abort runtime command can interrupt this process. // NOTE: Only the abort runtime command can interrupt this process.
static void homing_cycle(uint8_t cycle_mask, int8_t pos_dir, bool invert_pin, float homing_rate) static void homing_cycle(uint8_t cycle_mask, bool pos_dir, bool invert_pin, float homing_rate)
{ {
if (sys.execute & EXEC_RESET) { return; }
/* TODO: Change homing routine to call planner instead moving at the maximum seek rates uint8_t limit_state;
and (max_travel+10mm?) for each axes during the search phase. The routine should monitor #ifndef LIMIT_SWITCHES_ACTIVE_HIGH
the state of the limit pins and when a pin is triggered, it can disable that axes by
setting the respective step_x, step_y, or step_z value in the executing planner block.
This keeps the stepper algorithm counters from triggering the step on that particular
axis. When all axes have been triggered, we can then disable the steppers and reset
the stepper and planner buffers. This same method can be used for the locate cycles.
This will also fix the slow max feedrate of the homing 'lite' stepper algorithm.
Need to check if setting the planner steps will require them to be volatile or not. */
#ifdef LIMIT_SWITCHES_ACTIVE_HIGH
// When in an active-high switch configuration, invert_pin needs to be adjusted.
invert_pin = !invert_pin; invert_pin = !invert_pin;
#endif #endif
// Determine governing axes with finest step resolution per distance for the Bresenham // Compute target location for homing all axes. Homing axis lock will freeze non-cycle axes.
// algorithm. This solves the issue when homing multiple axes that have different float target[N_AXIS];
// resolutions without exceeding system acceleration setting. It doesn't have to be target[X_AXIS] = settings.max_travel[X_AXIS];
// perfect since homing locates machine zero, but should create for a more consistent if (target[X_AXIS] < settings.max_travel[Y_AXIS]) { target[X_AXIS] = settings.max_travel[Y_AXIS]; }
// and speedy homing routine. if (target[X_AXIS] < settings.max_travel[Z_AXIS]) { target[X_AXIS] = settings.max_travel[Z_AXIS]; }
// NOTE: For each axes enabled, the following calculations assume they physically move target[X_AXIS] *= 2.0;
// an equal distance over each time step until they hit a limit switch, aka dogleg. if (pos_dir) { target[X_AXIS] = -target[X_AXIS]; }
uint32_t step_event_count = 0; target[Y_AXIS] = target[X_AXIS];
uint8_t i, dist = 0; target[Z_AXIS] = target[X_AXIS];
uint32_t steps[N_AXIS]; homing_rate *= 1.7320; // [sqrt(N_AXIS)] Adjust so individual axes all move at homing rate.
clear_vector(steps);
for (i=0; i<N_AXIS; i++) {
if (cycle_mask & (1<<i)) {
dist++;
steps[i] = lround(settings.steps_per_mm[i]);
step_event_count = max(step_event_count,steps[i]);
}
}
// To ensure global acceleration is not exceeded, reduce the governing axes nominal rate // Setup homing axis locks based on cycle mask.
// by adjusting the actual axes distance traveled per step. This is the same procedure uint8_t axislock = (STEPPING_MASK & ~STEP_MASK);
// used in the main planner to account for distance traveled when moving multiple axes. if (bit_istrue(cycle_mask,bit(X_AXIS))) { axislock |= (1<<X_STEP_BIT); }
// NOTE: When axis acceleration independence is installed, this will be updated to move if (bit_istrue(cycle_mask,bit(Y_AXIS))) { axislock |= (1<<Y_STEP_BIT); }
// all axes at their maximum acceleration and rate. if (bit_istrue(cycle_mask,bit(Z_AXIS))) { axislock |= (1<<Z_STEP_BIT); }
float ds = step_event_count/sqrt(dist); sys.homing_axis_lock = axislock;
// Compute the adjusted step rate change with each acceleration tick. (in step/min/acceleration_tick) // Perform homing cycle. Planner buffer should be empty, as required to initiate the homing cycle.
uint32_t delta_rate = ceil( ds*settings.acceleration[X_AXIS]/(60*ACCELERATION_TICKS_PER_SECOND)); plan_buffer_line(target, homing_rate, false); // Bypass mc_line(). Directly plan homing motion.
st_prep_buffer(); // Prep first segment from newly planned block.
#ifdef HOMING_RATE_ADJUST st_wake_up(); // Initiate motion
// Adjust homing rate so a multiple axes moves all at the homing rate independently. while (STEP_MASK & axislock) {
homing_rate *= sqrt(dist); // Eq. only works if axes values are 1 or 0. // Check limit state.
#endif
// Nominal and initial time increment per step. Nominal should always be greater then 3
// usec, since they are based on the same parameters as the main stepper routine. Initial
// is based on the MINIMUM_STEPS_PER_MINUTE config. Since homing feed can be very slow,
// disable acceleration when rates are below MINIMUM_STEPS_PER_MINUTE.
uint32_t dt_min = lround(1000000*60/(ds*homing_rate)); // Cruising (usec/step)
uint32_t dt = 1000000*60/MINIMUM_STEPS_PER_MINUTE; // Initial (usec/step)
if (dt > dt_min) { dt = dt_min; } // Disable acceleration for very slow rates.
// Set default out_bits.
uint8_t out_bits0 = settings.invert_mask;
out_bits0 ^= (settings.homing_dir_mask & DIRECTION_MASK); // Apply homing direction settings
if (!pos_dir) { out_bits0 ^= DIRECTION_MASK; } // Invert bits, if negative dir.
// Initialize stepping variables
int32_t counter_x = -(step_event_count >> 1); // Bresenham counters
int32_t counter_y = counter_x;
int32_t counter_z = counter_x;
uint32_t step_delay = dt-settings.pulse_microseconds; // Step delay after pulse
uint32_t step_rate = 0; // Tracks step rate. Initialized from 0 rate. (in step/min)
uint32_t trap_counter = MICROSECONDS_PER_ACCELERATION_TICK/2; // Acceleration trapezoid counter
uint8_t out_bits;
uint8_t limit_state;
for(;;) {
// Reset out bits. Both direction and step pins appropriately inverted and set.
out_bits = out_bits0;
// Get limit pin state.
limit_state = LIMIT_PIN; limit_state = LIMIT_PIN;
if (invert_pin) { limit_state ^= LIMIT_MASK; } // If leaving switch, invert to move. if (invert_pin) { limit_state ^= LIMIT_MASK; }
if (axislock & (1<<X_STEP_BIT)) {
// Set step pins by Bresenham line algorithm. If limit switch reached, disable and if (limit_state & (1<<X_LIMIT_BIT)) { axislock &= ~(1<<X_STEP_BIT); }
// flag for completion.
if (cycle_mask & (1<<X_AXIS)) {
counter_x += steps[X_AXIS];
if (counter_x > 0) {
if (limit_state & (1<<X_LIMIT_BIT)) { out_bits ^= (1<<X_STEP_BIT); }
else { cycle_mask &= ~(1<<X_AXIS); }
counter_x -= step_event_count;
}
} }
if (cycle_mask & (1<<Y_AXIS)) { if (axislock & (1<<Y_STEP_BIT)) {
counter_y += steps[Y_AXIS]; if (limit_state & (1<<Y_LIMIT_BIT)) { axislock &= ~(1<<Y_STEP_BIT); }
if (counter_y > 0) {
if (limit_state & (1<<Y_LIMIT_BIT)) { out_bits ^= (1<<Y_STEP_BIT); }
else { cycle_mask &= ~(1<<Y_AXIS); }
counter_y -= step_event_count;
}
} }
if (cycle_mask & (1<<Z_AXIS)) { if (axislock & (1<<Z_STEP_BIT)) {
counter_z += steps[Z_AXIS]; if (limit_state & (1<<Z_LIMIT_BIT)) { axislock &= ~(1<<Z_STEP_BIT); }
if (counter_z > 0) {
if (limit_state & (1<<Z_LIMIT_BIT)) { out_bits ^= (1<<Z_STEP_BIT); }
else { cycle_mask &= ~(1<<Z_AXIS); }
counter_z -= step_event_count;
}
}
// Check if we are done or for system abort
if (!(cycle_mask) || (sys.execute & EXEC_RESET)) { return; }
// Perform step.
STEPPING_PORT = (STEPPING_PORT & ~STEP_MASK) | (out_bits & STEP_MASK);
delay_us(settings.pulse_microseconds);
STEPPING_PORT = out_bits0;
delay_us(step_delay);
// Track and set the next step delay, if required. This routine uses another Bresenham
// line algorithm to follow the constant acceleration line in the velocity and time
// domain. This is a lite version of the same routine used in the main stepper program.
if (dt > dt_min) { // Unless cruising, check for time update.
trap_counter += dt; // Track time passed since last update.
if (trap_counter > MICROSECONDS_PER_ACCELERATION_TICK) {
trap_counter -= MICROSECONDS_PER_ACCELERATION_TICK;
step_rate += delta_rate; // Increment velocity
dt = (1000000*60)/step_rate; // Compute new time increment
if (dt < dt_min) {dt = dt_min;} // If target rate reached, cruise.
step_delay = dt-settings.pulse_microseconds;
}
} }
sys.homing_axis_lock = axislock;
st_prep_buffer(); // Check and prep one segment. NOTE: Should take no longer than 200us.
if (sys.execute & EXEC_RESET) { return; }
} }
st_go_idle(); // Disable steppers. Axes motion should already be locked.
plan_init(); // Reset planner buffer. Ensure homing motion is cleared.
st_reset(); // Reset step segment buffer. Ensure homing motion is cleared.
delay_ms(settings.homing_debounce_delay);
} }
void limits_go_home() void limits_go_home()
{ {
// Enable only the steppers, not the cycle. Cycle should be inactive/complete. plan_init(); // Reset planner buffer before beginning homing cycles.
st_wake_up();
// Search to engage all axes limit switches at faster homing seek rate. // Search to engage all axes limit switches at faster homing seek rate.
homing_cycle(HOMING_SEARCH_CYCLE_0, true, false, settings.homing_seek_rate); // Search cycle 0 homing_cycle(HOMING_SEARCH_CYCLE_0, true, false, settings.homing_seek_rate); // Search cycle 0
@ -239,7 +153,6 @@ void limits_go_home()
#ifdef HOMING_SEARCH_CYCLE_2 #ifdef HOMING_SEARCH_CYCLE_2
homing_cycle(HOMING_SEARCH_CYCLE_2, true, false, settings.homing_seek_rate); // Search cycle 2 homing_cycle(HOMING_SEARCH_CYCLE_2, true, false, settings.homing_seek_rate); // Search cycle 2
#endif #endif
delay_ms(settings.homing_debounce_delay); // Delay to debounce signal
// Now in proximity of all limits. Carefully leave and approach switches in multiple cycles // Now in proximity of all limits. Carefully leave and approach switches in multiple cycles
// to precisely hone in on the machine zero location. Moves at slower homing feed rate. // to precisely hone in on the machine zero location. Moves at slower homing feed rate.
@ -247,16 +160,12 @@ void limits_go_home()
while (n_cycle--) { while (n_cycle--) {
// Leave all switches to release them. After cycles complete, this is machine zero. // Leave all switches to release them. After cycles complete, this is machine zero.
homing_cycle(HOMING_LOCATE_CYCLE, false, true, settings.homing_feed_rate); homing_cycle(HOMING_LOCATE_CYCLE, false, true, settings.homing_feed_rate);
delay_ms(settings.homing_debounce_delay);
if (n_cycle > 0) { if (n_cycle > 0) {
// Re-approach all switches to re-engage them. // Re-approach all switches to re-engage them.
homing_cycle(HOMING_LOCATE_CYCLE, true, false, settings.homing_feed_rate); homing_cycle(HOMING_LOCATE_CYCLE, true, false, settings.homing_feed_rate);
delay_ms(settings.homing_debounce_delay);
} }
} }
st_go_idle(); // Call main stepper shutdown routine.
} }

View File

@ -89,6 +89,7 @@ typedef struct {
uint8_t abort; // System abort flag. Forces exit back to main loop for reset. uint8_t abort; // System abort flag. Forces exit back to main loop for reset.
uint8_t state; // Tracks the current state of Grbl. uint8_t state; // Tracks the current state of Grbl.
volatile uint8_t execute; // Global system runtime executor bitflag variable. See EXEC bitmasks. volatile uint8_t execute; // Global system runtime executor bitflag variable. See EXEC bitmasks.
uint8_t homing_axis_lock;
int32_t position[N_AXIS]; // Real-time machine (aka home) position vector in steps. int32_t position[N_AXIS]; // Real-time machine (aka home) position vector in steps.
// NOTE: This may need to be a volatile variable, if problems arise. // NOTE: This may need to be a volatile variable, if problems arise.
uint8_t auto_start; // Planner auto-start flag. Toggled off during feed hold. Defaulted by settings. uint8_t auto_start; // Planner auto-start flag. Toggled off during feed hold. Defaulted by settings.

View File

@ -326,7 +326,7 @@ void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate)
for (idx=0; idx<N_AXIS; idx++) { for (idx=0; idx<N_AXIS; idx++) {
if (unit_vec[idx] != 0) { // Avoid divide by zero. if (unit_vec[idx] != 0) { // Avoid divide by zero.
unit_vec[idx] *= inverse_millimeters; // Complete unit vector calculation unit_vec[idx] *= inverse_millimeters; // Complete unit vector calculation
inverse_unit_vec_value = abs(1.0/unit_vec[idx]); // Inverse to remove multiple float divides. inverse_unit_vec_value = fabs(1.0/unit_vec[idx]); // Inverse to remove multiple float divides.
// Check and limit feed rate against max individual axis velocities and accelerations // Check and limit feed rate against max individual axis velocities and accelerations
feed_rate = min(feed_rate,settings.max_rate[idx]*inverse_unit_vec_value); feed_rate = min(feed_rate,settings.max_rate[idx]*inverse_unit_vec_value);
@ -339,7 +339,6 @@ void plan_buffer_line(float *target, float feed_rate, uint8_t invert_feed_rate)
} }
} }
// TODO: Need to check this method handling zero junction speeds when starting from rest. // TODO: Need to check this method handling zero junction speeds when starting from rest.
if (block_buffer_head == block_buffer_tail) { if (block_buffer_head == block_buffer_tail) {

View File

@ -125,7 +125,7 @@ void report_feedback_message(uint8_t message_code)
// Welcome message // Welcome message
void report_init_message() void report_init_message()
{ {
printPgmString(PSTR("\r\nGrbl " GRBL_VERSION " ['$' for help]\r\n")); printPgmString(PSTR("\r\nGrbl " GRBL_VERSION " ("GRBL_VERSION_BUILD ") ['$' for help]\r\n"));
} }
// Grbl help message // Grbl help message

View File

@ -20,7 +20,6 @@
#ifndef report_h #ifndef report_h
#define report_h #define report_h
// Define Grbl status codes. // Define Grbl status codes.
#define STATUS_OK 0 #define STATUS_OK 0
#define STATUS_BAD_NUMBER_FORMAT 1 #define STATUS_BAD_NUMBER_FORMAT 1

View File

@ -98,9 +98,9 @@ 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.max_travel[X_AXIS] = DEFAULT_X_MAX_TRAVEL; settings.max_travel[X_AXIS] = (-DEFAULT_X_MAX_TRAVEL);
settings.max_travel[Y_AXIS] = DEFAULT_Y_MAX_TRAVEL; settings.max_travel[Y_AXIS] = (-DEFAULT_Y_MAX_TRAVEL);
settings.max_travel[Z_AXIS] = DEFAULT_Z_MAX_TRAVEL; settings.max_travel[Z_AXIS] = (-DEFAULT_Z_MAX_TRAVEL);
write_global_settings(); write_global_settings();
} }

View File

@ -26,10 +26,11 @@
#include "nuts_bolts.h" #include "nuts_bolts.h"
#define GRBL_VERSION "0.9b" #define GRBL_VERSION "0.9b"
#define GRBL_VERSION_BUILD "20131210"
// 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 55 #define SETTINGS_VERSION 56
// 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)

View File

@ -26,10 +26,11 @@
#include "planner.h" #include "planner.h"
#include "nuts_bolts.h" #include "nuts_bolts.h"
// Some useful constants.
// Some useful constants
#define TICKS_PER_MICROSECOND (F_CPU/1000000) #define TICKS_PER_MICROSECOND (F_CPU/1000000)
#define DT_SEGMENT (1.0/(ACCELERATION_TICKS_PER_SECOND*60.0)) // min/segment #define DT_SEGMENT (1.0/(ACCELERATION_TICKS_PER_SECOND*60.0)) // min/segment
#define STEP_FTOL_MULTIPLIER 100000 // Multiplier converts floating point step rate to long
// integer for stepper algorithm step-distance counter.
#define RAMP_ACCEL 0 #define RAMP_ACCEL 0
#define RAMP_CRUISE 1 #define RAMP_CRUISE 1
@ -107,7 +108,7 @@ typedef struct {
float steps_remaining; float steps_remaining;
uint8_t ramp_type; // Current segment ramp state uint8_t ramp_type; // Current segment ramp state
float mm_complete; float mm_complete; // End of velocity profile from end of current planner block in (mm).
float current_speed; // Current speed at the end of the segment buffer (mm/min) float current_speed; // Current speed at the end of the segment buffer (mm/min)
float maximum_speed; // Maximum speed of executing block. Not always nominal speed. (mm/min) float maximum_speed; // Maximum speed of executing block. Not always nominal speed. (mm/min)
float exit_speed; // Exit speed of executing block (mm/min) float exit_speed; // Exit speed of executing block (mm/min)
@ -165,7 +166,7 @@ void st_wake_up()
} else { } else {
STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT); STEPPERS_DISABLE_PORT &= ~(1<<STEPPERS_DISABLE_BIT);
} }
if (sys.state == STATE_CYCLE) { if ((sys.state == STATE_CYCLE) || (sys.state == STATE_HOMING)){
// Initialize stepper output bits // Initialize stepper output bits
st.out_bits = settings.invert_mask; st.out_bits = settings.invert_mask;
// Initialize step pulse timing from settings. // Initialize step pulse timing from settings.
@ -282,9 +283,9 @@ ISR(TIMER2_COMPA_vect)
st.counter_dist += st.exec_segment->dist_per_tick; st.counter_dist += st.exec_segment->dist_per_tick;
// Execute Bresenham step event, when it's time to do so. // Execute Bresenham step event, when it's time to do so.
if (st.counter_dist > INV_TIME_MULTIPLIER) { if (st.counter_dist > STEP_FTOL_MULTIPLIER) {
if (st.step_count > 0) { // Block phase correction from executing step. if (st.step_count > 0) { // Block phase correction from executing step.
st.counter_dist -= INV_TIME_MULTIPLIER; // Reload inverse time counter st.counter_dist -= STEP_FTOL_MULTIPLIER; // Reload inverse time counter
st.step_count--; // Decrement step events count st.step_count--; // Decrement step events count
// Execute step displacement profile by Bresenham line algorithm // Execute step displacement profile by Bresenham line algorithm
@ -311,6 +312,10 @@ ISR(TIMER2_COMPA_vect)
if (st.out_bits & (1<<Z_DIRECTION_BIT)) { sys.position[Z_AXIS]--; } if (st.out_bits & (1<<Z_DIRECTION_BIT)) { sys.position[Z_AXIS]--; }
else { sys.position[Z_AXIS]++; } else { sys.position[Z_AXIS]++; }
} }
// Block any axis with limit switch active from moving.
if (sys.state == STATE_HOMING) { st.out_bits &= sys.homing_axis_lock; }
st.out_bits ^= settings.invert_mask; // Apply step port invert mask st.out_bits ^= settings.invert_mask; // Apply step port invert mask
} }
} }
@ -455,8 +460,8 @@ void st_update_plan_block_parameters()
*/ */
void st_prep_buffer() void st_prep_buffer()
{ {
if (sys.state == STATE_QUEUED) { return; } // Block until a motion state is issued
while (segment_buffer_tail != segment_next_head) { // Check if we need to fill the buffer. while (segment_buffer_tail != segment_next_head) { // Check if we need to fill the buffer.
if (sys.state == STATE_QUEUED) { return; } // Block until a motion state is issued
// Determine if we need to load a new planner block or if the block remainder is replanned. // Determine if we need to load a new planner block or if the block remainder is replanned.
if (pl_block == NULL) { if (pl_block == NULL) {
@ -485,6 +490,7 @@ void st_prep_buffer()
prep.step_per_mm = prep.steps_remaining/pl_block->millimeters; prep.step_per_mm = prep.steps_remaining/pl_block->millimeters;
if (sys.state == STATE_HOLD) { if (sys.state == STATE_HOLD) {
// Override planner block entry speed and enforce deceleration during feed hold.
prep.current_speed = prep.exit_speed; prep.current_speed = prep.exit_speed;
pl_block->entry_speed_sqr = prep.exit_speed*prep.exit_speed; pl_block->entry_speed_sqr = prep.exit_speed*prep.exit_speed;
} }
@ -497,7 +503,7 @@ void st_prep_buffer()
planner has updated it. For a commanded forced-deceleration, such as from a feed planner has updated it. For a commanded forced-deceleration, such as from a feed
hold, override the planner velocities and decelerate to the target exit speed. hold, override the planner velocities and decelerate to the target exit speed.
*/ */
prep.mm_complete = 0.0; prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block.
float inv_2_accel = 0.5/pl_block->acceleration; float inv_2_accel = 0.5/pl_block->acceleration;
if (sys.state == STATE_HOLD) { if (sys.state == STATE_HOLD) {
// Compute velocity profile parameters for a feed hold in-progress. This profile overrides // Compute velocity profile parameters for a feed hold in-progress. This profile overrides
@ -506,7 +512,7 @@ void st_prep_buffer()
float decel_dist = inv_2_accel*pl_block->entry_speed_sqr; float decel_dist = inv_2_accel*pl_block->entry_speed_sqr;
if (decel_dist < pl_block->millimeters) { if (decel_dist < pl_block->millimeters) {
prep.exit_speed = 0.0; prep.exit_speed = 0.0;
prep.mm_complete = pl_block->millimeters-decel_dist; prep.mm_complete = pl_block->millimeters-decel_dist; // End of feed hold.
} else { } else {
prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters); prep.exit_speed = sqrt(pl_block->entry_speed_sqr-2*pl_block->acceleration*pl_block->millimeters);
} }
@ -634,13 +640,13 @@ void st_prep_buffer()
supported by Grbl (i.e. exceeding 10 meters axis travel at 200 step/mm). supported by Grbl (i.e. exceeding 10 meters axis travel at 200 step/mm).
*/ */
// Use time_var to pre-compute dt inversion with integer multiplier. // Use time_var to pre-compute dt inversion with integer multiplier.
time_var = (INV_TIME_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))/dt; // (mult/isr_tic) time_var = (STEP_FTOL_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))/dt; // (ftol_mult/isr_tic)
if (mm_remaining > 0.0) { // Block still incomplete. Distance remaining to be executed. if (mm_remaining > 0.0) { // Block still incomplete. Distance remaining to be executed.
float steps_remaining = prep.step_per_mm*mm_remaining; float steps_remaining = prep.step_per_mm*mm_remaining;
prep_segment->dist_per_tick = ceil( (prep.steps_remaining-steps_remaining)*time_var ); // (mult*step/isr_tic) prep_segment->dist_per_tick = ceil( (prep.steps_remaining-steps_remaining)*time_var ); // (ftol_mult*step/isr_tic)
// Compute number of steps to execute and segment step phase correction. // Compute number of steps to execute and segment step phase correction.
prep_segment->phase_dist = ceil(INV_TIME_MULTIPLIER*(ceil(steps_remaining)-steps_remaining)); prep_segment->phase_dist = ceil(STEP_FTOL_MULTIPLIER*(ceil(steps_remaining)-steps_remaining));
prep_segment->n_step = ceil(prep.steps_remaining)-ceil(steps_remaining); prep_segment->n_step = ceil(prep.steps_remaining)-ceil(steps_remaining);
// Update step execution variables. // Update step execution variables.
@ -648,7 +654,7 @@ void st_prep_buffer()
// NOTE: Currently only feed holds qualify for this scenario. May change with overrides. // NOTE: Currently only feed holds qualify for this scenario. May change with overrides.
prep.current_speed = 0.0; prep.current_speed = 0.0;
prep.steps_remaining = ceil(steps_remaining); prep.steps_remaining = ceil(steps_remaining);
pl_block->millimeters = prep.steps_remaining/prep.step_per_mm; pl_block->millimeters = prep.steps_remaining/prep.step_per_mm; // Update with full steps.
plan_cycle_reinitialize(); plan_cycle_reinitialize();
sys.state = STATE_QUEUED; // End cycle. sys.state = STATE_QUEUED; // End cycle.
} else { } else {
@ -682,12 +688,14 @@ void st_prep_buffer()
// int32_t blength = segment_buffer_head - segment_buffer_tail; // int32_t blength = segment_buffer_head - segment_buffer_tail;
// if (blength < 0) { blength += SEGMENT_BUFFER_SIZE; } // if (blength < 0) { blength += SEGMENT_BUFFER_SIZE; }
// printInteger(blength); // printInteger(blength);
if ((sys.state == STATE_HOMING) || (sys.state == STATE_QUEUED)) { return; } // Force only one prepped segment.
} }
} }
/* /*
TODO: With feedrate overrides, increases to the override value will not significantly TODO: With feedrate overrides, increases to the override value will not significantly
change the planner and stepper current operation. When the value increases, we simply change the current planner and stepper operation. When the value increases, we simply
need to recompute the block plan with new nominal speeds and maximum junction velocities. need to recompute the block plan with new nominal speeds and maximum junction velocities.
However with a decreasing feedrate override, this gets a little tricky. The current block However with a decreasing feedrate override, this gets a little tricky. The current block
plan is optimal, so if we try to reduce the feed rates, it may be impossible to create plan is optimal, so if we try to reduce the feed rates, it may be impossible to create
@ -704,4 +712,10 @@ void st_prep_buffer()
equal to the block maximum speed and is in an acceleration or cruising ramp. At this equal to the block maximum speed and is in an acceleration or cruising ramp. At this
point, we know that we can recompute the block velocity profile to meet and continue onto point, we know that we can recompute the block velocity profile to meet and continue onto
the new block plan. the new block plan.
One "easy" way to do this is to have the step segment buffer enforce a deceleration and
continually re-plan the planner buffer until the plan becomes feasible. This can work
and may be easy to implement, but it expends a lot of CPU cycles and may block out the
rest of the functions from operating at peak efficiency. Still the question is how do
we know when the plan is feasible in the context of what's already in the code and not
require too much more code?
*/ */