University of Florida

Department of Electrical and Computer Engineering

EEL 5666

Intelligent Machine Design Laboratory

Final Report:

IAM

Intelligent Autonomous Mapping

Student Name: Christopher Piroli

Date: 12/8/99

TA's: Scott Jantz

Ivan Zapata

Instructor: Dr. A. Antonio Arroys

Table of Contents

•	Abstract	3

•	Executive Summary	4

•	Introduction	5

•	Integrated System	6

•	Mobile Platform	8

•	Actuation	9

•	Sensors	10

•	Behaviors	14

•	Experimental Layout and Design	15

•	Conclusion	18

•	References	20

•	Appendix A: Code	21

Abstract

IAM was an attempt at creating a autonomous mapping robot. In theory, IAM would move forward until it encountered an object. It would then perform counter-clockwise wall following, taking position readings as it went. As IAM was moving, it would create and store an outline of the object it was tracing in its memory. When requested to, IAM would dump this map onto a nearby screen. IAM did not succeed in doing this. It was able to wall follow and find positions but not at the same time.

IAM consisted of two parts, a mobile agent and a stationary beacon tree. The mobile agent made use of the beacon tree to determine its position. Additionally, the beacon tree was hooked to a nearby computer so information could be displayed on its monitor.

This report contains valuable schematics, code, and descriptions for students attempting to build a robot that makes use of ultrasound, performs wall following, or is able to find to find its position.

Executive Summary

IAM, intelligent autonomous mapping, was a robot intended to do simple mapping. It consisted of two parts, a mobile agent and a stationary beacon tree. The mobile agent made use of a Talrik platform and a 68HC11 EVBU and ME11 daughter board. It also used a Linx radio transmitter and a MAX chip ultrasonic receiver board. The stationary beacon tree was controlled by an MSCC11 single chip board. It made use of three signal boosters, a radio receiver, and a serial connection to a nearby computer. The mobile agent used two fully hacked servos and a caster to move about and bump, IR, and position sensors to detect its environment. The position sensor worked by timing ultrasonic waves as they traveled from the beacon tree to the mobile agent. It used this timing information to determine its distance from each beacon, and from that information it could place itself in a coordinate system with an origin at the base of the beacon tree.

IAM had three main behaviors: wall following, position determination, and mapping. It never really succeeded in mapping but performed its other two behaviors very well.

Introduction

When I was first deciding on what kind of robot to build, several ideas came to mind. They were all fairly different behaviors but they all shared one thing in common. The robot performing them needed to be able to know where it was at any given time. When I began discussing my ideas with the teaching assistants, I soon found out that the ability for a robot to know its location was not a solved problem. And so I decided to build IAM, a mapping robot that always knows where it is.

This report outlines my robots structure and behaviors.

Integrated System

IAM is comprised of two separate components: a mobile agent and a beacon tree.

For my mobile agent, I chose a Talrik body with a 68HC11 EVBU and an ME11 daughter board to control it. To this, I added bump switches and IR sensors to allow it to sense its immediate environment. Fully hacked servos controlled by a motor driver on the ME11 allowed the agent to move about. Lastly, a radio transmitter and an ultrasonic receiver allowed it to communicate with the beacon tree.

My stationary beacon tree was controlled by an MSCC11 single chip board. Connected to this were three signal boosters for my ultrasonic transmitters and a radio receiver. The boosters were connected to transducer beacons arranged as shown in Fig. 1. Finally, the MSCC11 was connected to a nearby computer through the serial port in order to display the information the being gathered by IAM.

The two components of IAM work together to find the position of the mobile agent. The agent sends a radio signal to the beacon tree, asking for it to fire a specified beacon. After doing this, the agent marks the time it sent the request. When an ultrasonic signal is received from the beacon, the agent again marks the time. It then uses these two times to determine its distance from the beacon. When the distance from all three beacons has been determined, the agent uses this information to calculate its position.

By keeping track of the location of the agent and whether or not the agent is near an object, IAM can create a map of its surroundings. I used wall-following in conjunction with IAM's tracking capabilities in an attempt to trace the outline of objects.

Mobile Platform

As stated before, I used the Talrik platform for my mobile agent. There were several reasons behind this decision. First, the Talrik was a finished, tested design. Rather than spending large amounts of time creating my own platform or hacking into an RC car, by using the Talrik I was able to concentrate on building my sensors. Second, the Talrik was an established design. Any questions I had were easily answered by the teaching assistants. Finally, the Talrik was a fairly ideal design for my robot. The relatively large body afforded more than enough room for adding sensors and additional hardware, and the two-wheel motion offered excellent maneuverability.

Actuation

