For our final project, we re-engineered a remote control car to autonomously navigate through a track by detecting lanes and centering itself between them as well as detect objects in front of it and avoid collision. The RC car detects lanes through image input from a low-resolution camera mounted at its front. Using an IR distance sensor, the car determines when to stop accelerating once a certain distance between a forward object has been breached. All computations based on sensor data are handled by an Atmel Mega644 MCU. Due to the nature of the input peripherals, especially the camera, this system is extremely time sensitive so that computations had to be optimized as much as possible in order for the car to be able to react and respond with proper movements in real time. In addition, given the limited computational capacity of this 8-bit MCU, our design made use of several computational efficiency strategies.
Rationale of Project Idea
The basic idea of our project stemmed from a rather playful interest in using an MCU to program a robot to perform some common everyday function autonomously. Given our lack of mechanical engineering expertise, an RC car was chosen as the hardware to be programmed since it provides all the components and infrastructure necessary for a simple mechanical system, all at a low cost with an easy-to-use interface. We decided to design the car so that it would automatically navigate a track made of parallel lines which were meant to mimic the roads that actual full-sized cars encounter. Given that there has been some societal interest in the development of automatic driving car technology, we figured that designing a low complexity system with this functionality would be an exciting and practical project to pursue.
Perusing through past ECE4760 final projects helped give us tips on how to approach our own project. The Line-Following Car of Spring 2007 uses photosensors to guide the vehicle along a single line track. Our original concept intended to use a low resolution camera as the input tracking device instead. Given the similarities in our projects, we were even more inspired to give our RC car the functionality of detecting a two line track and stay within the lane, which requires a more complex algorithm than a single line track follower. The Autonomous Self-Parking Car of Spring 2009 introduced us to a cheap, tractable IR distance sensor component that we later incorporated into our own design as a way to detect forward objects and avoid colliding with them.
All computations and processing are handled by the ATMega644 MCU. The MCU receives inputs from two peripherals the low resolution CMOS image sensor(camera), and IR distance sensor. Image input in the form of a 128×123 pixel array is processed in the MCU using the internal analog comparator, turning pixels that were originally represented by bytes of data into pixels now represented only by bits. Since our RC car only has to detect the image of a road line in contrast to the rest of its environment, this binary pixel representation is sufficient for this purpose and saves immense amounts of computation time. The voltage threshold for the analog comparator had to be adjusted to a proper value for a given road line color which we chose to be black. Processing of this image input from the camera is done by the MCU to generate signals that indicate whether the car should turn left or right or go straight. These command signals eventually control the servo motor on the RC car that allows it to turn left or right, but must first go through an H-Bridge circuit so that polar voltages can be created to drive the servo motor in both directions (since the MCU cannot generate negative voltages). The MCU also receives an analog input from the distance sensor which is processed with the MCUs internal ADC into an 8-bit value. This digital value can be mapped to an actual distance, but is not done in software since it would be unnecessary and would only add more computation time to an already time sensitive system. The 8-bit digital distance value is used in a simple control algorithm that determines the duty cycle of the PWM coming out of Timer2. The PWM controls the operation of the cars DC motor, supplying the motor with a higher voltage when its duty cycle is higher. The PWM is sent to a motor control circuit that is implemented using the same design as the control circuit from Lab 4 which uses an optoisolator to separate the MCU circuitry from the motor circuitry. The optoisolator is necessary so that excessive current draws from the motor do not damage the MCU hardware. We decided to only have the car move forward; therefore, a circuit like an H-Bridge was not required to operate the DC motor and only had to be driven in one direction. To power all of our hardware, several power sources had to be used. The target board for the MCU required a 9V battery for proper operation. Combined with the 5V regulator on the board this provided a constant 5V Vcc to the MCU. The camera was powered using the 5V supply on the MCU and since it required a minimal amount of current, this setup posed no problem to the system. The distance sensor is powered from a different battery source a battery pack consisting of three AA batteries in series at 1.5V each. The grounds of both this 4.5V battery pack and the MCU were tied together so that the analog voltage output of the distance sensor had a ground reference. The rest of the circuitry is properly isolated from the MCU and is powered from the cars battery setup which uses five AA batteries rated at 1.5V each for a 7.5V total supply. This served to be too much for the H-Bridge circuit which requires less of a voltage. To remedy that, diodes were placed in series between the positive terminal and the H-Bridge Vcc pin to drop the voltage instead of using an additional battery source.
Our high-level software design consists of three main functions as shown in the block diagram initialization, image processing and control, and distance sensing and control.
All software computations are done by the MCU using a 20MHz base clock. The initialize routines initiate the MCU I/O ports, timers, PWM driver, and ADC for general program operation and peripheral interfacing. The main loop of our software continuously cycles between the distance sensing and image processing control but skips image processing if the distance sensing code determines that the car should be stationary since capturing more images when the car should not be moving is unnecessary.This means that the software does not enter either of these functions with a set frequency but rather proceeds through the loop continuously so that the functions are called as soon as the CPU is free to make the computations. The distance sensing control involves reading a converted ADC value and controlling operation of the DC motor through adjusting a PWM duty cycle. At some threshold digital value that corresponds to a forward object being too close, the software will set the PWM duty cycle at a low value to stop the DC motor from turning. If that distance threshold is not reached, the car undergoes normal operation and the PWM duty cycle is set so that the car moves at a slow pace to allow for more effective response time by the image processing control. However, if the car is stationary, meaning that its previous PWM duty cycle is low, in the next distance sensing loop the software will jump start the car with a higher-than-normal PWM duty-cycle that only lasts for one cycle. This is necessary to combat friction that prevents the normal operation PWM duty cycle from starting the car. The jump start functionality was required since we did not want the car to move so fast during normal operation. The image processing control stage begins with setup of the camera since the image sensor hardware requires parameters to be set before its image capture functions can begin operation. Image processing begins with reading image input from the camera. To interface with the camera properly, the camera hardware is clocked at a rate specified by the MCU which is set with a period long enough for the MCU operations to store a pixel of image data in an array. Once the camera begins output of its image data to the MCU, the process cannot be interrupted else the image data array will be corrupted since the camera outputs its data continuously until it is finished. Thus, no interrupt service routines besides the one that generates the clock rate are used in our entire software. After the camera is set up, it continuously takes pictures and sends an ordered list of pixels to the MCU. This is fed into the MCUs internal 1 bit comparator, and is converted from a analog signal to a 1 bit black or white value. We store this 1 bit pixel in an optimized array called picture, and parse the proper lines to detect where the road lanes are. Once we find the lanes and determine the center of the lanes, we determine the proper turning condition. The result is used to control the H-bridge IN1 and IN2 inputs, which in turn control the steering of the car. The three task are continuously repeated.
Due to the low cost and relatively low complexity of our design, this project can easily be rebuilt by those interested in tinkering around with an RC car. The following sections describe the hardware that is used in detail and explains how they are set up.
Remote Control Car:
The RC car used in our project was the cheapest RC car we could find at our local Radioshack. It is a 4-wheel car with rear-wheel drive and front-wheel steering. Since a datasheet for the hardware was not provided with it, we had to manually test the cars connections and figure out how to properly operate its motor functions ourselves. Given the nature of our project, the RF functionality of the car was scrapped and the receiver board on the car was removed. Only six wires had to be tested to determine their function – two wires for the car battery, two wires for the rear-wheel DC motor, and two wires for the front-wheel servo motor.
The voltage across the car battery hovers around 7.5V, which was expected since the car requires five AA batteries rated at a nominal 1.5V each. To test the servo motor wires, we applied different voltages across it starting low and incrementing the voltage until a turning response by the motor was achieved. The servo motor turns in one direction with a positive voltage across it, and turns the other direction with a negative voltage across it, but does not have the capability to turn at varying angles. The servo motor begins responding at around a 3.8V threshold but reaches the max turn angle at a much slower rate. Applying a larger voltage across the motor causes the motor to reach the set turn angle faster.
Measurements were taken to determine the effect of varying voltages across the DC motor. Using parts of the tachometer circuit that we built in Lab 4 for this class, we were able to get a relatively accurate measurement of the cars wheel RPM for a given DC voltage across the motor. The data gathered shows us that the threshold voltage for the DC motor to power actual motion of the wheels is around 1.3V and that the voltage-to-RPM relationship is linear.
The Sharp IR sensor (GP2Y0A21YK) that we used is a very handy, cheap, and easy-to-use piece of hardware that can measure distances in a range from 10 to 80 centimeters. The sensor only has three connections that need to be interfaced with power supply, power ground, and its distance output. Given a supply voltage optimally between +4.5 to +5.5 volts, the sensor outputs its measurement of distance as an analog voltage between 0V and 3.1V as shown in.
Powering the Distance Sensor:
After several different attempts and methods of powering the distance sensor, we decided at last to use three AA batteries in series at 1.5V each for a total of +4.5V to power it. Since we found that the distance sensor drives a lot of current (typically 30mA), powering it off of the MCU posed problems to reliable MCU operation. In addition, we found that connecting the distance sensor across the power lines of the MCU introduced a lot of noise to the cameras operation since it too is powered by the MCUs power lines. Thus we ended up using another power source in the three AA batteries. However, the distance sensor output needs a common ground in order for the MCU to interpret the data correctly. The grounds of both the MCU and the 4.5V battery pack were thus connected so that distance sensor could be properly interpreted. This sort of unfavorable connection in theory could cause random and unexpected behavior, but since our system worked when tested, we decided to go along with it due to time constraints.
ADC Hardware Setup:
The analog output of the distance sensor is fed directly to the ADC that is internal to the MCU through PORTA1. Since the distance-sensing functionality has much lower priority than the image sensing functionality, our setup of the ADC hardware and the calculations using the resulting digital value were optimized to use the least amount of computation time possible. The ADC successive approximation circuitry requires an input clock frequency between 50-200kHz for maximum resolution. In our case, a higher frequency clock rate could have been used since we only make use of 8-bit resolution. But for safe measure, we used a clock prescaler of 128 on our 20MHz base clock for a resulting 156.25kHz ADC clock. Since a normal ADC conversion takes 13 ADC clock cycles, this meant that the average ADC conversion time is near 83.2 microseconds. For the ADC reference voltage, we chose to use the internal 2.56V generated by the MCU. This value was chosen because of convenience and because based on the output voltage vs distance curve of the sensor, a 2.56V value corresponds to a distance around 9cm which is at the edge of the operating limit of the sensor and is a small enough distance that the car should know to stop anyway. The ADC is capable of providing a 10-bit result. However, our system did not require that degree of accuracy and used only the higher 8 bits so that the of the two registers that hold the ADC result, only the high register had to be read which saves some computation time. To do this, the command for the ADC to left adjust its result had to be set in software. The resulting ADC conversion that we read from the high result register, ADCH, follows this formula:
Where Vin is the input coming from the distance sensor and Vref is the internal 2.56V value. The range of values of ADCH are thus between 0 and 255. We tested to see whether or not a Vin greater than 2.56V would be a problem but found that voltages greater than Vref resulted in an ADCH value of 255 which does not pose any problems to our system.
Since as much computation time had to be conserved for the image sensing software, sampling from the ADC was not periodically triggered and had to be manually started in software. More detail on the distance sensing software is discussed in a different section.
Motor Control Circuit
Our circuit that controls operation of the cars DC motor uses the same design as the motor control circuit that we used in Lab 4 for this class. We created a PWM using Timer2 Output A out of PORTD7. The duty cycle of the PWM eventually determines the voltage that is applied across the DC motor. The PWM is sent through a 4N35 optoisolator in order to isolate the MCU power lines from the DC motor and avoid damage of the MCU hardware from excessive current draws by the motor. A capacitor and a 1N4001 diode are connected in parallel with the DC motor to improve noise resistance and inductive switching spikes on the motor, respectively.
|General Hardware:||Part Number||Vendor||Quantity||Price|
|RC Car||Eztec Dodge� Ram SRT RC Truck||RadioShack||1||$17.00|
|Sharp GP2Y0A21YK IR Distance Sensor||GP2Y0A21YK||SparkFun||1||$13.50|
|Mitsubishi M64282FP CMOS Image Sensor||M64282FP||Owned Previously||1||$0.00|
|Toshiba TB6549PG H-Bridge IC||TB6549PG||DigiKey||1||$5.18|
|Solder Board||Owned Previously||2||$0.00|
|9 V Battery||Target||1||$3.00|
|TargetBoard||Provided by lab||1||$4.00|
|ATMega644||Provided by lab||1||$8.00|
|DIP socket||Provided by lab||2||$1.00|
|Header socket/plug||Provided by lab||56||$2.60|
|2 Pin Flat Jumper Cable||Provided by lab||4||$4.00|
For more detail: Autonomous visually steered car Using Atmega644
This free embedded project also found using:
- M64282FP image sensor