Akash Kukadiya Graduate Report Fall2012
Akash Kukadiya Graduate Report Fall2012
By
December 2012
This graduate project of Akash Pankajkumar Kukadiya is approved:
------------------------------------------------------------------ --------------------
Porf. Xiaojun Geng Date
------------------------------------------------------------------ --------------------
Prof. Ichiro Hashimoto Date
------------------------------------------------------------------ ---------------------
Prof. Ronald Mehler, chair Date
I would like to thank Prof. Ronald Mehler as the graduate project advisor. Prof.
Mehler helped me to understand the real challenges to address the problem. Not only did
project development and has been support for my financial aid. I also would like to thank
Prof. Xiaojun (Ashley) Geng and Prof. Ichiro Hashimoto as the committee members for
this project. Apart from that, I thank Prof. Ali Amini (ECE Dept. chair) for the extension
of my graduate term to complete my project and Prof. Ramin Roosta for providing
My special thanks to Robert Santogrossi for providing me with all free major
Lastly, I want to thank my parents for giving their unconditional support and
iii
TABLE OF CONTENTS
SIGNATURE PAGE……………………………………………………………………ii
ACKNOWLEDGEMENT………………………………………………………………iii
LIST OF FIGURES……………………………………………………………………...v
LIST OF TABLES………………………………………………………………………vii
ABSTRACT…………………………………………………………………………….viii
CHAPTER 1 INTRODUCTION……………………………………………………….1
CONCLUSION…………………………………………………………………………31
REFERANCES…………………………………………………………………………32
APPENDIX……………………………………………………………………………..33
iv
LIST OF FIGURES
Figure 2.4 System component diagram (“Design of autonomous indoor localization system” by
Robert Santogrossi)………………………………………………………………………………6
v
Figure 3.8 Spartan 3e FPGA board with two Xbee pro RF modules connected through RS-232
ports……………………………………………………………………………………………..18
Figure 4.2 Experiment set up to find received power for variable distance…………………….22
Figure 4.5 Black colored area from two RF stations shows 3m blind area……………………..24
vi
LIST OF TABLES
vii
ABSRTACT
By
The Autonomous indoor localization system is a sub system of the project that
(IARC), 6th mission. The system helps to locate the flying vehicle in a given indoor
situation. With help from the location data, the moving vehicle can easily navigate and
determine the next desired direction to achieve the goal in the competition. The challenge
of navigation becomes more complex due to several competition criteria. Among them,
one of the criteria is that the interior arrangement of the building is variable. So the
number of obstacles, the materials used as obstacles and the navigation path are subject to
change. Moreover, the navigation system cannot use a GPS system; instead, two wireless
posts are allowed to help the flying vehicle. To address such a problem, several
techniques are workable like calculating the time differential and measuring signal
strength between wireless devices. This project uses signal strength analysis to figure out
the distance between the flying vehicle and the RF station to calculate location into two
dimensions.
viii
CHAPTER 1
INTRODUCTION
The Autonomous Indoor Localization System was developed for utilization in the
International Aerial Robotics Competition (IARC), as a 6th mission to take place in late
International (AUVSI). This competition takes place every year, and this competition is
now in its 20th year. The objective of this competition is as follows. A fully autonomous
vehicle must be able to maneuver inside a fixed confined area arranged with a variable
number and nature of obstacles like walls and furniture. The vehicle must have
computation capability to maneuver inside the built structure either fully on the vehicle
itself or through communication with remote computers without any human intervention.
bidirectional. It has been observed that the built structure is generally made from
materials like plastic or paper. It strictly has one square meter entrance and one meter
wide inter-room passages. In the 6th mission, the vehicle must be able to maneuver and
steal an object (flash drive) and replace it with a similar object in order to delay the
detection of the operation. In order to maneuver, the vehicle can communicate with two
RF stations pre-posted inside the given confined area and must not use GPS to locate the
vehicle as per the competition rule guidelines. This paper gives a functional description
To solve the problem, lets breakdown it in to two simple steps. First, the
computation logic should be able to determine the current location of the moving vehicle
1
inside the built structure. Second, these data should be feedback to help the vehicle to
decide the next possible direction to follow without collision with any structure and find
the desired object. This paper discusses the first part explained here which require both
hardware and software components. Moreover, this paper is in continuation to the system
the college of engineering and computer science, California State University Northridge.
This paper uses a different approach which is described in next chapter of this paper.
2
CHAPTER 2
As per the IARC rules, the competition venue dimensions are crucial to build an
autonomous localization system on the vehicle and determine where the two remote RF
stations need to be placed. Figure 2.1 describes the fixed confined arena.
As we can see, the arena is 33m x 18m. This area is covered by the 3 meter placement
space, which is the initial placement area for the vehicle. To enter the arena a minimum
of one square meter and maximum of 2.44m window will be placed. Figure 2.2 gives a
more clear idea of an actual arena. The walls of the cubes could be made of Styrofoam
insulation, a thin sheathing material or a heavy paper. These materials will be used to
3
build the 2.44m cubes.
Here, cube arrangement is variable, but the outer dimensions remain the same. Having
this information, we can determine the overall map in which the two RF stations can be
mounted.
To calculate the distance between the vehicle and the RF station, two approaches
have been proposed. The first is to send signals from the vehicle to the RF stations and
send them back, counting the time difference. This approach has been carried out in the
earlier experiment and has a fundamental flaw. Since the area is small to navigate, time
differential is proportionally small between the vehicle and the RF post. In this situation,
we cannot expect reasonable resolution of the system. To calculate the perfect time
differential, the clocks of two RF stations should be synchronous to each other. Also, the
4
clock of the processor (mounted on the vehicle) must be very high. The second is to send
RF signals from the vehicle to the RF stations and receive them back and measure the
received power to determine the distance. This technique involves a number of factors
that affect the received power strength. These factors include the power transmission,
obstacles between devices, antenna orientation, type of antenna used, multipath and
antenna receiving sensitivity. All the factors mentioned here can be overcome accurately
Transmit power Here for the given arena; transmitting power should be enough to
cover the extreme points in the arena. The selected RF modules are powerful enough to
Obstacles between two devices This is a fundamental concern, since there could be
any number of walls and other objects which have different power attenuation
coefficient. The concrete walls, human body and different kind of metals have a high
power attenuation coefficient, but they are unlikely to appear in this scenario. The
materials have a low power attenuation coefficient which have been used. As a result, the
power attenuation can be ignored. A few tests have been carried out and are discussed in
chapter four, which suggests low effect on power attenuation for the materials used.
receiver from more than one path because of the reflection for the given geographic
condition. This phenomenon is impossible to avoid, but the question is how severely it
Antenna orientation and type of antenna Here the RF modules contain isotropic
antennas. An isotropic antenna has a uniform power pattern in all directions. So, the RF
5
stations do not need to orient in a specific direction. However, the height of the RF
stations is crucial because this project provides the location of the moving vehicle in two
dimensions. In this situation, the RF stations should be place roughly at the same height
as the vehicle maneuvers inside the arena. Figure 2.3 shows how the vehicle maneuvers
roughly in the two dimensional plane, which co-inside with the two RF stations.
Output Pins
FPGA
6
Further we need to fix the reference point (0,0) to one of the given RF stations. After
fulfilling the conditions previously explained, an algorithm has been written as given
below to calculate the distance in two dimensions. To understand the algorithm, consider
Figure 2.4
1. Determine the distance between the vehicle and transceiver A and the distance
imaginary triangle.
triangle.
5. Calculate the ratios of the hypotenuses of the similar triangles and calculate the X and
1. Determining the distance between two RF stations which are posted in the two
corners of the building can be done by measuring the received signal strength. For an
accurate measurement, the received power drop per unit distance has a
significant role. So, the RF transceivers must be optimized for the given area. For the
area of 30m x 15m, the diagonal of 33.54m is the longest distance. If the vehicle is
33.54m apart from one of the RF stations, the received power should be the minimum
of the RF station’s receiving capability. The X-bee pro module is capable to measure
-100dBm (0.1 Pico-watt) and store the receiving power in the hex notation which was
7
the wireless transceiver. The register only stores the value of the last successfully
indication.
In the AT Command Mode, the value may polled by using the ATDB
command.
When receiving in the API Mode, a byte in the packet contains the RSSI level.
This paper uses the second method which reads the DB register using the ATDB
command. The method is fully described in the next section. With the help of this
information, antenna calibration had been carried out; in other words, a detailed
experiment had been carried out on the distance verses receiving power. These data had
been used to determine the distance between the vehicle and the RF transceiver station.
9m
A
15m
12m
B
30m
Angle C in degrees: → ( ) →
8
A’ 9m
53.13°
15m
12m
30m
triangle:
Angle in degrees:
36.87° 9m
15m
12m
D E
30m
Side D in meters: ( )
Side E in meters: √
9
X
Y 9m
15m
12m
22.50m 37.50m
30m
5. Calculate the ratios of the hypotenuses of the similar triangles and calculate the X and
Ratio of hypotenuses:
Coordinate X in meters:
Coordinate Y in meters:
The algorithm setup explains how to find a relative location in two dimensions. The
algorithm written in the C language and implemented on the Xilinx Microblez softcore
processor gives seamless results while the vehicle is moving inside the building. The next
10
CHAPTER 3
As shown in figure 2.4, the Xilinx Spartan 3e FPGA starter board had been used
as a computation base. It is assumed for this experiment that the Xilinx Spartan 3e FPGA
board is a part of the moving vehicle. The Spartan 3e is the FPGA chip capable of
implementing midscale embedded design logic. The Spartan 3e FPGA board supports the
Microblaze softcore processor. The processor is a 32-bit RISC processor with highly
scalable features. The Xilinx Platform Studio (XPS) had been used to define the
processor components and the peripherals. Along with that, two RS-232 ports provided in
the board were used to communicate with the remote RF stations. The Spartan 3e board is
equipped with both DTE and DCE types of serial connection. Since it has been
implemented on FPGA board, modifications become very easy and handy as application
11
Figure 3.2 Microblaze system definition
Figure 3.2 shows different parameter options for the Microblaze softcore
processor. The processor clock was kept default to the Spartan 3e FPGA board, which
was 50 MHz. Local memory refers to the on-chip BRAM memory blocks which can be
defined maximum at 64 KB. The Microblaze is Harvard architecture; therefore, it has two
separate buses. One bus is connected to the data-memory, and another is connected to the
instruction-memory.
12
Figure 3.3 Available peripheral options to be connected with Microblaze
RS232 DCE, RS232 DTE, LCD 2x16, 6-bit LEDs, dlmb_cnlr and ilmb_cnlr has been
13
Figure 3.4 Embedded system view with selected IP components
Figure 3.4 shows the GUI representation of Microblaze system with all connection and
direction details.
14
Figure 3.5 Memory mapped addresses belong to each IP component
Figure 3.5 shows the memory mapped IP components. After completing the definition of
application.
Important features:
15
RF data rate: 250 kbps
Figure 3.6 shows an Xbee-pro configuration board with the USB support. The
board had been used to configure and test all RF modules used in the system with the X-
16
Figure 3.7 X-CTU setup window
Test/Query tab enables a modem test with given setting like baud rate, flow control, data
bits, parity and stop bits. All Xbee pro modules should be setup to the same settings and
17
Figure 3.8 Spartan 3e FPGA board with two Xbee pro RF modules connected through RS-
232 ports
18
To achieve the loopback mode in the above diagram, the Data Carrier Direct (pin
1), Date Terminal Ready (pin 4), Data Set Ready (pin 6), and Ring Indicator (pin 9)
signals must be wired together, the Received Data (pin 2) and Transmitted Data (pin 3)
signals must be wired together, and the Request To Sent (pin 7) and Clear To Send (pin
8) signals must be wired together. This wiring was accomplished on the RS232 ports of
19
CHAPTER 4
ANTENNA CALIBRATION
The Xbee-pro RF modules are equipped with an isotropic antenna. These modules
should be placed in the arena such that the antenna stands vertical. As a result, the
radiation pattern of the antenna exists strongest across the horizon. The RF modules
should not be placed inside any metal case to avoid misbehavior in the antenna radiation
pattern. Along with that, objects such as metal poles, metal studs or beams in structures,
concrete (it is usually reinforced with metal rods), elevators and the human body should
The PL parameter is used to select and read the power level at which the RF
module transmits power. When operating in Europe, XBee-PRO 802.15.4 modules must
operate at or below a transmit power output level of 10dBm. Users have five choices
www.digi.com). In this project, ‘0’ (10 dBm) transmit power level was selected since the
power level of 10dBm is sufficient to cover the maximum distance for the given scenario.
The RF module should not be configured so that it covers a distance more than required
because it causes a low power drop per unit distance. This leads to a decrease in the
system resolution. Figure 4.1 shows how to configure the power level using the X-CTU
software.
Transceiver A’, they were configured with the same channel[C] and PAN ID[3332]. The
Transceiver B and the Transceiver B’ were configured with the different channel [D] and
20
The DB parameter was used to read the received signal strength (in dBm) of
the last received packet. The reported values are accurate between -40 dBm and the RF
module's receiver sensitivity. The absolute values are reported. For example: 0x58 = -88
dBm (decimal). 0x0 will be reported if no packets have been received (since last reset,
AT command: ATDB
21
Having this information, the manual tests, shown in figure 4.2, were carried out to
find the relation between the distances against the received power.
Figure 4.2 Experiment set up to find received power for variable distance
One RF module was connected to a PC which interacts with the X-CTU software and
From the range test tab in X-CTU software, hit the start button to test the communication
setup. The successful connection can be determined by looking at the “Good” packet
The RF module with loopback mode has been moved in each step of 1 meter in
increasing fashion.
To get the exact value of the received power, open the terminal window. Hit random
characters. The characters colored in blue are transmitting packets and the characters
By typing “+++” sets the RF module in the AT command mode. In response, ‘OK’
Send “ATDB” command to read the “DB” register. This Command returns value in hex.
22
This step can be seen in figure 4.4
For a given distance, the received power often fluctuated during the experiment, but the
value shown in the table is the value that has been read the majority of the time. Because
of these fluctuations, the moving vehicle has to send the data (let say character) several
times and read the DB register and finalize the value. For example, if the moving vehicle
reads -58 dBm (0x3A) register value several times, that means the vehicle is 15m apart
Figure 4.5 Black colored area from two RF stations shows 3m blind area
24
It was observed that from 0m to 3m the DB register shows the minimum possible
value (highest value of received power) it can measure. Therefore, if the vehicle comes in
this area, we cannot determine the correct distance from the RF station. It is shown as a
25
CHAPTER 5
based on single Microblaze system, the hardware can be export to Xilinx software
development kit (SDK) to build a software application in the C language. The SDK
environment used to develop and debug the software which has been stored in the on-
3. After the completion of the C code, the SDK automatically built the application and
generate an elf (executable and linker file) file along with the board support package.
Then the elf file can be downloaded with the .bit, and the .bmm file to the FPGA board.
According to the application written, all LEDs are set to the off state initially. Then the
character. After reception of the sent character, all LEDs are turned on.
/*
* Microblaze system peripheral test program
* Author: Kukadiya Akash
* peripheral_test.c
*
* This program checks whether microblaze processor and peripheral connected
* are correctly instantiated inside FPGA
*/
#include <stdio.h>
#include "xparameters.h"
#include "xgpio.h"
#include "xstatus.h"
#include "platform.h"
#include "xuartlite.h"
//Global Variables
XGpio lcd;
XGpio sixLeds;
XTmrCtr timer;
26
XUartLite uartA, uartB;
int i;
char j;
int main()
{
print("Hello World\n\r");
print("Jay swaminarayan\n\r");
u8 sndData = 'a';
u8 recvData = 0;
XGpio_Initialize(&sixLeds, XPAR_LEDS_6BIT_DEVICE_ID);
XUartLite_Initialize(&uart, XPAR_RS232_DTE_DEVICE_ID);
XGpio_SetDataDirection(&sixLeds, 1, 0x00);
XGpio_DiscreteSet(&sixLeds, 1, 0x2A);
return 0;
}
The function “Map_distance” was written to find the distance between the vehicle
and the RF station by using Table 4.1. The system application must be able to read the
RF module register value in order to find the distance. However, after setting the RF
module to the AT command mode, we cannot simply send “ATDB” command in order to
27
read the value of receiving power. To do so, a separate software driver is needed to be
written that is able to send the AT commands from the Microblaze to the X-bee pro
modem. Due to unfamiliarity of the software driver development process, it hadn’t been
written. However, the function was written to map the received power values with the
The transceiver A was connected with the RS 232 DTE port on the FPGA board. The
transceiver B was connected with the RS 232 DCE port on the FPGA board.
Send a data (here a character) from the transceiver A and wait till it receives back. Then
change the transceiver A to the AT command mode. Send the ‘ATDB’ command to get
Store the register value to the variable ‘DB_register_value’. Call the function
‘Map_distance’ to assign the distance value associated with the received power level.
As a result, the distance between the vehicle and the two RF stations can be achieved.
The rest of the development code was taken from the reference “DESIGE OF AN
by Robert Santogrossi, to locate the moving vehicle. The section is shown in Appendix
A.
//Global Variables
XGpio lcd;
XGpio sixLeds;
XTmrCtr timer;
XUartLite uartA, uartB;
//Function Declaration
int Map_distance(int *DB_register_value);
28
/*
* This function maps register value to associated distance
*
* @param * DB_register_value(pointer to the DB_register_value)
*
* @return integer
*/
int Map_distance(int *DB_register_value) {
switch (DB_register_value){
case 1:
if (DB_register_value = 27)
Distance = 4;
break;
case 2:
if (DB_register_value = 29)
Distance = 5;
break;
case 3:
if (DB_register_value = 2A)
Distance = 6;
break;
case 4:
if (DB_register_value = 2D)
Distance = 7;
break;
case 5:
if (DB_register_value = 2E)
Distance = 8;
break;
case 6:
if (DB_register_value = 30)
Distance = 9;
break;
case 7:
if (DB_register_value = 33)
Distance = 10;
break;
case 8:
if (DB_register_value = 34)
Distance = 11;
break;
case 9:
if (DB_register_value = 36)
Distance = 12;
break;
case 10:
if (DB_register_value = 38)
29
Distance = 13;
break;
case 11:
if (DB_register_value = 39)
Distance = 14;
break;
case 12:
if (DB_register_value = 3A)
Distance = 15;
break;
//more case statements can be used, if have more distance verses received
//power data available
}
30
CONCLUSION
This paper is a study to solve the problem of given complexity that combines
hardware and software components together which is one of the important tasks to be
Competition (IARC), as a 6th mission. From this paper, one can understand the theory,
basic algorithm and how to use receiving power to determine the distance between two
wireless devices. This paper doesn’t show a fully functional system on hardware.
However, this new approach of measuring distance with help of signal strength analysis
is useful and also vary practical. It has been observed that for the given indoor scenario
general scenario that may have large obstacle like walls, concrete beams, metal and even
human body can give a wrong distance value of the moving object. This is due to variable
power attenuation. Another drawback in this project is the computation logic was carried
out on the FPGA board which is a more power and space consuming circuitry to mount
on the flying vehicle. To address this problem, a customized microcontroller based PCB
31
REFERANCES
ftp://ftp1.digi.com/support/documentation/90000982_A.pdf
Quick_start_guide_xbs2_development-kit.pdf
http://www.xilinx.com/support/documentation/sw_manuals/xilinx14_2/edk_ctt.pdf
Xilinx MicroBlaze Development Kit Spartan-3E 1600E Edition User Guide available at
http://www.xilinx.com/support/documentation/sw_manuals/
http://www.xilinx.com/forum
32
APPENDIX
The main function serves as the entry point for all functional codes in the system. The
main function along with required included files and associated defines and global variables are
shown below.
/*
* Author: Robert John Santogrossi
*
* Title: Localization Program
*
* Description: This code serves to track the location of
* an autonomous vehicle inside a defined building. Code
* for directing the vehicle to and into the building should
* be added. Code for moving the vehicle while inside the
* building should be added by utilizing the output of the
* tracking algorithm implemented in this code.
*
* Edited by: Akash Kukadiya
*/
#include "math.h"
#include "xgpio.h"
#include "xparameters.h"
#include "xtmrctr.h"
#include "xuartlite.h"
//Defines
#define BUILDING_LENGTH 30
#define DISTANCE_BETWEEN_POSTS 15
#define SYSTEM_RESOLUTION 3
#define TRANSCEIVER_A 0
#define TRANSCEIVER_B 1
#define TRANSCEIVER_A_ANGLE 0
int main()
{
int outsideBuilding = 1;
double DB_register_value_A = 0, DB_register_value_B = 0;
double distanceA = 0, distanceB = 0;
double xPosition = 0, yPosition = 0;
int xMap[BUILDING_LENGTH / SYSTEM_RESOLUTION];
33
int yMap[DISTANCE_BETWEEN_POSTS / SYSTEM_RESOLUTION];
initialize(xMap, yMap);
for(;;) {
while(outsideBuilding) {
/*Add Code to allow vehicle to enter building
and then toggle outsideBuilding to 0*/
}
while(!outsideBuilding) {
DB_register_value_A = get_received_power(TRANSCEIVER_A);
DB_register_value_B = get_received_power(TRANSCEIVER_B);
distanceA = Map_distance(DB_register_value_A);
distanceB = Map_distance(DB_register_value_B);
findPosition(&xPosition, &yPosition, TRANSCEIVER_A_ANGLE,
distanceA, distanceB);
logPosition(xMap, yMap, xPosition, yPosition);
displayPosition();
return 0;
}
All of the included files shown in the code above are required for full functionality of the
tracking system. In the main function, various necessary variables are declared and initialized
including the x any map arrays which are sized according to the system resolution and the
outside building flag variable. After the variable declarations the initialize function is called to
prepare the system for functionality. Inside the non-terminating for-loop, the code will first enter
a while loop. The code must be written inside this loop to allow the vehicle to enter the building
and toggle the outside building variable to 0. This code is outside the scope of this paper. Once
the vehicle is inside the building, program execution will enter the next while loop where the
34
indoor tracking algorithm is executed. More code must be written to move the vehicle while
inside the building to accomplish its objective while utilizing the output of the tracking algorithm
for assistance and toggle the outside building variable when exiting the building. This code, and
the code needed to return the vehicle back to its starting location are also outside the scope of
The initialization function is the first function to be entered from the program’s main
function. This function must be executed first because it prepares the system for all of the
functionality it is expected to perform. The delay functions are core pieces of code needed in
many aspects of the program and are very useful during the development of the code. These
4.1.1. Initialize
The initialization function serves to initialize and set registers for all of the peripherals
used in the remainder of the program. The initialize function also resets the X and Y position
maps. The function declaration, definition, and associated defined and global variables are
shown below.
//Defines
#define BUILDING_LENGTH 30
#define DISTANCE_BETWEEN_POSTS 15
#define ROW_2_COLUMN_1 0x40
#define SYSTEM_RESOLUTION 1
#define X_POS "X Pos: "
#define Y_POS "Y Pos: "
//Global Variables
XGpio lcd;
XGpio sixLeds;
XTmrCtr timer;
XUartLite uartA, uartB;
35
/*Associate the objects with the addresses for the LCD,
timer, and UARTs*/
XGpio_Initialize(&lcd, XPAR_CHARACTER_LCD_2X16_DEVICE_ID);
XGpio_Initialize(&sixLeds, XPAR_LEDS_6BIT_DEVICE_ID);
XUartLite_Initialize(&uartA, XPAR_RS232_DTE_DEVICE_ID);
XUartLite_Initialize(&uartB, XPAR_RS232_DCE_DEVICE_ID);
XTmrCtr_Initialize(&timer, XPAR_XPS_TIMER_1_DEVICE_ID);
/*Set data direction as output for the ports connected
to the LEDs and the LCD display*/
XGpio_SetDataDirection(&sixLeds, 1, 0x00);
XGpio_SetDataDirection(&lcd, 1, 0x00);
int i = 0;
The initialization function has no return value and requires two integer pointers as
parameters. The function first associates the global variable objects for the system peripherals
with the addresses they physically occupy in the system using initialization functions provided
by the generated Microblaze library. The GPIO ports of the LCD display and the LEDs are then
set to the data direction of output and timer channel 1 of the timer is set to count downwards.
Timer channel 1 is left in its default state of counting upwards. Next the LCD display is
initialized, the phrase “X Pos: ” is written on the display, the cursor is moved to the second row,
and the phrase “Y Pos: ” is written on the display. These custom LCD display functions will be
36
discussed later in the paper. The last task for the initialization function is to clear the memory
contents of the xMap array and the yMap array. Pointers to these arrays were passed as
parameters to the function so that they could be modified within the function. The outer for loop
iterated ten times clearing the xMap array on every iteration and clearing the yMap on only the
first five iterations. If the system resolution changes because of possible faster clock frequencies
all that needs to change is the SYSTEM_RESOLUTION define because size of the mapping
The millisecond delay function serves only to halt program execution for a specified
period of time in milliseconds. The function declaration, definition, and associated global
//Global Variables
XTmrCtr timer;
//Function Declaration
void msDelay(unsigned int time);
/*
* msDelay
* This function generates a millisecond time delay.
* Requires a timer that counts down.
*
* @param time (the amount of time in ms to delay)
*
* @return void
*/
void msDelay(unsigned int time) {
37
XTmrCtr_Stop(&timer, 1);
}
Figure 9: Millisecond delay function and necessary code
The millisecond delay function has no return value and requires one unsigned integer
parameter. The function first sets the reset value of timer channel 1 to the input parameter
multiplied by 100,000. The reset value is the value that the timer will be set to when it is reset or
expires by reaching a count of zero. At a 100MHz clock speed, every count on the timer counts
10ns. The time variable is multiplied by 100,000 because 10ns times 100,000 equates to 1ms.
The timer is then started and an empty while loop executes as long at the generated Microblaze
function XTmrCtr_IsExpired returns a value of true. When the value of true is returned, the loop
The microsecond delay function functions in the same fashion as the millisecond function
except that the unsigned integer time parameter is multiplied by 100 instead of 100,000 because
//Global Variables
XTmrCtr timer;
//Function Declaration
void usDelay(unsigned int time);
/*
* usDelay
* This function generates a microsecond time delay.
* Requires a timer that counts down.
*
* @param time (the amount of time in us to delay)
*
* @return void
*/
void usDelay(unsigned int time) {
38
XTmrCtr_Start(&timer, 1);
The LCD functions were written so that the output of the tracking algorithm can be
displayed. The LCD functions were written early in the development cycle of the software
because it provides a very useful debugging tool. These types of functions are explained below.
The write LCD port function serves to write an 8-bit byte to the GPIO port connected to
the LCD display peripheral on the FPGA board. The function declaration, definition, and
//Defines
#define INSTRUCTION 0
#define DATA 1
#define LCD_RS 0x20
//Global Variables
XGpio lcd;
//Function Declaration
void writeLcdPort(unsigned int type, unsigned int data);
/*
* writeLcdPort
* This function writes a byte to the LCD port
*
* @param type (the type of data to be written)
* @param data (the nibble of data to be written)
*
* @return void
*/
void writeLcdPort(unsigned int type, unsigned int data) {
switch (type) {
39
/*If the data is an instruction write the low nibble
Without asserting any bits on the high nibble*/
case INSTRUCTION:
XGpio_DiscreteWrite(&lcd, 1, data);
break;
The write LCD port function has no return value and requires two unsigned integer
parameters. The LCD peripheral accepts a byte of data at a time. The high nibble tells the LCD
to configure to read or write mode, whether the low nibble is a part of data or an instruction, and
to clock in the bits on the low nibble. If the instruction define is passed into the function, the
data are written to the port. The low nibble is written and the high nibble is left as its default 0.
A 0 on the high nibble enables write mode and the instruction register on the LCD display. If the
data define are passed into the function, a bitwise OR function is performed with the data and the
define LCD_RS. The low nibble is written and the high nibble is loaded with 2. A 2 on the high
nibble enables write mode and the data register on the LCD display.
The pulse enable function serves to assert and de-assert the enable line in the high nibble
while keeping the low nibble unchanged. The function declaration, definition, and associated
//Defines
#define INSTRUCTION 0
#define DATA 1
#define LCD_E 0x40
#define LCD_RS 0x20
40
//Global Variables
XGpio lcd;
//Function Declaration
void pulseEnable(unsigned int type, unsigned int data);
/*
* pulseEnable
* This function asserts and deasserts the enable signal without
* modifying the data
*
* @param type (the type of data to be written)
* @param data (the nibble of data to be written)
*
* @return void
*/
void pulseEnable(unsigned int type, unsigned int data) {
switch (type) {
The pulse enable function has no return value and requires two unsigned integer
parameters. Pulsing the enable line of the high nibble clocks the low nibble data or instruction
into the LCD controller. If the instruction define is passed into the function, a bitwise OR
operation is executed with the data and the LCD_E define. The low nibble data is unchanged
and the value 4 is loaded into the high nibble. A high nibble of 4 asserts the enable line and
41
keeps the mode set to instruction. After a 1us delay the only data are written which de-asserts
the enable line. This sequence causes an enable pulse. If the data define is passed into the
function, the same sequence of steps is performed except that the LCD_RS define is included in
The initialize LCD function serves to put the LCD controller into the proper mode to start
accepting instructions and data those will modify the display. The function declaration,
//Defines
#define INSTRUCTION 0
//Function Declaration
void initializeLcd(void);
/*
* initializeLcd
* This function initialized the LCD display to prepare
* for display of data
*
* @param void
*
* @return void
*/
void initializeLcd() {
42
pulseEnable(INSTRUCTION, 0x8);
msDelay(2);
//Display on sequence
writeLcdPort(INSTRUCTION, 0x0);
pulseEnable(INSTRUCTION, 0x0);
msDelay(2);
writeLcdPort(INSTRUCTION, 0xC);
pulseEnable(INSTRUCTION, 0xC);
msDelay(2);
The initialize LCD function has no return value and requires no parameters. The LCD
display on the FPGA board is wired to use a 4 bit data bus. As stated before, the high nibble
carries configuration bits and the lower nibble carries instructions or data. The instructions and
data however are 8 bits long. The FPGA board user guide and LCD documentation state that the
high nibble is clocked in first followed by the low nibble to complete one data or instruction
write to the LCD controller. The same documentation provides guidance on the sequence of
writes to the LCD controller and delay times that are needed to initialize the display. It is this
guidance that is implemented in this function. The LCD initialize function makes use of the
write LCD port and pulse enable functions passing in the instruction define, and delay functions
to complete its task. Two writes of 0x33 and 0x32 inform the controller that the 4-bit
communication protocol is being used. A write of 0x06 sets the entry mode with the option that
43
the LCD cursor auto-increment with every character written to the display. A write of 0x0C
turns on the display with the options that the characters written to the controllers DD RAM be
displayed, the cursor does not blink, and the cursor is not displayed. The final write of 0x01
clears the display and moves the cursor to the top left position of the display.
The write character function serves to write a character to the LCD display. The function
//Defines
#define DATA 1
//Function Declaration
void writeCharacter(unsigned int character);
/*
* writeCharacter
* This function writes a character to the LCD display
*
* @param character (the character to be written)
*
* @return void
*/
void writeCharacter(unsigned int character) {
The write character function has no return value and requires an unsigned integer
parameter. A character is 8 bits of data, but as mentioned previously, the high nibble must be
written first followed by the low nibble. To accomplish this, the high nibble is isolated by
44
shifting the character data to the right by 4 bits and performing a bitwise AND with 0x0F. This
moves the high nibble to the low nibble and clears the new high nibble. The low nibble is then
isolated by just performing the high nibble clearing bitwise AND function. The write LCD port
and pulse enable functions are then utilized with the data define to write the high nibble followed
by the low nibble. After the execution of this function, a character is actually viewable on the
display.
The write phrase function serves to write a character string to the LCD display. The
//Function Declaration
void writePhrase(char *phrase);
/*
* writePhrase
* This function writes a character string to the LCD display
*
* @param *phrase (pointer to the character string to write)
*
* @return void
*/
void writePhrase(char *phrase) {
The write phrase function has no return type and requires a pointer to a character string
parameter. This function dereferences the phrase pointer so that the data it pointed to is written
on the LCD display using the write character function. The address is then incremented to point
45
to the next character. This sequence continues until the data are a null value meaning that the
The write number function serves to write a number to the LCD display. The function
//Function Declaration
void writeNumber(int number);
/*
* writeNumber
* This function writes a number to the LCD display
*
* @param number (number to be written)
*
* @return void
*/
void writeNumber(int number) {
The write number function has no return type and requires an integer parameter. The
function must convert an integer into a character string in order to write the number to the LCD
screen. To do this, the character array to hold the to-be-converted integer is created and limited
to a reasonable 10 digits. The standard sprintf function is used to convert the number into a
character string and store it in the buffer character array. Once the character string is created, it
is passed into the write phrase function to be written on the LCD display.
46
4.2.7. Move Cursor
The move cursor function serves to move the cursor of the LCD controller to a specific
location on the display. The function declaration, definition, and associated define are shown
below.
//Defines
#define INSTRUCTION 0
//Function Declaration
void moveCursor(unsigned int position);
/*
* moveCursor
* This function moves the cursor on the LCD display
*
* @param position (the position to move the cursor to)
*
* @return void
*/
void moveCursor(unsigned int position) {
The move cursor function has no return value and requires an unsigned integer parameter.
This function performs much like the write character function in the fact that it first isolates the
high and low nibbles and then writes them to the LCD controller. Setting the MSB of the byte to
a 1 followed by the address to move the cursor to represent data needed to be sent in order to
move the cursor. To do this, the high nibble is isolated by using a bitwise OR function to
combine the cursor position with a 1 in the MSB, the result’s high nibble is shifted to the low
47
nibble and the new high nibble is cleared. The low nibble is isolated and the high and low
nibbles are written just as they are in the write character function.
The display position function serves to display the current x and current y positions of the
vehicle on the LCD display. The function declaration, definition, and associated defines and
//Defines
#define ROW_1_COLUMN_8 0x07
#define ROW_2_COLUMN_8 0x47
//Global Variables
int currentXPosition;
int currentYPosition;
//Function Declaration
void displayPosition();
/*
* displayPosition
* This function displays the x and y position on the
* LCD display
*
* @param void
*
* @return void
*/
void displayPosition() {
The display position function has no return value and requires no parameters. In this
function, the move cursor function is used to move the cursor before writing each global position
48
integer to the LCD display using the write number function. The cursors are moved to the eighth
column of the first and second rows of the LCD display because, at this point in the program
execution, the phrases “X Pos: ” and “Y Pos: ” are already written on the display.
The tracking algorithm functions were designed to implement the algorithm described in
the system theory section of this paper. Due to the sequential nature of the algorithm presented,
most of the functions were written in a cascade function in which one uses the other in a long
string of function calls to execute the algorithm. The functions are also written to accommodate
both reference angles when calculating the vehicle position. It is left to the main function to
The Get_received_power function sends a character from the uartA and uartB ten times
and receives back, and every time it reads the DB register value. The variable
//Defines
#define TRANSCEIVER_A 0
#define TRANSCEIVER_B 1
//Global Variables
XTmrCtr timer;
XUartLite uartA, uartB;
//Function Declaration
int get_received_power (unsigned int transceiver);
/*
* get_received_power
* This function initiates data transfer to two URATs connected through DTE
* and DCE pins and receives back the data and reads the received power
* strength in hex notation
*
* @param transceiver (the transceiver to use)
*
* @return read_DB_register (register value in hex)
49
*/
char get_received_power (unsigned int transceiver) {
int counter = 0;
u8 sndData1 = 0;
u16 sndData2 = ''+++'';
u16 sndData3 = ''ATDB'';
u8 recvData = 0;
u8 DB_register_value = 0;
switch (transceiver) {
case TRANSCEIVER_A:
do {
XUartLite_Recv(&uartA, &recvData, 1);
} while(recvData != sndData);
DB_register_value = recvData;
}
counter=0;
break;
case TRANSCEIVER_B:
DB_register_value = recvData;
}
counter=0;
break;
50
default:
break;
The find interior angle function serves to calculate an interior angle of the generated
triangle based on the angle required and the distance measurement of the two variable
sides and return the angle in degrees. The function declaration, definition, and associated
//Defines
#define DISTANCE_BETWEEN_POSTS 15
#define TRANSCEIVER_A_ANGLE 0
#define TRANSCEIVER_B_ANGLE 1
#define POST_ANGLE 2
//Function Declaration
double findInteriorAngle(int angleToFind, double sideA, double sideB);
/*
* findInteriorAngle
* This function calculates an interior angle of the generated
* triangle using the rule of cosines
*
* @param angleToFind (the interior angle to find)
* @param sideA (the distance from post A to vehicle)
* @param sideB (the distance from post B to vehicle)
*
* @return angle (the interior angle in degrees)
*/
double findInteriorAngle(int angleToFind, double sideA, double sideB) {
double a = 0;
double b = 0;
double c = 0;
double angle = 0;
51
a = sideA;
b = sideB;
c = DISTANCE_BETWEEN_POSTS;
break;
default:
break;
}
The find interior angle function returns a double and requires an integer and two double
parameters. By the time this function is executed in the normal flow of the program, a triangle
has been generated by finding the distance between the vehicle and each transceiver post. The
third side of the triangle is constant at 15m which is the distance between the posts. This
function can find any interior angle of that generated triangle. When the define for the desired
angle to find is passed into the function, the function first sets the distance parameters and
constant to the appropriate variables used in the rule of cosines. Once the variables are set for
the desired angle, the angle is calculated using the rule of cosines, converted from radians to
The find exterior angle function serves to calculate an exterior angle of the generated
triangle based on the angle required and the distance measurement of the two variable sides and
return the angle in degrees. The function declaration, definition, and associated defines are
shown below.
//Defines
52
#define DEG_90 90
//Function Declaration
double findExteriorAngle(int angleToFind, double sideA, double sideB);
/*
* findExternalAngle
* This function calculates an exterior angle of the generated
* triangle using the interior angle
*
* @param angleToFind (the interior angle to find)
* @param sideA (the distance from post A to vehicle)
* @param sideB (the distance from post B to vehicle)
*
* @return angle (the exterior angle in degrees)
*/
double findExteriorAngle(int angleToFind, double sideA, double sideB) {
The find exterior angle function returns a double and requires an integer and two double
parameters. In this function the angle to find and distances are first passed through to the find
interior angle function. After the interior angle is found, the exterior angle needed for the
tracking algorithm can simply be found by subtracting the interior angle from 90°. The exterior
The find similar opposite side function serves to calculate the opposite side of the larger
similar triangle based on a reference angle and the distance measurement of the two variable
sides and return the side in meters. The function declaration, definition, and associated defines
//Defines
#define BUILDING_LENGTH 30
53
#define DEG_180 180
#define PI 3.14159265
//Global Variables
double similarOppositeSide;
//Function Declaration
double findSimilarOppositeSide(int referenceAngle, double sideA, double
sideB);
/*
* findSimilarOppositeSide
* This function calculates the opposite side of the
* reference angle of the larger similar triangle
*
* @param referenceAngle (the angle to reference)
* @param sideA (the distance from post A to vehicle)
* @param sideB (the distance from post B to vehicle)
*
* @return side (the opposite side in meters)
*/
double findSimilarOppositeSide(int referenceAngle, double sideA, double
sideB) {
The find similar opposite side function returns a double and requires an integer and two
double parameters. This function first calls the find exterior angle function which returns the
requested exterior angle in degrees. The angle is then converted into radians so that it can be
used in a tangent function. The tangent of the angle equals the opposite side over the adjacent
side. To use this equation to find the opposite side, the tangent of the angle is calculated and
multiplied by the adjacent side which is the length of the building. This result is stored in a
global variable for efficient use in the find position function do be discussed later in this paper
54
4.3.5. Find Similar Hypotenuse
The find similar hypotenuse function serves to calculate the hypotenuse of the larger
similar triangle based on a reference angle and the distance measurement of the two variable
sides and return the hypotenuse in meters. The function declaration, definition, and associated
//Defines
#define BUILDING_LENGTH 30
//Function Declaration
double findSimilarHypotenuse(int referenceAngle, double sideA, double sideB);
/*
* findSimilarHypotenuse
* This function calculates the hypotenuse of the
* larger similar triangle
*
* @param referenceAngle (the angle to reference)
* @param sideA (the distance from post A to vehicle)
* @param sideB (the distance from post B to vehicle)
*
* @return side (the hypotenuse in meters)
*/
double findSimilarHypotenuse(int referenceAngle, double sideA, double sideB)
{
The find similar hypotenuse function returns a double and requires an integer and two
double parameters. This function first calls the find similar opposite side function which returns
the larger similar triangle opposite side in meters. The adjacent side is also known because it is
the constant length of the building. Knowing these two sides, the Pythagorean Theorem can be
55
4.3.6. Find Ratio
The find ratio function serves to calculate the ratio of the generated triangle to the larger
similar triangle based on a reference angle and the distance measurement of the two variable
sides and return the ratio. The function declaration, definition, and associated defines are shown
below.
//Defines
#define TRANSCEIVER_A_ANGLE 0
#define TRANSCEIVER_B_ANGLE 1
//Function Declaration
double findRatio(int referenceAngle, double sideA, double sideB);
/*
* findRatio
* This function calculates the ratio of the generated
* triangle to the similar triangle
*
* @param referenceAngle (the angle to reference)
* @param sideA (the distance from post A to vehicle)
* @param sideB (the distance from post B to vehicle)
*
* @return ratio (the ratio)
*/
double findRatio(int referenceAngle, double sideA, double sideB) {
56
The find ratio function returns a double and requires an integer and two double
parameters. This function first calls the find similar hypotenuse function which returns the larger
similar triangle’s hypotenuse in meters. Depending on if the similar triangle was found from the
corresponding transceiver post A or transceiver post B angle, the ratio is calculated using the
corresponding distance to the vehicle from transceiver post A or transceiver post B. The ratio is
The find position function serves to find the physical position of the vehicle within the
building based on a reference angle and the distance measurement of the two variable sides and
store the position. The function declaration, definition, and associated defines and global
//Defines
#define BUILDING_LENGTH 30
//Global Variables
double similarOppositeSide;
//Function Declaration
void findPosition(double *xPosition, double *yPosition, int referenceAngle,
double sideA, double sideB);
/*
* findPosition
* This function calculates x and y position of the vehicle
* and modifies the data pointed to by the parameters
*
* @param *xPosition (pointer to the x position variable)
* @param *yPosition (pointer to the y position variable)
* @param referenceAngle (the angle to reference)
* @param sideA (the distance from post A to vehicle)
* @param sideB (the distance from post B to vehicle)
*
* @return void
*/
void findPosition(double *xPosition, double *yPosition, int referenceAngle,
double sideA, double sideB) {
57
/*Multiply the ratio by the appropriate side and update
the data pointed to by the pointers*/
*xPosition = ratio * BUILDING_LENGTH;
*yPosition = ratio * similarOppositeSide;
}
Figure 27: Find position function and necessary code
The find position function has no return value and requires two pointers to doubles, an
integer, and two double parameters. This function first calls the find ratio function which returns
the ratio of the two similar triangles. The sides of similar triangles are proportional to each other
and this proportion is the ratio that was found. Multiplying this ratio by the building length in
the X axis gives the distance the vehicle is from the transceiver post in the X axis and
multiplying this ratio by the opposite side of the larger similar triangle in the Y axis gives the
distance the vehicle is from the transceiver post in the Y axis. These distances are calculated and
stored as the data pointed to by the pointers parameters passed into the function. The global
variable for the opposite side of the larger similar triangle is used in this function instead of
calling the find opposite similar side function for a performance gain. Each function that has a
role in calculating the position from the timer values should only be called once in the execution
of the tracking algorithm. This convention keeps the code running efficiently.
The scale position function serves to scale an x or y position value down to the scale
limited by the system resolution and return the scaled position. The function declaration,
//Defines
#define BUILDING_LENGTH 30
#define DISTANCE_BETWEEN_POSTS 15
#define SYSTEM_RESOLUTION 3
#define X_AXIS 0
#define Y_AXIS 1
58
//Function Declaration
double scalePosition(double position, int axis);
/*
* scalePosition
* This function scales the vehicle position according to the
* system resolution
*
* @param position (the x or y position)
* @param axis (the axis that the position variable represents)
*
* @return scaledPosition (the scaled x or y position)
*/
double scalePosition(double position, int axis) {
double scaledPosition = 0;
The scale position function returns a double and requires a double and an integer
parameter. As stated earlier in the system theory section of this paper, the system resolution
determines the size of the data structure used to map the building and track the vehicle. If the
resolution of the system is blocks of three square meters and the building is 30m by 15m, the
data structure used to map the building must be 10 units in the X axis and 5 units in the Y axis.
This function scales the actual distances down to the resolution of the system in the X axis and in
59
After the requested scaled value is calculated it is returned.
The round and normalize position function serves to prepare a scaled position to index
into a position map array. The function declaration, definition, and associated defines are shown
below.
//Defines
#define X_AXIS 0
#define Y_AXIS 1
//Function Declaration
int roundAndNormalizePosition(double scaledPosition, int axis);
/*
* roundAndNormalizePosition
* This function transforms the scaled position to the
* position in the map
*
* @param position (the position of the vehicle scaled)
* @param axis (the axis of the scaled position)
*
* @return roundNormalPosition
*/
int roundAndNormalizePosition(double position, int axis) {
double scaledPosition = scalePosition(position, axis);
switch (axis) {
case X_AXIS:
//Handle the case where the position is exactly 10
if(roundNormalPosition == 10) {
roundNormalPosition--;
}
break;
case Y_AXIS:
//Handle the case where the position is exactly 5
if(roundNormalPosition == 5) {
60
roundNormalPosition--;
}
break;
default:
break;
}
The round and normalize position function returns an integer and requires a double
parameter. This function first calls the scale position function which returns the scaled position
based on the system resolution. At this point, the position is still not ready to index into the X
and Y position map arrays because the value is a double. The floor of the position is taken and
then the value is casted to an integer. In the case where the X position becomes exactly 10, the
value is decremented by 1 and in the case where the Y position becomes exactly 5 the value is
decremented by 1. All other cases will index perfectly into the X and Y position mapping arrays.
The log position function serves to populate the x and y position map arrays with a
marker based on the position of the vehicle. The function declaration, definition, and associated
//Defines
#define X_AXIS 0
#define Y_AXIS 1
//Global Variables
int currentXPosition;
int currentYPosition;
//Function Declaration
void logPosition(int *xMap, int *yMap, double xPosition, double yPosition);
/*
* logPosition
* This function prepares the position data, sets the
* global position variables, and log the vehicle position
61
* in the map arrays
*
* @param *xMap (pointer to the x position map)
* @param *yMap (pointer to the y position map)
* @param xPosition (the x position of the vehicle)
* @param yPosition (the y position of the vehicle)
*
* @return void
*/
void logPosition(int *xMap, int *yMap, double xPosition, double yPosition) {
int roundNormalXPosition = roundAndNormalizePosition(xPosition, X_AXIS);
int roundNormalYPosition = roundAndNormalizePosition(yPosition, Y_AXIS);
62