IAM's actuation was limited to two fully hacked servos. I opened up two 42 ounce-inch servos and removed all the servo control circuitry from them. The gear tabs were then cut allowing them unrestricted rotation. Essentially the servos were hacked into gear-head motors. These motors were then controlled by the SN754410NE motor driver on the ME11 board. I attached three-inch Du-Bro wheels to the motors and my robot was mobile.

Sensors

Most of my time and effort in building IAM was spent on its sensor suite. IAM had three different types of sensors: bump, IR, and radio/ultrasound position tracking.

Bump Sensors: I had ten bump switches placed on IAM's mobile agent. Five were wired in parallel and evenly spaced around the front of the agent and five were similarly dealt with around the back. The robot was then fitted with a hard plastic bump ring so that any point of contact would trigger a bump switch. Fig. 2 shows a how the bump switched were wired.

As you can see, the analog port pin the bump switches were connected to would read a high value until a bump switch was closed. It would then be pulled down to low. The front and back bump sensors were kept distinct so that I could tell the direction the collision was coming from. The bump sensors were essentially used as back up for the IR. When wall-following, I would occasionally cut corners too sharply and veer into the wall. The bump sensors detected this, allowing me to back away and try again.

IR Sensors: These sensors were made up of five IR emitting LEDs and five hacked Sharp GPIU58Y IR detectors. The Sharp detectors are sold as 40 kHz digital IR sensors but were hacked to provide analog output values. The output of each of the IR detectors was fed into an analog port

pin. The LEDs were powered continuously by a 40kHz signal from the ME11 board. The IR emitters and detectors were arranged around the body of the agent roughly as shown in Fig. 3.

The three front facing Sharp detectors were used for initially detecting an object and for seeing interior curves when wall-following. The two side facing IR were used only during wall-following. The anterior side detector was used to keep the robot within a certain range from the wall and the posterior side detector was used for noticing sharp curves.

Position Detection: This sensor was fairly complicated. I will explain it by stepping through a typical range finding. It all begins by loading a number corresponding to the beacon you wish to activate into the SCI of the mobile agent. After doing this, the time is read from TCNT and stored for future use. The transmit pin of the SCI is connected to a Linx TXM 315 LC radio transmitter. As such, the signal loaded into the SCI is broadcast via radio. The beacon tree is equipped with a Linx RXM 315 LC radio receiver. This receiver is hooked into the receive pin of the beacon tree's SCI. The beacon tree polls its SCI until a signal is received. It then determines if the signal received was a signal to fire a beacon. If it was, the beacon tree uses a software loop to generate a 40 kHz signal on the pin of port B corresponding to the beacon requested. The tree produces this signal for about one millisecond and then begins polling the SCI again. Three of the pins of port B are hooked to the three ultrasonic beacons through what I call signal booster boards for lack of a better term. These booster boards are simply 4049 chips wired as shown in Fig. 4. I used this method of boosting transmitter power rather than the old method of using transformers and transistors, and it seems to be superior.

The output of the booster boards are sent to along to the transducers. I used five transducers linked in parallel for each beacon. The sound produced by the beacons then travels back towards the mobile agent and is picked up by a ring of six transducers. These transducers are hooked in parallel and fed into a MAX chip 40kHz receiver board. Schematics for this board are available on the IMDL home page and, as such, won't be reproduced here. I hooked the output of the receiver board to the input capture two pin of my mobile agent. When a signal is present on this pin, an interrupt is generated. Inside my interrupt handling routine, I immediately mark the time again and store it. The two times are then subtracted to arrive at a time of flight for the ultrasonic signal. There is always a constant error to be subtracted away as well. Once this is done you divide the result by 148

to arrive at a distance from transmitter to beacon in inches. This value would then be sent out over radio to the beacon tree. The beacon tree would recognize that the signals it was receiving were not beacon requests and print them to a nearby computer screen using the serial port. This process is repeated twice more to determine the distance to each beacon.

Once the distances to the three beacons has been determined the position of the mobile agent can be found. Recall the arrangement of beacons as shown in Fig 1. Let A be the distance between beacon 1 and beacon 2 in inches and B be the distance between beacon 1 and beacon 3 in inches. Given values for A and B, I derived the following formulae to determine the position of the mobile agent (the formulae are basically a consequence of the law of cosines):

X=((distance to beacon 1)^2 - (distance to beacon 2)^2 + A^2)/2A

Y=((distance to beacon 1)^2 - (distance to beacon 3)^2 + B^2)/2B

The values for X and Y would be sent out over radio to be displayed on screen much as the individual distances were. And that is position detection.

Behaviors

IAM had three main behaviors: wall following, position finding, and mapping.

