DC Motor Speed Control Part I: Open-Loop Command

In this article, we discuss speed control of a simple brushed DC motor with incremental encoder feedback. A standard PID algorithm is implemented on PIC24EP256MC202, a 70 MIPS microcontroller from Microchip. We focus on constructing an experimental platform using a small DC motor commercially available and off-the-shelf H-bridge driver. This motion control setup will be used in our subsequent articles

DC Motor and Encoder

One way to construct a cheap experimental setup for motion control is to find a used DC servomotor with encoder equipped. Quality control of second-hand stores is a major problem; not everyone would be lucky to find a set in good-condition. There is no simple way to verify that the encoder is working okay. Fortunately, brand new DC motor with encoder unit can now be bought online within budget. An example is DC motor product line from www.pololu.com . Here we select their 19:1 Metal Gearmotor 37Dx52L mm with 64 CPR Encoder product as shown in Figure 1. This motor is equipped with a bare incremental encoder at the bottom as in Figure 2. A 12V power source is needed to drive the motor, and 5V for the encoder circuit. For other specs, please refer to the data on Pololu website.

Figure 1 a DC motor with encoder from www.pololu.com

Figure 2 incremental encoder unit at the bottom end of DC motor

H-bridge Motor Driver

There are many H-bridge motor driver products from various vendors, including Pololu, that could be used in this project. It happens that I have an old board model HMD-10A from Anycontrol Ltd, Thailand handy. It works fine in the desired setup. What makes this driver different from other products is the inverse polarity of PWM signal; i.e., the motor speed is proportional to the duty cycle of logic 0. So to make the controller algorithm less confusing, I use 1/6 of 74LS04 hex inverter at the drive input to make motor speed proportional to duty cycle of logic 1. The inverter also functions as a 3.3 to 5 volt level shifter and an buffer to the PWM output.

Since our simple experimental setup does not need any load at the motor output, it is convenient to mount DC motor, H-bridge drive and interface protoboard on a piece of wood as shown in Figure 3.

Figure 3 our “poorman” DC motor experimental setup

The board on the right (not screwed on wood) is our PIC32EP256MC202 module. The prototype is soldered and wired as in Figure 4. Such board could be assembled easily with budget around USD 20. Actually, not all components shown in Figure 4 are needed for the experiment in this article.

Figure 4 top and bottom view of PIC24EP256MC202 controller board

Open-Loop Experiment

To perform an initial test for our DC motor setup, we attempt to drive the motor in an open-loop fashion. This involves sending a pair of signals: PWM for motor speed, and DIR for direction (0 = clockwise and 1 = counter-clockwise). The PWM module is setup for 16-bit resolution as explained in “A Note on Output Compare (PWM) Module of PIC24E” article, with one exception. In that article the PWM module obtains the clock source from the peripheral clock, whose frequency is too high for our DC motor driver. This makes it difficult to command low-speed turning of the motor. So we instead assign a timer output as clock source to the PWM. For example, to use timer 2, setup OCTSEL bits in the OC1CON1 register as follows

OC1CON1bits.OCTSEL = 0b000;  // select Timer 2 as clock

Then initialize timer 2 to the desired frequency. Say, to set timer 2 interrupt at 8.7 KHz rate,

void initT2() // Initialize Timer 2 to use as PWM clock
    _T2IE = 0;  // disable first
    T2CON = 0x8010 ; 		// Internal Clock (FOSC/2)=70MHZ,
    PR2   = 1000;        //ts/(tcy*64) where tcy = 1/70M
    TMR2  = 0x0000 ;
    _T2IF = 0;
    _T2IE = 1;

Do not forget that, even though timer 2 has no particular task in its service routine, we need to reset _T2IF so that the next timer interrupt could occur

void __attribute__((interrupt, auto_psv)) _T2Interrupt(void)
    _T2IF = 0;

The open-loop test needs no feedback. Even though the actual RPM is read from the QEI module of PIC24EP, the data is used for plotting a comparison only.

So, to create a reasonable speed command, we need to somehow find the relationship between the PWM value and motor speed. From the DC motor datasheet, at 12 Vdc the maximum speed of geared output shaft is 500 RPM with no load. This should be achieved when PWM value is at 100%. The PWM resolution is 16-bit. So let us define the following parameters

#define PWMMAX 65535  // maximum PWM for 16-bit resolution
#define MAXRPM 500   // maximum motor speed is 500 RPM

Construct a speed command variable scmd, in the range of +/- 500 RPM. Whenever this variable is updated by the user in real-time, the DIR value is determined by the sense, and PWM value is computed accordingly and written to the OC1R register. The C-code for such task can be written as follows (PWMVal is defined globally and DIR is the latch register of digital output pin used to control direction)

       if (scmd < 0)   {  // negative sense
            PWMVal = (unsigned int)-scmd*PWMMAX/MAXRPM;
            if (PWMVal>PWMMAX) PWMVal = PWMMAX;
            DIR = 1;   // CCW direction
        else   {     // positive sense
            PWMVal = (unsigned int)scmd*PWMMAX/MAXRPM;
            if (PWMVal>PWMMAX) PWMVal = PWMMAX;
            DIR = 0;   // CW direction
        }   // if (scmd < 0)
        OC1R = PWMVal;

Now, to obtain the actual motor speed, we simply read from the VEL1CNT register of QEI1 module, and convert to RPM

     QEIvVal = VEL1CNT;  // read velocity each vsamp
     srpm = 60*QEIvVal/(Ts*4*ENCPPM);  // actual motor speed in RPM

where Ts is the sampling period, and ENCPPR is defined as total number of encoder pulses per round, 1200 for this motor. Note that the QEI module is set up to detect each rising and falling edges of quadrature signals A and B. This increases the resolution 4 times.

Set the speed command variable scmd to 10 RPM. The plot in Figure 5 compares the actual motor speed to the command. Well, from this comparison, the open-loop speed control performs poorly. The speed error is more than 150 %. This might come from certain factors. Our linear estimation of the PWM versus motor speed relationship could be inaccurate, or data from the manufacture is obtained from a different setup. etc.

Figure 5 comparison between actual motor speed and command

In any case, without feedback one could not hope for a reliable speed regulation. In the next article, we will exploit PID feedback to cope with this speed error and combat disturbances such as when load changes.



Comments are closed.