[ Overview | The Car | Communication | Controller | Receiver | Steering Control | Speed Control | Results | Appendix ]
We decided to build transmitter and receiver modules for a radio-controlled (RC) car, as well as implement variable-speed motor control and a continuous steering function. The simple speed controls included in most RC kits seldom offer more than three forward speeds and one reverse speed; furthermore, steering controls in most Radio Shack toys only offer binary steering: Either the car is turning left, right or not at all. We felt that overcoming these limitations would make any RC car more realistic to handle and ultimately more fun to drive.
A Tamiya RC model kit was bought from a Maryland hobby store, along with a rudimentary radio control unit to verify that original units operation. After making sure all parts were assembled correctly, the mechanical speed control, speed control servo, and radio receiver module were all removed. The car we selected already implements continuous steering with a servo attached to the steering linkage; however, because the radio receiver was no longer being used, we decided to leave the servo in and reverse engineer its interface.
The original implementation of speed control in the car consists of a servo which mechanically moves the arm of a simple high-power potentiometer. While the motion of the servo is continuous, the circuit only produces six discrete levels: three forward, two reverse, and neutral. Hobbyists in RC cars often replace this assembly with an electronic speed control (ESC), which uses pulse width modulation to provide a smooth speed control. We chose to simulate the function of these commercially available ESCs by using the microprocessor to modulate pulse width across the motor.
An RC car is of little value if the controls are tethered to the vehicle. However, we determined during the design process that the radio system was mostly irrelevant to the actual project, and that the time required to build the system would seriously impede on the rest of the project. We decided instead to use a pair of commercially available radio modems. The devices, made by National Semiconductor and used by Laplink under the AirShare label, claim to establish a 115 kbps serial connection at a distance of up to 30 feet with clear line-of-sight. While this range is inferior to that of commercially available radio control units, it is more than adequate to prove that the rest of the design works.
|Forward||0000||0000 - 1111|
|Reverse||0001||0000 - 1111|
|Left||0010||0000 - 1111|
|Right||0011||0000 - 1111|
A simple communication protocol was established to send messages from the controller to the car. Because the connection is serial, we encode each command into a byte-long packet. The top nibble denotes the command, and the lower nibble represents the level at which the command is to be executed. For discrete operations (like headlights), the second nibble determines which functions are to be toggled. Communication travels one way from the controller to the car, which cuts down on the hardware required for either unit.
The original controller used spring centered potentiometers to produce analog signals which controlled the speed and direction of the car. The analog signals were transmitted to the car via a 75 MHz AM radio link.
In order to emulate the true RC car experience, we decided that we needed something more visually intuitive than two potentiometers stuck into a breadboard. We purchased a simple PC joystick from Radio Shack and removed the "turbo" button circuitry. Using the existing interface cable, we were able to connect the internal potentiometers and pushbuttons to the receiver board without cosmetically altering the joystick.
Our design for the controller uses National Semiconductor serial ADCs to convert the analog waveform from the potentiometers to a digital signal. For example, the 8-bit value obtained from the forward/reverse potentiometer is compared against a known value for that potentiometers centered value; we can therefore determine whether the user intends to go forward or backward, and the rate at which she plans to do so. These data are used to generate the opcode and value to be sent to the car over the serial connection.
After encoding, the character is sent to the car. The controller polls the user inputs one after another, sending out data regardless of a change in state of the input.
In many ways, the receiver unit acts like a conventional microprocessor: Instructions are fetched from the input byte stream, decoded into an operation and magnitude, and dispatched to the proper control unit. Depending on the instruction, most of the work is done by either the speed control or the turning control; all other instructions control simple on/off devices and can be controlled directly in the receivers main loop.
As stated above, steering is controlled by a servo. Rather than supplying a simple voltage, servos operate on a fixed voltage source and a control line that is pulsed to dictate the turn angle. Previous work on the servo left us with a DAC circuit, and we could have added a 555-based timer circuit for pulse width modulation; however, we decided to simplify the design by driving the servo off the mcu. We used the Timer0 interrupt subroutine in conjunction with user input from the transmitter to determine the pulse width to be applied and sent through the mcu's port pins.
The received four-bit digital signal denotes the desired speed of the motor. Instead of using a digital-to-analog converter, we decided to drive the motor at full voltage and use pulse width modulation to control speed. Several products exist which accomplish this task; however, it is a simple matter to implement PWM on the microcontroller. A timer interrupt is used to count 16 ticks, and the given magnitude determined how many of those ticks the motor will be driven.
Due to the motors excessive power, it is impossible to drive the motor directly from the microcontroller. The speed control circuit solves this problem by amplifying the signals generated by the Atmel 4414 chip to allow large power transistors to drive the motor. The motor can draw a significant amount of current, roughly 7-8 amps, when turned on. The amplifier uses 200W rated BJTs in a class B push-pull configuration to drive this load. Since the base current to the power BJTs is still on the order of several hundred mAs, intermediate transistors were used to drive the base currents, which turn on and turn off the large BJTs. The intermediate transistors are wired together with the power BJTs in pairs so that the gain of each pair is significant enough to allow it to be driven by the output ports on the microcontroller.
In short, the system works. The joystick is able to move the car forwards and back, and turn left and right. However, it was a long road getting to this point.
The pulse width modulation, as it was originally conceived, was far too fast for the motor to turn at all. Slowing down the period to approximately one second, up from 1 millisecond, solved the problem; however, there is a noticeable "jerk" to the forward and backward motions of the car. It may be possible to reduce the period, perhaps in half or even smaller; this was not tested in time for the project deadline. There was some initial irregularity in the pulse itself; instead of regular intervals, it seemed as though the pulses were being interrupted by some external stimulus. Careful programming to avoid register clobbering solved much of the problem, but irregularities occasionally appear at unpredictable times.
Turning the car is nicely variable but not particularly smooth. The same irregularities found in the speed control manifest themselves to a greater extent in the servo, causing the wheels to jerk slightly left and right of the desired turn angle. We suspect the problem to be extremely difficult to solve with the Atmel mcu, as pulse widths for the servo vary from 1 to 2 milliseconds; at those small periods, it is difficult to get very accurate timing with the Timer0 interrupt. Perhaps a 555 circuit would have solved this problem.
The software portion of the project was easy to design, and the implementation is quite simple. By avoiding complicated code, we are able to concentrate on hardware issues. Because most of this project relies on carefully designed circuitry, the reliability of the program greatly simplifies the debugging process.
Easily the most contentious and dangerous piece of hardware in the project, the motor control circuitry is both particularly frustrating to design and test. The lack of high power, high current handling MOSFETs in Ithaca made the task significantly more challenging. Many combinations of high power BJTs were used, and a few can drive the car forward. Throughout the testing process we experienced excessive current draw in any number of the BJTs despite transistor biasing and current limiting attempts. Several high power transistors were rendered unusable after a couple seconds of exposure in these circuits. Several fingers bear the mark of instantaneous thermal transfer from contact with the now defunct BJTs. I even saw a 16 gauge wire solder itself in a few seconds when a previous attempt with a 30 watt soldering iron for 20 min was unsuccessful.
Prior to the development of the working push-pull amplifier, none of the circuits was able to drive the car in both the forward and reverse directions. Many disastrous results were experienced before a successful combination of components was discovered. Sometimes the behavior of the circuits defied even Pspice. One of the circuits can be pulse width modulated between fast and very fast, but could not be turned off. The lesson learned is that the trick to working with BJTs is having a very tight control over the base currents. Again, power MOSFETs would have made this significantly easier.
Transmitter source code
Receiver source code
Copyright 1999, Diesel and Iceman
Special thanks to: The electricity gods, for sparing Diesel's life; Matt Harlan, for his patience and expertise; and Bruce Land, for making learning fun.