Gps Homing Robot Final Report

68
GPS Homing Robot Final Report Team Members:

Transcript of Gps Homing Robot Final Report

GPS Homing Robot

Final Report

Team Members:Zachary Chaves (CMPE)

Phillip Johnson (EE)Gregory Wilkosz (EE)

Advisor:Dr. John E. Ayers

January 6, 2004ECE 292

Table of Contents

Abstract................................................................................................................................3Objective..............................................................................................................................3Design..................................................................................................................................3

Compass...........................................................................................................................3Preliminary Design......................................................................................................3Problems Encountered.................................................................................................4Final Design................................................................................................................4

Drive System...................................................................................................................5Preliminary Design......................................................................................................5Problems Encountered.................................................................................................6Final Design................................................................................................................8

Vehicle Speed Reduction...............................................................................................10Preliminary Design....................................................................................................10Problems Encountered...............................................................................................10Final Design..............................................................................................................11

Collision Avoidance......................................................................................................12Preliminary Design....................................................................................................12Problems Encountered...............................................................................................12Final Design..............................................................................................................12

GPS System...................................................................................................................14Preliminary Design....................................................................................................14Problems Encountered...............................................................................................16Final Design..............................................................................................................18

Alternative Designs...........................................................................................................18LCD / Keypad User Interface Module...........................................................................18

Preliminary Design....................................................................................................18Problems Encountered...............................................................................................20Final Design..............................................................................................................20

Budget/Parts.......................................................................................................................21Timelines...........................................................................................................................22Conclusion.........................................................................................................................24Appendix A........................................................................................................................25Appendix B………………………………………………………………………………53

Abstract

Every possible location on the Earth’s surface has been mapped by coordinates, which makes it possible to express any location accurately. Satellites broadcast to these locations so that any receiver may realize its location. This is the theory behind the Global Positioning System (GPS). The purpose of this project is to build a robot that is capable of navigating itself by taking full advantage of this technology.

Objective

In order to fulfill the objectives of this project, certain requirements must be outlined. These parameters will shape the way this project is carried out, from design decisions to economic constraints. The most crucial objective will allow an operating vehicle to navigate from one point to another using an onboard GPS navigation system. The vehicle should not get stuck or turn over easily. The destination and any needed initializing inputs should be the only data input into the system. The vehicle should be able to traverse multiple types of terrains and navigate the entire course (point A to point B) that has been input by the operator. Simple obstacles in the vehicle's path should be navigable. The overall weight of the vehicle, with all components applied, should weigh less than 10kg (22 lbs.). The overall cost of the project, which includes testing and other incidental costs, should not cost more than one thousand dollars.

Design

Compass

Preliminary Design

Since the Garmin GPS-LVS16 only provides a calculated compass heading output when the unit is moving, a stand-alone compass is needed in order to determine the direction that the vehicle is facing. The initial design involved a PNI V2Xe 2-axis 360 degree resolution digital compass. This compass required a 3VDC input which would have been easily pulled from the Zilog microcontroller board. The means by which it output data to communicate with microcontrollers is SPI communication protocol.

Problems Encountered

Due to the lack of turning precision of our vehicle, a digital compass with great precision was not necessary. The PNI V2Xe’s output using SPI communication protocol was also determined to involve too much work with software.

Final Design

We chose to use the Dinsmore 1490 digital compass with 45 degree resolution (8-directional). The 8-directional compass provided enough resolution to indicate to the software which direction the vehicle was traveling to assist in navigation. This compass outputs to four general purpose I/O pins of our microcontroller. These bits determine the directional orientation of the compass. This was much easier to implement than the PNI V2Xe digital compass. Figure 2 shows the schematic for interfacing the Dinsmore 1490 digital compass to the Zilog Z8 Encore! microcontroller. The following Figure 1 shows the digital compass mounted to the top of the vehicle without the white plastic enclosure.

Figure 1: Dinsmore 1490 Digital Compass mounted on top of vehicle.

Figure 2: Dinsmore 1490 Digital Compass / Zilog Z8 Encore! MCU Interface Schematic

Drive SystemOur requirement for the drive system was to be able to move a vehicle or robot in

a desired direction depending on the information obtained from the GPS. Another requirement is that the vehicle would need to carry all the required hardware, weigh less than 10 kg, and able to move over many different terrains.

Preliminary DesignOur first job was to find a vehicle that would cover many different terrains. We

decided that a vehicle which uses tracks, similar to a military tank, would achieve this goal. We also found a vehicle that would be able to cross water obstacles because the tracks are able to paddle through the water. The vehicle we found, produced by TYCO Industries, is called The Landshark, which is a radio controlled (R/C) vehicle that has a six volt battery. The overall weight of the vehicle is less than seven pounds, which should allow us to add the necessary components and not go over our weight limit of 22 kg.

Once the vehicle was determined to be suitable for our needs, we needed to learn how to control the vehicle with a microcontroller. We began by disassembling the vehicle so we could look at the drive system already inside the vehicle. We found that the vehicle has two direct current (DC) motors and a motor controller board. Examining the motor controller board, we noticed that there was a decoder chip that helps drive the motors. After finding the data sheet for the PT8A978P decoder chip, we determined that

we would be able to use the existing motor controller board to control the vehicle. Using an oscilloscope, we found that the incoming signal from the R/C unit was a frequency-shift keyed (FSK) square wave signal, as shown in Figure 3. We noticed that the signal has two distinct sections: information and end sections. The information section has a frequency of 1.64 kHz, while the end section has a frequency of 820 Hz. The end section only supplies four pulses to the entire control stream, while the information section will vary depending upon the desired function. Once we determined the proper sequencing of the input signal we would be able to duplicate these signals to control the vehicle.

Figure 3: FSK Input Signal to Motor Control Board Decoder

Problems EncounteredThe first problem that we encountered in the design of the drive system was the

combination of the information and end sections of the signal. We determined that a 2:1 multiplexer (MUX) would be able to combine the two signals properly. However, we would need to design a control signal that would allow the switching of the MUX. This signal would also vary according to the drive function that we desired. Since the Zilog microcontroller that we were using has four timers, we would be able to use one timer in its pulse width modulation (PWM) function. This allowed us to switch from the 820Hz to 1.64 kHz signal and output a similar drive signal that the R/C remote supplies.

Another problem was the type of MUX that we would use in our system. Originally we found an Analog Device 8180 switching MUX. This item would switch from one input to another with only a 10ns delay, which would not interfere with our desired output signal. However, this device requires a negative voltage for proper operation. Our Zilog Development Kit does not have the negative supply voltage for this device. We also determined that to create the negative voltage would be an added cost that would not be necessary. Therefore we searched the internet and found Texas

Instrument’s SN54AHC157 Quadruple 2:1 MUX. This device would work with an operating voltage of -0.5V to 7V and therefore would be able to be attached to the Zilog Development board with no problems. This is possible because there is a prototype area on the Development board that will accept two 16-pin SOIC devices, allowing us to attach the device to the development board and not create another circuit board to insert into the vehicle.

Another aspect of the drive system is the ability for the user to use the R/C remote to control the vehicle whenever they feel it is necessary. An interrupt signal would be required to turn the microcontroller’s drive system off and allow the remote’s signal to take over. We first thought that the output signal form the remote could be used to create the interrupt. This option would not work properly. The remote signal would always interrupt the system because when there was no incoming signal an interrupt would still be noticed. This was due to the average output voltage with no signal applied was greater than 0.5V. The average output voltage was around 1.3V, therefore some signal conditioning was required to accomplish this task. We were able to obtain a KIA 393P Comparator from the lab and create the circuit shown in Figure 4. This comparator would allow the remote signal to activate the interrupt, but not when there was an average output voltage.

D 1

1N 4 4 8

1 2

-

+

U 1A

K I A 39 3

3

21

84

+6Vfrom Battery Pack

C 1. 1 u F

R 11 0 K

Interrupt Signalto Microcontroller

0+3.3VReference Voltage

Drive Signal FromR/C Remote

0

Figure 4: Comparator Circuit

