Basic Starter Package - Tutorial #5

Tutorial #5 - (Part 2) Use of the PWM to Control a DC Motor's Speed

copyright, Peter H. Anderson, Dept of EE,
Morgan State University, Baltimore, MD, Dec 19, '97


This tutorial focuses on how to control a DC motor using a L293 quad push-pull driver. The direction is controlled by a switch and the speed by two pushbuttons using the PWM command.

This is then extended to the use a variable resistor to control the period of a free running 555 clock. The Stamp measures the period using the PULSIN command and uses this to control the speed of the DC motor.

Use of the L293 as an "H" Bridge.

Please refer to Figure #1. Note that LEDs on P3, P2, P1 and P0 may be left in place, and in fact LED1 and LED0 are useful for debugging.

Switches S14, S13 and S12 are not used, but may be left in place.

Note that when Stamp output P2 is at a logic one, sections 1 and 2 of the L293 are enabled. If Stamp outputs P1 and P0 are at zero and one, respectively, transistors Q_2_down and Q_1_up are on, all other transistors are off, and current flows one way through the motor winding. However, if Stamp outputs P1 and P0 are at one and zero, respectively, transistors Q_2_up and Q_1_down are on and current flows in the opposite direction.

This is summarized in the following table;

     P1   P0   Q_2_up    Q_2_down  Q_1_up    Q_1_down  Action

     0    0    off       on        off       on        none
     0    1    off       on        on        off       one way
     1    0    on        off       off       on        other way
     1    1    on        off       on        off       none
Note that for the 0 0 state, both sides of the motor are near ground and no current flows. For the 1 1 state, both sides are near +12V and again, no current flows.

Thus, the control of the motor's direction may easily be implemented by outputting either 0 1 or 1 0 on P1 and P0.

All of this has assumed L293 input EN12 under the control of Stamp output P2 is at logic one. If it is at zero, all transistors are off and no current flows through the motor's winding.

Thus, controlling the amount of time output P2 is high using the PWM command may be used to vary the duty cycle and thus control the speed of the motor.

Program PWM_4.BS2.

The speed control portion of program PWM_4 is quite similar to PWM_3 from Part 1 of this PWM tutorial. Note that the high and low thresholds have been revised to 253 and 110. By experimenting with the motor we have found that a duty of 110, reduces the motors effective voltage to nominally five volts (110/256 * 12) and the motor ceases to turn. The value of 253 is of course, near the maximum speed. The selection of 253 rather than 255 was to avoid the troublesome overflow problem which would only confuse the discussion.

Switch S15 controls the direction of the motor.

' Program PWM_4.BS2
' Causes DC motor to move at a direction specified by switch S15. 
' Speed is controlled by pushbutttons PB11 and PB10.  Depression 
' of PB11 causes the motor to move faster.  Depression of PB10 
' causes motor to go slower.
' P. H. Anderson, Dec 18, '97

     MAX_DUTY CON 253
     MIN_DUTY CON 110


     CYCLES = 25

     OUT1=0         ' one way

     OUT1=1         ' other way
     GOTO SPEED     ' not really necessary



     DUTY = MAX_DUTY          ' already at the maximum

     DUTY = MIN_DUTY          ' already at the minimum

Switch S15 is read and either 01 or 10 is output on Stamp outputs P1 and P0.

The pushbuttons are read and the duty cycle is either left the same, increased or decreased.

It is important to note that very little time is spent outside execution of the PWM command. Recall, that exit from the PWM command causes the terminal go into a high impedance state, which in this case would probably be seen by the L293 as a logic one on EN12. Thus, any appreciable time spent away outside the PWM command may cause the motor to noticeably increase in speed.

Program MOT_POT.BS2.

The following program illustrates how the speed of a DC motor might be controlled using a potentiometer, much like a variable speed electric drill.

The obvious technique would of course be to place a variable resistor in series with the motor. However, recognize that such a motor draws amperes of current and a series approach would require a very expensive potentiometer with next to no wiper resistance and capable of withstanding the arcing associated with such currents.

Rather, in these days of inexpensive processors, the potentiometer might change the period of a 555 astable multivibrator which is read by the processor and the value of the period is mapped in to a duty cycle.

Please refer to Figure #2. Note that the theory of the operation of a 555 is discussed in Appendix I.

Note that when the 10K pot is at one limit, R1 is 11K and R2 is 1K resulting in a period of 450 usecs. When at the other limit, R1 is 1K and R2 is 11K resulting in a period of 800 usecs. This is summarized in the following table;

     Pot       R1   R2   T= (R1+2*R2)*C*ln(2)     Desired Duty

     One Limit 11K  1K   450 usecs           110 (Motor at min)
     Other Lim 1K   11K  800 usecs           255 (Motor at max)
Thus, by measuring the period, one might develop an expression for duty in terms of T. Note that in developing such expressions, try to use common sense and test your expression as opposed to consulting some elusive text. I just don't like what my students refer to as "plugging in the equations" as there is no understanding and blindly plugging just leads to a lot of problems.

Note that 450 is to mapped to 110, suggesting (T-450) + 110. At least this works for this point.

But, 800 (350 above 450) is to be mapped to 255 (145 above 110).

Consider, DUTY = (T-450) * 145 / 350 + 110. For T=450, this reduces to 110. For T=350, we have 350 * 145/350 + 110 or 255. Seems to work!

Thus, in the following program, the time the pulse is high and low is measured and this results in a period which is mapped to a new duty.

This is not all done in one block of code as I did not desire to stay away from the PWM for any appreciable period of time. Thus, note that determining the new duty is done in steps and these steps are interspersed with shots of PWM, each for 25 msecs. Of course, this leads to a 150 ms lag in the motor responding to a new value of the potentiometer, but my feeling is that the user will not note a 1/7 second lag. When I let up on my electric drill, it takes several seconds for the thing to coast to a halt.

Was this precaution really necessary in this design. Probably not, but I offer the concept as a possible solution when you have a task that is long which must be performed while PWMing. Break the task up.

[Note that the whole approach to the problem is a bit flawed. In fact, I would use the RCTIME function and scrap the 555. However, the intent of the tutorial is to illustrate the use of the PULSIN command and this is a nice example.]

' Drives DC Motor using L293D.  
' Speed is determined by the setting of a potentiometer which 
' controls the period of a 555 astable.  The period is read by the 
' Stamp using the PULSIN command and the value is mapped into a
' duty cycle in the range of 128 to 255.
' Direction is controlled by S15.
' P. H. Anderson, Dec 18, '97

DUTY           VAR WORD
T_HI_DIV_2     VAR WORD  ' high time of pulse in number of 2usec
T_LO_DIV_2     VAR WORD  ' low time of pulse in number of 2usec
T              VAR WORD  ' period in usecs

     DIRS = $000F
     DUTY = 110          ' Motor near off

     PWM 2, DUTY, 25

     OUT0 = 0
     OUT1 = 1
     GOTO TOP_1

     OUT0 = 1
     OUT1 = 0
     GOTO TOP_1     

     PWM 2, DUTY, 25
     PULSIN 8, 1, T_HI_DIV_2
     PWM 2, DUTY, 25
     PULSIN 8, 0, T_LO_DIV_2
     PWM 2, DUTY, 25
     T = (T_HI_DIV_2 + T_LO_DIV_2)*2
     PWM 2, DUTY, 25
     IF (T > 450) THEN SKIP_1
        T = 450     ' if its less than 450 then set it to 450

     IF (T < 800) THEN SKIP_2
        T = 800     ' if its higher than 800, set it to 800

     PWM 2, DUTY, 25
     DUTY = (T-450) * 145 / 350 + 110 ' map this into a new duty

The nature of the PULSIN command is;

     PULSIN pin, 1, var
where the "one" indicates to measure the time from the next positive going transition to the subsequent negative going transition. The time, in 2 usec clicks is copied to the variable. Thus, if the variable is a word, the PULSIN command may handle up to 65,535 usecs times 2 or nominally 131 msecs. If, no signal is found, the result is returned as $FFFF (65,535). There are two ways this could occur; if no positive going signal was observed within 131 msecs of execution of the command, or if a positive transition was found, but no negative going transition was observed within 131 ms after the positive transition. Note that the high and low times are in 2 usec clicks. Thus, in calculating the period, the two are summed and multiplied by two. In the above discussion, minimum and maximum periods of 450 and 800 usecs were calculated, and these are based on "perfect components" having a tolerance of zero and life isn't that kind. Rather than get into an exhaustive design exercise, I simply decided that is the value of T was less than 450, set it to 450, and if greater than 800, set it to 800. The latter is particularly important as a value greater than 800 will cause a duty greater than 255 ($FF). However, recall that the PWM duty is a byte having a value in the range of 0 to 255 and thus a duty greater than 255 will in fact result in an overflow. Thus, failing to limit the period to 800 may result in the user eagerly pulling that trigger fully back to do some serious drilling, only to find the motor comes to a halt.


The theory of using an 'H' bridge to control a DC motor was presented. Changing directions requires no more than reversing the state of two bits. The PWM command offers an inexpensive technique for varying the effective voltage across the motor winding and thus varying the speed.

This was extended to using a potentiometer to control the period of a 555 clock and using the period to determine the speed of the motor. The intent here was to introduce an application of the PULSIN command and to illustrate how two points, in this case 450 and 800, might be linearly mapped to another quantity.

Other applications of the PWM command, including A/D conversion and displaying quantities on an inexpensive 200 mV panel meter are included in Part 3 of the PWM Tutorial.

Other applications of the PULSIN command including the measurement of temperature using a thermistor and the measurement of relative humidity are discussed in the tutorials dealing with EEPROM and Weather Measurements.