Table of Contents

Abstract................................................................................................................................2 Objective..............................................................................................................................2 Design..................................................................................................................................2 Compass...........................................................................................................................2 Preliminary Design......................................................................................................2 Problems Encountered.................................................................................................3 Final Design.................................................................................................................3 Drive System....................................................................................................................4 Preliminary Design......................................................................................................4 Problems Encountered.................................................................................................5 Final Design.................................................................................................................7 Vehicle Speed Reduction.................................................................................................9 Preliminary Design......................................................................................................9 Problems Encountered.................................................................................................9 Final Design...............................................................................................................10 Collision Avoidance.......................................................................................................11 Preliminary Design....................................................................................................11 Problems Encountered...............................................................................................11 Final Design...............................................................................................................11 GPS System...................................................................................................................13 Preliminary Design....................................................................................................13 Problems Encountered...............................................................................................15 Final Design...............................................................................................................17 Alternative Designs............................................................................................................17 LCD / Keypad User Interface Module...........................................................................17 Preliminary Design....................................................................................................17 Problems Encountered...............................................................................................19 Final Design...............................................................................................................19 Budget/Parts.......................................................................................................................20 Timelines............................................................................................................................21 Conclusion.........................................................................................................................23 Appendix A........................................................................................................................24

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 (8directional). 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 System
Our 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 Design Our 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 frequencyshift 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 Encountered The 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.
+6V from Battery Pack

D 1 1

U 1A 2 C 1 .1 u F 3 2 + K IA 3 9 3 4 8 1

R 1 10K

Drive Signal From R/C Remote

1N 448

Interrupt Signal to Microcontroller

0 +3.3V Reference Voltage

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.

U 1

820 Hz Signal

2 5 11 14 3 6 10 13 1 15

1 2 3 4 1 2 3 4

A A A A B B B B

1 2 3 4

Y Y Y Y

4 7 9 12

Controller Generated Drive Signal

U 2 2 5 11 14 3 6 10 13 1 15 1 2 3 4 1 2 3 4 A A A A B B B B 1 2 3 4 Y Y Y Y 4 7 9 12

Drive Signal to Vehicle Drive Board

1.64 kHz Signal

A /B G 74AH C 157

A /B G 74AH C 157

PWM Signal

0

Drive Signal from R/C Remote

Interrupt Signal

0

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 Design The 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 Time Forward 22 13.414 ms Reverse 40 24.39 ms Turn_Left 58 35.366 ms Turn_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:

( TOP )( SC ) = RV
P 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: ECT ×100 = HTR ICT Once the high time ratio is found, we can find the PWMV by using the following equation:   HTR   PWMV = RV 1 −       100   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 Design Once 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 Encountered Our 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

Speed Change Input from Microcontroller

LS1 2 1 3

4 5 U 1 3 1 C 1 0 .1 u F V IN AD J LM317 R 1 VO U T 2

Vehicle Battery Input

R ELAY SPD T

Voltage Output to Motor Controller Board

17k R 2 10k

0

Figure 6: Vehicle Speed Reduction Circuit

0

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.

H I

Left Sensor Output

D 2 D 1N 4448 R 1 9 .6 M C 1 .0 1 u F

U 1A 8 3 2 + 4 1 LM 393

R 5 10k

Port D3 Interrupt

0 0

H I

Center Sensor Output

D 3 D 1N 4448 R 2 9 .6 M C 2 .0 1 u F

U 1B 5 6 + 7 LM 393

R 6 10k

Port D4 Interrupt

H I

0

Right Sensor Output

D 4 D 1N 4448 R 3 9 .6 M C 3 .0 1 u F

U 2A 8 3 2 + 4 1 LM 393

R 7 10k

Port D5 Interrupt

0 0

6V Battery Input

U 3 3 C 4 .1 u F 1 V IN AD J LM 317 R 4 10k VO U T 2

H I

0

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: Longitude: 41 48.4280 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.

U 1

Vss Vcc Vee R S R /W E D B0 D B1 D B2 D B3 D B4 D B5 D B6 D B7

1 2 3 4 5 6 7 8 9 1 1 1 1 1

LCD DISPLAY

