Pages: [1]   Go Down
Author Topic: interrupt for multiple stepper motors - optimized approach  (Read 579 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Karma: 0
Posts: 26
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi everyone in the fellow arduino community!   smiley-mr-green

I was hoping i get could some thoughts/improvements on the way I'm approaching this code.  For the last year or so, I've been working on a project which involves being able to control up to 5 stepper motors in real time.  Each of the stepper motors require a digital pin to be toggled high/low at upwards of about 100kHz.  Given the fact this is is relatively fast (max interrupt speeds for a single ISR I've ready about are 1MHz on the Due) and that the timing of the motors is time sensitive, I want to make sure I'm approaching things in an optimized way.

I'm about to take another fresh go at the code and am thinking of the following structure; for each motor we are doing two time specific things:
1) toggling the step pin HIGH/LOW, the frequency of which is changed based on the stepper speed we want -- dictates as velocity.
2) adjusting the frequency with which we toggle the step pin HIGH/LOW; this is done at equal intervals -- dictates as acceleration.

point 1) is taken care of as follows:
- I've written up my own little library (named from here on as Engine) that keeps track of information for each declared motor.
- using the very excellent DueTimer library I setup an ISR that calls a step() function in my library, the step() function being simply defined along the lines of:
void Engine::step() {
   digitalWriteDirect(_stepPin, toggle = !toggle); // fast write to our step pin, alternates between HIGH/LOW

where digitalWriteDirect is defined as:
inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;

This gives me a nice way of stepping motors at my required frequencies; however, in order to change the speed of motors, I have to adjust the frequency with which the step() function is called.

point 2) is handled as follows:
at this point, we've already used upwards of 5 timers (1 for each motor) which leaves us with only 4 left (correct me if I'm wrong). So we will have to do things the manual way by defining an accelerate function within my Engine library which adjusts speed and gets checked all the time (here is where we start slowing down); we'll need to accelerate for each motor (M) with something that looks like this:
void loop() {

with accelerate() being pseudo defined as something like:
void Engine::accelerate() {

   time = micros();

   if (time >= previousTime + _updateInterval) { // only update speeds after equal time intervals (_updateInterval) have passed: manual implementation of ISR

      given some condition, adjust our ISR call frequency for step(); // adjust our stepper speed
      update the proper ISR timer registry // update our ISR frequency which adjusts our stepping speed
      previousTime = time;



here is where your smart brains come in; does anyone see an alternate approach?  weakness to my approach?  where can i speed things up?  would you do anything differently?  thanks everyone ahead of time!
« Last Edit: October 13, 2013, 01:17:30 pm by titous » Logged

Pages: [1]   Go Up
Jump to: