Pages

Autonomous Car


Introduction
Let us begin with one key observation: cars are cool.   From consumer transportation to manufacturing to childrens' toys, vehicles in their many forms are some of today's most influential machines.   Autonomous vehicles are already in use in many manufacturing facilities, and they are also sold as toys.   Perhaps one day, the world's highways will be filled with cars requiring no user intervention.   While we are not there yet, and may never get there, an autonomous vehicle can serve as a very interesting and practical design exercise.

Our vehicle uses optical sensors to follow a line on the floor.   Some autonomous vehicles used in manufacturing use a similar concept, following magnetic strips embedded in the factory floor.   The versatility of an optical design should be readily apparent, since re-routing the vehicle requires no more than re-painting a line.



Our vehicle uses reflective phototransistors to follow a line on the ground beneath it.   The state of the phototransistors is captured, and the car is controlled accordingly by an Atmel 8515 microcontroller.   If the car detects a small deviation from the line, it will correct its path by steering in the appropriate direction.   If it detects a large deviation, it will take more "drastic" measures to correct its path: it will back up while steering itself back towards the line until it re-centers itself.   It then continues on its path.

The original objective for this project was to optimize the car for the speed with which it navigated the line.   To do this, we would have increased the speed when little compensation was needed, and decreased the speed as more was needed.   This optimization, however, did not require much more effort on our part than the heuristic outlined above.   This is because the speed is mechanically regulated by the gradual acceleration of the car in balance with the direction reversal for large corrections.


Hardware
The hardware for this project was the bulk of the work.   Because we were making a moving vehicle, we decided that it would be best not to have any of the circuitry on breadboards.   Breadboards are also expensive, so we probably would have had to disassemble the car after its demonstration.   We therefore chose to wire-wrap all of the circuitry.   This required a fair amount of labor, but it was well worth it in the end.

The car we selected is fairly simple to operate.   It has a rear wheel drive, complete with a differential, which is powered by a DC motor.   The steering is not controlled by a servo, but rather by a solenoid.   This results in an "all or nothing" control over the steering, but we did not find this to be overly constraining.   We built two H-bridges using TIP-31, TIP3055, and TIP-42 BJTs to deliver power to the steering and the drive motor.   Because of the current requirements (the drive motor and steering solenoid could draw several amps), we used 20-gauge wire for the high-current areas of the H-bridges rather than the 30-gauge wire used for the rest of the circuit.   Schematics of the H-bridges and supporting CMOS logic appear below.

To detect the line, we use an array of five reflective photo-sensor pairs manufactured by Fairchild Semiconductor.   We mounted them just ahead of the front wheels on a threaded rod to allow us to reposition them as necessary.   The current through the photo-transistor depends on the intensity it detects, but what we really need is a logic level output.   We therefore used an open-loop-gain amplifier made from an LMC7111 op-amp.   A trim-pot allowed us to set a threshold level, and LEDs were used to aid in calibration.   A schematic of the circuit used for the photo-sensors appears below.

Because of the high current draw from the motor and steering, we decided to use a separate power supply for the logic.   The logic runs on 6V while the car's motors run on 12V.   This initially resulted in some careless bugs, but we seem to have avoided problems with any inductive "kick" from the motor and solenoid.


Software
The software for the autonomous car was not overly complicated, but it provides most of the functionality we could have hoped for.   The drive motor is controlled by the 8515's pulse width modulator to give us good control over the speed of the vehicle.   The drive direction, steering control, and photo-sensors use I/O ports.   The heuristic described in the "high level design" section above is implemented using a single state machine design style.

There is one state in the machine for each of the photo-sensors.   We tried to assume as little as possible about the width of the line relative to the spacing of the photo-sensors, though ideally the width of the line will be smaller than the minimum spacing between photo-sensors (about 2.5cm, but configurable).   The machine polls the inputs for a potential state change every 10ms.   We determined (by experiment) that this time base was necessary to ensure that none of the photo-sensors would cross the line without the car "noticing."   The state machine itself follows quite directly from the heuristic described above, and we will leave a more thorough description of it to our code (see appendix A).

In order to avoid the need for switches, our car starts and stops itself based on the status of the photo-sensors.   The car will not start moving until the middle photo-sensor (and only the middle photo-sensor) is on the line.   If no photo-sensor detects the line for 1.5 seconds, the car stops; it assumes that the line has ended, or that it is hopelessly lost.   If all of the photo-sensors detect darkness, then the car stops since it has probably been picked up.   We can take advantage of this feature when designing courses by placing a thick cross bar at the end of the course (like a T) to stop the car at the end.


Results
We had very favorable results.   Our car has successfully navigated a number of courses of varying length and complexity, all containing turns drastically sharper than the turning radius of the car.   The ability of the car to distinguish line from floor was about what we expected.   A line in electrical tape on the floor of Phillips Hall works quite effectively.   Our design is not entirely bug-free, nor is the car fail-proof.   Given more time, we could add features like the ability to navigate courses which cross themselves (like a figure-8), or track down that pesky bug which infrequently surfaces (we suspect a power-supply isolation problem).   All-in-all, the functionality of this vehicle is quite robust so long as we don't crash it into anything.

