Saturday 10 September 2011

Bipolar Stepper Motors - making them work.

An opportunity came to hande recently - an old PC was scrapped and it had a DVD drive in ti. I took the chance to totally disassemble it and discovered a lovely stepper motor with gearing and so forth to make it into a linear actuator.



The problem was, how to drive the beast. Firstly, it was obviously a stepper motor as it had > 2 leads coming from it. How was it wired up, though. Well, firstly I got a voltmeter and worked out that it was simply to 20 ohm coils. This means it was a dreaded bipolar stepper - harder to drive than unipolar.

I decided to have a go. I soldered on some power leads and hooked it up to my DFRobot L298 Motor shield. Then, I had to write the code.

It turns out that there is no ready source code for this handy. Basically, the motor has to be driven by a dual h-bridge arrangement working the coils using digital square waves that go between +5 and -5V through 0V. This can be seen roughly as sine waves. They waves need to be about 90 degress out of phase.


Basically, the DFRobot board allows you to control the speed and direction of each motor only. I built a function to set speeed and direction of each motor based on the steps 0->7 in the diagrams. Each step waas a function. I put these functions into an array of function pointers and simply called them in order to get movement. Stepping back throught the table gave reverse motion.

Here's the simple code:

//Arduino PWM Speed Control:
int E1 = 6;  
int M1 = 7;
int E2 = 5;                        
int M2 = 4;  

#define  DELAY  2
#define  PWR    200

void
MotorsOff()
{
    analogWrite(E1, 0);   //PWM Speed Control
    analogWrite(E2, 0);   //PWM Speed Control
 
}

void
Step0()
{
    // 0
    digitalWrite(M1,HIGH);  
    analogWrite(E1, PWR);   //PWM Speed Control

    digitalWrite(M2, HIGH);      
    analogWrite(E2, 0);   //PWM Speed Control
    delay(DELAY);
}
void
Step1()
{
    // 1
    digitalWrite(M1,HIGH);  
    analogWrite(E1, PWR);   //PWM Speed Control

    digitalWrite(M2, HIGH);      
    analogWrite(E2, PWR);   //PWM Speed Control
    delay(DELAY);
}
void
Step2()
{
    // 2
    digitalWrite(M1,HIGH);  
    analogWrite(E1, 0);   //PWM Speed Control

    digitalWrite(M2, HIGH);      
    analogWrite(E2, PWR);   //PWM Speed Control
    delay(DELAY);
}
void
Step3()
{   
    // 3
    digitalWrite(M1,LOW);  
    analogWrite(E1, PWR);   //PWM Speed Control

    digitalWrite(M2, HIGH);      
    analogWrite(E2, PWR);   //PWM Speed Control
    delay(DELAY);
}
void
Step4()
{   
    // 4
    digitalWrite(M1,LOW);  
    analogWrite(E1, PWR);   //PWM Speed Control

    digitalWrite(M2, HIGH);      
    analogWrite(E2, 0);   //PWM Speed Control
    delay(DELAY);
}
void
Step5()
{   
     // 5
    digitalWrite(M1,LOW);  
    analogWrite(E1, PWR);   //PWM Speed Control

    digitalWrite(M2, LOW);      
    analogWrite(E2, PWR);   //PWM Speed Control
    delay(DELAY);
}
void
Step6()
{   
     // 6
    digitalWrite(M1,LOW);  
    analogWrite(E1, 0);   //PWM Speed Control

    digitalWrite(M2, LOW);      
    analogWrite(E2, PWR);   //PWM Speed Control
    delay(DELAY);
}
void
Step7()
{   
      // 7
    digitalWrite(M1,HIGH);  
    analogWrite(E1, PWR);   //PWM Speed Control

    digitalWrite(M2, LOW);      
    analogWrite(E2, PWR);   //PWM Speed Control
    delay(DELAY);
}

#define  NUM_STEPS  8

int *steps[NUM_STEPS] = {(int *)Step0,(int *)Step1,(int *)Step2,(int *)Step3,(int *)Step4,(int *)Step5,(int *)Step6,(int *)Step7};


void setup()
{
    pinMode(M1, OUTPUT);  
    pinMode(M2, OUTPUT);
}

void loop()
{
  int  i;
  void  (*j)();
 
  for (i = 0; i < 450; i++)
  {
   
    j = (void (*)())steps[i % NUM_STEPS];
   
    (*j)();
  }
 
  MotorsOff();
  delay(1000);
 
  for (i = 450; i > 0; i--)
  {
   
    j = (void (*)())steps[i % NUM_STEPS];
   
    (*j)();
  }

 
}

6 comments:

  1. oh wow, you have way too much time on your hands. Can you pop round and scrub my pool or pull up a few weeds ;-)

    ReplyDelete
  2. I have tested your code, it works fine. I was wondering how can we possibly increase the rotation speed of the stepper engine ?

    ReplyDelete
    Replies
    1. You could try increasing the PWM power to 255 and decreasing the delay to 1 or even 0. Ultimately, the best solution is some hardware: http://littlebirdelectronics.com/products/big-easy-driver

      Delete
    2. You could try increasing the PWM power to 255 and decreasing the delay to 1 or even 0. Ultimately, the best solution is some hardware: http://littlebirdelectronics.com/products/big-easy-driver

      Delete
    3. If I increase or decrease the PWM then the stepper has more or less power but it does not act on the speed.

      Delete
  3. Thanks for the post! I tested the code on my L298P, and I keep getting this error:

    Arduino: 1.8.1 (Windows 10), Board: "Arduino Leonardo"

    Probeer_shield:112: error: two or more data types in declaration of 'setup'

    void setup()

    ^

    C:\Users\OneDrive\Documents\Arduino\Probeer_shield\Probeer_shield.ino:11:11: warning: ISO C++ forbids declaration of 'MotorsOff' with no type [-fpermissive]

    MotorsOff()

    ^

    exit status 1
    two or more data types in declaration of 'setup'

    Any idea what could be wrong? I used yours directly.

    ReplyDelete