Once the interrupt was working properly, we noticed that the Texas Instrument’s MUX would not allow us to switch another set of input signals to the second set of inputs on the MUX. We found that the control signal operates all four selectors on the device, not a control signal for every two inputs. Therefore we needed another MUX device on the board to allow us to complete this operation. This was not a big problem because the Zilog Development board has two locations for 16-pin SOIC devices in the prototype area. We attached another MUX to the second location and made the selector input the output of the interrupt signal. Figure 5 shows the connection of the two MUX’s that combine the drive signal and switches from the microcontroller to the remote signal.

Drive Signal toVehicle Drive Board

Controller GeneratedDrive Signal

1.64 kHzSignal

InterruptSignal

DriveSignalfromR/CRemote

PWMSignal

U 2

7 4A H C 1 5 7

11 5

4791 2

25

1 11 4

36

1 01 3

A / BG

1 Y2 Y3 Y4 Y

1 A2 A3 A4 A

1 B2 B3 B4 B

00

U 1

7 4A H C 1 5 7

11 5

4791 2

25

1 11 4

36

1 01 3

A / BG

1 Y2 Y3 Y4 Y

1 A2 A3 A4 A

1 B2 B3 B4 B

820 HzSignal

Figure 5: MUX Schematic

After all the components were applied to the vehicle and testing commenced, we found that the vehicle moved in a pulsing motion. We found that by applying the vehicle’s battery to the Zilog Development board for power, we would lose power every time the motors were engaged. This alerted us to the fact that the supply voltage of the 6V battery would drop below 3V and cause the Zilog board to reset. We were able to overcome this problem by inserting a battery pack specifically for the microcontroller. This battery pack holds four AAA batteries and supplies enough power (6V) to energize the Zilog Development board.

Final DesignThe final design of the drive system first required the programming of the Zilog

microcontroller to output the proper timing signals. This was accomplished by using the onboard timers. One timer (TMR0) was initialized to output a continuous 820 Hz square wave, while another timer (TMR1) was initialized to output a continuous 1.64 kHz square wave. Once this was accomplished, a third timer (TMR2) was required to output a varying PWM signal. This varying signal would control a MUX that would combine the output of the other two timers. However, this PWM signal would change depending upon the function that was required. So if the program wanted the vehicle to move forward, a certain PWM would be required. To determine the proper PWM signal, we found that the end code, which is four pulses at 820 Hz, lasted for only 4.878 ms. Then, looking at the data sheet for the decoder device on the motor controller board, we determined the appropriate times for each movement function of the vehicle. These times are shown in Table 1. With these times determined, the PWM signal would be designed to produce a low for 4.878ms and then go high for a given time, depending on the drive function.

Drive Function Required Pulses TimeForward 22 13.414 msReverse 40 24.39 ms

Turn_Left 58 35.366 msTurn_Right 64 39.024 ms

Table 1: PWM Signal for Certain Drive Functions

Now that the function times were determined, we could design the proper code to accomplish these tasks. We created a drive class in our program so we could use the functions wherever they are required. One function, Forward, would begin by initializing TMR0 and TMR1. Then we initialized TMR2 to run in PWM mode. Now we need to determine the proper code to make the signal at the times required. First we need to find the desired time-out period (TOP) by adding the end code time and the information code time. For the Forward function we used 18.292 ms to achieve proper operation. This value will be used to help determine the proper reload values (RV), which are required in programming TMR2. The reload values are determined by using the equation below:

The system clock (SC) for the Zilog Development board runs at 18.432 MHz, while we determined that the prescale (P) value to be 16. Now that the reload value was obtained, we converted this value to a hexadecimal (hex) value. The highest two values of this number will be applied to T2RH, while the lowest go to T2RL. Now we can determine the pulse width modulation value (PWMV). First, we must find the high time ratio (HTR). We can achieve this value by using the end code time (ECT) and the information code time (ICT) and using the equation below:

Once the high time ratio is found, we can find the PWMV by using the following equation:

Now that the PWMV was obtained, we can convert this value to a hex value. The highest two values of this number will be applied to T2PWMH, while the lowest go to T2PWML. This completes the initialization of TMR2, which will vary for each drive function. Now we could attach the SN54AHC157 MUX to the Zilog Development board and attach the appropriate outputs to the MUX. The proper connections can be seen in the first MUX shown in Figure 4. Once these connections were completed, we tested the final output signal from the MUX with an oscilloscope. We found that the signal was not perfect. There was more end code pulses than were desired, so we modified the T2PWML and T2PWMH values to ensure the proper output from the MUX. The output of the MUX would be considered the completed drive signal, which we could take and input into the decoder chip on the vehicle’s drive board and would be able to control the vehicle.

Since the Forward and Reverse functions of the drive system will be used to control for extended periods, these functions will run the three timers continuously. However, the Turn_Left and Turn_Right functions will only apply their output drive signal for a certain amount of time. This was achieved by using two simple for loops that

will provide delay. This delay was determined by testing and allows the vehicle to turn approximately 45 degreed in either direction. The final function designed was Stop. This function is accomplished by turning all timers off and allowing no signal to the vehicle’s drive board. The entire drive program can be seen in Appendix A.

Now that the microcontroller can control the vehicle, we looked into allowing the user to override the system and take control using the R/C remote. We proceeded by noticing where the drive signal on the vehicle’s drive board is applied to the decoder chip and removed a section of the trace on the board to not allow the signal to connect. We then attached a wire to either side of the broken connection and attached a connector to the opposite end. This connector will allow us to connect to the Zilog Development board. The drive signal from the vehicle was then attached comparator, as seen in Figure 5. The output of the second MUX will then be attached to the wire that connects to the decoder’s input pin on the vehicle’s drive board.

Next, we inserted a quad AAA battery pack into the vehicle’s interior case to power the Zilog board. We then attached a single-pole single-throw (SPST) switch to the exterior of the vehicle to allow us to turn the Zilog Development board on or off. We also found that the Zilog board fit inside the vehicle’s case with a few modifications. The modifications included attaching a slim board to the Zilog Development board and removing some ribbing from the vehicle’s interior case. Now the Zilog board will not slide around and dislodge its connections.

Vehicle Speed Reduction

Preliminary DesignOnce testing commenced with the compass and drive system enabled, we found

that the vehicle moves quickly along the ground. We decided that if the vehicle were to reduce its speed, then we would be able to control the vehicle’s progress and allow the avoidance detection system to handle obstacles more efficiently.

Problems EncounteredOur first problem was to determine how to slow the vehicle down. We began by

trying to use the drive system program. We found that the program was using its Turbo mode for forward progress. So we determined that by changing the information code to change the mode to just Forward, we could possibly slow the vehicle. This was not the case. The current vehicle’s motor control board was designed to only allow Turbo mode by placing a ground at one of the control pins on the decoder device.

Our next idea was to reduce the amount of voltage to the motor control board in an attempt to slow the vehicle. We tested this by using a variable DC power supply and attached it to the input power on the motor control board. We found we could easily reduce the speed of the vehicle using this method. However, we were still concerned about being able to use the vehicle at higher speeds because the higher speed is required when the vehicle maneuvers through water. The vehicle already moves slowly in water at its current speed, but if we were to slow it down, it would take forever to move across water. So we decided that we should attach a relay to the vehicle and have the

microcontroller switch the relay from 3V to 6V when the GPS determined that the vehicle was moving slower than normal.

Final Design

We designed a circuit that includes a voltage regulator, a LM317 Universal Adjustable Regulator, and a relay that will reduce the input voltage to the vehicle’s motor control board. The relay was implemented on the circuit board, but can not be activated. It was intended to allow the program to increase speed when the GPS detects the vehicle is moving slow, mainly when the vehicle is in the water this would occur. However, we determined that a test in water was not going to be performed; therefore the relay routine was not implemented. The speed reduction circuit is shown in Figure 6 below.

0

U 1

L M 3 1 7

3

1

2V I N

A D J

V O U T

C 10 .1 u F

L S 1

R E L A Y S P D T

35

412

0

Speed ChangeInput fromMicrocontroller

VehicleBatteryInput

R 1

1 7 k

