steppernxtvc

# Stepper Motor Theory and Direction/Speed/Displacement Control

Author: Xinke (Rebecca) Cao
Keywords: unipolar stepper motor, LEGO NXT, transistors, IRF510

## Motivation and Audience

This tutorial is for users who want to expand on the control of the stepper motor in terms of velocity and direction control. In addition, the theory on how to control the stepper motor is also shown in this tutorial.

### Reference Tutorials / Video Demos

Here is where you will find the tutorial on using the stepper motor through ULN2003A.
Here is where you will find the tutorial on using the stepper motor through IRF510.

Stepper motor with IRF510 moving clockwise 180 degrees can be seen on this YouTube video.
Stepper motor with ULN2003A moving clockwise 180 degrees can be seen on this YouTube video.

Stepper motor with IRF510 moving counterclockwise 90 degrees can be seen on this YouTube video.
Stepper motor with ULN2003A moving counterclockwise 90 degrees can be seen on this YouTube video.
The speed of the stepper motor can range up to 4 rpm due to the limit of the speed at which NXT brick runs its program.

General Knowledge
Stepper motor can be split into three categories: unipolar, bipolar, or hybrid. In a unipolar stepper motor, there are wires called central tap wires to allow the motor to switch directions without having to switch the direction of the current. Therefore, in a 5-lead stepper motor, 4 wires are used to control the stepping and 1 wire is the central tap; in a 6-lead stepper motor, 4 wires are used to control the stepping and 2 wires are the central tap. Having the advantage of not having to switch the direction of the current for an unipolar stepper motor, one can just control the sequence of the stepping instead of having to use a H-bridge to control the current as well.
The bipolar stepper motors requires a switch of the direction of current; therefore, as mentioned before, one need an H-bridge to control a bipolar stepper motor as explained here.

Mechanical Parts
When you try to make the stepper motor move, you move the internal motor inside. What you see, the golden metal part of the stepper, is the key shaft on the exterior.
When the internal shaft moves, it can either move with half-stepping (5.625 degrees per step) or move with full-stepping (11.25 degrees per step). The header file that I wrote uses full-stepping because full-stepping gives you the maximum torque but half-stepping gives you 70% of the maximum torque. Running in full-step driving mode will need 32 steps to move the internal shaft a full revolution.
The gear ratio of the internal shaft to the key shaft is approximately 64:1. Therefore, using the full-step driving, you need 32*64 = 2048 steps to move the key shaft 360 degrees.

The Wires
The 28BYJ-48 5V unipolar stepper motor has 5 wires: red, orange, yellow, pink, and blue. The red wire is called the center tap wire, and it should be connected to a voltage source ranging from 5V to 12 V DC as shown here.
The other wires has to be raised to a higher potential in a certain sequence to move the stepper motor. For example, for full-step drive, you have to raise both yellow & orange at the same time; then, you raise orange & blue at the same time; then, you raise blue & pink at the same time; finally, you raise pink & yellow at the same time. If you repeat the sequence, the motor is going to keep on moving. If you use the sequence backwards, the motor is going to move in the opposite direction. In addition, how fast these sequences are fired will determine the speed at which the stepper motor moves.

Finding the Central Tap Wire for a Unipolar Stepper Motor
Using a ohmmeter, with one terminal of the ohmmeter on one lead of the stepper motor, another terminal of the ohmmeter on another lead of the stepper motor, measure the resistance between all pairs of wires. Then, when you find a wire that will cause the resistance between pairs of wires to read about a half of a resistance between other pairs of wires, you've found the central tap wire.

### Programming

StepperBoth.h
This is the header file for the stepper motor where the stepper motor is declared as a struct to allow multiple functions to change the values inside the struct because classes are not supported on the NXC.

```struct Stepper
{
byte I2Cport;
int orange_bit;
int yellow_bit;
int pink_bit;
int blue_bit;

unsigned long delay_btw_steps;
int steps_per_rev;
};```

Next, a speed setter is declared to allow the user to set the speed of the stepper motor.

```void SetSpeed(Stepper &t, int rpm)
{
t.delay_btw_steps = 60 * 1000 / t.steps_per_rev / rpm;
//this estimates how many ms one step should take based on rpm
}```

Then, a function will be used to change the values inside the struct. The values include the I2C port for the NXT, the I2C address, the bit number that the 4 main wires of the stepper motor is connected to on the PCF8574A. Finally, you have to set up how many steps that the stepper motor will take to make a full revolution. In the case of full-stepping and for the 28BYJ-48, you need 2048 steps per revolution.

```void StepperInit(Stepper &t, byte I2Cport,int I2CAddr8574,int orange_bit, int yellow_bit, int pink_bit, int blue_bit, int steps_per_rev)
{
t.I2Cport = I2Cport;
t.orange_bit = orange_bit;
t.yellow_bit = yellow_bit;
t.pink_bit = pink_bit;
t.blue_bit = blue_bit;
t.steps_per_rev = steps_per_rev;
}```