P1 1 14 2 15 3 16 4 17 5 18 6 19 7 20 8 21 9 22 10 23 11 24 12 25 13 C O N N E C TO R D B 25

0 1 2 3 4

21076

U 2

1 2 3 4 5 6 7 8 9

1 2 3 4 5 6 7 8 9

152063

Keypad

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.

Excess 307.02

Total Amount Used on Project 509.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:

Jan 2004

Feb 2004 1/2 8/2 15/2 22/2 29/2

Mar 2004 7/3 14/3 21/3 28/3 4/4

Apr 2004 11/4 18/4 25/4

ID 1 2 3 4 5 6 7 8

Task Name Formed Teams Project Statement Project Specifications Research Possible Components Design Purchase Components Project Broken Down Into Sections 290 Presentation

Start 1/20/2004 1/30/2004 2/6/2004 2/18/2004 2/18/2004 3/8/2004 4/1/2004 4/30/2004

Finish 2/2/2004 2/10/2004 2/19/2004 4/13/2004 5/4/2004 5/14/2004 5/5/2004 4/30/2004

Duration
25/1

2w 1.5w 2w 8w 11w 10w 5w .2w

ECE 290 Timeline

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

Sep 2004

Oct 2004

Nov 2004

ID

Task Name

Start 8/30/2004 9/23/2004 9/13/2004 9/23/2004 9/13/2004 12/10/2004

Finish 12/10/2004 10/29/2004 10/29/2004 12/10/2004 12/10/2004 12/10/2004

Duration
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 Build Sections 2 Drive System 3 Digital Compass 4 GPS 5 Debugging 6 291 Presentation

15w 5.4w 7w 11.4w 13w .2w

ECE 291 Timeline

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; //destlon1 = -72.151543; DI(); destlat1 = 41.48436; destlon1 = -72.15148; //these are our default values //change one to north, the debugger goes north //these coordinates are middle of campus

////////////// 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; timer_2sec = 0; } if (update_direction == TRUE) {

// Indicate main routine to read sensor

//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; T3H = 0x00 ; T3L = 0x00 ; T3CTL |= 0x80 ;

// Disable T3 // Restart from 0 // Turn On T3

while (current_ms < milliseconds) ; T3CTL &= 0x7F; }

// Delay loop // Stop T3

void init_delay(void) // timer initialization module { SET_VECTOR(TIMER3,isr_timer3); T3H = 0x00; // Start value = 0 T3L = 0x00; T3CPH = 0x48; // 1ms reload counter T3CPL = 0x00; T3CTL = 0x01; // Continuous mode; clock divide by 1 IRQ2E0 &= 0x7F; IRQ2E1 |= 0x80; // T3 has lowest priority } #pragma interrupt void isr_timer3(void) { current_ms++ ; } // interupt service routine // 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++) { for(c=0;c<6000;c++) { ; //PEOUT |= 0x80; } } T0CTL |= 0x80; T1CTL |= 0x80; T2CTL |= 0x80;

// First loop to turn timer on // Second loop to turn timer on for 5 secs // Output to MUX to disable signal from timers // and enable signal from hand held controller

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 register PECTL = 0x0F; // Lower Nibble Input; Higher Nibble Output } unsigned char encode_direction(unsigned char dir,double numlat,double numlon) direction { unsigned char heading_direction; getdir(destlat1,destlon1); //sent go

//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 West diren = 7; break; case 0x07: // North diren = 0; break;

case 0x09: // South East diren = 3; break; case 0x0B: // East diren = 2; break; case 0x0C: // South West diren = 5; break; case 0x0D: // South diren = 4; break; case 0x0E: // West diren = 6; break; case 0x00: case 0x01: case 0x02: case 0x04: case 0x05: case 0x08: case 0x0A: case 0x0F: default : not get here, fix compass if so diren = 8; default break; } // 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); if (dist < 50) { Stop(); } ////////////// end see if there /////////////////// //feet away

//should //north is

////////////// 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(); else Turn_Right(); } ////////////// end 'necessary turn?' /////////////////// }

/////////////////////////// void getgps(void) { inituart0(); stage = 0x00;

