## Worked example: Stepper driving second hand of clock

This is the example that we looked at in class last week, in which a stepper motor is driving the second hand of a clock. The stepper drives the second hand forward by (approximately) 6 degrees once a second. I should point out that this example is intended to illustrate the basic method of controlling a stepper with a dsPIC – as it stands, it’s certainly not a very accurate clock!

Ok, here’s the code:

```//
// dsPIC30F4011 Stepper clock second hand example
// Written by Ted Burke
// Last updated 10-10-2012
//

#include <xc.h>
#include <libpic30.h>

// Configuration settings
_FOSC(CSW_FSCM_OFF & FRC_PLL16); // Fosc=16x7.5MHz, Fcy=30MHz
_FWDT(WDT_OFF);                  // Watchdog timer off
_FBORPOR(MCLR_DIS);              // Disable reset pin

// Function prototypes
void rotate(double degrees);
void step_forward();
void step_back();

// global variables
double rotor_angle;
double step_angle;
long step_time;

int main()
{
// Make all port D pins outputs
TRISD = 0;

// Use initial position as angle origin
rotor_angle = 0;

// Stepper properties
step_time = 300000L; // 10ms
step_angle = 0.17578125; // 360.0 divided by 2048

// Now rotate the stepper 6 degrees once every second
while(1)
{
rotate(6.0); // Move forward 6 degrees
__delay32(19760000); // Delay for rest of second
}

return 0;
}

void rotate(double degrees)
{
// The target angle is the current angle
// plus the requested angle of rotation.
double target_angle = rotor_angle + degrees;

// Now keep stepping in the appropriate
// direction until the target is reached.
if (degrees > 0)
{
while(rotor_angle < target_angle) step_forward();
}
else
{
while(rotor_angle > target_angle) step_back();
}
}

void step_forward()
{
// Turn off the previous phase and turn
// on the next one.
if (LATD == 0b0001) LATD = 0b0010;
else if (LATD == 0b0010) LATD = 0b0100;
else if (LATD == 0b0100) LATD = 0b1000;
else if (LATD == 0b1000) LATD = 0b0001;
else LATD = 0b0001;

// Increment the global angle tracker.
rotor_angle = rotor_angle + step_angle;

// Delay to allow rotor to move.
__delay32(step_time);
}

void step_back()
{
// Turn off the previous phase and turn
// on the next one.
if (LATD == 0b0001) LATD = 0b1000;
else if (LATD == 0b0010) LATD = 0b0001;
else if (LATD == 0b0100) LATD = 0b0010;
else if (LATD == 0b1000) LATD = 0b0100;
else LATD = 0b0001;

// Decrement the global angle tracker.
rotor_angle = rotor_angle - step_angle;

// Delay to allow rotor to move.
__delay32(step_time);
}

```

The circuit is as follows: This entry was posted in Uncategorized. Bookmark the permalink.