If There Were a Next Time
The only significant problem we have with the vehicle is that we never really had good control over the speed.   The pulse width modulator gives us reasonably good control over the acceleration (effective voltage on the drive motor), but does not give us good control over the speed.   Given a chance to build the car again, we would have used another photo-sensor to read markings on one of the rear wheels to determine the speed.   We would then have used a feedback control system to keep the car close to a target speed.   That way, our heuristic could really vary the speed of the car rather than just the voltage on the drive motor.


Appendix A: Code Listing
#include <90s8515.h>

/* speed and direction output pins */
#define speed           OCR1B                   //use PWM for speed control
#define drivedir        PORTA.0
#define turndir         PORTA.1
#define turn            PORTA.2

/* direction signal values */
#define fwd             1
#define rev             0
#define dirleft         1
#define dirright        0

/* state definitions */
#define center          0
#define left            1
#define farleft         2
#define right           3
#define farright        4
#define start           5

/* photosensor values */
#define LEDS            ~PINC   //inverted since "on" is for a black line

#define LLL             (0x01 & LEDS) == 0x01   //far left sensor
#define LL              (0x02 & LEDS) == 0x02   //slightly left sensor
#define CC              (0x04 & LEDS) == 0x04   //center sensor
#define RR              (0x08 & LEDS) == 0x08   //slightly right sensor
#define RRR             (0x10 & LEDS) == 0x10   //far right sensor

/* other definitions */
#define t0reload        256-62          //1 ms timebase @ 4MHz
#define deltaT          10              //state change time


unsigned char state;
unsigned int watchdog;                  //stops car if no line is found after time
unsigned int farcount;                  //after backing up, car steers and waits before going forward
unsigned int t_statemachine;            //task timer
void initialize(void);
void steer_off(void);
void steer_left(void);
void steer_right(void);
void reset(void);
void statemachine(void);

void steer_off(void)
{
        turn = 0;
}

void steer_left(void)
{
        turndir = dirleft;
        turn = 1;
}

void steer_right(void)
{
        turndir = dirright;
        turn = 1;
}

void reset(void)                        //turn off steering and stop car; return to start state
{
        steer_off();
        speed = 0;
        state = start;
}

void statemachine(void)
{
        t_statemachine = deltaT;        //reset machine timer

        if(LEDS == 0x1f)                //all LEDS off (car has been picked up in the air)
        {
        reset();
        }

        /* We want to reset the watchdog timer to 0 as long as
         * at least one sensor is on the line. */
        if(LEDS != 0)
        {
                watchdog = 0;
        }
        /* If the watchdog counter reaches 1.5 seconds, the car should be stopped.  However,
         * if we're backing up to find the line again, let it go until 3 seconds have passed. */
        if((watchdog++ == 1500/deltaT) && (drivedir != rev))
        {
        reset();
        }
        else if(watchdog == 3000/deltaT)
        {
        reset();
        }
        switch(state)
        {
                case start:                             //initial state
                        if(LEDS == 0x04)                //do nothing until only center sensor is on
                        {
                                drivedir = fwd;
                                speed = 200;
                                state = center;
                        }
                        break;
                case center:                            //center of car is on the line
                        if(LL)                          //near left sensor on, steer left to correct
                        {
                                steer_left();
                                state = left;
                        }
                        else if(RR)                     //near right sensor on, steer right to correct
                        {
                                steer_right();
                                state = right;
                        }
                        break;
                case left:
                        if(CC)
                        {
                                steer_off();            //we're back on track, go straight
                                state = center;
                        }
                        else if(LLL)                    //we're way off track, back up and turn the
                        {                               //wheels in the opposite direction to correct
                                drivedir = rev;
                                speed = 255;
                                steer_right();
                                state = farleft;
                        }
                        break;
                case right:
                        if(CC)
                        {
                                steer_off();
                                state = center;
                        }
                        if(RRR)
                        {
                                drivedir = rev;
                                speed = 255;
                                steer_left();
                                state = farright;
                        }
                        break;
                case farleft:                           //we're currently backing up to find the line
                        if(LL)                          //the inner left sensor is back on the line, so
                        {                               //go forward again & flip the steering 
                                steer_left();
                                drivedir = fwd;
                                state = left;
                        }
                        break;                          //otherwise, continue backing up
                case farright:
                        if(RR)
                        {
                                steer_right();
                                drivedir = fwd;
                                state = right;
                        }
                        break;
        }
}

interrupt [TIM0_OVF] void t0(void)                      //establishes 1msec time base
{
        TCNT0 = t0reload;
        if(t_statemachine > 0) t_statemachine--;
}

void main(void)
{
        initialize();

        while(1)
        {
                if(t_statemachine == 0) statemachine(); //fire off state machine if it's time
        }
}