//set up to return the north pole // initialize UART

while(readit){ if(stage && new_byte){ ////////////// start find correct starting sequence /////////////////// if( stage == 0x01 && x=='G') stage = 2; else if(stage else if(stage == 0x02 && stage = 3; x=='P')

== 0x03 && x=='R') stage = 4; ////////////// end find correct starting sequence /////////////////// else if(stage == 0x04 && stage = 4; x!=',') //get to first comma

else if(stage else if(stage // // to loop until signal else if(stage

== 0x04 && stage = 5;

x==',')

//get past comma //utc data //reset if data not valid //this functions //pass comma

== 0x05 && x!=',') { stage = 5; if (x=='V') stage = 0x00; } == 0x05 && stage = 6; == 0x06 && stage = 6; == 0x06 && stage = 7; loopmode = 0;

x==','){ }

else if(stage else if(stage

x!=',') x==','){ }

//status data //pass comma //[0] for sign

////////////// start get latitude string /////////////////// else if(stage == 0x07 && x!=','){ //latitude data latch[loopmode] = x; loopmode++; } == 0x07 && x==','){ //pass comma stage = 8; latch[loopmode]=0x00; } ////////////// end get latitude string /////////////////// else if(stage else if(stage == 0x08 && latsig = x; == 0x08 && stage = 9; loopmode = 0; x!=',') x==','){ } ////////////// start get longitude string //////////////// else if(stage == 0x09 && x!=','){ //longitude data lonch[loopmode] = x; loopmode++; } else if(stage

//NULL last value

//lat hemisphere //pass comma //[0] for sign

== 0x09 && x==','){ //pass comma stage = 10; lonch[loopmode]=0x00; } ////////////// end get longitude string //////////////// else if(stage == 0x0A && lonsig = x; readit = 0; } = 0x00; = 0x00; x!=','){

else if(stage

//NULL last value

//lon hemisphere

else stage new_byte } }

//

//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 minutes numlonu = floor(numlonu) + (numlonu-floor(numlonu))/.6; while (numlatu<0) numlatu = 360+numlatu; while (numlonu<0) numlonu = 360+numlonu; numlatu = numlatu*(3.14159/180); //put in radians //normalize

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

} int getdir(double latdes, double londes) { getgps(); latc=numlatu; lonc=numlonu; getd(latc,lonc,destlat1,destlon1); gettc(); ////////////// start course find //////////////// tc1 = tc1*(180/3.14159); while (tc1>=360){ tc1=tc1-360;} while (tc1<0){ tc1=tc1+360;} if (tc1<23) { { { { { { { { //ne course1 = 1;} else if (tc1<113) else if (tc1<158) else if (tc1<203) else if (tc1<248) else if (tc1<292) else if (tc1<338) else //e course1 = 2;} //se course1 = 3;} //s course1 = 4;} //sw course1 = 5;} //w course1 = 6;} //nw { course1 = 7;} //n course1 = 0;} //n course1 = 0;} // turn radians to angle //make sure angle is between 0 and 360 //get 'here' // range (-2pi,2pi) // range (-2pi,2pi) //update the global 'd'; a measure of distance

else if (tc1<68)

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))))); else temp2 = -sqrt(1/(1+(1/(tan(latc)*tan(latc))))); while (d>=6.28319){ d=d-6.28319;} while (d<0){ d=d+6.28319;} //make sure angle is between 0 and 2pi

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)) tc1 = 0; else tc1 = acos(temp1/temp2); ////////////// end get tcl //////////////// ////////////// begin fixtcl //////////////// temp3=destlon1-lonc; while (temp3>=6.28319){ temp3=temp3-6.28319;} while (temp3<0){ temp3=temp3+6.28319;} if ((temp3>=0)&&(temp3<3.14159)) tc1 = 2*3.14159-tc1; //tcl >0 else tc1 = tc1; //tcl <0 ////////////// end fixtcl //////////////// return acos(temp1/temp2); } double cos(double cx) { while (cx>=6.28319){ cx=cx-6.28319;} while (cx<0){ cx=cx+6.28319;} //make sure angle is between 0 and 2pi //catch rounding errors

