0

I have a stepper controller board that I need to pulse every 40 uS or so.

I also have I2C sensors and Serial writes to preform.

Currently I run an update call in a tight loop, but the I2C sensors and Serial writes cause considerable delays which makes the motors stutter and come to a halt.

I would like to use an ISR to call the motor update method periodically.

However I cannot for the life of me figure this timer stuff out.

Here's my current attempt:

void TC4_Handler() {
 Stepper::updateAll();
}
void setup() {
 // Timer stuff
 // Set up the generic clock (GCLK4) used to clock timers
 REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) | // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz
 GCLK_GENDIV_ID(4); // Select Generic Clock (GCLK) 4
 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
 REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
 GCLK_GENCTRL_GENEN | // Enable GCLK4
 GCLK_GENCTRL_SRC_DFLL48M | // Set the 48MHz clock source
 GCLK_GENCTRL_ID(4); // Select GCLK4
 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
 // Feed GCLK4 to TC4 and TC5
 REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK4 to TC4 and TC5
 GCLK_CLKCTRL_GEN_GCLK4 | // Select GCLK4
 GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK4 to TC4 and TC5
 while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
 REG_TC4_COUNT16_CC0 = 0x000F; // Set the TC4 CC0 register as the TOP value in match frequency mode
 while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization
 //NVIC_DisableIRQ(TC4_IRQn);
 //NVIC_ClearPendingIRQ(TC4_IRQn);
 NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest)
 NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC)
 REG_TC4_INTFLAG |= TC_INTFLAG_OVF; // Clear the interrupt flags
 REG_TC4_INTENSET = TC_INTENSET_OVF; // Enable TC4 interrupts
 // REG_TC4_INTENCLR = TC_INTENCLR_OVF; // Disable TC4 interrupts
 REG_TC4_CTRLA |= TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz
 TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode 
 TC_CTRLA_ENABLE; // Enable TC4
 while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization
 // ...
}
VE7JRO
2,51519 gold badges27 silver badges29 bronze badges
asked Apr 27, 2017 at 15:43

1 Answer 1

1

As Stepper::updateAll(); isn't shown I don't know what it does. For accurate timing it would make sense to use hardware-operated output-compare output pins like TIOAx and TIOBx, instead of running some code to drive the pins when an interrupt occurs.

If you need to control several wires per motor – such that a pulse on a single output line isn't enough – you might consider using a 74HC595 (or other shift register) to transfer the bits. Thus, each time an output compare occurs, the TIOAx and TIOBx line would pulse the ST_CLK (store-clock) line of the SR, to transfer bits from the shift chain flipflops to the output flipflops; then, at its leisure the interrupt routine can shift the next set of bits out to the '595, ready to be transferred at the correct moment, when the next output compare occurs.

During stepper acceleration or deceleration, the timer count-limit would also need to be updated within the ISR.

answered Apr 27, 2017 at 20:00
2
  • I'm using this driver pololu.com/product/2975, all Stepper::updateAll() does is to check if the step pin needs to be pulsed. Commented Apr 27, 2017 at 20:40
  • In that case, you should use a TIOAx or TIOBx line to pulse the A4988, and should calculate timer count-limits for the ISR to set. In other words, don't "check if the step pin needs to be pulsed" – which amounts to trying to run the stepper using polling, which is a bad idea – but instead calculate when the step pin needs to be pulsed, set timer accordingly, and have the timer pulse the A4988. Commented Apr 27, 2017 at 23:25

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.