0

Voltage Outputto MotorController Board

R 21 0 k

Figure 6: Vehicle Speed Reduction Circuit

Collision Avoidance

Preliminary Design

The purpose of the collision avoidance system is to allow the vehicle to move around obstacles that impede its progress. The vehicle could both run into the obstacle and move around them, or sense the oncoming object and make the vehicle move around the obstacles. We have this option due to the GPS’s ability to sense the forward motion of the vehicle and determine that it is not moving any farther and then have a routine that would move the vehicle in a coordinated manner that could possible miss the obstacle.

Problems Encountered

We found a sensor that would allow us to recognize an object that is in front of us, but the output would vary depending upon the distance the object is from the sensor. We needed to determine the output voltage from the sensor for a desired distance. With the proper output voltage of the sensor set at 1.2 volts, we needed a way to make an input to he microcontroller to either be a high or low. We determined that a comparator with a reference voltage of 1.2 volts would be adequate. After initial testing of the comparator circuit with the microcontroller we found that the input capacitors would not discharge. Therefore a resistor in parallel with the input capacitor would be required for proper operation.

Final Design

We began by researching for sensors that would notice objects that are more than 8 inches from the sensor. We found that the Sharp GP2D12 sensors would detect objects from 4 to 31 inches (10 to 80 cm) away from the sensor. The output of the sensor would increase as the object became closer. Therefore we determined that a comparator circuit, as shown in Figure 7, would allow us to detect objects that we about 10 inches from the vehicle. We also needed to detect objects directly in front of the vehicle and from either the left or right sides. We found that using three sensors would give us enough coverage to allow the vehicle to proceed without missing any medium size objects. We then proceeded with the programming of the microcontroller to allow these sensors to interrupt the system when an obstacle is detected. Then, depending upon which sensor is active, the program will turn the vehicle in the appropriate direction and move forward for a short amount of time. Then the interrupt routine will end and proceed with the main portion of the routine.

R 61 0 k

R 29 . 6 M

HI

Port D3Interrupt

-

+

U 2 A

L M 3 9 3

3

21

84

C 3. 0 1 u F

U 3

L M 3 1 7

3

1

2V I N

A D J

V O U T

HI

C 2. 0 1 u F

Port D4Interrupt

HI

0

HI

R 51 0 k

0

0

D 3

D 1 N 4 4 4 8

C 4. 1 u F

0

-

+

U 1 A

L M 3 9 3

3

21

84

D 2

D 1 N 4 4 4 8

RightSensorOutput

R 41 0 k

-

+

U 1 B

L M 3 9 3

5

67

R 19 . 6 M

R 71 0 k

R 39 . 6 M

0

Port D5Interrupt

6VBatteryInput

CenterSensorOutput

D 4

D 1 N 4 4 4 8

0

LeftSensorOutput

C 1. 0 1 u F

Figure 7: Collision Avoidance Circuit

GPS System

Preliminary Design

For finding out where the vehicle is and where it needs to go a global position system (GPS) is a perfect choice. Not only is it universal but it keeps its precision. This vehicle requires a compact GPS unit that is affordable, does not use a lot of power, and updates fast enough to work in real time. This is necessary because the vehicle is expected to travel efficiently, as if a human were operating the vehicle. The GPS we chose to use is the Garmin GPS 16-LVS. This device weighs 6.4 oz and can fit right on top of our vehicle. It also has brackets to mount it to the head of the vehicle. The electrical characteristics are also reasonable in that they will use less than 25% of the vehicles power and are shown below Table 2.

Table 2: GPS Electrical Characteristics

The acquisition times of the GPS are shown below in Table 3. While this is a bit sluggish, the receiver has such a wide range of accuracy that a more frequent update would be redundant.

Table 3: GPS Update Speeds

The GPS 16-LVS also has a UART port which can interface directly with the microcontroller board. Because the GPS needs to transmit lots of information about where it is it is best that such hard wiring be avoided.

Another huge convenience to this is that the details of timing and receiving data are already defined for the UART port. The work is only in setting up the devices to work with each other in software.

Other models considered were usually more expensive, too big, or too confusing to use. However one board by Zilog was designed specifically for a GPS, as shown below in Figure 8. This would have been extremely easy to implement. The disadvantages to this board would be the size and that it would be easily breakable. A picture is shown below. Note how much room the LCD screen and the keypad would have taken up.

Figure 8: Zilog Designed GPS Board

Compare this board with the board we decided to use for this project shown below in Figure 9. This board has everything needed with the disadvantage being in challenge to implement. This board also fits snugly inside our vehicle. These pictures are sized relative to each other.

Figure 9: Zilog Z8 Encore!® MCU

Problems Encountered

The GPS sends out its data on a simple comma delimited code scheme. We tested this on a computer and were able to see this information directly. The information sequence we are looking at is defined as shown below in Table 4.

Table 4: GPS Output Data

The main problem was in not being able to read anything from the GPS. We were struggling with this for some time. The GPS worked fine with a laptop computer and it was hooked up to the board exactly the same way. It turned out that the RS-232 connector was set up differently, the receive and transmit ports were reversed in the order Garmin determined to be correct.

In Figure 10 below, the latitude and longitude variables are filling up with values. These are the expected numbers for:

Latitude: 41 48.4280 Longitude: 072 15.1543

Figure 10: Latitude and Longitude Values

Final Design

The GPS was wired to the board as shown below in Figure 11.

Figure 11: GPS Wiring Diagram

It was then mounted to the front of the vehicle by making use of the brackets on the bottom of the device. The cord was then cut and a new RJ-45 connector was attached to shorten the 16 foot cable. The new shortened cord was then plugged in to the microcontroller using a RJ-45 to DB-9 adapter. Afterwards, the hardware was attached and the programming of the microcontroller began. The completed program can be seen in Appendix A.

Alternative Designs

LCD / Keypad User Interface Module

Preliminary Design

The purpose of the liquid crystal display (LCD) / keypad user interface module was to enable a user to input destination coordinates to the vehicle. The vehicle would then autonomously travel to the input destination coordinates. The LCD that was chosen for this application was a 16 x 4 LCD parallel display. This particular LCD had an onboard LSI HD4470 controller. The keypad that was chosen was a 16-button indoor/outdoor keypad. These components were enclosed in a plastic housing. Windows were cut in the plastic case to enable mounting of the components. The connections between the LCD / keypad and the microcontroller board were accomplished by the use of a DB-25 connector. The following Figure 12 is of the User Interface Module (UIM) containing the LCD and keypad.

LCD

DISP

LAY

U 1

2 1 0 7 6

1 41 31 21 11 09

67

12

5

34

8

D B 7D B 6D B 5D B 4D B 3D B 2

ED B 0

V s sV c c

R / W

V e eR S

D B 1

P 1

C O N N E C TO R D B 2 5

1 32 51 22 41 12 31 02 2

92 1

82 0

71 9

61 8

51 7

41 6

31 5

21 4

1

Keyp

ad

U 2

1 5 2 0 6 3

9

67

12

5

34

8

9

67

12

5

34

8

Figure 12: Schematic of User Interface Module

Problems Encountered

Approximately three weeks were spent working on the UIM. The software initialization routine was what took up most of that time. Without any success, this portion of the project was placed on the back burner until more important components of the project were successful.

Final Design

Without any success implementing the UIM, the module was deemed unimportant to the completion of the project. Focus was then returned to the implementation of the GPS with the vehicle.

Budget/Parts

This section shows the parts that were ordered and whether they were used or not. The overall project was well under the proposed budget of $1000. The detailed list of purchased parts is shown in Appendix B. Chart 1 shows the distribution of funds and how they were applied to this project.

Total Amount Used on Project 509.02

Excess 307.02

Total Amount Spent 183.96

Chart 1: Distribution of Funds

Timelines

The following timeline shows the progression of our project through the first semester:

ECE 290 Timeline

ID Task Name Start Finish DurationJan 2004 Feb 2004 Mar 2004 Apr 2004

25/1 1/2 8/2 15/2 22/2 29/2 7/3 14/3 21/3 28/3 4/4 11/4 18/4 25/4