//make sure angle is between 0 and 2pi

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){ cx=cx-6.28319;} while (cx<0){ cx=cx+6.28319;}

//make sure angle is between 0 and 2pi

if ((cx>=0)&&(cx<3.14159)) return sqrt(1/(1+(1/(tan(cx)*tan(cx))))); else return -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))))); else temp1 = -sqrt(1/(1+(1/(tan(latc)*tan(latc))))); if ((destlat1>=0)&&(destlat1<3.14159)) temp1 = temp1*sqrt(1/(1+(1/(tan(destlat1)*tan(destlat1))))); else temp1 = 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 d dist = floor(20884586*d); //convert d to feet 20884586 return dist; //and put in 'dist': distance in feet } void inituart0(void) { DI(); PAADDR = ALT_FUN; // Configure for alternate function PACTL |= PORTA_UART_TXD | PORTA_UART_RXD; // Enable UART0 TxD0/RxD0 pins SET_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); U0BRL = (char)(BRG0 & 0xff); IRQ0ENH |= 0x18; IRQ0ENL |= 0x18; // Baud Rate High // Baud Rate Low

// Highest Priority // Highest priority // Transmit enable, Receive Enable, No Parity, 1 Stop

U0CTL0 = UART_RXD_EN | UART_TXD_EN; IRQ0 = 0x00; EI(); // Enable global interrupt } #pragma interrupt // interupt service routine void isr_uart_rec_0(void) { x = U0D; // get value if(stage==0x00){ stage = 0x01;

new_byte = 0x01; } else new_byte = 0x01; } #pragma interrupt void 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; PCADDR = 0x02; PCCTL |= 0x80; T2CTL |= 0x80; } void Reverse(void) { init_820Hz(); init_1640Hz();

// sets priority IRQ1ENH |= 0x08*/ // setting Port C7 as alternate function // setting Port C7 as alternate function // enable timer

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; PCCTL |= 0x80; T2CTL |= 0x80; } 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 // setting Port C7 as alternate function // setting Port C7 as alternate function // enable timer

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; PCCTL |= 0x80; // setting Port C7 as alternate function // setting Port C7 as alternate function // First loop to turn timer on // Second loop to turn timer on for .5 secs // enable timer

for(i=0;i<68;i++) { for(c=0;c<3000;c++) { T2CTL |= 0x80; } } T2CTL &= 0x7F; T1CTL &= 0x7F; T0CTL &= 0x7F; } void Turn_Right(void) { int i; int c; init_820Hz(); init_1640Hz();

//disable timer 2 //disable timer 1 //disable timer 0

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; PCCTL |= 0x80; // setting Port C7 as alternate function // setting Port C7 as alternate function // First loop to turn timer on // Second loop to turn timer on for .5 secs

for(i=0;i<60;i++) { for(c=0;c<3000;c++)

{ T2CTL |= 0x80; } } T2CTL &= 0x7F; T1CTL &= 0x7F; T0CTL &= 0x7F; } //disable timer 2 //disable timer 1 //disable timer 0 // enable timer

void Stop(void) { T0CTL &= 0x7F; T1CTL &= 0x7F; T2CTL &= 0x7F; } #include <ez8.h> #include "compass_main.h"

// disable timer0 // disable timer1 // disable timer2

// Extern for LED/ Timer0 ISR unsigned 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 interrupt void isr_timer3(void) { static int timer_2sec; if(digit == 3) { // Port E6 PEOUT &= 0xBF; // PEO &= 0xBF; For older ZDS

