In this tutorial, we explain how to use PWM explained earlier to control a motor. We will discuss first about earlier methods of controlling motors with tansistors and explain the advantages of PWM before having a real hands-on demonstration.

 Controlling a motor

In Tutorial 5, we have explained that we can control a LED by PWM. An interesting feature is that it was possible to dimm the LED luminosity and make it look like an analog dimmer (i.e. the voltage seemed to be variable although it's simply binary, either full voltage or 0).

The advantage of this method is that it's a lot more power-efficient. If we control the LED the analog way, it will be power efficient only when fully powered. In all other cases, the analog voltage adjustment will act as a resistor that consumes what you don't want to got to the LED. The digital way consists in using intervals of full power separated by intervals of no power, quickly enough to make it look continuous.

This can be used the same way to control a motor.

Running the motor backwards

When powering a motor, it is interesting to have the possibility to reverse its rotation. We can do that by powering one pin or the other.

HBridgeThis figure shows a set of 4 transistors controlling a motor. Due to the shape of the schematic, this is called a H bridge. It accepst 2 command signals A and B. A controls whether the positive wire of the motor will be connected to VCC or ground, and B does the same for the negative wire.

REOBoard implements 2chips containing 2 H bridges each. It is therefore possible to control 4 DC motors.

 The following pictures show the current path depending on command signals A and B. The interesting thing about this topology is that although it is a single power supply (i.e. not symmetric), DC motors can be run in either direction.

 

HBridgeNeg

HBridgePos

 

 

 

 

 

 

 

In this case, if we wire A and B to PWM outputs, we can control the motor power in either direction.

The programming point of view

Having one pole of the motor running with PWM, the other pole must of course be bound to the ground. Therefore when setting the motor speed, we have to permanently enable or disable PWM depending on the command sign.

The most tricky function looks like this:

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

void SetSpeed(int16 speed) {
    int8 sgn = 1;                            //    Sign of speed
    if(speed < 0) {
        sgn = -1;
        speed = -speed;
    }
    else if(speed > 0) sgn = 1;
    else sgn = 0;
    //    Truncate the speed
    if(speed > 999) speed = 999;
    //    Now process the different cases.
    if(sgn == 0) {
        P1SEL &= ~BIT4;
        P1SEL &= ~BIT5;
        P1OUT &= ~(BIT4+BIT5);
    }
    else if(sgn > 0) {
        P1SEL &= ~BIT4;
        P1SEL |= BIT5;
        P1OUT &= ~BIT4;
        TA0CCR4 = speed;
    }
    else {
        P1SEL &= ~BIT5;
        P1SEL |= BIT4;
        P1OUT &= ~BIT5;
        TA0CCR3 = speed;
    }
}

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

Some explanation: the SetSpeed function checks for the sign (i.e. the rotation direction) of the command. There are 3 cases:

  • First if the command is 0, then the motor has to brake. This can be done by grounding both wires.
  • If the command is positive, then the positive wire (controlled by timer's 4th output, BIT 5, has to be enabled while the other one, BIT4, has to be grounded.
  • The third case is the opposite. BIT 4 has to be enabled for PWM and BIT 5 has to be grounded. In either case, the absolute value of speed is set to the relevant timer CCR (either TA0CCR3 or TA0CCR4).

The whole program

Most of the ADC program (tutorial 5) has been reused. The two new fucntions are the PWM configuration and speed settings. The complete source code (except the utilities functions that can be downloaded) is at the end of this page.

The ADC is used a little bit differently. The idea is that when the potentiometer is half scale, then the rotation speed is 0. When it is at 0, the rotation speed is full backwards, and when it is at full scale, then the rotation speed is full forwards.

The following oscilloscope screens shows the processor load.

MotCPULoad

MotCPULoad2

The frequency of motor update is 64 Hz, which is good enough for a manual frequency update.

The speed update takes about 9.6µs which is less than 0.1% CPU load.

Conclusion

We have shown that a motor control can easily be setup, that takes almost no processing power for a real contol system. This shows that even with all its motors used, REOBoard may have about 1% CPU load, which leaves a lot of room for other processing.

Download the C code

A summary of the first tutorials has been added as a downloadable zip file here.