Beacon Locating Robot – Powered by Arduino and IR Transceiver by Christopher Hazlett
After I built my first Arduino-based robot, I wanted to graduate to a little more advanced behavior, and I had it my mind to make a robot that would find a home base via an IR Beacon. Plus I saw that Pololu had the perfect parts for the job, the IR Beacon Transceiver pair. My wife was gracious enough to get me some IR distance sensors, a servo and the transceivers for my birthday in August. If she keeps supporting my hobbies like this, she'll have more robots than she can handle. As always, I'll start with the parts.
The Parts
I, of course, re-used parts from my last robot, but I'll include the links here as well. My robots are nothing if not a source of parts for the next robot.
- Arduino (1 @ $30.00 from Adafruit.com) - I actually got the Arduino Starter kit from Adafruit.com which also came with the 9V battery holder you see in the pictures and videos below.
- Arduino Motor Shield (1 @ $19.50 from Adafruit.com) - I used the motor shield again in this project because I only needed access to the six analog pins for the sensors on the Arduino and it's just so darn easy to use.
- RP5 Tracked Chassis (1 @ 49.95 from Pololu.com) - This chassis has proven to be very versatile and big enough to support a wide array of sensors.
- IR Beacon Transceiver Pair (1 @ 49.95 from Pololu.com) - Fantastic kit from Pololu.com (my favorite store for all things robotic. This acts as the core of the robot's sensors.
- Sharp GP2Y0A02YK0F Analog Distance Sensor 20-150cm (1 @ 13.95 from Pololu.com) - Pretty much your standard IR distance sensor from Sharp.
- GWS PICO Sub-Micro Servo (1 @ 15.95 from Pololu.com) - Great little servo. There's not much more to it than that.
- Pololu RP5 Expansion Plate RRC07A (Narrow) Solid Black (1 @ 6.95 from Pololu.com) - Pololu.com just recently started offering this gem and makes changing and building a robot on the RP5 chassis a little more like geek nirvana than it was before.
- Pololu RP5 Expansion Plate RRC07B (Wide) Solid Black (1 @ 11.95 from Pololu.com) - The bottom plate on the robot.
- Aluminium Standoffs (2 @ 1.95 from Pololu.com) - Little posts...nothing more, nothing less.
- Tamiya 70164 Universal Metal Joint Parts (2 @ 3.90 from Pololu.com) - These are great construction pieces to have lying around. I didn't actually use both kits, but I have two and I know I used scews and nuts from both.
I also used various crimped and un-crimped wires lying around that I use regularly, but that's a separate post.
The Robot
![]()

It's a pretty simple concept, place a home base somewhere and then have the robot find said home base from it's current location and make it's way there. When I first started thinking about how to execute this project, I thought it was going to be much more complicated to institute the seeking behavior I was looking for. The IR transceivers from Pololu.com were much better than I thought they'd be and had a lot of power. As you can see in the video below, the beacons are powerful enough to work around corners, so I never ended up putting a seeking algorithm in place. The beacon took care of that for me. All I had to do was make sure it avoided walls on its way to the home base. To accomplish that, I put the servo and Sharp distance sensor on the front and performed a sweep with the sensor and read the values from analog input 0. That's the bare bones of the robot.
The Home Base

For the home base, I took one of the transceivers and raised it to the height of the robot's head. This ended up being unnecessary. The robot would find the beacon if it was at any level. The home base didn't have to do anything, so I just powered it up and let it run.
The Code
There are a couple of gotchas when writing the code. Because the IR transceivers are always reading, I had to do a comparison of each reading to determine which of the directional sensors was the highest. You can't just read the input as an on or off. The second and harder portion of the code (and actually the most fun) was determining which direction to make the robot move. At first, I just let the robot move after determining which direction was currently being read from the beacon. In practice, this seems completely fine, but you'll see in the videos that the beacon itself changes directions quite frequently. This made the robot indecisive. To combat this problem, I figure out the Mode of the readings. Essentially, I took the last ten readings and counted what the most prevalent direction was. This smoothed out the robot's behavior and it behaved as expected.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 | #include <Servo.h> #include <AFMotor.h> #define TOPSPEED 200 // SERVO SCANNING VARIABLES // Servo myservo; // create servo object to control a servo int servoPosition = 0; // variable to store the servo position const int SERVO_PIN = 10; int floorState = 0; long frontReading = 0; boolean scanIncrement = true; //increase position? byte servoIncrementValue = 6; byte servoDecrementValue = 6; // MOTOR VARIABLES // AF_DCMotor rightMotor(4, MOTOR12_8KHZ); AF_DCMotor leftMotor(3, MOTOR12_8KHZ); // TRANSCEIVER VARIABLES // int notFoundSensitivity = 500; int west = 0; int south = 0; int east = 0; int north = 0; int dir = 0; boolean detected = false; // TRANSCEIVER DIRECTION MODE VARIABLES // const int NUM_READINGS = 10; int directionReadings[NUM_READINGS]; int modeOfDirections = 1; int index = 0; void setup() { Serial.begin(38400); myservo.attach(SERVO_PIN); // attaches the servo on pin 9 to the servo object myservo.write(0); rightMotor.setSpeed(200); leftMotor.setSpeed(200); delay(1500); } void loop() { scan(); move(); } void move() { if(servoPosition >= 0 && servoPosition <= 84 && frontReading > 550){ //Object on the left turnLeft(); }else if((servoPosition >= 85 && servoPosition <= 105) && frontReading > 600){ // Object in Front turnAround(); }else if((servoPosition >= 106 && servoPosition <= 180) && frontReading > 550){ // Object on the Right turnRight(); }else{ moveTowardBeacon(); } } void moveTowardBeacon() { readTransceiverandSetDirection(); if(modeOfDirections == 3 || modeOfDirections == 4){ //South or West turnRight(); } else if(modeOfDirections == 2) { // East turnLeft(); } else if(modeOfDirections == 1){ //North moveForward(); } } void scan() { scanIncrement ? servoPosition+=servoIncrementValue : servoPosition-=servoDecrementValue; //increment or decrement current position if (servoPosition >= 180){ scanIncrement = false; servoPosition = 180; } else if (servoPosition <= 1){ scanIncrement = true; servoPosition = 1; } frontReading = measureFront(); //Serial.print(servoPosition); //Serial.print("|"); //Serial.print(frontReading); //Serial.print(";"); myservo.write(servoPosition); delay(15); } long measureFront() { return analogRead(0); } void moveForward(){ Serial.println("Move Forward"); rightMotor.run(FORWARD); leftMotor.run(FORWARD); } void speedUp(){ for (int i=0; i==TOPSPEED; i++) { rightMotor.setSpeed(i); leftMotor.setSpeed(i); } } void slowToStop(){ for (int i=TOPSPEED; i==0; i--) { rightMotor.setSpeed(i); leftMotor.setSpeed(i); } rightMotor.run(RELEASE); leftMotor.run(RELEASE); } void turnLeft(){ Serial.println("Turn Left"); rightMotor.run(BACKWARD); leftMotor.run(FORWARD); } void turnRight(){ Serial.println("Turn Right"); rightMotor.run(FORWARD); leftMotor.run(BACKWARD); } void stop(){ Serial.println("Stop"); rightMotor.run(RELEASE); leftMotor.run(RELEASE); delay(500); } void turnAround(){ stop(); delay(500); moveBackward(); delay(300); turnLeft(); delay(300); stop(); //runAway = true; } void moveBackward(){ Serial.println("Move Backward"); rightMotor.run(RELEASE); leftMotor.run(RELEASE); rightMotor.run(BACKWARD); leftMotor.run(BACKWARD); } // BEACON LOGIC // void readTransceiverandSetDirection(){ west = analogRead(2); south = analogRead(3); east = analogRead(4); north = analogRead(5); getDirection(); setModeOfDirections(); } boolean foundBeacon(){ if(west < notFoundSensitivity and east < notFoundSensitivity and south < notFoundSensitivity and north < notFoundSensitivity){ return false; }else{ return true; } } void getDirection(){ int minValue = 1200; if(minValue > west){ minValue = west; dir = 4; } if(minValue > south){ minValue = south; dir = 3; } if(minValue > east){ minValue = east; dir = 2; } if(minValue > north){ minValue = north; dir = 1; } addDirectionToReadings(); //Serial.print("W:"); //Serial.print(west); //Serial.print(" | S:"); //Serial.print(south); //Serial.print(" | E:"); //Serial.print(east); //Serial.print(" | N:"); //Serial.println(north); //Serial.println("================================="); //if(dir == 1){ // Serial.println("North"); //}else if(dir == 2){ // Serial.println("East"); //}else if(dir == 3){ // Serial.println("South"); //}else if(dir == 4){ // Serial.println("West"); //} } void addDirectionToReadings(){ directionReadings[index] = dir; index = (index + 1); if (index >= NUM_READINGS) // if we're at the end of the array... index = 0; } // ========================================= // In order to smooth out the directions readings from the // IR transceiver, You have to take the mode (most prevalent number in a collection) // of the directionReadings Array. This allows the program to determine which // direction is being read the most from the device. // Otherwise, the readings make the robot squirrelly. // ======================================== void setModeOfDirections(){ int currentValue = directionReadings[0]; int counter = 1; int maxCounter = 1; int modeValue = modeOfDirections; int directionCounts[4] = {0,0,0,0}; //{North(1), East(2), South(3), West(4)} for (int i = 1; i < NUM_READINGS; ++i){ Serial.print(directionReadings[i]); Serial.print("|"); ++directionCounts[directionReadings[i]-1]; } //Determine mode of directions from count array Serial.println(""); int modeCount[2] = {1,directionCounts[0]}; //This array holds the current maximum count and the direction it points to. for(int i = 0; i < 4; ++i){ //Serial.print(directionCounts[i]); //Serial.print("|"); if(modeCount[1] >= directionCounts[i]){ modeCount[0] = i + 1; // set direction modeCount[1] = directionCounts[i]; //set count } } modeOfDirections = modeCount[0]; Serial.println(""); Serial.print("Direction Mode: "); Serial.println(modeOfDirections); } |
There you have it. Let me know if you have any questions about the code or construction.
- Chris
June 4th, 2010 - 07:52
Hi Chris,
I’m doing an MSc and my thesis is about path following. I just bought the Pololu Beacon (hopefully i’ll receive it next week) to achieve a path following algorithm. I’m going to implement the first beacon on a RC car (Leader) and the second one on an autonomous robot (Follower).
I saw that you used a 9v battery for the IR beacon, is that enough ? I mean the Voltage range is 6-16V and maybe the IR signal range could be higher if we use 15V battery, what do you think about ?
Another question: the IR beacon gives the direction of the leader (+- 25°) right, but what about the range of the IR LEDs and sensor. I mean is it possible to determine the distance between the two beacon just from the output signal of the IR sensor ? Is there any kind of signal proportionality from the distance ?
I am asking this because I would like to try to implement a fuzzy logic controller with the bearing/distance as input and velocity/angular velocity as output.
Thanks and good job by the way =)
Guillaume
June 9th, 2010 - 10:44
@Guillame
The voltage seemed like enough. I could get at least 25 feet away from the base and the robot would find it just fine. For me it was just that operating the motors, arduino and ir beacons was more than one 9v power supply could handle.
I’m not sure about distance. I found that It was easier to determine direction than distance in this project. However, determining distance wasn’t my goal. With some experimentation, I think it’s possible, but you may need to check on the Pololu forums to see how others achieved it. I would hook up my robots and run a few tests, but everything is boxed up (I just recently moved) and I was rolling my own motor shield before I moved (which wasn’t working quite right).
Good luck. Let me know how you fair.
- Chris
[WORDPRESS HASHCASH] The poster sent us ‘0 which is not a hashcash value.
July 16th, 2010 - 03:04
Hi Chris
Thanks for the reply.
I received my Pololu beacon pair last month and I could test it on my robot. The range of the IR beacon is really impressive and much better than the 20″ feet announced on the website.
Anyway I have implemented the beacon on my robot but I just get the orientation of the other beacon (North, East, South and West), no way to get the distance between the 2 devices. So I will have to trust the US sensor to avoid the collision with the leader.
I design just a simple algorithm (not C code) for the ATOM-pro PIC (my robot’s controller). And the first observation are that it can reach the other beacon –> that is a win =)
What about you ? Have you made some progress on your project or it is still boxed up ?
Byebye
Guillaume
July 22nd, 2010 - 05:50
by the way, here is a video you can see the robot motion. it is not so fluid right now so I have to make to code better.
http://www.youtube.com/watch?v=t3XzdJa_PiA
Guillaume
August 6th, 2010 - 16:23
@Guillaume
The robot looks great. Sorry I haven’t been monitoring comments as of late, but I’m finally getting back to work on electronics experimentation and I’m working on some posts. I have unboxed everything and have set up a great workbench with all my parts and what not.
The robots look really nice. Are you writing up your project experience anywhere, or would you like to? Send me an email: chris at robotishappy.com.
- Chris
October 29th, 2010 - 10:34
hi chris,
i’ve read Pololu IR Transceiver pair datasheet. it stated that this type of sensors produce digital output. so, why u connected this output pins of sensors to the analog input of microcontroller? are this sensors produces analog output? i’m confuse rite now..
November 6th, 2010 - 22:49
If that thing can find it’s way back home again I wish it would teach my stupid dog to follow him.
January 26th, 2011 - 02:39
Hi Chris,
thank you for this post. It’s really helping with my final year project requirements. If you don’t mind can you please email to me all the circuit connection?my email:suhaimirosti@yahoo.com.Thanks a lot.
February 3rd, 2011 - 17:54
Hi! This is great. Actually, you inspired our project.
Problem is, how can we know if the robot is indeed at the base? I don’t understand why the code you posted checks if ALL the receivers are below 500, and if so, the beacon is NOT found? Are you saying that if the robot found the beacon, ALL receivers will output HIGH? Please email me if you have the time. Thanks!
February 4th, 2011 - 22:20
Hi Chris,
We are 4th year Mechanical engineering students assisting the US Army to develop a hexapod robot with Reconnaissance capabilities at a specified “target” (in this case “Home Base”). Your robot has inspired us to go with the polulu IR transceiver route. We would greatly appreciate if you could assist us with the Hardware/Construction aspect of your design with either more pictures or a schematic.
I can be contacted at ss10@umbc.edu
Thank you for your time and help.
March 5th, 2011 - 20:01
I was just wondering if I could get a schematic of your robot. I am new to robotics and I think it would be helpful in my trying to figure this stuff out.
Thanks
May 21st, 2011 - 17:46
Hey Chris,
I could you please send me the schematics for this robots, im starting out with the arduino and this will help me out alot thanx. Please email me if you have the chance.
October 2nd, 2011 - 01:57
Hi Chris.
I am currently taking BEng and may i know that what is the usage of your servo? Is servo driver nessesary? Thanks for your reply.