PEOUT |= 0x40; PEOUT &= 0xBF; } else if (digit == 2) { // Port E5 PEOUT &= 0xDF; PEOUT |= 0x20; PEOUT &= 0xDF; } else if (digit == 1) { // Port G7 PGOUT &= 0x7F; PGOUT |= 0x80; PGOUT &= 0x7F; } else if (digit == 0) { // Port E7 PEOUT &= 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 sensor timer_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) { T0CTL &= 0x7F; T0CTL |= 0x21; T0H = 0x00; T0L = 0x01; T0RH = 0x02; T0RL = 0xBE;

// timer initialization module // disable timer // set prescalar to 16 and mode to Continuous // Start value = 01 // Start value = 01 // The two registers TOCPH and TOCPL together // 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; PACTL |= 0x02; T0CTL |= 0x80; } void init_1640Hz(void) { T1CTL &= 0x7F; T1CTL |= 0x21; T1H = 0x00; T1L = 0x01; T1RH = 0x01; T1RL = 0x5F; // timer initialization module // disable timer // set prescalar to 16 and mode to continuous // Start value = 01 // Start value = 01 // The two registers TOCPH and TOCPL together // dictate the period of the rectangular waveform // setting Port A1 as alternate function // setting Port A1 as alternate function // enable timer

/*IRQPS |= 0x80; SET_VECTOR(P7AD, isr_Timers); // initialization of TIMER2 vector IRQ1ENL &= 0x80; // sets priority IRQ1ENH |= 0x80; // sets priority*/ PCADDR = 0x02; PCCTL = 0x82; T1CTL |= 0x80; } // setting Port C1 as alternate function // setting Port C1 as alternate function // enable timer

#define FREQ 18432000 #define BAUD0 4800

// 18.432MHz // 9.6K baud for UART0

#define BRG0 FREQ/(BAUD0*16L) // NOTE THE TYPECAST HERE #define UART0 #define PORTA_UART_RXD #define PORTA_UART_TXD #define UART_TXD_EN #define UART_RXD_EN #define DATA_DIR 0x01 #define ALT_FUN 0x02 #define OUT_CTL 0x03 0x10 0x20 0x80 0x40

// Data Direction // Alternate Function

void inituart0(void); void getgps(void); //updates gps double getlat(void); //returns latitude double getlon(void); //returns longitude int 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 variable unsigned 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 #define ALT_FUN 0x02 #define OUT_CTL 0x03 #define HDR_EN 0x04 #define SMRS_EN 0x05 // Data Direction // Alternate Function // Output Control (Open-Drain) // High Drive Enable // 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 #define IRQ_U0TXI #ifdef EZ8_UART1 #define IRQ_U1RXI #define IRQ_U1TXI #endif #define REGFILEADDR_U0TXD #define REGFILEADDR_U1TXD #define CLOCK_DIVISOR divisor used. #define BAUD_9600 #define BAUD_19200 19200. #define BAUD_38400 38400. #define BAUD_57600 57600. #define BAUD_115200

(BYTE)0x10 (BYTE)0x08 (BYTE)0x40 (BYTE)0x20 0xF40 0xF48 16 9600UL 19200UL 38400UL 57600UL 115200UL //!< The default clock //!< Baud rate 9600. //!< Baud rate //!< Baud rate //!< Baud rate //!< Baud rate 115200.

#define DATABITS_8 8 processor mode used with UARTs. #define DATABITS_9 9 multiprocessor mode used with UARTs (not supported in this release). #define STOPBITS_1 bits used in the driver. #define STOPBITS_2 #define PAR_NOPARITY #define PAR_ODPARITY #define PAR_EVPARITY 1 2 0 3 2

//!< 8-bit single //!< 9-bit //!< The number of stop

//!< No parity. //!< Odd parity. //!< 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 value for user applications. Usable values 0xF0 to 0xFE #define UART_IO_PENDING Pending'. #define UART_IO_COMPLETE complete'.

((BYTE)0xF0)

//!< The error code base

((BYTE)1) ((BYTE)0)

//!< Definition for 'IO //!< Definition for 'IO

/*! * \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 ; BUFFSIZE_T next_in ; BUFFSIZE_T next_out ; BUFFSIZE_T size ; } FIFO ; /*! Macro definitions */ #define SETBRK_UART0() #define RESETBRK_UART0() U0CTL0 |= UART_CTL0_SBRK U0CTL0 &= ~UART_CTL0_SBRK

//!< The FIFO buffer //!< The in-pointer //!< The out-pointer //!< The FIFO buffer size

