Working with Pololu DRV8825 stepper driver

I've gotten so much help from this forum that I thought I might give something back in return.

I recently began tinkering with the Pololu DRV8825 stepper motor driver. It turns out to be a very nifty solution. Very clean and easy to write code for. Below is my test loop. Two things to note: 1) NO LIBRARIES!, and 2) NO INTERRUPTS!. Yup, by using the hardware PWM off Timer2, all one needs to do is set OCR2A and OCR2B and you get variable speed. Many thanks to Nick for the nifty solution to that problem. I got it off his website.

Now, this approach does have some downside. In exchange for the extreme simplicity of using the hardware PWM and the timer, one gives up the capability of gang-of-motors. That's fine for my project. I just need to drive two motors simultaneously. The equivalent use of Timer0 will take care of that. I'm not worried about millis() or micros(). Got my own cheap_delay().

So, anyway, here's the code.

/*
  Using Timer 2. 1024 prescale, F_CPU/1024 divisor, 50% duty cycle:
  
                                                            [calculated]  
  base freq  OCR2A  OCR2B  pulse width(ms)  pin3 freq(Hz)   RPM (@200 steps/rev)
  ---------  -----  -----  ---------------  -------------   --------------------
         61    255    127                8             61    18
        120    129     64                4            120    36
        240     64     32                2            240    72
        480     32     15                1            489   144
    --> 960     15      7              0.5            977   288 <--
    |  1920      7      3             0.26           1954   576   |
    |                                                             |
    --> 960 seems to be about the limit of the 28BYG301 <----------
*/

// As currently configured, LOW on the direction pin is CCW.
// HIGH reverses to CW. Default to LOW for start.

int main( void )
{
  int direction = 0;    // 0 is LOW, 1 is HIGH.
  
  // Setup the outputs: pin 3 for STEP, pin 4 for DIR. Per DVR8825 pinout.
  DDRD   |= (1 << 3);   // Enable pin 3 for OUTPUT to step the DRV8825
  DDRD   |= (1 << 4);   // Enable pin 4 for OUTPUT for step direction.
  
  // Setup Timer2: fast PWM, clear OC2B on compare, 1024 prescale.
  TCCR2A |= (1 << WGM20) | (1 << WGM21) | (1 << COM2B1 );
  TCCR2B |= (1 << WGM22) | (1 << CS22 ) | (1 << CS21) | (1<< CS20);
    
  while(1)
  {
    
// Speed up.

    for( int freq = 61; freq < 961; freq += 10 )
    {
      OCR2A     = ((F_CPU / 1024) / freq) - 1;
      OCR2B     = ((OCR2A + 1) / 2) - 1;
      cheap_delay( 100000 );
    }

// Slow down.      

    for( int freq = 960; freq > 60; freq -= 10 )
    {
      OCR2A     = ((F_CPU / 1024) / freq) - 1;
      OCR2B     = ((OCR2A + 1) / 2) - 1;
      cheap_delay( 100000 );
    }

// Reverse direction.

    if( direction )         // Direction is HIGH (CW)
    {
      PORTD  &= ~(1 << 4);  // Set DIR pin LOW.
      direction = 0;        // Record for the next pass thru the test loop.
    }
    else                    // Direction is LOW (CCW)
    {
      PORTD  |= (1 << 4 );  // Set DIR pin HIGH.
      direction = 1;        // Record for the next pass thru the test loop.
    }
  }
}

void cheap_delay( volatile unsigned long count )
{
  while( count > 0 ) count--;
}

what is nick's website??

thanks,

ewholz