1 2w2/2/20041/20/2004Formed Teams

2 1.5w2/10/20041/30/2004Project Statement

3 2w2/19/20042/6/2004Project Specifications

4 8w4/13/20042/18/2004Research Possible Components

5 11w5/4/20042/18/2004Design

6 10w5/14/20043/8/2004Purchase Components

7 5w5/5/20044/1/2004Project Broken Down Into Sections

8 .2w4/30/20044/30/2004290 Presentation

The following timeline shows the progression of our project through the second semester:

ECE 291 Timeline

ID Task Name Start Finish DurationSep 2004 Oct 2004 Nov 2004

29/8 5/9 12/9 19/9 26/9 3/10 10/10 17/10 24/10 31/10 7/11 14/11 21/11 28/11 5/12

1 15w12/10/20048/30/2004Build Sections

2 5.4w10/29/20049/23/2004Drive System

3 7w10/29/20049/13/2004Digital Compass

4 11.4w12/10/20049/23/2004GPS

5 13w12/10/20049/13/2004Debugging

6 .2w12/10/200412/10/2004291 Presentation

Conclusion

In final tests, the GPS Homing Robot would unreliably progress towards its preprogrammed destination. Since the vehicle relied so heavily on the 8-directional compass, it did not have that great of accuracy as far as heading direction. The vehicle was programmed to travel forwards for three heading directions to reduce abruptness of driving towards its destination. Say if the desired heading was north, the vehicle would travel forwards for north, northwest, and northeast.

Without hazard avoidance implemented, the vehicle could not avoid any hazards and the user would have to follow the vehicle closely and pick it up if collision with an obstacle was imminent. All of the hardware aspects of the project were completed well before the Senior Design Day deadline. The software bugs which needed to be worked out were the most time consuming of any problems encountered. Testing for the project was a difficult and lengthy process. Since the GPS only provided valid outputs while outdoors, the only way we could test and debug was through trial and error outdoors. Not only did it take upwards of 5 minutes for each test (GPS acquire time and setup), but the vehicle motor and compass batteries would run out of energy quickly. For the project to successfully fulfill all of its specifications, more software work would need to be done and tested.

Appendix A

#include "compass_main.h"#include "Timer.h"#include "Drive.h"#include <ez8.h>#include <math.h>#include <stdio.h>#include <stdlib.h>

unsigned char current_ms;static int timer_2sec;

main(){

int i,c;unsigned char direction,update_direction;

//destlat1 = 41.48428; //these are our default values//destlon1 = -72.151543; //change one to north, the debugger goes northDI();destlat1 = 41.48436; //these coordinates are middle of campusdestlon1 = -72.15148;

////////////// begin normalize destination ///////////////////while (destlat1<0)

{destlat1 = 360+destlat1;}while (destlon1<0)

{destlon1 = 360+destlon1;}

destlat1 = destlat1*(3.14159/180);destlon1 = destlon1*(3.14159/180);

////////////// end normalize destination ///////////////////

////////////// begin initializations /////////////////////init_delay();//init_portF_gpio();initialize_compass();EI();

////////////// end initializations ///////////////////

////////////// start mainloop ///////////////////while(1)

{timer_2sec ++;if (timer_2sec == 10000) {

update_direction = TRUE; // Indicate main routine to read sensortimer_2sec = 0;

}

if (update_direction == TRUE) //if it is time to update direction{

encode_direction((PEIN & READ_SENSOR),destlat1,destlon1);update_direction = FALSE;

for (i=0; i < 400; i++) // delay a bit, prevents spinning{

for (c=0; c < 3000; c++){;}

}

}

} ////////////// end mainloop ///////////////////

}/*void init_portF_gpio(void){ PFADDR = 0x01; // PA Data Dir = output: updated PFCTL = 0x04; // PA Out Ctrl = push-pull PFHDE = 0x00; // OUTPUT : updated PFOUT = 0x00;}

void delayms (unsigned int milliseconds){

current_ms = 0;T3CTL &= 0x7F; // Disable T3

T3H = 0x00 ; // Restart from 0T3L = 0x00 ;T3CTL |= 0x80 ; // Turn On T3

while (current_ms < milliseconds); // Delay loop

T3CTL &= 0x7F; // Stop T3}

void init_delay(void) // timer initialization module{ SET_VECTOR(TIMER3,isr_timer3);

T3H = 0x00; // Start value = 0T3L = 0x00;T3CPH = 0x48; // 1ms reload counterT3CPL = 0x00;T3CTL = 0x01; // Continuous mode; clock divide by 1IRQ2E0 &= 0x7F;IRQ2E1 |= 0x80; // T3 has lowest priority

}

#pragma interrupt // interupt service routinevoid isr_timer3(void){

current_ms++ ; // Increment count}

void isr_Timers(void){ int i;

int c;SET_VECTOR(P7AD,isr_Timers); //Setup the vector for PORTD2 interrupt ,HIGH priority

T0CTL &= 0x7F;T1CTL &= 0x7F;T2CTL &= 0x7F;

PFOUT = 0x01; delayms(5000);/*for(i=0;i<500;i++) // First loop to turn timer on{

for(c=0;c<6000;c++) // Second loop to turn timer on for 5 secs{

;//PEOUT |= 0x80; // Output to MUX to disable signal from timers

// and enable signal from hand held controller}

}T0CTL |= 0x80;T1CTL |= 0x80;T2CTL |= 0x80;

PFOUT = 0x00;}*/

////////////////////////////////////////////////////////

void initialize_compass(void){// Set up the hardware for reading the Sensor// Port B pins 0-3 are all inputs, Port B pin 4 for INTR generation

PEADDR = 0x01; // Select Data direction sub registerPECTL = 0x0F; // Lower Nibble Input; Higher Nibble Output

}

unsigned char encode_direction(unsigned char dir,double numlat,double numlon) //sent go direction{

unsigned char heading_direction;

getdir(destlat1,destlon1); //this fuction updates "course"; the nessasary direction to take

switch ((PEIN & READ_SENSOR))//encode direction

{case 0x03: // North East

diren = 1;break;

case 0x06: // North Westdiren = 7;

break;

case 0x07: // Northdiren = 0;

break;

case 0x09: // South Eastdiren = 3;

break;case 0x0B: // East

diren = 2;break;

case 0x0C: // South Westdiren = 5;

break;case 0x0D: // South

diren = 4;break;

case 0x0E: // Westdiren = 6;

break;case 0x00: case 0x01: case 0x02: case 0x04: case 0x05: case 0x08: case 0x0A: case 0x0F: default : //should

not get here, fix compass if sodiren = 8; //north is

defaultbreak;

}

// 7nw 0n 1ne// 6w 2e// 5sw 4s 3se //course(direction I need to go)//dir(direction I am going)//if -1<=course-dir<=1, forward//if 1<course-dir<=4, turn left//if 4<course-dir turn right//if 1<dir-course<4, turn right//if 4<dir-course turn left

////////////// begin see if there ///////////////////getdist(destlat1,destlon1); //feet awayif (dist < 50){

Stop();}

////////////// end see if there ///////////////////

////////////// begin 'necessary turn?' /////////////////// if (diren<8){

if ((-1<=course-diren)&&(course-diren<=1))Forward();

else if (((1<course-diren) && (course-diren<=4))||(4<diren-course)) Turn_Left();

elseTurn_Right();

}////////////// end 'necessary turn?' ///////////////////

}

///////////////////////////void getgps(void) //set up to return the north pole{

inituart0(); // initialize UARTstage = 0x00;

