F12: Self-Driving GPS Following Car

From Embedded Systems Learning Academy
Jump to: navigation, search

Self-Driving GPS Following Car


The objective of this project is to create an autonomous vehicle that follows another car. A leading car will continually inform the autonomous car of its location. The autonomous car will then drive to the target location while avoiding obstacles along the way.

Introduction and Objectives

The Self-Driving GPS Following Car follows another car by driving to the GPS coordinates of the leading car. A ZigBee communication link transmits the GPS data from the leading car to the following car. The following car utilizes a GPS and a compass to determine its own location and orientation relative to magnetic north. Using the two pairs of GPS coordinates and the orientation of the car, the bearing and distance necessary to be traveled is calculated. The car uses proximity sensors, so the car can avoid obstacles while navigating to the destination.

The project required the following objectives to be accomplished:

  • Read GPS coordinates of the leading car and the following self-driving car
  • Use XBee modules to send and receive GPS coordinates from the leading car to the following car
  • Compute the true north bearing and distance necessary for the following car to reach the leading car
  • Account for difference between true north and magnetic north in bearing calculation
  • Read the magnetic north bearing using a compass
  • Read the distance to objects using proximity sensors
  • Control steering motor to steer left, right, and straight using a motor controller
  • Control direction motor to move forward, backward, and stop using a motor controller
  • Determine algorithm to drive toward destination
  • Determine algorithm to avoid obstacles

Team Members and Responsibilities

  • Elias Barboza
    • PWM driver, motor controllers, and obstacle avoidance
  • Caleb Chow
    • Read compass, read GPS coordinates, and move toward target GPS coordinates
  • Stephen Lu
    • ADC driver, read proximity sensors, compute distance based on measurement, and obstacle avoidance


Week Number Planned Items Actual Items

Week 1: Design
(October 29)

  • Order Parts
  • Design proximity sensors placement
  • Design algorithm to avoid obstacles
  • Design algorithm to move toward GPS coordinate
    using compass
  • Ordered parts
  • Designed proximity sensor placement
  • Designed obstacle avoidance algorithm
  • Designed move to destination GPS algorithm

Week 2: Construction
(November 5)

  • Upgrade leading car with microcontroller, XBee, GPS,
    and a battery pack
  • Upgrade following car with microcontroller, XBee, GPS,
    compass, proximity sensors, motor controllers, and a
    battery pack
  • Read GPS coordinate from GPS module
  • Tested proximity sensors
  • Finished ADC and PWM drivers
  • Paired XBee modules
  • Read GPS coordinates and computed required bearing and
    distance to travel to destination

Week 3: Drivers
(November 12)

  • Read direction from compass
  • Enable car driving capabilities / motor controllers
  • Send / receive data using XBee modules
  • Motors controllers fully interfaced
  • Mounted proximity sensors, motor controllers, microcontroller, and GPS
  • Created upgrade module for leading car

Week 4: Coding
(November 19)

  • Code obstacle avoidance
  • Tested obstacle avoidance
  • Sent GPS data from leading car to following car
  • Swapped to non-tilt compensated compass
  • Mounted compass
  • Restructure and reorganize code

Week 5: Coding
(November 26)

  • Code moving toward GPS coordinate
  • Tested obstacle avoidance
  • Swapped a proximity sensor to unify sensors
  • Swapped to less power hungry motor controllers
  • New motor controllers fully interfaced
  • Upgraded to use 5xAA battery pack
  • Rewired parts with finalized placement

Week 6: Testing
(December 3)

  • Testing
  • Tested obstacle avoidance
  • Tested move to GPS coordinate

Week 7: Finalization
(December 10)

  • Make final changes for demo
  • Finalize content in Wiki article
  • Tested move to GPS coordinate

Parts List & Cost

Parts Quantity Cost Link

RC Car -
Beetle RC Car



Previously owned

Microcontroller -
2012 SJ One Board



SJ One Board Info

XBee Module -
XBee 1mW Chip Antenna



Digi Datasheet

GlobalSat ET-318



Globalsat DataSheet

Motor Controller -
Secret L293D Motor Driver



Solarbotics Datasheet

Compass -



Devantech Datasheet

Sonar Range Finder -



MaxBotix Datasheet

Design & Implementation

Hardware Design

Leading Car

The leading car consists of the following additional hardware:

  • XBee module
  • GPS module
  • 3.3V regulator circuit

The leading car is responsible for sending its GPS coordinates to the following car. This is accomplished by sending the raw GPS data over ZigBee to the following car. The GPS and XBee modules both use UART to communicate, so no microcontroller is necessary. The paired XBee modules will take care of the data transfer. Both modules ran off the same 3.3V power supply, which came from a regulator off of the car’s battery pack.

Leading Car Block Diagram

Following Car

The following car consists of the following additional hardware:

  • SJ One board
  • XBee module
  • GPS module
  • 2x Motor controllers
  • Compass
  • 3x proximity sensors
  • 5 cells of AA battery pack
  • 5V regulator circuit
  • Power switch

The following car is responsible for avoiding obstacles and for driving to a destination coordinate. To accomplish this, the car needs to know its own location, the target coordinate, information about its surroundings, and be able to move. Its own location was determined using a GPS and a compass, while the target coordinate was received from the leading car over ZigBee. Proximity sensors were used to get information about its surroundings and motor controllers enabled control over the motors. A microcontroller was used to control all the peripheral devices. The compass and the motor controllers required a regulated 5V power supply, which came from a 5V regulator off of the car’s battery pack, while the microcontroller could take anywhere between around 4.5V to 9V, which came straight off of the car’s battery pack. The remaining devices took 3.3V, which came regulated from the microcontroller. The 5V regulator required a voltage higher than 5V, which resulted in the car’s battery pack being upgraded to five cells of AA batteries.

Following Car Block Diagram

Hardware Interface

Leading Car
The following table shows the pin connections for the XBee module to send the GPS module's data to the receiving end of the XBee.

GPS to XBee Pin Connections

GPS Pin XBee Pin



Following Car
The following table shows the pin connections for the SJ One board to communicate with the peripherals.

SJ One Board Pin Connections

SJ One Board Pin Destination Pin Description



GPS data received for following car



GPS data received using XBee for leading car


Compass SDA

Serial data


Compass SCL

Serial clock

ADC0-3 / ADC0-out

Front proximity sensor analog out

Analog distance reading for front sensor


Left proximity sensor analog out

Analog distance reading for left sensor


Right proximity sensor analog out

Analog distance reading for right sensor

GPIO P1.24

Steering motor enable

Set steering amount

GPIO P1.25

Steering motor dir1

Set steering direction

GPIO P1.22

Steering motor dir2

Set steering direction


Direction motor enable (PWM)

Set speed

GPIO P1.19

Direction motor dir1

Set motor direction

GPIO P1.23

Direction motor dir2

Set motor direction

The GPS and XBee both communicated with the microcontroller using UART while the compass used I2C. There were no other alternatives that could be selected on the modules.

The three proximity sensors on the other hand had a selection of three outputs to choose from: UART, analog, or PWM. Since the UARTs and PWMs were all taken, analog outputs were selected to be used for the sensors.

A PWM and GPIOs were used to control the motors. The PWM was used to control the speed of the direction motor and GPIOs were used for the direction. The steering motor did not require a PWM since setting the amount to steer left or right was not necessary. The signals to the motor controllers were set using the logic table below to enable steering and direction movement.

Motor Controller Logic Table

Enable Dir1 Dir2 Direction Motor Steering Motor





Steer straight





Steer straight




Rotate forward direction

Steer left




Rotate backward direction

Steer right





Steer straight

Software Design

The project was built on top of the FreeRTOS sample project with the UART, I2C, and ADC drivers included. Additional tasks were created to enable multitasking.


The following tasks were used on the self-driving car:

  • Terminal Task
    • Handles commands to get system information and set runtime configurations for logging and navigation options
  • XBee GPS Task
    • Reads and processes GPS data through XBee module to keep coordinates of the leading car updated
  • My GPS Task
    • Reads and processes own GPS data to keep own coordinates updated
  • Sensors Task
    • Keeps own heading relative to magnetic north updated
    • Keeps distances from objects in front, to the left, and to the right of the car updated
  • Navigation Task
    • Uses motor controllers to drive
    • Uses distances from objects to avoid obstacles
    • Uses its own and the leading car's GPS coordinates to compute necessary heading to travel at to reach destination
    • Uses compass heading and required heading to align itself to destination
  • Info Task
    • Handles logging of own GPS and XBee GPS readings, sensor readings, and navigation information

The tasks were created such that the GPS tasks have a higher priority than the rest. Since GPS data was stored into a buffer by UART, the data could not be allowed to collect or else by the time the car updates the coordinates, the data will already by outdated. The tasks were also designed with different sleep delays. The GPS tasks had no delay since they will automatically sleep when there is no data to read, while the sensors task had a delay of 75mS. The bare minimum allowed was 49mS, which was limited by the proximity sensors. Additional delay was added for safe measure to prevent reading echos. The navigation task was set to have a delay of 50mS. A delay less than the sensors was selected so that the worst case time before readjusting the motors to the driving conditions was 125mS. This would allow the car to have a faster reaction time.

Shared Resources

In order to allow data to be accessed by multiple tasks, certain variables had to be made accessible globally. This was accomplished by using handles to the data. For the data that had to be updated simultaneously, such as GPS coordinates, a semaphore was used to lock the data. Integers that had to be shared were not required to be locked since the variables could be updated with a single instruction.