#define ENABLEPARITY_UART0() #define DISABLEPARITY_UART0() #define SETODDPARITY_UART0() UART_CTL0_PSEL)) | (PAR_ODPARITY<<3) #define SETEVENPARITY_UART0() UART_CTL0_PSEL)) | (PAR_EVPARITY<<3) #ifdef EZ8_UART1 #define SETBRK_UART1() #define RESETBRK_UART1() #define ENABLEPARITY_UART1() #define DISABLEPARITY_UART1() #define SETODDPARITY_UART1() UART_CTL0_PSEL)) | (PAR_ODPARITY<<3) #define SETEVENPARITY_UART1() UART_CTL0_PSEL)) | (PAR_EVPARITY<<3) #endif /*! * \brief Receive a character. */ INT getch( VOID ) ;

U0CTL0 |= UART_CTL0_PEN U0CTL0 &= ~UART_CTL0_PEN U0CTL0 = (U0CTL0&~(UART_CTL0_PEN| U0CTL0 = (U0CTL0&~(UART_CTL0_PEN|

U1CTL0 |= UART_CTL0_SBRK U1CTL0 &= ~UART_CTL0_SBRK U1CTL0 |= UART_CTL0_PEN U1CTL0 &= ~UART_CTL0_PEN U1CTL0 = (U1CTL0&~(UART_CTL0_PEN| U1CTL0 = (U1CTL0&~(UART_CTL0_PEN|

/*! * \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
Newark 25B6465 90F5336 90F4263 90F5403 90F5371 23C1433 91F5861 90F5302 50F6398 50F4687 10N175 1 4 4 4 4 1 4 4 1 2 1 Plastic Box 8-pin IDC Connector 8-pin Strain Relief Cover 6-pin IDC Connector 6-pin Dust Cover 25-pin D-type Connector AD8180AR 2-1 Multiplexer Screwlock Kit 25-pin D-type 6 ft. Cable 9-volt Battery Cable RJ45 Crimp Connectors, 10 ct. Shipping and Sales Tax 10.91 0.76 0.98 0.37 0.28 6.16 4.95 1.91 5.03 1.18 17.34 10.91 3.04 3.92 1.48 1.12 6.16 19.80 7.64 5.03 2.36 17.34 50.92 10.91 3.04 3.92 1.48 1.12 6.16 9.90 7.64 5.03 2.36 17.34 9.90

Part Number

Qty

Description

Price (ea.)

Total

Used

Not Used

50.92

Digikey 269-3249-ND 296-12605-1ND A-25993-ND A-26967-ND 1 5 100 4 Zilog Microprocessor Educational Kit Quad 2-1 Data Selector SN74AHC157 Female Connectors, crimped 6-pin Connector,.1", 1RW Shipping 39.95 0.40 0.18 0.47 39.95 2.00 17.69 1.88 17.00 39.95 1.20 17.69 0.94 0.80 0.94 17.00

Jameco 103190 152063 210761 100765 Junun.org GP2D12 7 7 Sharp Distanve Measuring Sensor 3-pin JST Cables for Sensor 8.25 1.10 57.75 7.70 24.75 3.30 33.00 4.40 3 1 1 50 10-pin connector, .1", 1RW Keypad 16 Buttons, 4x4 16x4 LCD Display Female Connectors, crimped 0.42 14.95 22.95 0.11 1.26 14.95 22.95 5.50 0.84 14.95 22.95 5.50 0.42

Dinsmore 1490 PNI 11862 Garmin 010-00258-02 1 GPS16-LVS Unit TYCO R/C Tigershark w/ Battery Pack Fast Lane 6V Battery and Charger Thread Rod, 3/16" 141.00 141.00 141.00 1 V2Xe 2-Axis Compass Module 55.00 55.00 55.00 2 Dinsmore 8-pos Digital Compass 13.00 26.00 26.00

Misc.

1 1 1

90.00 26.95 0.45

90.00 26.95 0.45

90.00 26.95 0.45

1 1 1 1

Dremel Collet Electrical Tape Dremel Cutting Kit 9-volt Battery, 2 ct. Misc. Hardware Sales Tax

3.49 2.49 15.99 6.49 4.75 2.02

3.49 2.49 15.99 6.49 4.75 2.02

3.49 2.49 15.99 6.49 4.75 2.02

Totals

692.98 509.02

183.96

Sign up to vote on this title
UsefulNot useful