added acceleration curve synchronization, memory leak found and corrected
authorArthur Wolf <wolf.arthur@gmail.com>
Thu, 8 Nov 2012 10:14:25 +0000 (11:14 +0100)
committerArthur Wolf <wolf.arthur@gmail.com>
Thu, 8 Nov 2012 10:14:25 +0000 (11:14 +0100)
src/libs/SlowTicker.cpp
src/libs/SlowTicker.h
src/libs/StepTicker.cpp
src/libs/StepperMotor.cpp
src/libs/StepperMotor.h
src/modules/robot/Stepper.cpp
src/modules/robot/Stepper.h
src/modules/tools/endstops/Endstops.cpp

index 9df400b..da9863d 100644 (file)
@@ -34,6 +34,10 @@ void SlowTicker::set_frequency( int frequency ){
 }
 
 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 );
@@ -42,12 +46,15 @@ void SlowTicker::tick(){
             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(); 
 }
 
index 5434be6..b2fa321 100644 (file)
@@ -23,7 +23,7 @@ class SlowTicker : public Module{
         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);
@@ -33,6 +33,7 @@ class SlowTicker : public Module{
             } 
             this->set_frequency(this->max_frequency); 
             this->hooks.push_back(hook);
+            return hook;
         }
 
         vector<Hook*> hooks; 
index dae2259..98be9ce 100644 (file)
@@ -157,11 +157,11 @@ extern "C" void TIMER0_IRQHandler (void){
     // 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 );
index 4d82f71..8a93c9b 100644 (file)
@@ -18,6 +18,8 @@ StepperMotor::StepperMotor(){
     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) {
@@ -30,6 +32,8 @@ StepperMotor::StepperMotor(Pin* step, Pin* dir, Pin* en) : step_pin(step), dir_p
     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
@@ -52,6 +56,11 @@ void StepperMotor::tick(){
         // 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; 
@@ -106,6 +115,9 @@ void StepperMotor::move( bool direction, unsigned int steps ){
     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; 
index f48ef2b..70e4add 100644 (file)
@@ -26,14 +26,25 @@ class StepperMotor {
         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;
index 5a23546..b9f83f0 100644 (file)
@@ -13,7 +13,7 @@
 #include <vector>
 using namespace std;
 #include "libs/nuts_bolts.h"
-
+#include "libs/Hook.h"
 #include <mri.h>
 
 
@@ -44,7 +44,7 @@ void Stepper::on_module_loaded(){
     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 ); 
@@ -143,9 +143,10 @@ void Stepper::on_block_begin(void* argument){
     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
@@ -193,13 +194,13 @@ uint32_t Stepper::trapezoid_generator_tick( uint32_t dummy ) {
           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) {
@@ -257,4 +258,45 @@ void Stepper::set_step_events_per_minute( double steps_per_minute ){
 
 }
 
+// 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
index 3188e81..a4b3bd3 100644 (file)
@@ -45,6 +45,7 @@ class Stepper : public Module {
         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];
@@ -77,6 +78,7 @@ class Stepper : public Module {
         bool paused;
         bool force_speed_update;
         bool enable_pins_status;
+        Hook* acceleration_tick_hook;
 
         StepperMotor* main_stepper;
 
index 079819f..ce3aa83 100644 (file)
@@ -42,8 +42,8 @@ void Endstops::on_config_reload(void* argument){
 // 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