Wall Following: When IAM was reset, it would immediately begin to trundle forward and would continue doing so until it encountered an obstacle. IAM would then enter wall following mode and would stay in this mode until it received a tap on its rear bumper. IAM would begin by turning until its left side was facing the obstacle. It would then circle the wall in a counter-clockwise direction. While wall following, IAM made use of its IR and bump sensors to navigate interior and exterior curves. When IR readings became too high it veered right, too low and it would veer left. It was also equipped with a rear wall detector that should always sense a nearby object. If this sensor ever went low, IAM would turn very sharply to the left. This system allowed IAM to move in a very tight loop around an obstacle with sharp turns but rarely veer into the wall.

Position Detection: This behavior was mainly a consequence of using the position finding sensors. IAM would poll a new beacon about once every 150 milliseconds. If it received no signal back it would continue polling until a signal was received.

Mapping: This behavior came about while performing the two previous behaviors simultaneously. IAM would record valid positions in two-dimensional array and dump these position to the screen when it received a tap on its rear bumper.

Experimental Layout and Results

IR Sensors: I measured distance versus analog port value for forward and side obstacles while testing my IR sensors. The data gathered is presented below in Tables 1 and 2 and Figs. 5 and 6.

Position Detection: While not moving, my position detection worked well. Beacon distances had an accuracy around ± 2 inches. This lead to position readings ranging from dead on to about a foot off in the X and/or Y directions. While moving, my position detection was more or less completely unreliable.

Conclusion

I feel that I accomplished many things during the course of this project. I created an excellent wall following algorithm. I introduced a new way to power ultrasonic transmitters without having to use the horrible, nasty, burning audio transformer method. I then used this new technique to create a fairly accurate tracking system. In the end, though, my robot did not map. As such, I mainly consider my project to be a failure.

I feel, though, that with two simple changes, my project would have been successful. First, I should never have tried to take position readings while moving. This was painfully obvious in that my tracking system failed entirely when I tried to do so. Instead of attempting to take reading on the fly, I should have paused the robot each time I attempted to locate my position. Since the tracking system worked while stationary this would have solved almost all of my problems. The second change I should have made was to slow things down. I tried to sample the beacons as quickly as possible in order to get accurate readings while moving. This would often cause me to send a new beacon request while ultrasound from the last one was still bouncing around. This, of course, gave me spurious distance readings. While recently tinkering with my project, I increased the pause between reading to one second and all of my readings calmed down.

With these minor changes in place, I feel that I've mostly solved the problem of tracking a robot's position. Improvements in accuracy could definitely be made though. Two improvements come readily to mind. The first is to increase the distance between the beacons. I placed my beacons a scant 27 inches apart. Moving this out to several feet would increase the accuracy of the determined position. The second is to place more beacons about the area. Adding more beacons would allow you to determine your position from more than one source. Independent position readings could then be averaged to improve accuracy.

I'd like to conclude this report with a quote by Jack Handy. At many points during the semester I understood exactly where he was coming from:

"Probably the main problem with owning a robot is when you want him to go out in the snow to get the paper, he doesn't want to go because it's so cold, so you have to get out your whip and start whipping him, and the kids start crying, and oh why did I ever get this stupid robot?"

References

This project was made possible by:

•	Motorola and Maxim, for donating parts

•	Mekatronix and past IMDL'ers, for creating such useful things as the Talrik platform, hacked IR sensors, and 40kHz receiver boards

•	Toshiba and Eric Anderson, for showing me there are different ways to boost ultrasonic transmitters than the horrible, evil, fire-summoning audio transformers

•	Scott Jantz and Ivan Zapata, without whom I'd still be trying to get the hang of this whole soldering thing

•	Dr. Arroyo, for convincing me I could handle IMDL and senior design in the same semester

Appendix A: Code

#include <analog.h>

#include <motorme.h>

#include <clocktjp.h>

#include <isrdecl.h>

#include <vectors.h>

#include <servome.h>

#include <stdio.h>

#define LEFT_MOTOR 0

#define RIGHT_MOTOR 1

#define MAX_SPEED 100

#define ZERO_SPEED 0

#define AVOID_THRESHOLD 115

#define FRONT_IR analog(1)

#define RIGHT_IR analog(2)

#define LEFT_IR analog(3)

#define FRONT_WALL_IR analog(6)

#define BACK_WALL_IR analog(7)

#define FRONT_BUMP analog(4)

#define REAR_BUMP analog(0)

#define TRUE 1

#define FALSE 0

#define PAUSE 30

#define TDRE 0x80

#pragma interrupt_handler TIC3_isr

unsigned int time1,time2;

int dist1,dist2,dist3,coord1,coord2,coord3;

int match1=FALSE,match2=TRUE;

int index=0,signal=1;

void findObject(void);

void circObject(void);

void alignToWall(void);

void goForward(void);

void goBack(void);

void TIC3_isr();

void main()

