changed atomic access for updating the acceleration profile
the stepper interrupt is only halted when necessary and for the shortest time possible (8% cycle time)
This commit is contained in:
parent
67608a5014
commit
ea09ddba99
2
Makefile
2
Makefile
@ -42,7 +42,7 @@ FUSES = -U hfuse:w:0xd2:m -U lfuse:w:0xff:m
|
||||
# Tune the lines below only if you know what you are doing:
|
||||
|
||||
AVRDUDE = avrdude $(PROGRAMMER) -p $(DEVICE) -B 10 -F
|
||||
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -I. -ffunction-sections
|
||||
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(CLOCK) -mmcu=$(DEVICE) -I. -ffunction-sections --std=c99
|
||||
|
||||
# symbolic targets:
|
||||
all: grbl.hex
|
||||
|
63
planner.c
63
planner.c
@ -23,6 +23,7 @@
|
||||
/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/atomic.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -34,8 +35,6 @@
|
||||
#include "protocol.h"
|
||||
#include "motion_control.h"
|
||||
|
||||
uint32_t planner_steps_counter;
|
||||
|
||||
#define SOME_LARGE_VALUE 1.0E+38 // Used by rapids and acceleration maximization calculations. Just needs
|
||||
// to be larger than any feasible (mm/min)^2 or mm/sec^2 value.
|
||||
|
||||
@ -103,7 +102,8 @@ static uint8_t prev_block_index(uint8_t block_index)
|
||||
static uint8_t calculate_trapezoid_for_block(block_t *block, uint8_t idx, float entry_speed_sqr, float exit_speed_sqr)
|
||||
{
|
||||
// Compute new initial rate for stepper algorithm
|
||||
uint32_t initial_rate = ceil(sqrt(entry_speed_sqr)*(RANADE_MULTIPLIER/(60*ISR_TICKS_PER_SECOND))); // (mult*mm/isr_tic)
|
||||
// volatile is necessary so that the optimizer doesn't move the calculation in the ATOMIC_BLOCK
|
||||
volatile uint32_t initial_rate = ceil(sqrt(entry_speed_sqr)*(RANADE_MULTIPLIER/(60*ISR_TICKS_PER_SECOND))); // (mult*mm/isr_tic)
|
||||
|
||||
// TODO: Compute new nominal rate if a feedrate override occurs.
|
||||
// block->nominal_rate = ceil(feed_rate*(RANADE_MULTIPLIER/(60.0*ISR_TICKS_PER_SECOND))); // (mult*mm/isr_tic)
|
||||
@ -132,23 +132,50 @@ static uint8_t calculate_trapezoid_for_block(block_t *block, uint8_t idx, float
|
||||
if (decelerate_after > block->step_event_count) { decelerate_after = block->step_event_count; }
|
||||
}
|
||||
|
||||
// safe block adjustment
|
||||
cli();
|
||||
uint8_t block_buffer_tail_hold= block_buffer_tail; // store to avoid reading volatile twice
|
||||
uint8_t block_buffer_head_hold= block_buffer_head; // store to avoid reading volatile twice
|
||||
uint8_t idx_inside_queue;
|
||||
// is the current block inside the queue? if not: the stepper overtook us
|
||||
if(block_buffer_head_hold>=block_buffer_tail_hold) idx_inside_queue= idx>=block_buffer_tail_hold && idx<=block_buffer_head_hold;
|
||||
else idx_inside_queue= idx<=block_buffer_head_hold || idx>=block_buffer_tail_hold;
|
||||
if(idx_inside_queue && (idx!=block_buffer_tail_hold || idx==block_buffer_head_hold || !st_is_decelerating())) {
|
||||
uint8_t block_buffer_tail_hold= block_buffer_tail; // store to avoid rereading volatile
|
||||
// check if we got overtaken by the stepper
|
||||
if(idx==prev_block_index(block_buffer_tail_hold)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check where the stepper is currently working relative to the block we want to update
|
||||
uint8_t block_buffer_tail_next= next_block_index(block_buffer_tail_hold);
|
||||
if(idx==block_buffer_tail_hold || idx==block_buffer_tail_next) {
|
||||
// we are close to were the stepper is working, so we need to block it for a short time
|
||||
// to safely adjust the block
|
||||
|
||||
// I counted the cycles in this block from the assembler code
|
||||
// It's 42 cycles worst case including the call to st_is_decelerating
|
||||
// @ 16MHz this is 2.6250e-06 seconds, 30kHz cycle duration is 3.3333e-05 seconds
|
||||
// -> this block will delay the stepper timer by max 8%
|
||||
// given that this occurs not very often, it should be ok
|
||||
// but test will have to show
|
||||
|
||||
// ATOMIC_BLOCK only works with compiler parameter --std=c99
|
||||
ATOMIC_BLOCK(ATOMIC_FORCEON) {
|
||||
// reload block_buffer_tail in case it changed
|
||||
uint8_t block_buffer_tail_hold2= block_buffer_tail;
|
||||
if(idx!=block_buffer_tail_hold2) {
|
||||
if(block_buffer_tail_hold2==block_buffer_tail_next)
|
||||
return false; // the stepper didn't overtook in the meantime
|
||||
} else {
|
||||
if(st_is_decelerating())
|
||||
return false; // we want to change the currently running block and it has already started to decelerate
|
||||
}
|
||||
|
||||
block->decelerate_after= decelerate_after;
|
||||
block->initial_rate= initial_rate;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// let's assume the stepper did not complete two blocks since we loaded block_buffer_tail to block_buffer_tail_hold
|
||||
// so the block we want to change is not currently being run by the stepper and it's safe to touch it without precautions
|
||||
block->decelerate_after= decelerate_after;
|
||||
block->initial_rate= initial_rate;
|
||||
sei();
|
||||
return(true);
|
||||
} else {
|
||||
sei();
|
||||
return(false); // this block is currently being processed by the stepper and it already finished accelerating or the stepper is already finished with this block: we can no longer change anything here
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -212,7 +239,6 @@ static uint8_t planner_recalculate()
|
||||
block_t *curr_block = &block_buffer[current_block_idx];
|
||||
uint8_t plan_unchanged= 1;
|
||||
|
||||
planner_steps_counter= 0;
|
||||
if(current_block_idx!=block_buffer_tail) { // we cannot do anything to only one block
|
||||
float max_entry_speed_sqr;
|
||||
float next_entry_speed_sqr= 0.0;
|
||||
@ -222,7 +248,6 @@ static uint8_t planner_recalculate()
|
||||
planned_block_tail= current_block_idx;
|
||||
break;
|
||||
}
|
||||
planner_steps_counter++;
|
||||
|
||||
// TODO: Determine maximum entry speed at junction for feedrate overrides, since they can alter
|
||||
// the planner nominal speeds at any time. This calc could be done in the override handler, but
|
||||
|
@ -22,8 +22,6 @@
|
||||
#ifndef planner_h
|
||||
#define planner_h
|
||||
|
||||
extern uint32_t planner_steps_counter;
|
||||
|
||||
// The number of linear motions that can be in the plan at any give time
|
||||
#ifndef BLOCK_BUFFER_SIZE
|
||||
#define BLOCK_BUFFER_SIZE 18
|
||||
|
@ -157,8 +157,7 @@ void printBlock() {
|
||||
else block_position[2]+= b->steps_z;
|
||||
fprintf(block_out_file,"%d, ", block_position[2]);
|
||||
|
||||
fprintf(block_out_file,"%f, ", b->entry_speed_sqr);
|
||||
fprintf(block_out_file,"%d", planner_steps_counter);
|
||||
fprintf(block_out_file,"%f", b->entry_speed_sqr);
|
||||
fprintf(block_out_file,"\n");
|
||||
|
||||
last_block= b;
|
||||
|
Loading…
Reference in New Issue
Block a user