There are two different versions to drive the stepper motor, one is “StepperRunIRF510,” which is used for the stepper motor that is connected to IRF510. The second one is the “StepperRunULN2003A,” which is used for the stepper motor that is connected to the ULN2003A.

```void StepperRunIRF510(Stepper &t, int stepsToMove)
{
long prevTick;
int steps_left = abs(stepsToMove);

// array variables (since NXC's I2C functions take array variables
byte WriteBuf[2]; // data written to PCF8574A.  Declares a two one-byte variables
byte ReadBuf[]; // data received from PCF8574A.  We won't be reading any data but we need this for I2CBytes
int RdCnt = 1; // number of bytes to read

SetSensorLowspeed (t.I2Cport); // PCF8574A connect to NXT

// First, set address with first I2CWrite.  Recall, WriteBuf[1] has address 0xF0 0x00
WriteBuf[1] = 0x00; // i.e. write zeros to port sets up PCF8574A for writing

if (stepsToMove > 0)    //CCW
{
prevTick = CurrentTick();
while (steps_left > 0)
{
switch(abs(steps_left % 4 - 3))
{
case 0:
WriteBuf[1] = pow(2,t.orange_bit)+pow(2,t.yellow_bit);
break;
case 1:
WriteBuf[1] = pow(2,t.yellow_bit)+pow(2,t.pink_bit);
break;
case 2:
WriteBuf[1] = pow(2,t.pink_bit)+pow(2,t.blue_bit);
break;
case 3:
WriteBuf[1] = pow(2,t.blue_bit)+pow(2,t.orange_bit);
break;
} //end switch
steps_left--;
while(CurrentTick()-prevTick < t.delay_btw_steps);
prevTick = CurrentTick();
} //end while
} //end if

if (stepsToMove < 0)    //CW
{
prevTick = CurrentTick();
while (steps_left > 0)
{
switch(steps_left % 4)
{
case 0:
WriteBuf[1] = pow(2,t.orange_bit)+pow(2,t.yellow_bit);
break;
case 1:
WriteBuf[1] = pow(2,t.yellow_bit)+pow(2,t.pink_bit);
break;
case 2:
WriteBuf[1] = pow(2,t.pink_bit)+pow(2,t.blue_bit);
break;
case 3:
WriteBuf[1] = pow(2,t.blue_bit)+pow(2,t.orange_bit);
break;
} //end switch
steps_left--;
while(CurrentTick()-prevTick < t.delay_btw_steps);
prevTick = CurrentTick();
} //end while
} //end if
} //end void```

To move the stepper motor counterclockwise, the stepper motor has to follow the blue-orange, pink-blue, yellow-pink, and orange-yellow cycle. This is why I used

`abs(steps_left % 4 - 3)`

in the switch-case statement, this will allow me to choose cases in the order of 3-2-1-0 cycle.
To move the stepper motor clockwise, the stepper motor has to follow the orange-yellow, yellow-pink, pink-blue, and blue-orange cycle. This is why I used

`steps_left % 4`

in the switch-case statement. This will allow me to choose the cases in the order of 0-1-2-3 cycle.
For the ULN2003A version, I have to reverse the bits. Since the PCF8574A is an I2C expander with 8 bits, this is why I have to use codes such as:

`WriteBuf[1] = 255-pow(2,t.orange_bit)+pow(2,t.yellow_bit);`

in the stepper motor control for the ULN2003A version.

To use the header file from “StepperBoth.h,” you need to define a struct for the stepper motor first. All of these sample codes are inside the file named “Stepper_UsingLibrary.nxc.”

`Stepper t;  //define a struct for the stepper motor we are using`

To initialize the members of the struct for the stepper motor, you have to use the “StepperInit()” function.
Below is an example for the stepper motor with the IRF510:

`StepperInit(t,S1,0x70,6,7,1,0,2048);  //For IRF510`

Below is an example for the stepper motor with ULN2003A:

`StepperInit(t,S1,0x70,3,2,1,0,2048);  //For ULN2003A`

To set the speed, you have to use the “SetSpeed()” function:

`SetSpeed(t,4);  //set the speed for the stepper motor in rpm`

Disclaimer: the limit on the speed using the header file is 4 rpm
To run the stepper motor for a certain amount of steps, you have to use the “StepperRun__” function.
For the IRF510, you use:

`StepperRunIRF510(t,-1024);`

For the ULN2003A, you use:

`StepperRunULN2003A(t,-1024);`

### Final Words

In summary, one can control it used the “SetSpeed” function. To control the direction, one can input a positive or a negative step value. In addition, one can specify how many steps to take to control the angular displacement.