This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Stepper motor pulses; how to perform acceleration?

Hi,

Experimenting on a stepper motor control (DRV8834). I want to be able to send a single square wave output, with a specified number of pulses. I managed to put together something that works ok using two timers and PPI after reading posts on DevZone. Now I need to find a way to modify this to achieve acceleration / decceleration. I would prefer in the same style using PPI if possible. Any suggestions?

typedef enum {
  MICROSTEP_1 = 1,
  MICROSTEP_2 = 2,
  MICROSTEP_4 = 4,
  MICROSTEP_8 = 8,
  MICROSTEP_16 = 16,
  MICROSTEP_32 = 32
}step_mode_t; 

void move_linear(uint32_t travel_distance_um, uint32_t mm_per_sec, step_mode_t step_mode)
{
    const uint8_t step_len_um = 13;
    
    float nbr_pulses = (float)(travel_distance_um*step_mode)/step_len_um;
    uint32_t nbr_toggles = (uint32_t)(nbr_pulses*2);
    float pt_pulses_us = ((float)travel_distance_um*1000/mm_per_sec)/nbr_toggles;
    uint32_t timer_ticks_reload = (uint32_t)(pt_pulses_us / 0.0625) + 3;
  
    // Stop timers before change
    NRF_TIMER1->TASKS_STOP = 1; 
    NRF_TIMER2->TASKS_STOP = 1;
    
    //Setup pulse out pin
    NRF_GPIOTE->CONFIG[0] = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos |
    GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos |
    LED_1 << GPIOTE_CONFIG_PSEL_Pos | 
    GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos; 

    //Setup pulse counter
    NRF_TIMER2->MODE = 1; //Counter mode
    NRF_TIMER2->BITMODE = 3; //32 bit
    NRF_TIMER2->TASKS_CLEAR = 1; //Clear counter value
    NRF_TIMER2->CC[1] = nbr_toggles; //Stop after <nbr> of pulses
    NRF_TIMER2->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos;
    
    //Setup pulse out timer
    NRF_TIMER1->MODE = 0; //Timer mode
    NRF_TIMER1->BITMODE = 3; //32 bit
    NRF_TIMER1->PRESCALER = 0; //16Mhz 
    NRF_TIMER1->CC[1] = timer_ticks_reload;
    NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE1_CLEAR_Enabled << TIMER_SHORTS_COMPARE1_CLEAR_Pos;

    //PPI connections
    NRF_PPI->CH[0].EEP = (uint32_t) &NRF_TIMER1->EVENTS_COMPARE[1]; // input = compare event of timer1
    NRF_PPI->CH[0].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[0]; // output = polarity toggle of the selected gpio 
    NRF_PPI->FORK[0].TEP = (uint32_t) &NRF_TIMER2->TASKS_COUNT;
    NRF_PPI->CH[1].EEP = (uint32_t) &NRF_TIMER2->EVENTS_COMPARE[1]; // input = compare event of timer2
    NRF_PPI->CH[1].TEP = (uint32_t) &NRF_TIMER2->TASKS_CAPTURE[1]; 
    NRF_PPI->FORK[1].TEP = (uint32_t) &NRF_TIMER1->TASKS_STOP; //Stop pulse timer afer X pulses counted
    
    NRF_PPI->CHENSET = (PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos);
    NRF_PPI->CHENSET = (PPI_CHENSET_CH1_Enabled << PPI_CHENSET_CH1_Pos);

    //*(uint32_t*)0x40009C0C = 1; // pan73_workaround
    NRF_TIMER2->TASKS_START = 1; // Start counter
    NRF_TIMER1->TASKS_START = 1; // Start timer
}

int main(void)
{
    move_linear(13, 10, MICROSTEP_16);
    while(1);
}

BR

//Ola  

Parents
  • An update of the progress...


    For now, I have accepted that it will be difficult to achieve this without sw intervention during acc/deccl. I have made an example with a different approach;
    I use PWM driver to generate the pulses in different phases; acceleration phase, target speed sphase and decceleration phase. For acceleration and decceleration phases, I generate a single pulse and re-triggers with updated frequency from ISR until desired pulses and end frequency is obtained. For the target speed phase, I simply start PWM with the static target frequency and a specific number of repeats until ISR is triggered. The different phases will start each other after they finish. Apart from a higher cpu load this works acceptable for now.

Reply
  • An update of the progress...


    For now, I have accepted that it will be difficult to achieve this without sw intervention during acc/deccl. I have made an example with a different approach;
    I use PWM driver to generate the pulses in different phases; acceleration phase, target speed sphase and decceleration phase. For acceleration and decceleration phases, I generate a single pulse and re-triggers with updated frequency from ISR until desired pulses and end frequency is obtained. For the target speed phase, I simply start PWM with the static target frequency and a specific number of repeats until ISR is triggered. The different phases will start each other after they finish. Apart from a higher cpu load this works acceptable for now.

Children
Related