Wednesday, February 20, 2008

Variable Speed Motor Control

Pulse Width Modulation (PWM) is a way to control the speed of a motor.  The following example program, pwm.c, demonstrates PWM with the Atmega32.  A motor is run in the forward direction from slow-->fast-->slow, and then in the reverse direction from slow-->fast-->slow. 

In order for the program to work, the microprocessor needs to be connected to some circuitry to drive the motor, probably an H-Bridge, which allows bi-directional control of a motor (e.g. you can get it to spin in either direction, by way of sending current forward or backwards through the circuit).

Here are some kinds of motor-driving H-Bridges:


general reference on H-Bridges: http://www.discovercircuits.com/H/hbridge.htm

---------------------

//

// pwm.c

//

// a simple program to control the speed of a DC motor in the forward and reverse directions, using Pulse Width Modulation (PWM).

// This program requires an hbridge motor driver (such as L6203 or LMD18200), a 12-24V DC motor, and a sufficient power supply (12-24V).

//

// rtwomey@ucsd.edu

//



// includes

#include <avr/io.h> // include I/O definitions (port names, pin names, etc)

#include <avr/interrupt.h> // include interrupt support


#include "global.h" // include our global settings

#include "uart.h" // include uart function library

#include "rprintf.h" // include printf function library

#include "timer.h" // include timer function library (timing, PWM, etc)


// function prototypes

int pwmDemo(void);


// program

int main(void)

{

// initialize the UART (serial port)

uartInit();

// set the baud rate of the UART for our debug/reporting output

uartSetBaudRate(57600);

// initialize rprintf system

rprintfInit(uartSendByte);

// initialize the timer system

timerInit();

// initialize pins for PWM

// set OC1B (PD4) to output for PWM

// set OC1A (PD5) to output for PWM

// set PD6 to output for DIR

// set PD7 to output for BRAKE

sbi(DDRD, PD4);

sbi(DDRD, PD5);

sbi(DDRD, PD6);

sbi(DDRD, PD7);


// turn off pull-up resistor on those pins

cbi(PORTD, PD4);

cbi(PORTD, PD5);

cbi(PORTD, PD6);

cbi(PORTD, PD7);

// print a welcome message so we know things are working

rprintf("rnnnWelcome to the PWM demonstration!rn");


// run the demo

while(1) {

pwmDemo();

};

return 0;

}


int pwmDemo(void)

{

// PWM demo cycle

int i=0;

// initialize timer1 for PWM output, 8 bit resolution.

rprintf("Initializing timer1 for PWMrn");

timer1PWMInit(8);


// turn on the channel A PWM output of timer1

// - this signal will come out on the OC1A I/O pin (PD5)

rprintf("Turning on timer1 channel A PWM outputrn");

timer1PWMAOn();


// turn on the channel B PWM output of timer1

// - this signal will come out on the OC1B I/O pin (PD4)

rprintf("Turning on timer1 channel B PWM outputrn");

timer1PWMBOn();


// set direction to 1 (forward);

//rprintf("Setting direction pin (PD6) to forward (1)rn");

//sbi(PORTD, PD6);


// set brake to 0 (no braking)

//rprintf("Setting brake pin (PD7) to no braking (0)rn");

//cbi(PORTD, PD7);


// sweep through range of pwm duty cycles in forward direction. 

for(i=0; i<=255; i++)

{

// set duty cycle;

timer1PWMASet(i);

rprintf("Forward = %drn", i);

    timerPause(10);

}


// wait

rprintf("Pause for 0.5 second...rn");

timerPause(500);


for(i=255; i>=0; i--)

{

// set duty cycle;

timer1PWMASet(i);

rprintf("Forward = %drn", i);

    timerPause(10);

}

// wait

rprintf("Pause for 0.5 second...rn");

timerPause(500);


rprintf("Turning off PWM in forward dir (PWMA)rn");

timer1PWMAOff();


// wait

rprintf("Pause for 0.5 second...rn");

timerPause(500);


// set direction to 0 (reverse);

//rprintf("Setting direction pin (PD6) to reverse (0)rn");

//cbi(PORTD, PD6);


// sweep through range of pwm duty cycles in forward direction. 

for(i=0; i<=255; i++)

{

// set duty cycle;

timer1PWMBSet(i);

rprintf("Reverse = %drn", i);

    timerPause(10);

}

// wait

rprintf("Pause for 0.5 second...rn");

timerPause(500);


for(i=255; i>=0; i--)

{

// set duty cycle;

timer1PWMBSet(i);

rprintf("Reverse = %drn", i);

    timerPause(10);

}

rprintf("Turning off PWM in reverse dir (PWMB)rn");

timer1PWMBOff();


// wait

rprintf("Pause for 0.5 second...rn");

timerPause(500);


// now turn off all PWM on timer1

rprintf("Turning of all PWMrn");

timer1PWMOff();


// wait

rprintf("Pause for 0.5 second...rn");

timerPause(500);


return(0);

}


No comments: