DC Motor Controller for R/C Applications

Note: This page contains information that is now quite old. It refers to long obsolete parts and possibly has dead links. No further development is being done.

This is a relatively simple Pulse Width Modulated DC motor controller intended for Radio Control applications. It features:

  • High current capacity

  • Brake

  • Atmel AVR microcontroller

  • Battery low detection

  • Standard RC servo interface from a receiver

  • Various software features for safety of flying models

The speed controller is based on circuits of the form given in Eric Behr's collection, in particular those contributed by Milan Lulic and Josef Hoeltzl. Please refer to those and other articles and circuit diagrams, which may contain additional protection for the circuit than that used here.

Disclaimer: this circuit was originally developed for radio-controlled flight applications. The circuit is offered here for educational purposes only as an aid to understanding. It is not a proven design. Any person who wishes to develop a circuit based on this is entirely responsible to ensure that it is constructed correctly and that it works reliably before using it in any flight application.

The speed controller has been used with Speed 400 and 560 motors with good success. The use of a microcontroller makes the operation of the circuit quite reliable (in contrast to the sentiments expressed by Eric Behr about the circuits featured on his site). So far no printed circuit board has been produced for this circuit, and you will note that no attempt has been made to use SMD components. Most of the parts are available locally in South Australia. Despite this its overall weight is only about 19gm, including heavy gauge wiring to the battery and motor. This is quite acceptable for medium size model aircraft (1m wingspan and above). The use of selected MOSFETs means that it can theoretically work up to quite high currents (50A or more), although so far it has only been tested to about 12A. It is not expected to be
entirely trouble free above that point.

Circuit Operation

I will give here a detailed description of the circuit operation, as this is where my interest lies.

The core of the circuit is the motor controller itself which is on the bottom right of the circuit above. The PWM signal from the microcontroller is buffered by Q4. This inverts the signal so account must be made for this in the program. The motor-on state is obtained by pulling the pin PB3 low. This inverted signal is applied to the MOSFET Q2. This device connects the negative terminal of the motor to ground resulting in current flowing through the motor. The choice of the IRL1104 was made because its resistance in the on state is very low, about 8 milliohms, and in addition it is quite reasonably priced. The best MOSFETs readily available at the time of this choice could go down to 2 milliohm. To get a feel for the implications of this choice, if Q2 is on all the time (full motor speed), and there is a current flow of 12A for example, then Q2 will drop 0.1V and dissipate 1.2W. This is hardly even worth providing a heatsink. The IRL1104 is rated up to 74A at 100ºC in the TO220 package (seen in the photographs), and 2W in surface mount. No particular attention has been made to heat dissipation but this will be addressed if higher powers are tested later. Q1 is a low cost MOSFET of similar ratings to the IRL1104, but it does not need to have a particularly low on resistance. I used a readily available STP30NE06L 60V, 30A, 35milliohms on resistance.

Q3 inverts the signal again and applies it to the MOSFET Q1. This device switches on when the motor is switched off. Thus during the off period of the PWM cycle, when the changing currents in the motor windings generate large voltage spikes, Q1 provides a short circuit and protects the circuit (notably Q2) from damage. Also if the motor is turned off for a long period during flight and the propellor continues to spin with the aircraft movement (windmilling), Q1 again provides a short circuit to the generated currents. This reacts against the propellor and reduces the spinning considerably.

The circuit consisting of D3 and C9 is used to lift the Q1 gate voltage above its source voltage when Q1 needs to be switched on. When the motor control is in the motor-on state, Q3 is turned on and
C9 charges up to a voltage Vcc between the left hand end and the right hand end, which is at zero volts due to Q2 being turned on. When the motor control is changed to the motor-off state, D3 becomes reverse biased and is effectively an open circuit. Q2 turns off and Q1 turns on at the same time, so the right hand end of C9 rises to Vcc. This lifts the voltage at the left hand end to twice that value, while D3 prevents it from being discharged. The following simulation shows this for a 10V supply. The OFF signal is from the microcontroller. You can see that the motor negative terminal has tried to generate a large spike but that it has been cutoff by Q1 turning on. C9 lifts the gate signal to 20V ensuring that Q1 stays on.

The remaining parts of the circuit are relatively simple compared to this.

  • The LM2940-5.0 is a low dropout voltage regulator providing 5V to the microcontroller. As the battery voltage falls, this 5V is maintained until the battery voltage falls below about 5.5V (typically). Needless to say you should not use battery packs with a fully charged voltage close to this value, but ensure that the 5.5V is reached only when the battery pack is close to being fully discharged. The capacitor C2 is used to provide some smoothing of the circuit supply voltage in the face of current spikes caused by the motor switching. Such spikes can generate significant voltage spikes due to the non-zero internal resistance of the battery and connecting wires. These spikes could upset the microntroller operation. The capacitor C1 should preferably be a ceramic type that provides low resistance at quite high frequencies for stability purposes. The datasheet does not mention this but it is a safe strategy. Capacitor C3 should be a Tantalum type (which can be as low as 22µF) both for its small size and its suitability for preventing oscillation of the regulator (see the datasheet).

  • R3 and C6 provide a power-on reset, and allow external reset from the parallel programming port.

  • I have used a crystal X1 here, but the timing accuracy needed is probably not that critical and a simpler RC circuit should be used as specified in the microcontroller datasheet.

  • VR1 and R1 are used to monitor the battery voltage. This voltage is scaled down and limited to 5V by the zener diode D1 to protect the microntroller. This voltage is compared to a fixed 3.3V reference provided by R2 and D2.

  • The signal from the receiver enters on the right, is buffered by Q5 and passes to input PB4 for monitoring. The 5V power is provided directly to the receiver (be very careful to get the polarity right here when wiring up the receiver). You can of course choose to use a separate battery for the receiver (and hence the servos), in which case the microcontroller need not monitor battery voltage or take action to prevent full discharge of the batteries.

  • Finally the parallel input is used for programming the microntroller flash memory. This is provided by a simple 5 pin header. An old parallel port printer cable was butchered to pull out the desired signals. The parallel port interface follows that used by the AVR-gcc tools as described by Guido Socher (this article is getting a little old now, but is still very informative).


The prototype was constructed on a prototyping PC board of the form used for IC circuit work. The boards are cut to size, in this case 34mm by 60mm. This diagram simply shows one layout that is possible. I found after a couple of tries that this form factor tends to have reasonably small area (lowest board weight) and fits flying models a little better than a square shape. It should be mounted so that the programming interface is accessible. Wiring was done with very thin wire-wrap wire. For mechanical reliability some form of foam epoxy potting should be used, but that will immediately prevent any maintenance work being done on the board. At least a layer of foam plastic held in place with a wrap of tape around the board may reduce the effects of excessive vibration in the case of heavy landings. Watch out that the metal heatsinks on the TO-220 ICs do not get in the way of any other exposed metal. Insulation tape could be used here.

Battery Eliminator Circuit

The BEC is controlled by VR1. The setting of this control requires some careful thought. Firstly you should be familiar in detail with the discharge characteristics of your battery pack. Test the battery pack by discharging it at the current that your motor will draw when in use. This may or may not be full speed depending on how you intend to fly. Take measurements of the battery voltage and the current at regular time intervals. For NiCd and NiMH batteries the discharge will be somewhat flat for most of the time then will drop away quite rapidly near the end. You need to set the control so that the voltage at which the microcontroller is triggered is at a point near the end of the discharge characteristic. If you set it too high then the microcontroller will trigger too early and cutoff your flight time. If set too low then the battery may not have sufficient juice to allow you to bring the craft safely back to earth.

Once you have determined the desired cutoff voltage, apply that voltage to the controller from an external power unit (you will need to rig up something to do this) and set VR1 so that the voltage at pin 12 is the same as that at pin 13 (nominally 3.3V). The following graph shows the measured discharge curve for an 8 cell NiCD pack, 1300mAH, discharged nominally at 6A. A suitable cutoff point would be 8.5V if the motor is to draw that level of current continuously. You will then have up to a minute of full speed flight left if it is needed.

In our dreams we could use one of the AVR microcontrollers with an ADC function, and actually measure the battery voltage directly. The program could then trigger according to its own idea of when the battery pack is nearly flat. This would eliminate the components associated with the BEC, and could be made to adapt to a variety of battery packs. Such a program would need to be quite smart.


The AVRfreaks site provides a lot of useful information and examples of the use of the AVR series microcontrollers. Programming was done in C using the AVR-gcc tool suite. These tools are available for Linux (and also Windows if you really must). The tool suite that I use under Linux is called CDK4AVR. This is a compilation of a range of AVR programming tools including assemblers, C, C++, Ada debuggers (notably gdb for those with Unix experience) and in-circuit programmer software for uploading binaries to the device. Here is a HOWTO for using some of this software under Fedora 6.

The device used was the ATMEL AT90S2313-10 with 2K flash ROM, 128bytes SRAM, analogue comparator, three parallel ports and two timers. Information about devices can also be found at AVRfreaks.
The program is unsophisticated and relies on polling of various signals and events. Interrupts are not used. The microcontroller provides a hardware PWM output but this also is not used because of its complexity. The speed of the microcontroller is such that no timing problems arise for this application. The program is "modularised" through the use of macros rather than subroutine calls as the latter impose a large time and memory overhead.

The main task of the program is to poll the incoming motor servo control signal on PB4 to detect when it changes. This signal has a period of about 22ms for "standard" receivers. For the JR Propo R700 R/C receiver the pulse width is between 1.08ms and 2.04ms. The trim can vary this from 1.02ms to 2.15ms. Set up timer 0 clock frequency to 10MHz/256, that is a period of 25.6 microseconds, and look for a pulse width count more than 43 (1.11ms) and less than 78 (2.00ms). We do this by polling the signal until it turns on high, then start timer 0. Continue polling until it is low, then read the timer.

Once we have the pulse width count, we generate a PWM signal using the timer 1 interrupt. Set the clock for timer 1 at 10MHz/8 giving a 0.8 microsecond resolution. If the incoming pulse width is between 43 and 78, scale up by 8. A maximum count of 230 gives a PWM period of about 210us (about 5kHz). Start the timer for the first part of the PWM cycle, check for comparator match, and toggle the PWM output. Set the timer to count for the remainder of the cycle, then toggle the PWM output again, and so on.

A section of code is activated once every "timer_count" cycles to provide a place for execution of infrequent events. This includes battery voltage checking and lost signal checking. The motor speed changes occur here also, even though the computation of speed change is done every cycle and smoothed.  A valid signal is one that falls within a range of pulse widths from just below the lowest to just above the highest (using about 130us safety margin). When starting to look for a signal, on power up or after a lost signal has been detected, this valid range is much reduced to just above the minimum pulse width. This ensures that the motor is kept in the off state until the operator has reduced the control to zero motor speed, at which time the motor can be turned on.

When a sequence of valid signals exceeds a count of 16 in a row, then the signal is considered good and a change of motor speed is permitted. The absence of this good signal indication is also used to determine if a signal has been lost. As a lost signal normally results in the failure of pulses to arrive, so an additional variable is used to track this condition. This variable is reset at the end of the "infrequent events" period and is set when a valid signal is received. The program makes sure that at least five pulse periods are present within the "infrequent event" period, otherwise a false "lost signal" can occur, disabling the motor prematurely. A timer_count of 10000 seems to be adequate for this period with a 10MHz microcontroller clock. When the signal strength becomes too low the JR Propo R700 produces random pulses out (response to noise) while the JETI Rex 5 simply stops in a high or low state.

The motor is not enabled until detection of a valid signal that demands a motor off condition. That is, once the motor has been disabled by an event (usually battery low but also on startup), the operator must reduce the motor control to zero in order to re-enable it. The motor is turned off if the signal disappears for a given period of time (nominally 1 second).

A battery low signal, detected by the analogue comparator, will cause the motor
to be turned off and disabled. If the battery recovers, the motor can be re-enabled. When the battery falls below the threshold, causing the motor to be turned off, the voltage will jump up again as the current falls away, and the battery may recover some of its strength. This will cause the program to detect a good voltage again. The operator can then glide the model safely to earth (if he is a better pilot than me), or if needed can restart the motor. One option in the program is to allow the motor to be restarted but only operated up to a reduced maximum speed (further reduced every time the battery low condition is detected). The pilot must bring the craft back to earth and not keep flying. For gliders of course the pilot may choose to continue flying but will not use the motor.

If you use the program, make sure that it is configured correctly for your application. It probably won't work otherwise as you expect.


So far the controller has been bench tested to ensure correct response of the program for normal operation, battery low, signal loss and poor signal conditions. It has flown for a total of 5 seconds - the rather short time not being a result of problems with the controller, but rather the ham-fisted operator. It survived a bumpy landing.

Further Work

This is not necessarily work to be done, but rather a wish list. It may well happen.

  • Printed circuit board using SMD components to provide a truly small, lightweight controller.

  • Testing up to much higher currents and consideration of heatsink requirements (at all currents).

First created 17 September 2004.
Last Modified 30 May 2007
© Ken Sarkies 2004