GPS Data Handling

The two GPS tasks processed GPS data identically. GPS data was received following the National Marine Electronics Association (NMEA) specifications. Since the only necessary information to read was latitude and longitude, sentences of type GGA were selected to be processed so that the coordinates could be stored for use in navigation.

In the navigation task, computations had to be made to get from having two sets of GPS coordinates to knowing how to steer toward the destination. NMEA sentences store the coordinates in a degree-decimal minute format (DDDMM.MMMM). In order to make use of the coordinates for distance and bearing calculations, the coordinates have to be converted to decimal degree format (DDD.DDDD). Trigonometry can be used with the coordinates in decimal degree format to compute the distance and bearing necessary. But, the bearing computed is relative to the true north while the compass reading is relative to magnetic north. Since magnetic north is constantly changing depending on the geographical location, the difference, or magnetic declination, needs to be accounted for. The end result of all the computation is the target angle desired to be read on the compass, which indicates the direction of the destination.

Obstacle Avoidance

Obstacle avoidance was accomplished by using the distances read from the proximity sensors. The following flowchart shows the algorithm used to avoid obstacles.

Obstacle Avoidance Algorithm

Hardware Implementation

All of the components are interfaced through the SJOneboard which has a built-in LPC1758 Microcontroller. The three sonar sensors provide their data readings through ADC as voltage values, which are interpreted accordingly in software, based on their datasheet specifications. There are two motor controllers in the system, one for each motor in the car. The rear motor and its controller is manipulated with PWM, which enables for changes in speed. The PWM is connected to the enable pin in the motor controller to save battery and for better control of the motor. The front motor controller is always enabled since the motor is not used very often. Each motor controller has two direction pins, thus all four pins are connected to four GPIO ports on the main SJOne board. The last two components, the GPS and Compass are connected to the board through I2C and ADC, respectively.

The photos below show our hardware implementation.

Following Car Wire-wrap Board

Following Car LPC Microcontroller

Following Car Internal View
Following Car Front View

Software Implementation

Terminal Task

In order to simplify development, a configuration utility was used. The configuration utility allowed for calibrations to be made without reprogramming the microcontroller. This allowed for faster testing and calibration of the sensors, motor speed, and logging without having to rebuild every time. The configuration utility also allowed us to log sensor information in order to know the readings when the car was not connected directly to the terminal and it was in motion. The utility modifies the program variables directly in the flash memory with the use of specific terminal commands.

XBee GPS and My GPS Tasks

All this task did was process the received GPS data from UART into a latitude and longitude coordinate. A NMEA sentence was verified to be valid by checking the checksum. Once the sentence was verified, the fields were parsed to get the coordinates.

Sensors Task

The sensors task used I2C to read compass data and ADC to read the proximity sensors. A compass reading was made by reading two bytes. A high byte register and low byte register was read and combined to create the reading. The data was then converted to the standard 360 degree format. Proximity sensor readings were made by reading the analog output from the sensor. The value was compared to the supply voltage to determine how much of the maximum range an object was at.

Navigation Task

In order to drive the car, the navigation task used sensor readings and navigation information to control the motor controllers. The motor controllers were controlled by using a PWM to set the motor speed and GPIO pins to set the motor directions. Speeds and directions were determined by checking distances from objects, whose thresholds could be configured. Objects at different thresholds would make the car react differently. When there were no obstacles, car would drive toward the destination by calculating the bearing needed to get from the starting GPS coordinate to the destination GPS coordinate. Under drive to destination condition, the car would steer to align its bearing with the required bearing and drive forward.

Info Task

The info task uses the configuration utility to determine what information to log and whether to log to the flash memory or just display it. Sensor readings and navigation information were all capable of being logged.

Testing & Technical Challenges

Sensor Thresholds

Values needed to be determined for a number of thresholds. The thresholds were front detect, front backup, side detect, and side backup. The detect thresholds trigger the car to slow down and the backup thresholds trigger the car to backup.

We spent quite a bit of time figuring out the perfect front threshold. We needed to figure out the best values for these thresholds. We don’t want the thresholds to be too small so that the car doesn’t have enough space to slow down, stop, and backup. We also do not want the thresholds to be too large so that the car is always backing up when it has room to turn away from the obstacle.

Sound Reflections

The proximity sensors are ultrasonic, meaning they send out a sound wave and calculate how much time it takes for the reflected echo to come back. However, when our following car is in a corner, the sound waves might not reflect back to the source sensor, but to the other two sensors, making the car backup or turn unnecessarily.

To fix this problem, we would need more sensors to detect a larger radius and also a more descriptive picture of the obstacle. However, due to limited ADC pins we were only able to use a maximum of three sensors.

Compass Interference