void initialize(void)
{
        DDRA = 0xff;                    //PORTA is an output
        DDRC = 0x00;                    //PORTC is an input
        PORTC = 0xe0;                   //internal pullups off, except for the top 3 unused bits

        /* set up PWM to cycle every ~32 msec */
        TCCR1A = 0x20 + 0x01;           //non-inverted, 8-bit PWM
        TCCR1B = 0x04;                  //prescale to 256

        /* set up timer 0 to interrupt every 1 msec */
        TIMSK = 0x02;                   //timer 0 overflow interrupt
        TCCR0 = 0x03;                   //prescale to 64
        TCNT0 = t0reload;

        watchdog = 0;
        t_statemachine = deltaT;        //initialize task timer

        state = start;                  //initialize state variable
        #asm("sei")                     //fire up the interrupts
}
Appendix B: Schematics
Figure 1: H-bridge connected to drive motor
Figure 2: H-bridge used for the steering control Figure 3: Circuit used for each photosensor

0 comments:

Post a Comment

Share your knowledge

Related Posts Plugin for WordPress, Blogger...

Popular Projects

program for Dual DAC 8051 Microcontroller Based DC Motor Control A Microcontroller Based Turbidity Meter A m -Controller Based Thermostat ASCII to BCD conversion in 8051 AT90LS8515 Digital Message Machine Audio Frequency Response Analyzer Audio Homing Robot Automated Juice Mixer Automated Pet Feeder Autonomous Car Autonomous Parallel Parking RC Car Autonomous Search Robot Autonomous Tank Autonomous Vehicle Contrast Following Rover Autonomous navigating robot BCD number to ASCII in 8051 Balance Bot Blind Bot Blood Pressure Monitor Bloodshed Dev-C++ 5 Compiler/IDE Breath Alcohol Tester Converters on TI MSP430 CrossStudio MSP430 IDE Design of a Real-Time Digital Guitar Tuner Digital Oscilloscope Digital Stethoscope Digital clock project using PIC16C54A microcontroller Digital thermometer ECG monitoring system GPS Data Logger with Wireless Trigger Handwriting Recognition Systm Home Security System Home energy managment IAR Embedded Workbench IDE INFRARED TRACKING SYSTEM IntelliBOT Laser Communications System Line following van MSP-EXP430FG4618 Development Tool and the eZ430 kits MSP430FG4618 device implement a Buzzer tone generator MSP430FG4618 device implement a Real Time Clock MSP430FG4618 device implement a voltage ramp generator MSP430FG4618 device present a message on the LCD Basic Microcontroller(8051) Lab Mivo- RFID based mobile payment system Multi-Zone Fire Alarm System PC based temperature control PIC 16f877 RPM Meter PIC16C54 dual dice electronic project circuit PIC16F84A digital thermometer microcontroller project PIC16F886 horn driver PWM motor contoller with MSP430 Program Block data transfer in 8051 Program to add two BCD numbers in 8051 Program to check whether a 4th bit of a byte is 1 Program to convert ASCII to hex in 8051 Program to count from 0-9 in 8051 Program to count number of 1's in a given data byte in 8051 Program to divide an 8 bit no by another 8 bit number in 8051 Program to find largest of n numbers in 8051 Program to find the LCM of two numbers in 8051 Program to find the square of an 8 bit number in 8051 Program to generate 50msec delay in 8051 Program to implement BCD counter to count from 0-99 in 8051 Program to implement BCD counter to count from 99-0 in 8051 Program to interchange two blocks of data in 8051 Program to multiply 16 bit number by 8 bit number in 8051 Program to search an element in an array in 8051 Program to sort an array of 10 elements in 8051 Programming the ez430 Proximity Security System RAMP wave in 8051 RC Car Controller RObo Dog Radio-controlled Truck Retina color tracker Robotic Arm Controller with GUI Robotic Car Traction Control Safety-sensor vehicle Security Entrance System Self-Powered Solar Data Logger Snake Arm Ultrasonic Positioning Control System Store FFh if 1 Super Train Controller TI MSP430 Microcontrollers Timers on the MSP430 TouchPad Drawing Board Ultra-Sonic Parking Assistant Ultrasonic Parking Controller Ultrasonic Range finder Voice Activated Alarm Clock Voice Recognition Robotic Car Voting Machine Weather Station Web-Monitored Thermostat Wireless Drawing Device Wireless Telemetry Wireless message Communicator Write a C program to display the code of the key pressed in 8051 Zigbee Wireless Relay Control and Power Monitoring System add two multibyte numbers in 8051 convert a decimal number to hex number in 8051 convert an 8bit Hex number to decimal number in 8051 convert hex number to ASCII number in 8051 eZ430-F2013 Development Tool use SD16_A ADC eZ430-RF2500 Development Tool use ADC10 else store 00 in the same location in 8051 find the GCF of two numbers in 8051 find the average of 10 numbers in 8051 generate Fibonacci series in 8051 metal detector project microcontroller using IAR Embedded Workbench program for Elevator Interface in 8051 program for Stepper motor interface in 8051 spectrum analyser square wave in 8051 triangle wave in 8051 voice recognition security system

Sites U missed

Hint

Open Pictures in new page by right click on it, if it is not shown full image.