Note: There are many types of motors (and also sub-classes) – this post is about the most commonly encountered motor (as in electric toothbrushes, mobile phone vibrating motors), also known as a permanent magnet brushed or DC commutator motor – just referred to as a DC motor below.
This post is to document some experiments in driving DC motors using the BBB. The end result was a simple, low-cost circuit that it is hoped can perform well for many robotic applications for the BBB. While it can operate with many typical small DC motors, it is easiest to use with some higher-performance motors that are expensive new, but are often available as surplus or used motors from ebay.
Some tests were done to investigate the performance, and the videos below show some of the tests in action. The results were measured and are recorded further below. The exercise required a mini test set up, it was quickly made from not-great construction skills, balsa and PVA glue and sprayed with acrylic primer to soak into the wood and hopefully make it a bit tougher. It is described in detail further below.
In this video, pay close attention at the green label attached to the motor shaft and the LCD display below. For now, bear in mind that the motor is actually running 16 times the speed (it is geared down 16:1) and is under a load.
What problem do we not want in the design?
If you’ve tried to use PWM with a H-bridge (and no feedback) to attempt to control the speed of a DC motor then you will have noticed that although it works well when the motor is driving nothing apart from its spindle, in a real scenario the speed is not in your control; where the motor is driving a load the behaviour changes and the speed is reduced; it may even stall. As an example: you’ve just created a mobile robot, and it relies on the PWM mechanism just mentioned. It may run fine on a perfect surface, but as soon as it encounters an incline - or a rug - , the behavior is unpredictable because it’s motion (speed, and hence position [maybe totally stalled]) has been affected by the load that it is experiencing, and often this is not possible to predict. If it is relying on timing and speed (i.e. dead reckoning) to figure out where it is, then the result will now be very inaccurate. Also, the motor may now be suffering from operating outside of its specification if the motor has slowed or stalled.
What is the PWM signal doing?
Motors turn at a speed dependant on voltage, and the PWM signal is essentially supplying a certain (average) voltage to the motor dependant on the PWM duty cycle. PWM is not necessarily the best way to drive a motor, but it is convenient in a digital world.
How about Stepper Motors?
The effect mentioned above makes it difficult to use such a motor system when you want to do accurate things in robotics, and so stepper motors sometimes get chosen.
However, a stepper motor while the best and appropriate choice for some scenarios isn’t always the right option. They are less efficient (a problem for battery powered and small, lightweight designs) and they cannot be run at such a high speed (in the low range of a few thousand RPM with acceleration) – however they are designed for high positional accuracy, and also provide far higher torque for a given size than a DC motor. With DC motors gearing is often needed to obtain a useful torque and a useful speed. Ungeared the speed of DC motors can run well beyond 10,000 RPM.
How can the problem be solved?
As an example scenario - the Mars rovers did not use stepper motors for their wheels; they used DC motors.
It is clear that the voltage (or PWM duty cycle) needs to be adjustable and this can be achieved with an automatic feedback mechanism (also known as closed loop control). Feedback can come from different methods.
Adding feedback provides the capability to adjust the PWM drive depending on real conditions that the motor is experiencing. If the motor is slowing due to load, then the error (difference between the desired speed and the actual speed) can be used to increase the PWM on-time in order to increase the motor speed.
So, a closed loop motor controller needs to be pursued.
The plan of attack
The normal method is to manage the entire control using a DSP. However for this experiment a combination of analog, digital and software methods were used. It comes at the expense of additional hardware and the usual inflexibility of hardware versus a software implementation when it comes to making adjustments or implementing more advanced algorithms. This is especially true with control applications like motors. So, while this method may be of less practical use nowadays for commercial projects, it serves two purposes
(a) It still gives good performance for custom, one-off designs for home use
(b) It is useful to show the fundamentals of the behaviour, in the analog domain to compare with a software implementation
The latter purpose serves as a good learning exercise, since control theory isn’t the easiest thing in the world without practical examples.
How does it work?
A typical H-bridge circuit was used (consisting of four MOSFETs). There are a lot of bad circuits for this particular topic on the Internet..
The actual circuit used is shown further below.
The motor is a conventional brushed DC motor, but it has a number of high-performance features (however any motor could have been used – but not with the same results). This type of motor can be obtained used from ebay; for a new motor, the cost is high but for good reason: the technical features allow the motor to rotate more smoothly than conventional lower-cost DC motors and have a higher power for a given size and rotate faster and run cooler. When you consider that similar motors made it to Mars then the cost doesn’t seem so bad. These motors are an attractive choice in addition for the fact that they can be purchased with built-in gearing and encoder which greatly simplifies projects.
Regardless of motor choice, it is possible to use an external encoder. There are different types of encoders and as a digression there are some high-resolution ones made by Avago.
These encoders are nice because they can be fitted onto the end of any shaft in a system, it doesn’t need to be the motor shaft. These encoders are overkill and not advised for this particular task (but they would be absolutely great for – say – home telescope control), and a far lower cost method is to use this IC and a small magnet. I’ve not had a chance to try it, so I’d be interested to hear if anyone else has.
The exact number of pulses per revolution does not matter, but you don’t want it too high, because it makes it harder to generate an error signal with the low cost circuit as will be seen later.
Typically PWM is generated by a microcontroller but in this case an analog circuit was used, for a voltage controlled PWM setting. The feedback signal is generated by creating (using the rotary encoder) pulses of a fixed width, each time an encoder transition occurs. The fixed width pulses occur more rapidly when the speed is increased. They are converted to an analog signal using a classic op-amp circuit known as an integrator and this signal is used to adjust the voltage controlled PWM level.
The entire system mentioned above can run without a processor (except for setting direction and the PWM voltage), with the analog circuitry described above and digital logic. It was decided to feed the fixed pulse signal into the BBB, so that it could count the pulses; this allows a second control loop of course; in my case the pulses were used to measure the rotation or distance travelled so that the motor could decelerate or stop under program control when it reaches a certain position. The BBB is ideal because the pulses are fairly narrow and frequent. The BBB's PRU capability can easily capture them without skipping, and there was no need to use an interrupt input.
You might be wondering (and so was I) if it can have anywhere near the accuracy or repeatability of a stepper motor because there is no control of individual windings in the motor, so it may overshoot. Or, the gearing (which would nearly always be required with a DC motor) may cause play (backlash) and cause inaccuracy. So a test was needed. The theory was that accuracy (compared to a stepper motor) should be achievable but to find out how accurate, tests were required (described below).
Conveniently most of the circuit was implemented in just a few ICs. ON Semi’s MC33033 is a very low cost (and high performance - great value for money) motor controller intended for a different type of motor (three-phase brushless motors) but the datasheet shows that it can be used for DC motors in an open loop (i.e. no feedback) design. However the datasheet also shows a closed loop three-phase brushless design so it was decided to try to combine bits of the two circuits. The end result is that the single MC33033 IC is used for the entire motor control and for the op-amp integrator.
The IC also features a capability to protect the motor (for example if it experiences a very high load) by monitoring the current and reducing the PWM width accordingly.
The rotary encoder output is converted to a fixed width pulse train using a dedicated low-cost IC (MC33039). The PWM setting voltage is achieved using a TI dual 10-bit DAC (the second channel is not used but could be utilised for a second motor or some other purpose). Clearly the BBB could have generated a PWM train to use as a DAC, but the DAC simplifies the software.
A more detailed explanation of the control loop, error signal and results will be added at a later date to this post – I wanted to get the bulk of the information out while it was still fresh in my head.
In quick results, for my test-bed, the speed under a certain load (described further below) and compared with a reduced load was very similar at about 4700RPM (not measured very accurately at the moment – to be updated later).
The actual H-bridge was based on external MOSFETs for flexibility in future. Note that you may find you need the usual external diodes across the MOSFETs (the internal one is not well spec’d for some MOSFETs). The inductor is not essential but is useful if your motor has a low inductance, to help smooth the ripple current.
The entire circuit is quite small and fits on a 3.5x5cm PCB. All parts (although surface-mount) are hand solderable with a normal soldering iron.
Test Bed and Results
In quick tests, the performance is nice; it is possible to adjust the speed with far greater control than H-Bridge circuits driven by PWM with no feedback, and the motor can be driven very slowly or fast and in all cases the motor can overcome a load. The way it was tested is described here.
The problem was that it is hard to create a fixed load; friction against the motor shaft could have been used, but the concern was that it would be varying, or become very unrepeatable. So, it was decided to try a ‘tug of war’ type of test, where another motor would be connected to the motor under test. The ‘fighting’ motor (not a technical term!) would try to turn the other way (i.e. to try to turn the motor under test to rotate in the opposite direction), by applying an adjustable voltage to it. A low enough voltage was applied so that the motor was just on the threshold of rotating in the opposite direction (about 0.9V in this case – called the ‘fighting’ voltage in the test results for now). I was worried about damaging the motor, so I didn’t do this test for long. However, the current consumption was fairly low (about 26mA) so it was a semi-calculated risk.
A side view of the test bed can be seen here:
To couple the motors, clear plastic tubing (actually heatshrink but it was not shrunk) was coated on the inside with PVA glue and then placed over the gears on the two motors. This was so that the join could be slightly flexible if the motors were not perfectly aligned, and so that the tube could be easily removed afterwards (and the glue scraped off) without damaging the gears.
The motors were mounted in the balsa wood blocks and were wrapped in tape and epoxied in position. The epoxy and tape can be removed, so it is not permanent.
The holes at the top of the blocks were going to originally have nylon screws to hold the motors in place but the motors were easier to align with glue.
The actual rotation (versus the programmed desired rotation amount) was measured using a FRDM-KL46Z board (even though the BBB could have done it of course).
The KL46Z makes an excellent low-cost ($15) test tool for this purpose; it is described in detail here. It has a built-in LCD for displaying data:
Two main categories of test will be done – measuring distance and measuring speed. Currently only a couple of distance related tests have been completed. More results will be published later as they are done.
Test 1 – Short distance at a slow speed
The motor under test was programmed to rotate for one revolution (360 degrees), at a slow speed. The actual rotation (in degrees) was measured.
This is a video of the test (results are detailed further below):
Test 2 – Long distance at a fast speed
The motor under test was set to rotate at its highest speed and to turn 10 revolutions (3600 degrees). The actual rotation (in degrees) was measured. The video is shown at the top of this post (in the introduction).
The motor had a rotary encoder that generated 12 cycles per motor revolution; this results in 12*4 = 48 quadrature pulses per revolution. The motor was geared down by a ratio of 16:1, so the number of pulses per revolution (360 degrees) is 48*16 = 768 pulses. As mentioned, the FRDM board was used to count pulses and display them on the LCD.
Each test was run five times, and the results are listed below.
This is really just some of the tests that really ought to be done, but the initial results are promising. The system is very low cost (with e-bay motors for home use) and allows the BBB to accurately control movement.
Given the very compact size of the motors (the ones used for the tests were 10mm diameter), the closed loop DC motor method is a good alternative to stepper motors or the ‘continuous rotation’ modified servos for some scenarios.
Additional tests will be run and documented soon (while the test-bed still exists).
The test code and schematic are attached. The test code is just programmed to rotate 10 revolutions when run and then exit.
The code currently uses the following connections on the BBB, but you may wish to select better ones (I just used these because I was already using them for a different project); these ones clash with HDMI which would then need to be disabled. You need pins which can be configured for PRU GPO and GPI (i.e. using R30 and R31) as shown here. I used PRU1 in my example.
To compile the code, type
Copy the BB-BONE-MOTOR-00A0.dtbo file that will be generated into /lib/firmware