The LSM303DLM compass uses the Earth’s magnetic field to determine the direction it is facing. Therefore, the compass has to be at least 6 inches away from any magnet, according to the datasheet. The GPS module on the car uses a magnet as its antenna so we knew we had to mount our compass, as explained in our hardware implementation section.

The interference became a problem when we were testing the compass indoors. There are a lot of sources of magnetic fields inside classrooms from computers. When we hard coded the car to always go north (0 degrees), the car will start going in one direction, before turning around and heading off to a different location. This problem will be solved when we test our car outdoors.

GPS Accuracy

Our GPS modules work the best outdoors. The GPS modules take a while to boot up, around 45 seconds to a minute. While testing outdoors, we connected our car via USB to Hercules until we received the GPS signal. Then, we unplugged the car but still left the car on so the GPS doesn’t shut off. We verified the GPS coordinates by printing out the coordinates in Hercules and putting them into Google Maps. However, the GPS module on our leading car was not very accurate. When we place the two cars next to each other, the coordinates are not the same, and differ by around 15 meters.

Power Consumption

We changed motor controllers around halfway through the project. The old motor controllers needed at least 6V to be powered. A 9V battery drained too quickly to be suitable for actual testing and demonstration purposes. The next idea was to take the 4 AA batteries’ voltage and use a voltage booster to boost it up to the necessary voltage. After a week of testing, the voltage booster stopped working due to overheating and the regulator melting. Preet suggested to use a new motor controller, the current one used in the car. This one only needed 5V as the supply.

Another power consumption problem was the compass. It needed a minimum of 5V to power on. This means the 4 AA batteries that produce 4.8V is not enough to power the compass. Since the voltage booster stopped working, we needed another way to produce more voltage. To fix the problem, we added another AA to the battery pack to create 6V. This required breaking one of the tabs on the battery pack and soldering more metal tabs to it. Using 5 AA batteries allowed us to power our motor controllers, the compass and the LPC1758 board.

XBee Range

The range of the Xbee modules should be 400 feet according to the datasheets. When testing outdoors, the following car seemed to drive away from the leading car. To debug the problem, we connected the following car via USB to Hercules and read the GPS data from both cars. Then, one member of the team walks away from the computer with the lead car until the leading car GPS data becomes invalid or inconsistent. After testing, the range of the Xbee modules was only 40-50 feet.

Bad Front Sensor

When we bought our parts, we only bought two proximity sensors, one pointing towards the left, and the other pointing towards the right. After a discussion with Preet, he suggested to add a sensor pointing forward and he provided us one. This sensor used I2C and passes the distance detected in inches as data. However, the maximum distance measured by the sensor was only 24 inches, which is too small to be our front threshold. We were able to find a 3rd proximity sensor that was the same as the other two side sensors. This sensor could measure up to 254 inches and is sufficient enough for our thresholds.

Motor Speeds

The motor controllers output a PWM signal to control the motors. The higher the duty cycle, the faster the motor spins. However, this will consume more energy. The duty cycle must be high enough for the wheels to overcome the friction of the ground. During the testing phase, the car also produces a high pitch sound, indicating that the duty cycle is not high enough. With the old motor controllers, when the duty cycle too high, the batteries drained quickly. With the new motor controllers that are more efficient and use less power, the duty cycle can be set to the maximum of 100 without draining the battery quickly.

Another side-effect of a high duty cycle is the car will travel too fast and have less time to stop and avoid obstacles. To fix this problem, the front and side thresholds were increased to allow the car to stop and backup without hitting obstacles.


The GPS Following Car is, in general, an embedded system that connects together five different components that are interfaced together in software through protocols such as I2C, UART, and ADC. The main objective of the project was to create a car that would be able to follow another car automatically by acquiring the necessary information from the leading car, such as GPS coordinates and heading. The challenge of the project was for the following car to be able to travel to its destination by itself without colliding with any external objects. This challenge was tackled by following a very strict and efficient object-avoiding algorithm.

As a team of engineers, this project enhanced our programming skills by taking our knowledge of the C and C++ languages and putting them to use to ensuring that the system worked effectively and efficiently. We learned to communicate and share information with one another in a way that we were always productive and learned to manage our time effectively to make consistent progress throughout the semester. Also, our understanding of operating systems was challenged in this project because the system as a whole is based on FreeRTOS. By having an actual O.S. run our system we were challenged to meet acceptable CPU efficiency levels, to make use of the available memory efficiently by limiting our tasks to only using the amount of stack necessary to execute.

Project Video

Demonstration Video

Project Source Code



Dr. Haluk Özemek
Preet Kang

References Used

Compute distance between coordinates: [1]
Compute bearing to get from one coordinate to another: [2]
Adjust bearing to magnetic bearing: [3]


ZIP file: TODO