while(readit){ if(stage && new_byte){

////////////// start find correct starting sequence /////////////////// if( stage == 0x01 && x=='G')

stage = 2;

else if(stage == 0x02 && x=='P')stage = 3;

else if(stage == 0x03 && x=='R')stage = 4;

////////////// end find correct starting sequence ///////////////////

else if(stage == 0x04 && x!=',') //get to first commastage = 4;

else if(stage == 0x04 && x==',') //get past commastage = 5;

else if(stage == 0x05 && x!=',') { //utc datastage = 5;

// if (x=='V')// stage = 0x00; //reset if data not valid

//this functions to loop until signal

}else if(stage == 0x05 && x==','){ //pass comma

stage = 6;}

else if(stage == 0x06 && x!=',') //status datastage = 6;

else if(stage == 0x06 && x==','){ //pass commastage = 7;loopmode = 0; //[0] for sign

}

////////////// start get latitude string ///////////////////else if(stage == 0x07 && x!=','){ //latitude data

latch[loopmode] = x;loopmode++;}

else if(stage == 0x07 && x==','){ //pass commastage = 8;latch[loopmode]=0x00; //NULL last value

}////////////// end get latitude string ///////////////////

else if(stage == 0x08 && x!=',') //lat hemispherelatsig = x;

else if(stage == 0x08 && x==','){ //pass commastage = 9;loopmode = 0; //[0] for sign

}

////////////// start get longitude string ////////////////else if(stage == 0x09 && x!=','){ //longitude data

lonch[loopmode] = x;loopmode++;}

else if(stage == 0x09 && x==','){ //pass commastage = 10;lonch[loopmode]=0x00; //NULL last value

}////////////// end get longitude string ////////////////

else if(stage == 0x0A && x!=','){ //lon hemispherelonsig = x;readit = 0;}

else // stage = 0x00;

new_byte = 0x00;

} //end if statement} //end while loop

////////////// start string to double ////////////////ch = latch;numlatu = strtod(ch,0x00);ch = lonch;numlonu = strtod(ch,NULL);

////////////// end string to double ////////////////

////////////// start string fixings ////////////////if (latsig=='S' || latsig=='s')

numlatu = (-1)*(numlatu);if (lonsig=='W' || lonsig=='w')

numlonu = (-1)*(numlonu);////////////// end string fixings ////////////////

////////////// start 'here' manipulation ////////////////numlatu = numlatu/100;numlonu = numlonu/100;numlatu = floor(numlatu) + (numlatu-floor(numlatu))/.6; //decimal is in minutesnumlonu = floor(numlonu) + (numlonu-floor(numlonu))/.6;

while (numlatu<0) //normalizenumlatu = 360+numlatu;

while (numlonu<0)numlonu = 360+numlonu;

numlatu = numlatu*(3.14159/180); //put in radians

numlonu = numlonu*(3.14159/180);////////////// end 'here' manipulation ////////////////

}

