27 static uint8_t block_buffer_tail;
28 static uint8_t block_buffer_head;
29 static uint8_t next_buffer_head;
30 static uint8_t block_buffer_planned;
50 static uint8_t plan_prev_block_index(uint8_t block_index)
124 static void planner_recalculate()
127 uint8_t block_index = plan_prev_block_index(block_buffer_head);
130 if (block_index == block_buffer_planned) {
return; }
136 float entry_speed_sqr;
143 block_index = plan_prev_block_index(block_index);
144 if (block_index == block_buffer_planned) {
148 while (block_index != block_buffer_planned) {
150 current = &block_buffer[block_index];
151 block_index = plan_prev_block_index(block_index);
159 if (entry_speed_sqr < current->max_entry_speed_sqr) {
170 next = &block_buffer[block_buffer_planned];
172 while (block_index != block_buffer_head) {
174 next = &block_buffer[block_index];
182 if (entry_speed_sqr < next->entry_speed_sqr) {
184 block_buffer_planned = block_index;
207 block_buffer_tail = 0;
208 block_buffer_head = 0;
209 next_buffer_head = 1;
210 block_buffer_planned = 0;
216 if (block_buffer_head != block_buffer_tail) {
219 if (block_buffer_tail == block_buffer_planned) { block_buffer_planned = block_index; }
220 block_buffer_tail = block_index;
227 return(&block_buffer[block_buffer_head]);
233 if (block_buffer_head == block_buffer_tail) {
return(NULL); }
234 return(&block_buffer[block_buffer_tail]);
241 if (block_index == block_buffer_head) {
return( 0.0 ); }
242 return( block_buffer[block_index].entry_speed_sqr );
248 if (block_buffer_tail == next_buffer_head) {
return(
true); }
269 static void plan_compute_profile_parameters(
plan_block_t *block,
float nominal_speed,
float prev_nominal_speed)
272 if (nominal_speed > prev_nominal_speed) { block->
max_entry_speed_sqr = prev_nominal_speed*prev_nominal_speed; }
280 uint8_t block_index = block_buffer_tail;
284 while (block_index != block_buffer_head) {
285 block = &block_buffer[block_index];
287 plan_compute_profile_parameters(block, nominal_speed, prev_nominal_speed);
288 prev_nominal_speed = nominal_speed;
321 float unit_vec[
N_AXIS], delta_mm;
339 block->
steps[B_MOTOR] = labs((target_steps[X_AXIS]-position_steps[X_AXIS]) - (target_steps[Y_AXIS]-position_steps[Y_AXIS]));
342 for (idx=0; idx<
N_AXIS; idx++) {
348 if ( !(idx == A_MOTOR) && !(idx == B_MOTOR) ) {
350 block->
steps[idx] = labs(target_steps[idx]-position_steps[idx]);
353 if (idx == A_MOTOR) {
355 }
else if (idx == B_MOTOR) {
362 block->
steps[idx] = labs(target_steps[idx]-position_steps[idx]);
366 unit_vec[idx] = delta_mm;
424 float junction_unit_vec[
N_AXIS];
425 float junction_cos_theta = 0.0;
426 for (idx=0; idx<
N_AXIS; idx++) {
433 if (junction_cos_theta > 0.999999) {
437 if (junction_cos_theta < -0.999999) {
443 float sin_theta_d2 = sqrt(0.5*(1.0-junction_cos_theta));
461 block_buffer_head = next_buffer_head;
465 planner_recalculate();
476 for (idx=0; idx<
N_AXIS; idx++) {
494 if (block_buffer_head >= block_buffer_tail) {
return((
BLOCK_BUFFER_SIZE-1)-(block_buffer_head-block_buffer_tail)); }
495 return((block_buffer_tail-block_buffer_head-1));
503 if (block_buffer_head >= block_buffer_tail) {
return(block_buffer_head-block_buffer_tail); }
513 block_buffer_planned = block_buffer_tail;
514 planner_recalculate();
plan_block_t * plan_get_current_block()
Returns address of first planner block, if available. Called by various main program functions...
int32_t line_number
Block line number for real-time reporting. Copied from pl_line_data.
if(axis_words)
STEP 3: Error-check all commands and values passed in this block. This step ensures all of the comma...
float programmed_rate
Programmed rate of this block (mm/min).
void plan_sync_position()
Reset the planner position vectors. Called by the system abort/initialization routine.
#define N_AXIS
Axis array index values. Must start with 0 and be continuous.
uint8_t plan_buffer_line(float *target, plan_line_data_t *pl_data)
Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position in mi...
int32_t position[N_AXIS]
The planner position of the tool in absolute steps. Kept separate.
#define MINIMUM_JUNCTION_SPEED
Used by variable spindle output only. This forces the PWM output to a minimum duty cycle when enabled...
float acceleration[N_AXIS]
uint8_t direction_bits
The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
Planner data prototype. Must be used when passing new motions to the planner.
#define MINIMUM_FEED_RATE
Sets the minimum feed rate the planner will allow. Any value below it will be set to this minimum...
float spindle_speed
Desired spindle speed through line motion.
void plan_cycle_reinitialize()
Re-initialize buffer plan with a partially completed block, assumed to exist at the buffer tail...
float plan_compute_profile_nominal_speed(plan_block_t *block)
Computes and returns block nominal speed based on running condition and override values.
void plan_update_velocity_profile_parameters()
Re-calculates buffered motions profile parameters upon a motion-based override change.
float convert_delta_vector_to_unit_vector(float *vector)
uint8_t condition
Block bitflag variable defining block run conditions. Copied from pl_line_data.
#define PL_COND_FLAG_RAPID_MOTION
Define planner data condition flags. Used to denote running conditions of a block.
float plan_get_exec_block_exit_speed_sqr()
Called by step segment buffer when computing executing block velocity profile.
float entry_speed_sqr
The current planned entry speed at block junction in (mm/min)^2.
#define BLOCK_BUFFER_SIZE
The number of linear motions that can be in the plan at any give time.
float millimeters
The remaining distance for this block to be executed in (mm).
void plan_reset()
Initialize and reset the motion plan subsystem.
uint8_t f_override
Feed rate override value in percent.
float acceleration
Axis-limit adjusted line acceleration in (mm/min^2). Does not change.
float previous_nominal_speed
Nominal speed of previous path line segment.
#define PL_COND_FLAG_SYSTEM_MOTION
Single motion. Circumvents planner state. Used by home/park.
uint8_t get_direction_pin_mask(uint8_t axis_idx)
Returns direction pin mask according to Grbl internal axis indexing.
#define X_AXIS
Axis indexing value.
#define PLAN_OK
Returned status message from planner.
float spindle_speed
Block spindle speed. Copied from pl_line_data.
plan_block_t * plan_get_system_motion_block()
Returns address of planner buffer block used by system motions. Called by segment generator...
float limit_value_by_axis_maximum(float *max_value, float *unit_vec)
system_t sys
Declare system global variable structure.
int32_t sys_position[N_AXIS]
NOTE: These position variables may need to be declared as volatiles, if problems arise.
float steps_per_mm[N_AXIS]
float rapid_rate
Axis-limit adjusted maximum rate for this block direction in (mm/min)
float max_entry_speed_sqr
Maximum allowable entry speed based on the minimum of junction limit and.
uint8_t plan_get_block_buffer_available()
Returns the number of available blocks are in the planner buffer.
void plan_discard_current_block()
Called when the current block is no longer needed. Discards the block and makes the memory...
int32_t line_number
Desired line number to report when executing.
float max_junction_speed_sqr
NOTE: This value may be altered by stepper algorithm during execution.
float previous_unit_vec[N_AXIS]
Unit vector of previous path line segment.
uint32_t step_event_count
The maximum step axis count and number of steps required to complete this block.
uint8_t plan_get_block_buffer_count()
Returns the number of active blocks are in the planner buffer.
#define PL_COND_FLAG_INVERSE_TIME
Interprets feed rate value as inverse time when set.
memset(pl_data, 0, sizeof(plan_line_data_t))
Zero pl_data struct.
memcpy(block_coord_system, gc_state.coord_system, sizeof(gc_state.coord_system))
uint8_t r_override
Rapids override value in percent.
#define PL_COND_FLAG_NO_FEED_OVERRIDE
Motion does not honor feed override.
float feed_rate
Desired feed rate for line motion. Value is ignored, if rapid motion.
Define planner variables.
uint8_t condition
Bitflag variable to indicate planner conditions. See defines above.
uint8_t plan_check_full_buffer()
Returns the availability status of the block ring buffer. True, if full.
This struct stores a linear movement of a g-code block motion with its critical "nominal" values...
void st_update_plan_block_parameters()
Called by planner_recalculate() when the executing block is updated by the new plan.
void plan_reset_buffer()
Reset buffer only.
uint32_t steps[N_AXIS]
NOTE: Used by stepper algorithm to execute the block correctly. Do not alter these values...
plan_line_data_t * pl_data
uint8_t plan_next_block_index(uint8_t block_index)
Returns the index of the next block in the ring buffer. Also called by stepper segment buffer...