{

CLEAR_BIT(TMSK2,0x03);

CLEAR_BIT(TCTL2,0x02);

SET_BIT(TCTL2,0x01);

SET_BIT(TMSK1,0x01);

CLEAR_BIT(SPCR,0x20);

asm("clr $102c\n");

BAUD=0xb2;

SCCR2=0x0c;

init_analog();

init_motorme();

init_clocktjp();

printf("\n\n\n");

printf("\n\x1b[1;1H%dDistance 1 Distance 2 Distance 3 X Position Y Position\n");

*(unsigned char *) 0x7000=0x07; /* turn on IR */

while ((SCSR & TDRE) == 0);

SCDR=0x0f;

wait(1000);

INTR_ON();

findObject();

circObject();

}

void TIC3_isr()

{

time2=TCNT;

if(TFLG1 & 0x01){

if(match1==match2){

match2=!match2;

if(index==0) {

dist1=(time2-time1-9916)/148;

printf("\x1b[3;4H %d \n",dist1);

index=1;

signal=2;

}

else if(index==1){

dist2=(time2-time1-9800)/148;

coord1=(dist1*dist1-dist2*dist2+784)/56;

printf("\x1b[3;18H %d \n",dist2);

index=2;

signal=4;

}

else if(index==2){

dist3=(time2-time1-9620)/148;

coord2=(dist1*dist1-dist3*dist3+625)/50;

printf("\x1b[3;32H %d \n",dist3);

printf("\x1b[3;46H %d \n",coord1);

printf("\x1b[3;61H %d \n",coord2);

index=0;

signal=1;

}

}

CLEAR_FLAG(TFLG1,0x01);

}

}

void findObject(void)

{

int irdf,irdr,irdl,irdfw,irdbw;

while(TRUE){

if(((irdfw=FRONT_WALL_IR)>AVOID_THRESHOLD)

|| ((irdl=LEFT_IR)>AVOID_THRESHOLD)

|| ((irdf=FRONT_IR)>AVOID_THRESHOLD)

|| ((irdr=RIGHT_IR)>AVOID_THRESHOLD)

|| ((irdbw=BACK_WALL_IR)>AVOID_THRESHOLD))

return;

motorme(RIGHT_MOTOR,MAX_SPEED);

motorme(LEFT_MOTOR,MAX_SPEED);

wait(PAUSE);

}

}

void goForward(void)

{

int i;

for(i=0;i<35;i++){

motorme(RIGHT_MOTOR,MAX_SPEED);

motorme(LEFT_MOTOR,MAX_SPEED);

wait(20);

}

}

void goBack(void)

{

int i;

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

motorme(RIGHT_MOTOR,-100);

motorme(LEFT_MOTOR,-20);

wait(20);

}

}

void circObject(void)

{

int irdf,irdr,irdl,irdfw,irdbw,stay=TRUE,timer=10;

int fbmp,rbmp,speedr,speedl,norm,i=0;

alignToWall();

while(stay){

if((i=(i+1)%timer)==0){

match1=!match1;

while ((SCSR & TDRE) == 0);

SCDR=signal;

time1=TCNT;

if(index==2) timer=14;

else timer=10;

}

irdf=FRONT_IR;

irdr=RIGHT_IR;

irdl=LEFT_IR;

irdfw=FRONT_WALL_IR;

irdbw=BACK_WALL_IR;

fbmp=FRONT_BUMP;

rbmp=REAR_BUMP;

speedr=MAX_SPEED/3;

speedl=MAX_SPEED/3;

if((irdr>AVOID_THRESHOLD+10)

|| (irdf>AVOID_THRESHOLD+10)

|| (irdl>AVOID_THRESHOLD+10)){

alignToWall();

}

else{

if(irdfw<93){

speedr=MAX_SPEED/2;

speedl=MAX_SPEED/4.5;

if(irdbw<89){

speedr=MAX_SPEED/1;

speedl=MAX_SPEED/5.5;

}

if(irdbw<AVOID_THRESHOLD){

speedl=MAX_SPEED/8;

}

}

if(irdfw>105)

speedr= MAX_SPEED/6;

if(irdfw>110)

speedl= MAX_SPEED;

if(fbmp<100) goBack();

if(rbmp<100) goForward();

motorme(RIGHT_MOTOR,speedr);

motorme(LEFT_MOTOR,speedl);

wait(PAUSE);

}

}

}

void alignToWall(void)

{

int irdf,irdr,irdl,irdfw,irdbw,stay=TRUE,speedr,speedl;

while(stay){

irdf=FRONT_IR;

irdr=RIGHT_IR;

irdl=LEFT_IR;

irdfw=FRONT_WALL_IR;

if((irdfw<irdr) ||

(irdfw<irdf) ||

(irdfw<irdl)){

speedr=-MAX_SPEED/4;

speedl=MAX_SPEED/4;

}

else {

speedr=speedl=0;

stay=FALSE;

}

motorme(RIGHT_MOTOR,speedr);

motorme(LEFT_MOTOR,speedl);

wait(PAUSE);

}

}