}
void SlowTicker::tick(){
+
+ LPC_GPIO1->FIODIR |= 1<<20;
+ LPC_GPIO1->FIOSET = 1<<20;
+
for (unsigned int i=0; i<this->hooks.size(); i++){
Hook* hook = this->hooks.at(i);
hook->counter += ( hook->frequency / this->max_frequency );
hook->call();
}
}
+
+ LPC_GPIO1->FIOCLR = 1<<20;
+
}
extern "C" void TIMER2_IRQHandler (void){
if((LPC_TIM2->IR >> 0) & 1){ // If interrupt register set for MR0
LPC_TIM2->IR |= 1 << 0; // Reset it
- global_slow_ticker->tick();
}
+ global_slow_ticker->tick();
}
void set_frequency( int frequency );
void tick();
// For some reason this can't go in the .cpp, see : http://mbed.org/forum/mbed/topic/2774/?page=1#comment-14221
- template<typename T> void attach( double frequency, T *optr, uint32_t ( T::*fptr )( uint32_t ) ){
+ template<typename T> Hook* attach( double frequency, T *optr, uint32_t ( T::*fptr )( uint32_t ) ){
Hook* hook = new Hook();
hook->frequency = frequency;
hook->attach(optr, fptr);
}
this->set_frequency(this->max_frequency);
this->hooks.push_back(hook);
+ return hook;
}
vector<Hook*> hooks;
// That can happen tipically when we change blocks, where more than usual computation is done
// This can be OK, if we take notice of it, which we do now
if( LPC_TIM0->TC > global_step_ticker->period ){ // TODO : remove the size condition
-
+
LPC_GPIO1->FIODIR |= 1<<19;
LPC_GPIO1->FIOSET = 1<<19;
- uint32_t start_tc = LPC_TIM0->TC;
+ uint32_t start_tc = LPC_TIM0->TC;
// How many ticks we want to skip ( this does not include the current tick, but we add the time we spent doing this computation last time )
uint32_t ticks_to_skip = ( ( LPC_TIM0->TC + global_step_ticker->last_duration ) / global_step_ticker->period );
this->direction_bit = 0;
this->remove_from_active_list_next_reset = false;
this->is_move_finished = false;
+ this->signal_step = false;
+ this->step_signal_hook = new Hook();
}
StepperMotor::StepperMotor(Pin* step, Pin* dir, Pin* en) : step_pin(step), dir_pin(dir), en_pin(en) {
this->direction_bit = 0;
this->remove_from_active_list_next_reset = false;
this->is_move_finished = false;
+ this->signal_step = false;
+ this->step_signal_hook = new Hook();
}
// Called a great many times per second, to step if we have to now
// we have moved a step 9t
this->stepped++;
+ // Do we need to signal this step
+ if( this->stepped == this->signal_step_number && this->signal_step ){
+ this->step_signal_hook->call();
+ }
+
// is this move finished ? 11t
if( this->stepped == this->steps_to_move ){
this->is_move_finished = true;
this->fx_counter = 0; // Bresenheim counter
this->stepped = 0;
+ // Do not signal steps until we get instructed to
+ this->signal_step = false;
+
// Starting now we are moving
if( steps > 0 ){
this->moving = true;
void pause();
void unpause();
-
template<typename T> void attach( T *optr, uint32_t ( T::*fptr )( uint32_t ) ){
Hook* hook = new Hook();
hook->attach(optr, fptr);
this->end_hook = hook;
}
+
+ template<typename T> void attach_signal_step(uint32_t step, T *optr, uint32_t ( T::*fptr )( uint32_t ) ){
+ this->step_signal_hook->attach(optr, fptr);
+ this->signal_step_number = step;
+ this->signal_step = true;
+ }
+
+
Hook* end_hook;
+ Hook* step_signal_hook;
+
+ bool signal_step;
+ uint32_t signal_step_number;
StepTicker* step_ticker;
Pin* step_pin;
#include <vector>
using namespace std;
#include "libs/nuts_bolts.h"
-
+#include "libs/Hook.h"
#include <mri.h>
this->on_config_reload(this);
// Acceleration ticker
- this->kernel->slow_ticker->attach( this->acceleration_ticks_per_second, this, &Stepper::trapezoid_generator_tick );
+ this->acceleration_tick_hook = this->kernel->slow_ticker->attach( this->acceleration_ticks_per_second, this, &Stepper::trapezoid_generator_tick );
// Attach to the end_of_move stepper event
this->kernel->robot->alpha_stepper_motor->attach(this, &Stepper::stepper_motor_finished_move );
if( this->kernel->robot->beta_stepper_motor->steps_to_move > this->main_stepper->steps_to_move ){ this->main_stepper = this->kernel->robot->beta_stepper_motor; }
if( this->kernel->robot->gamma_stepper_motor->steps_to_move > this->main_stepper->steps_to_move ){ this->main_stepper = this->kernel->robot->gamma_stepper_motor; }
- if( block->initial_rate == 0 ){
- this->trapezoid_generator_tick(0);
- }
+ // Synchronise the acceleration curve with the stepping
+ this->synchronize_acceleration(NULL);
+
+
}
// Current block is discarded
return 0;
}
- if(current_steps_completed <= this->current_block->accelerate_until + 1) {
+ if(current_steps_completed <= this->current_block->accelerate_until) {
this->trapezoid_adjusted_rate += ( skipped_speed_updates + 1 ) * this->current_block->rate_delta;
if (this->trapezoid_adjusted_rate > this->current_block->nominal_rate ) {
this->trapezoid_adjusted_rate = this->current_block->nominal_rate;
}
this->set_step_events_per_minute(this->trapezoid_adjusted_rate);
- }else if (current_steps_completed > this->current_block->decelerate_after + 1) {
+ }else if (current_steps_completed > this->current_block->decelerate_after) {
// NOTE: We will only reduce speed if the result will be > 0. This catches small
// rounding errors that might leave steps hanging after the last trapezoid tick.
if(this->trapezoid_adjusted_rate > this->current_block->rate_delta * 1.5) {
}
+// This function has the role of making sure acceleration and deceleration curves have their
+// rythm synchronized. The accel/decel must start at the same moment as the speed update routine
+// This is caller in "step just occured" or "block just began" ( step Timer ) context, so we need to be fast.
+// All we do is reset the other timer so that it does what we want
+uint32_t Stepper::synchronize_acceleration(uint32_t dummy){
+
+ LPC_GPIO1->FIODIR |= 1<<21;
+ LPC_GPIO1->FIOSET = 1<<21;
+
+
+ // No move was done, this is called from on_block_begin
+ // This means we setup the accel timer in a way where it gets called right after
+ // we exit this step interrupt, and so that it is then in synch with
+ if( this->main_stepper->stepped == 0 ){
+ // Whatever happens, we must call the accel interrupt asap
+ // Because it will set the initial rate
+ // We also want to synchronize in case we start accelerating or decelerating now
+
+ // Accel interrupt must happen asap
+ NVIC_SetPendingIRQ(TIMER2_IRQn);
+ // Synchronize both counters
+ LPC_TIM2->TC = LPC_TIM0->TC;
+
+ // If we start decelerating after this, we must ask the actuator to warn us
+ // so we can do what we do in the "else" bellow
+ if( this->current_block->decelerate_after > 0 && this->current_block->decelerate_after < this->main_stepper->steps_to_move ){
+ this->main_stepper->attach_signal_step(this->current_block->decelerate_after, this, &Stepper::synchronize_acceleration);
+ }
+ }else{
+ // If we are called not at the first steps, this means we are beginning deceleration
+ NVIC_SetPendingIRQ(TIMER2_IRQn);
+ // Synchronize both counters
+ LPC_TIM2->TC = LPC_TIM0->TC;
+ }
+
+ LPC_GPIO1->FIOCLR = 1<<21;
+
+
+}
+
+
//#pragma GCC pop_options
int config_step_timer( int cycles );
void turn_enable_pins_on();
void turn_enable_pins_off();
+ uint32_t synchronize_acceleration(uint32_t dummy);
Block* current_block;
int counters[3];
bool paused;
bool force_speed_update;
bool enable_pins_status;
+ Hook* acceleration_tick_hook;
StepperMotor* main_stepper;
// Start homing sequences by response to GCode commands
void Endstops::on_gcode_received(void* argument){
Gcode* gcode = static_cast<Gcode*>(argument);
- if( gcode->has_letter('G' )){
- if( gcode->get_value('G') == 28 ){
+ if( gcode->has_g){
+ if( gcode->g == 28 ){
// G28 is received, we have homing to do
// First wait for the queue to be empty