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

Stepper motor driver using PPI

I need to drive a stepper motor without software intervention, since strict timing is a must.In the following image you can see the required wave-forms - the motor requires two PWM like signals, but i also need to be able to stop exactly after n cycles, where n can be from 1 to 1000. I saw the sample code added next, which generates the required wave-form, but have no way of stopping it after the n'th cycle, except by generating a timer SW interrupt where i stop the wave-form. But this is SW dependent  and i want fully automation. 

NRF_GPIOTE->CONFIG[0] = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos |
GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos |
IO_UART_RXD /* IO_MOT_APHASE */ << GPIOTE_CONFIG_PSEL_Pos |
GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos;

NRF_GPIOTE->CONFIG[1] = GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos |
GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos |
IO_UART_TXD /* IO_MOT_BPHASE */<< GPIOTE_CONFIG_PSEL_Pos |
GPIOTE_CONFIG_OUTINIT_Low << GPIOTE_CONFIG_OUTINIT_Pos;

// 16mhz / 2^4 = 1mhz --> 1us --> 2000 --> 2ms
NRF_TIMER1->PRESCALER = 4;
NRF_TIMER1->CC[1] = 2000;
NRF_TIMER1->CC[2] = 4000;
NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE2_CLEAR_Enabled << TIMER_SHORTS_COMPARE2_CLEAR_Pos;

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->CH[1].EEP = (uint32_t) &NRF_TIMER1->EVENTS_COMPARE[2];
NRF_PPI->CH[1].TEP = (uint32_t) &NRF_GPIOTE->TASKS_OUT[1];

NRF_PPI->CHENSET = (PPI_CHENSET_CH0_Enabled << PPI_CHENSET_CH0_Pos) | (PPI_CHENSET_CH1_Enabled << PPI_CHENSET_CH1_Pos);

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

  • Hi,

     

    You can use the PPI FORK (for instance: NRF_PPI->FORK[0].TEP = (uint32_t) &NRF_TIMERx->TASKS_COUNT;) functionality to fork out one of the EVENTS_COMPARE to another TIMERx->TASKS_COUNT (additional timer needs to be init'ed correctly and started), then when the desired amount of TASKS_COUNT has been reached, you can stop the TIMER1 via another PPI channel.

    Remember that a timer in low power count mode requires a different init configuration compared to a "timer" configured timer.

     

    A side note: Please note that the timers start counting from zero, so in order to set a interval of 2 and 4 ms, you'll need to subtract one:

    NRF_TIMER1->CC[1] = 2000 - 1;
    NRF_TIMER1->CC[2] = 4000 - 1;

     

    Best regards,

    Håkon

  • I managed to implement what you suggested by myself. Thanks a lot

Related