int getdir(double latdes, double londes){

getgps(); //get 'here'

latc=numlatu; // range (-2pi,2pi)lonc=numlonu; // range (-2pi,2pi)

getd(latc,lonc,destlat1,destlon1); //update the global 'd'; a measure of distance

gettc();

////////////// start course find ////////////////tc1 = tc1*(180/3.14159); // turn radians to angle

while (tc1>=360){ //make sure angle is between 0 and 360tc1=tc1-360;}

while (tc1<0){tc1=tc1+360;}

if (tc1<23) { //ncourse1 = 0;}

else if (tc1<68) { //necourse1 = 1;}

else if (tc1<113) { //ecourse1 = 2;}

else if (tc1<158) { //secourse1 = 3;}

else if (tc1<203) { //scourse1 = 4;}

else if (tc1<248) { //swcourse1 = 5;}

else if (tc1<292) { //wcourse1 = 6;}

else if (tc1<338) { //nwcourse1 = 7;}

else { //ncourse1 = 0;}

course = course1;////////////// end course find ////////////////

return course1;}

double gettc(){//does the equivilent of the function below/* acos(

(sin(destlat1)-sin(latc)*cos(d)

)/(

sin(d)*cos(latc))

);*/

////////////// begin get tcl ////////////////if ((destlat1>=0)&&(destlat1<3.14159))

temp1 = sqrt(1/(1+(1/(tan(destlat1)*tan(destlat1)))));else

temp1 = -sqrt(1/(1+(1/(tan(destlat1)*tan(destlat1)))));

if ((latc>=0)&&(latc<3.14159))temp2 = sqrt(1/(1+(1/(tan(latc)*tan(latc)))));

elsetemp2 = -sqrt(1/(1+(1/(tan(latc)*tan(latc)))));

while (d>=6.28319){ //make sure angle is between 0 and 2pid=d-6.28319;}

while (d<0){d=d+6.28319;}

if ((d<1.5708)||(d>4.7124))temp2 = temp2*sqrt(1/(1+tan(d)*tan(d)));

else temp2 = temp2*(-sqrt(1/(1+tan(d)*tan(d))));

temp1 = temp1-temp2;

if ((d>=0)&&(d<3.14159))temp2 = sqrt(1/(1+(1/(tan(d)*tan(d)))));

else

temp2 = -sqrt(1/(1+(1/(tan(d)*tan(d)))));

if ((latc<1.5708)||(latc>4.7124))temp2 = temp2*sqrt(1/(1+tan(latc)*tan(latc)));

else temp2 = temp2*(-sqrt(1/(1+tan(latc)*tan(latc))));

if (((temp1-temp2)>-.0001)&&((temp1-temp2)<.0001)) //catch rounding errorstc1 = 0;

elsetc1 = acos(temp1/temp2);

////////////// end get tcl ////////////////

////////////// begin fixtcl ////////////////temp3=destlon1-lonc;while (temp3>=6.28319){ //make sure angle is between 0 and 2pi

temp3=temp3-6.28319;}while (temp3<0){

temp3=temp3+6.28319;}

if ((temp3>=0)&&(temp3<3.14159))tc1 = 2*3.14159-tc1; //tcl >0

elsetc1 = tc1; //tcl <0

////////////// end fixtcl ////////////////

return acos(temp1/temp2);

}

double cos(double cx){

while (cx>=6.28319){ //make sure angle is between 0 and 2picx=cx-6.28319;}

while (cx<0){cx=cx+6.28319;}

if ((cx<1.5708)||(cx>4.7124))return sqrt(1/(1+tan(cx)*tan(cx)));

else return (-sqrt(1/(1+tan(cx)*tan(cx))));

}

double sin(double cx){

while (cx>=6.28319){ //make sure angle is between 0 and 2picx=cx-6.28319;}

while (cx<0){cx=cx+6.28319;}

if ((cx>=0)&&(cx<3.14159))return sqrt(1/(1+(1/(tan(cx)*tan(cx)))));

elsereturn -sqrt(1/(1+(1/(tan(cx)*tan(cx)))));

}

double getd(double lat1d,double lon1d,double lat2d,double lon2d){

//this fuction does the equivilent of below function//acos(// sin(lat1d)*sin(lat2d)+cos(lat1d)*cos(lat2d)*cos(lon1d-lon2d)// );while (latc>=6.28319){ //make sure angle is between 0 and 2pi

latc=latc-6.28319;}while (latc<0){

latc=latc+6.28319;}while (lonc>=6.28319){ //make sure angle is between 0 and 2pi

lonc=lonc-6.28319;}while (lonc<0){

lonc=lonc+6.28319;}

if ((latc>=0)&&(latc<3.14159))temp1 = sqrt(1/(1+(1/(tan(latc)*tan(latc)))));

elsetemp1 = -sqrt(1/(1+(1/(tan(latc)*tan(latc)))));

if ((destlat1>=0)&&(destlat1<3.14159))temp1 = temp1*sqrt(1/(1+(1/(tan(destlat1)*tan(destlat1)))));

elsetemp1 = temp1*(-1)*sqrt(1/(1+(1/(tan(destlat1)*tan(destlat1)))));

if ((latc<1.5708)||(latc>4.7124))temp2 = sqrt(1/(1+tan(latc)*tan(latc)));

else temp2 = (-sqrt(1/(1+tan(latc)*tan(latc))));

if ((destlat1<1.5708)||(destlat1>4.7124))temp2 = temp2*sqrt(1/(1+tan(destlat1)*tan(destlat1)));

else temp2 = temp2*(-sqrt(1/(1+tan(destlat1)*tan(destlat1))));

temp3 = lonc - destlon1;while (temp3>=6.28319){ //make sure angle is between 0 and 2pi

temp3=temp3-6.28319;}while (temp3<0){

temp3=temp3+6.28319;}if ((temp3<1.5708)||(temp3>4.7124))

temp2 = temp2*sqrt(1/(1+tan(temp3)*tan(temp3)));else

temp2 = temp2*(-sqrt(1/(1+tan(temp3)*tan(temp3))));d=acos(temp1+temp2);//temp1 = (latc)(destlat1)(latc)(destlat1)(lonc - destlon1)//return acos(sin(lat1d)*sin(lat2d)+cos(lat1d)*cos(lat2d)*cos(lon1d-lon2d));return d;

}

int getdist(double latdes, double londes){

getd(latc,lonc,latdes,londes); //get ddist = floor(20884586*d); //convert d to feet 20884586return dist; //and put in 'dist': distance in feet

}

void inituart0(void){DI();PAADDR = ALT_FUN; // Configure for alternate functionPACTL |= PORTA_UART_TXD | PORTA_UART_RXD; // Enable UART0 TxD0/RxD0 pinsSET_VECTOR(UART0_RX, isr_uart_rec_0); // Update ISR TABLE (occurs during compiling not run time)SET_VECTOR(UART0_TX,isr_tr); // Update ISR TABLE (occurs during compiling not run time)

U0BRH = (char)(BRG0 >> 8); // Baud Rate HighU0BRL = (char)(BRG0 & 0xff); // Baud Rate Low

IRQ0ENH |= 0x18; // Highest PriorityIRQ0ENL |= 0x18; // Highest priority

U0CTL0 = UART_RXD_EN | UART_TXD_EN; // Transmit enable, Receive Enable, No Parity, 1 StopIRQ0 = 0x00;EI(); // Enable global interrupt}

#pragma interrupt // interupt service routinevoid isr_uart_rec_0(void){

x = U0D; // get valueif(stage==0x00){

stage = 0x01;

new_byte = 0x01;}

else new_byte = 0x01;

}

#pragma interruptvoid isr_tr(void){

}

/*************************************************//****************************************************************************** File: Drive.c* Description: This code will initiate timer 2 in PWM and for a certain amount* of ON/OFF timer that will control the AD8081. The AD8081 will* all the 820 and 1640 Hz signals to be combined. The output of * the AD8081 will be input into the vehicle decoder and drive the * vehicle in the appropriate direction.********************************************************************************/

#include <eZ8.h>#include "Timer.h"#include "Drive.h"

void Forward(void){

init_820Hz();init_1640Hz();

T2CTL &= 0x7F; // disable timer T2CTL |= 0x23; // set mode to PWM and prescalar to 16

T2H = 0x00; // Start value = 00 don't change T2L = 0x01; // Start value = 01 don't change T2PWMH = 0x4B; // change these 4 values for different duty cycle T2PWML = 0x67; // this routine is now for 50% duty cycle T2RH = 0x62; // The two registers T2CPH and T2CPL together T2RL = 0x6E; // dictate the period of the rectangular waveform // T2PWMH and T2PWML dictate the duty cycle of the // rectangular pulses

/* IRQPS |= 0x80; SET_VECTOR(P7AD, isr_Timers); // initialization of TIMER2 vector IRQ1ENL |= 0x80; // sets priority IRQ1ENL &= 0x08

IRQ1ENH |= 0x80; // sets priority IRQ1ENH |= 0x08*/

PCADDR = 0x02; // setting Port C7 as alternate function PCCTL |= 0x80; // setting Port C7 as alternate function T2CTL |= 0x80; // enable timer}

void Reverse(void){

init_820Hz();init_1640Hz();

T2CTL &= 0x7F; // disable timer T2CTL |= 0x23; // set mode to PWM and prescalar to 16

T2H = 0x00; // Start value = 01 don't change T2L = 0x01; // Start value = 01 don't change T2PWMH = 0x7C; // change these 4 values for different duty cycle T2PWML = 0xFF; // this routine is now for 50% duty cycle T2RH = 0x93; // The two registers T2CPH and T2CPL together T2RL = 0xED; // dictate the period of the rectangular waveform // T2PWMH and T2PWML dictate the duty cycle of the // rectangular pulses

/*IRQPS |= 0x80; SET_VECTOR(P7AD, isr_Timers); // initialization of TIMER2 vector IRQ1ENL |= 0x80; // sets priority IRQ1ENL &= 0x08 IRQ1ENH |= 0x80; // sets priority IRQ1ENH |= 0x08*/

PCADDR = 0x02; // setting Port C7 as alternate function PCCTL |= 0x80; // setting Port C7 as alternate function T2CTL |= 0x80; // enable timer

}

void Turn_Left(void){

int i;int c;init_820Hz();init_1640Hz();

T2CTL &= 0x7F; // disable timer T2CTL |= 0x23; // set mode to PWM and prescalar to 16

T2H = 0x00; // Start value = 01 don't change T2L = 0x01; // Start value = 01 don't change T2PWMH = 0x8C; // change these 4 values for different duty cycle

T2PWML = 0xC4; // this routine is now for 50% duty cycle T2RH = 0xA3; // The two registers T2CPH and T2CPL together T2RL = 0xAD; // dictate the period of the rectangular waveform // T2PWMH and T2PWML dictate the duty cycle of the // rectangular pulses

PCADDR = 0x02; // setting Port C7 as alternate function PCCTL |= 0x80; // setting Port C7 as alternate function

for(i=0;i<68;i++) // First loop to turn timer on{

for(c=0;c<3000;c++) // Second loop to turn timer on for .5 secs{

T2CTL |= 0x80; // enable timer}

}

T2CTL &= 0x7F; //disable timer 2T1CTL &= 0x7F; //disable timer 1T0CTL &= 0x7F; //disable timer 0

}

void Turn_Right(void){

int i;int c;init_820Hz();init_1640Hz();

T2CTL &= 0x7F; // disable timer T2CTL |= 0x23; // set mode to PWM and prescalar to 16

T2H = 0x00; // Start value = 01 don't change T2L = 0x01; // Start value = 01 don't change T2PWMH = 0x5D; // change these 4 values for different duty cycle T2PWML = 0x7C; // this routine is now for 50% duty cycle T2RH = 0x74; // The two registers T2CPH and T2CPL together T2RL = 0x6D; // dictate the period of the rectangular waveform // T2PWMH and T2PWML dictate the duty cycle of the // rectangular pulses

PCADDR = 0x02; // setting Port C7 as alternate function PCCTL |= 0x80; // setting Port C7 as alternate function

for(i=0;i<60;i++) // First loop to turn timer on{

for(c=0;c<3000;c++) // Second loop to turn timer on for .5 secs

{T2CTL |= 0x80; // enable timer

}}

T2CTL &= 0x7F; //disable timer 2T1CTL &= 0x7F; //disable timer 1T0CTL &= 0x7F; //disable timer 0

}

void Stop(void){

T0CTL &= 0x7F; // disable timer0T1CTL &= 0x7F; // disable timer1T2CTL &= 0x7F; // disable timer2

}

#include <ez8.h>#include "compass_main.h"

// Extern for LED/ Timer0 ISRunsigned char update_flag;extern unsigned char update_direction;//extern int digit;unsigned char digit;//int timer_2sec;

// Extern for UART/ I2C ISRs//extern char compass_control_register;//extern char compass_status_register;

// *************************************************//* This Timer ISR get called every 1ms. //**************************************************/*#pragma interruptvoid isr_timer3(void) {

static int timer_2sec;if(digit == 3){

// Port E6PEOUT &= 0xBF; // PEO &= 0xBF; For older ZDS

PEOUT |= 0x40;PEOUT &= 0xBF;

} else if (digit == 2){

// Port E5PEOUT &= 0xDF;PEOUT |= 0x20;PEOUT &= 0xDF;

} else if (digit == 1){

// Port G7PGOUT &= 0x7F;PGOUT |= 0x80;PGOUT &= 0x7F;

}else if (digit == 0){

// Port E7PEOUT &= 0x7F;PEOUT |= 0x80;PEOUT &= 0x7F;

}

update_flag = 1; // Indicate the main routine to update data

timer_2sec ++;if (timer_2sec == 2000) {

update_direction = TRUE; // Indicate main routine to read sensortimer_2sec = 0;

}}

/****************************************************************************** File: Timer.c* Description: This code will initiate the two timers which are constantly * used within the Drive System program to the proper settings.********************************************************************************/

#include <eZ8.h>#include "Timer.h"

void init_820Hz(void) // timer initialization module{ T0CTL &= 0x7F; // disable timer T0CTL |= 0x21; // set prescalar to 16 and mode to Continuous T0H = 0x00; // Start value = 01 T0L = 0x01; // Start value = 01 T0RH = 0x02; // The two registers TOCPH and TOCPL together T0RL = 0xBE; // dictate the period of the rectangular waveform /* IRQPS |= 0x80; SET_VECTOR(P7AD, isr_Timers); // initialization of TIMER2 vector IRQ1ENL &= 0x80; // sets priority IRQ1ENH |= 0x80; // sets priority*/

PAADDR = 0x02; // setting Port A1 as alternate function PACTL |= 0x02; // setting Port A1 as alternate function T0CTL |= 0x80; // enable timer}

void init_1640Hz(void) // timer initialization module{ T1CTL &= 0x7F; // disable timer T1CTL |= 0x21; // set prescalar to 16 and mode to continuous T1H = 0x00; // Start value = 01 T1L = 0x01; // Start value = 01 T1RH = 0x01; // The two registers TOCPH and TOCPL together T1RL = 0x5F; // dictate the period of the rectangular waveform /*IRQPS |= 0x80; SET_VECTOR(P7AD, isr_Timers); // initialization of TIMER2 vector IRQ1ENL &= 0x80; // sets priority IRQ1ENH |= 0x80; // sets priority*/

PCADDR = 0x02; // setting Port C1 as alternate function PCCTL = 0x82; // setting Port C1 as alternate function T1CTL |= 0x80; // enable timer}

#define FREQ 18432000 // 18.432MHz#define BAUD0 4800 // 9.6K baud for UART0

#define BRG0 FREQ/(BAUD0*16L) // NOTE THE TYPECAST HERE

#define UART0#define PORTA_UART_RXD 0x10#define PORTA_UART_TXD 0x20#define UART_TXD_EN 0x80#define UART_RXD_EN 0x40

#define DATA_DIR 0x01 // Data Direction#define ALT_FUN 0x02 // Alternate Function#define OUT_CTL 0x03

void inituart0(void);void getgps(void); //updates gpsdouble getlat(void); //returns latitudedouble getlon(void); //returns longitudeint getdir(double, double); //returns int direction, getdir(lat,lon)double gettc(void);double cos(double);double sin(double);double getd(double,double,double,double);int getdist(double, double);void isr_uart_rec_0(void);void isr_tr(void);

unsigned char x='0'; // UART receive data variableunsigned char stage=0,new_byte=0;double numlatu,numlonu;double latc,lonc,d,tc1,temp1,temp2,temp3,temp4;int course1;

char latch[12];char lonch[12];char latsig,lonsig;char *ch;

int loopmode;int readit=1;

double destlat1,destlon1;int diren, course;unsigned int dist;

void initialize_compass(void);

void read_sensor(void);void update_status(void);void select_intr_port(void);void isr_Timers(void);void init_portF_gpio(void);void init_delay(void);unsigned char encode_direction(unsigned char,double,double);void isr_timer3(void);void delayms (unsigned int milliseconds);

#define TRUE 1#define FALSE 0

#define UPDATE_INTERVAL 1000 // 1000 milliseconds or 1 second#define READ_SENSOR 0x0F#define SET_ERROR_BIT 0x08#define CHK_ERR_BIT_SET 0x08

/* FROM Z8ENCORE.H */ #define DATA_DIR 0x01 // Data Direction#define ALT_FUN 0x02 // Alternate Function#define OUT_CTL 0x03 // Output Control (Open-Drain)#define HDR_EN 0x04 // High Drive Enable#define SMRS_EN 0x05 // Stop Mode Recovery Source Enable

/********************************************************** File : Drive.h* Description : prototype functions*************************************************************************/

void Forward(void);void Reverse(void);void Turn_Left(void);void Turn_Right(void);void Stop(void);

/********************************************************** File : Timer.h* Description : prototype functions*************************************************************************/

void init_820Hz(void);void init_1640Hz(void);

void isr_Timers(void);

/*!\file uart.h * \brief Header file for Z8 Encore! UART Devices. * * This file contains header information required by UART driver * implementations for Z8 Encore! microcontrollers. * * This source file uses Doxygen-style comments to generate documentation * automatically. * * Copyright (C) 1999-2004 by ZiLOG, Inc. * All Rights Reserved. */#ifndef _UART_H_#define _UART_H_

#include <defines.h>#include <uartdefs.h>

/*! UART interrupt enable definitions used */#define IRQ_U0RXI (BYTE)0x10#define IRQ_U0TXI (BYTE)0x08

#ifdef EZ8_UART1#define IRQ_U1RXI (BYTE)0x40#define IRQ_U1TXI (BYTE)0x20#endif

#define REGFILEADDR_U0TXD 0xF40#define REGFILEADDR_U1TXD 0xF48

#define CLOCK_DIVISOR 16 //!< The default clock divisor used.

#define BAUD_9600 9600UL //!< Baud rate 9600.#define BAUD_19200 19200UL //!< Baud rate 19200.#define BAUD_38400 38400UL //!< Baud rate 38400.#define BAUD_57600 57600UL //!< Baud rate 57600.#define BAUD_115200 115200UL //!< Baud rate 115200.

#define DATABITS_8 8 //!< 8-bit single processor mode used with UARTs.#define DATABITS_9 9 //!< 9-bit multiprocessor mode used with UARTs (not supported in this release).

#define STOPBITS_1 1 //!< The number of stop bits used in the driver.#define STOPBITS_2 2

#define PAR_NOPARITY 0 //!< No parity.#define PAR_ODPARITY 3 //!< Odd parity.#define PAR_EVPARITY 2 //!< Even parity.

/*! * The error codes consists of both the errors reported by the UART device * (through status registers), and the errors that occur in the UART driver * software. */#define UART_ERR_NONE ((BYTE)0x00) //!< The error code for success.#define UART_ERR_KBHIT ((BYTE)0x01) //!< The error code for keyboard hit.#define UART_ERR_FRAMINGERR ((BYTE)0x02) //!< The error code returned when Framing error occurs in the character received.#define UART_ERR_PARITYERR ((BYTE)0x03) //!< The error code returned when Parity error occurs in the character received.#define UART_ERR_OVERRUNERR ((BYTE)0x04) //!< The error code returned when Overrun error occurs in the receive buffer register.#define UART_ERR_BREAKINDICATIONERR ((BYTE)0x05) //!< The error code returned when Break Indication Error occurs.#define UART_ERR_INVBAUDRATE ((BYTE)0x06) //!< The error code returned when baud rate specified is invalid.#define UART_ERR_INVPARITY ((BYTE)0x07) //!< The error code returned when parity option specified is invalid.#define UART_ERR_INVSTOPBITS ((BYTE)0x08) //!< The error code returned when stop bits specified is invalid.#define UART_ERR_INVDATABITS ((BYTE)0x09) //!< The error code returned when data bits per character specified is invalid.#define UART_ERR_BUSY ((BYTE)0x0A) //!< Definition for 'UART busy'.#define UART_ERR_NULLPOINTER ((BYTE)0x0B) //!< The error code returned when a null pointer is passed by user application.

#define UART_ERR_FAILURE ((BYTE)-1) //!< The error code for failures.

#define UART_ERR_USERBASE ((BYTE)0xF0) //!< The error code base value for user applications. Usable values 0xF0 to 0xFE

#define UART_IO_PENDING ((BYTE)1) //!< Definition for 'IO Pending'.#define UART_IO_COMPLETE ((BYTE)0) //!< Definition for 'IO complete'.

/*! * \brief The settings required to configure the UART driver. * * This structure will contain all the information required to * configure the UART device. This structure is used for opening * (initializing) the UART device as well as for re-configuring * the UART device. */typedef struct{ INT32 baudRate ; //!< The baudrate. BYTE stopBits ; //!< The number of stopbits. BYTE parity ; //!< The parity bit option.

} UART ;

typedef UINT8 BUFFSIZE_T ;

/*! * \brief The FIFO structure. * * This structure is used to hold information about the software * transmit/receive FIFO buffers implemented in interrupt mode. */typedef struct{

UCHAR *pBuffer ; //!< The FIFO bufferBUFFSIZE_T next_in ; //!< The in-pointerBUFFSIZE_T next_out ; //!< The out-pointerBUFFSIZE_T size ; //!< The FIFO buffer size

} FIFO ;

/*! Macro definitions */#define SETBRK_UART0() U0CTL0 |= UART_CTL0_SBRK#define RESETBRK_UART0() U0CTL0 &= ~UART_CTL0_SBRK

#define ENABLEPARITY_UART0() U0CTL0 |= UART_CTL0_PEN#define DISABLEPARITY_UART0() U0CTL0 &= ~UART_CTL0_PEN#define SETODDPARITY_UART0() U0CTL0 = (U0CTL0&~(UART_CTL0_PEN|UART_CTL0_PSEL)) | (PAR_ODPARITY<<3)#define SETEVENPARITY_UART0() U0CTL0 = (U0CTL0&~(UART_CTL0_PEN|UART_CTL0_PSEL)) | (PAR_EVPARITY<<3)

#ifdef EZ8_UART1#define SETBRK_UART1() U1CTL0 |= UART_CTL0_SBRK#define RESETBRK_UART1() U1CTL0 &= ~UART_CTL0_SBRK#define ENABLEPARITY_UART1() U1CTL0 |= UART_CTL0_PEN#define DISABLEPARITY_UART1() U1CTL0 &= ~UART_CTL0_PEN#define SETODDPARITY_UART1() U1CTL0 = (U1CTL0&~(UART_CTL0_PEN|UART_CTL0_PSEL)) | (PAR_ODPARITY<<3)#define SETEVENPARITY_UART1() U1CTL0 = (U1CTL0&~(UART_CTL0_PEN|UART_CTL0_PSEL)) | (PAR_EVPARITY<<3)#endif

/*! * \brief Receive a character. */INT getch( VOID ) ;

/*! * \brief Detect any key strokes in the keyboard connected to the default UART device. */UCHAR kbhit( VOID ) ;

/*! * \brief Transmit a character. */reentrant UCHAR putch( CHAR ) ;

/*! * \brief Initialize the UART0 device. */VOID open_UART0( VOID ) ;

/*! * \brief Configure the UART0 device. */UCHAR control_UART0( UART *pUART ) ;

/*! * \brief Set baudrate for UART0 device.

*/UCHAR setbaud_UART0( UINT32 baud ) ;

/*! * \brief Set Parity for the UART0 device. */UCHAR setparity_UART0( UCHAR parity ) ;

/*! * \brief Set Stopbits for the UART0 device. */UCHAR setstopbits_UART0( UCHAR stopbits ) ;

/*! * \brief Write data bytes to the UART0 device. */reentrant UCHAR write_UART0( CHAR *pData, UINT16 nbytes ) ;

/*! * \brief Return transmitter status for UART0. */UCHAR get_txstatus_UART0( VOID ) ;

/*! * \brief Read data bytes from the UART0 device. */UCHAR read_UART0( CHAR *pData, UINT16 *nbytes ) ;

/*! * \brief Return receiver status for UART0. */UCHAR get_rxstatus_UART0( VOID ) ;

/*! * \brief Flush receiver for UART0. */UCHAR flush_UART0( VOID ) ;

/*! * \brief Close the UART0 device. */VOID close_UART0( VOID ) ;

#ifdef EZ8_UART1/*!

* \brief Initialize the UART1 device. */VOID open_UART1( VOID ) ;

/*! * \brief Configure the UART1 device. */UCHAR control_UART1( UART *pUART ) ;

/*! * \brief Set baudrate for UART1 device. */UCHAR setbaud_UART1( UINT32 baud ) ;

/*! * \brief Set Parity for the UART1 device. */UCHAR setparity_UART1( UCHAR parity ) ;

/*! * \brief Set Stopbits for the UART1 device. */UCHAR setstopbits_UART1( UCHAR stopbits ) ;

/*! * \brief Write data bytes to the UART1 device. */reentrant UCHAR write_UART1( CHAR *pData, UINT16 nbytes ) ;

/*! * \brief Return transmitter status for UART1. */UCHAR get_txstatus_UART1( VOID ) ;

/*! * \brief Read data bytes from the UART1 device. */UCHAR read_UART1( CHAR *pData, UINT16 *nbytes ) ;

/*! * \brief Return receiver status for UART1. */UCHAR get_rxstatus_UART1( VOID ) ;

/*! * \brief Flush receiver for UART1.

*/UCHAR flush_UART1( VOID ) ;

/*! * \brief Close the UART1 device. */VOID close_UART1( VOID ) ;#endif /*! EZ8_UART1 */

#endif /*! _UART_H_ */

/*! End of File */

Appendix B

Mfr Part Number Qty Description Price

(ea.) Total Used Not Used

Newark                25B6465 1 Plastic Box 10.91 10.91 10.91    90F5336 4 8-pin IDC Connector 0.76 3.04   3.04  90F4263 4 8-pin Strain Relief Cover 0.98 3.92   3.92  90F5403 4 6-pin IDC Connector 0.37 1.48   1.48  90F5371 4 6-pin Dust Cover 0.28 1.12   1.12  23C1433 1 25-pin D-type Connector 6.16 6.16 6.16    91F5861 4 AD8180AR 2-1 Multiplexer 4.95 19.80 9.90 9.90  90F5302 4 Screwlock Kit 1.91 7.64 7.64    50F6398 1 25-pin D-type 6 ft. Cable 5.03 5.03 5.03    50F4687 2 9-volt Battery Cable 1.18 2.36 2.36    10N175 1 RJ45 Crimp Connectors, 10 ct. 17.34 17.34 17.34        Shipping and Sales Tax   50.92   50.92               Digikey                269-3249-ND 1 Zilog Microprocessor Educational Kit 39.95 39.95 39.95  

 296-12605-1-ND 5

Quad 2-1 Data Selector SN74AHC157 0.40 2.00 1.20 0.80

  A-25993-ND 100 Female Connectors, crimped 0.18 17.69 17.69    A-26967-ND 4 6-pin Connector,.1", 1RW 0.47 1.88 0.94 0.94      Shipping   17.00   17.00                              Jameco                103190 3 10-pin connector, .1", 1RW 0.42 1.26 0.84 0.42  152063 1 Keypad 16 Buttons, 4x4 14.95 14.95 14.95    210761 1 16x4 LCD Display 22.95 22.95 22.95    100765 50 Female Connectors, crimped 0.11 5.50 5.50                 Junun.org                GP2D12 7 Sharp Distanve Measuring Sensor 8.25 57.75 24.75 33.00    7 3-pin JST Cables for Sensor 1.10 7.70 3.30 4.40               Dinsmore                1490 2 Dinsmore 8-pos Digital Compass 13.00 26.00 26.00                 PNI                11862 1 V2Xe 2-Axis Compass Module 55.00 55.00   55.00               Garmin                010-00258-02 1 GPS16-LVS Unit 141.00 141.00 141.00                 

Misc.   1TYCO R/C Tigershark w/ Battery Pack 90.00 90.00 90.00  

    1 Fast Lane 6V Battery and Charger 26.95 26.95 26.95      1 Thread Rod, 3/16" 0.45 0.45 0.45  

    1 Dremel Collet 3.49 3.49 3.49      1 Electrical Tape 2.49 2.49 2.49      1 Dremel Cutting Kit 15.99 15.99 15.99      1 9-volt Battery, 2 ct. 6.49 6.49 6.49        Misc. Hardware 4.75 4.75 4.75        Sales Tax 2.02 2.02   2.02

Totals 692.98 509.02 183.96