Introduction: Robotic Indoor Navigation With RFID/NFC Tags

About: I am a Ham Radio operator, computer geek, robotic hobbyist. I've been "playing" with microcontrolers for the last several years, basic stamps, arduinos, and arduino like controllers, Raspberry PI, PICs & PICax…

The idea is to use RFID/NFC tags placed in a grid pattern on ground. The robot contains a "map" of the RFID/NFC tags ID numbers. and Using this number knows where it is on the map. (under the strictest this robot uses NFC)

I am using a small home/student/educational robot called a Bitty Bot Rover - It's a 2 wheeled robot, with a Arduino Mega 2560, and L298 motor driver. The battery is 9v. It's a simple 2 wheeled robot, and any should work for this project.

The project is still a work in progress, but I will admit, it's a slow work in progress. And a prove of concept for a 2 wheel robots.

Introduction: This type of indoor location has been used for years inside factories and warehouses. Mainly with 4 wheeled robots that are expensive, and have some type of omin-wheel (meaning they can move in all 4 directions just by turning the wheels in different directions) Here is a video of one of the industrial robots

My robot is different in costs (under $100 and in some cases under $50 depending on the robot cassie used)

uses only 2 wheels, and can not move in all four directions without turning the whole body of the robot.

Turning the body of the robot was the biggest challenge of this project.

Step 1: What Is RFID/NFC?

RFID (Radio Frequency IDentification) is the use of radio waves to read and capture information stored on a tag attached to an object. A tag can be read from up to several feet away and does not need to be within direct line-of-sight of the reader to be tracked.

There are two types of RFID tags. Active and passive. An active RFID tag includes their own power source giving them a range of the signal of up to 100 meters.
A passive RFID tag doesn’t contain its own power source. The tag is activated by the electromagnetic energy transmitted from the RFID reader. The disadvantage of the passive RFID tags is the lowest range of the signal which is around 25 meters. A much smaller range compared with the active RFID tags.

NFC stands for Near Field Communication. Essentially, it's a way for your phone to interact with something in close proximity. It operates within a radius of about 4 cm and provides a wireless connection between your device and another. NFC is a specialized subset of the RFID technology which uses radio waves to identify the items. The NFC systems operate at the 13.56 MHz frequency, and the technology is capable of using the same NFC device as an NFC reader and an NFC tag. This unique feature of the NFC technology allows NFC devices to communicate peer-to-peer.

These NFC tags don’t require a power source like other methods do. The disadvantage is the short range when the device is detected. Your robot should be around 30 cm away (or less) from the chip to read its serial number.

Step 2: Parts & Skills Needed.

Other than a two wheeled robot (hopefully already put together,and working).

You'll need a RFID tag reader - I used RC522 RFID for Arduino M5 MFRC-522 Radiofrequency Inducing Reader Sensor, and found it on eBay for around $3.00 U.S. Dollars with shipping.

You may find it a little cheaper on Aliexpress, or just searching a bit on eBay. This is a SPI device, and has good support. You don't need any special library to use it.

These are 13.56Mhz passive readers, and support the following types of tags:

Supported card types: mifare1 S50,mifare1 S70, mifare UltraLight, mifare Pro, mifare Desfire

This is important to know, since you'll need to get tags that are supported by your reader.

Next you'll need the NFC tags: Again I found them on eBay, but there are many choices - the important thing here is that your reader will read them. For my project I made a 3 x 5 grid (15 tags), as I said before a prove of concept. I want to scale this up to room size (100s of tags). So Depending on what size you want your project will determine how many tags you need. (I would get more than you need, that's just me thou) Generally this is one of those items it gets cheaper to buy more. 50 tags are just under $16 U.S. dollars or $0.32 cents a tag.

A 3x4 Membrane matrix keypad (used to set a location to go to) - These fluctuate in price between $3 and $7 dollars (I don't know why)

The keypad library is needed:

A HMC5883L Triple Axis Compass about $2.00 U.S. Dollars. Found this on eBay, but again check around, there maybe cheaper places to buy it from.

** I used foam board to make a antenna mast, and lay my NFC grid out on. Foam board is under $2.00 at the "dollar" store. I'm not including it in the parts/break down because you may want to use something else.

A Parallax (9600 baud) Serial 16x02 LCD screen - I choose this screen because I had it sitting, not using it. Because it's a serial screen I didn't need anything extra (no extra librarys). It could just be hooked up to the RX line of the Arduino, and display. These are expensive at $25 plus shipping. A cheaper alternative is the Tinkerkit LCD module (16x02) these can be found on eBay/Amazon, and maybe some other places for around $7.00

**I have a couple of the TinkerKit LCDs, I've not tried it with the Robot, but they should work if you flash them with the Leonardo bootloader and a slightly modified version of Sparkfun Serial LCD code - both are beyond the scoop of this instructable, but

Tinkerkit LCD have a Leonardo MCU, making them a good deal for $7.00)


The RFID tag reader, HMC5883L typical come with the pin unsoldered, so minor soldering is required.

This Instructables doesn't go into building your robot, so some software skills will be need to adapt the code for your uses.

Final List:

  • RFID tag reader $3
  • NFC sticker tags $16
  • 3x4 Membrane Matrix Keyboard $7
  • HMC5883L Compass $2
  • 1602 Serial LCD $25 or $7

Total: $53 or $35

2 Wheeled Robot w/Arduino Mega and L298 driver $?? $20 to $50

Step 3: Make Your Grid.

This is one of the easier steps, We need to decide how big you want your "map" to be.

For me I was limited to a 2ft by 3ft area, and was only able to make a 3x5 grid.

So for me I drew three lines about 6 inches apart from each other, these became the rows.

And at a right angle to those lines I drew 5 lines also about 6 inches apart.Making the columns for my grid.

At each intersection I wrote the row and column number starting with 0,0 and going to 2,4.

A NFC tag will be placed at each intersection, and a "map" will be created inside the Arduino Sketch.

Location 0,0 is the top, left corner of my map. While Location 2,4 is the lower right corner.

We end up with 15 intersections.

Step 4: Reading Your Tags Getting the Checksum or Serial Numbers

Each tag contains some information on it already. And some tags can have information written to them, some can not. For this project we are not interested in writing to the tags, just reading the serial numbers so we can start to make a map for the robot to follow.

In the above video I use the numbers from the tags to turn on and off leds.

The RC522 is a SPI device, and needs to be hooked up to the SPI bus of the Arduino you are using. We are going to use the Serial monitor and read the tags.

For this I will use a UNO, The reset pin will be connected to PIN 5, SS to PIN 10 (PIN 53 on the MEGA), MOSI to PIN 11, MISO to PIN 12 and SCK to PIN 13.

We are going to use this sketch:

Load the sketch on your Arduino, open the serial console, and hold a tag in front of the reader.

In the serial console you should see a number, this is a number (that so far) has been unique to each tag.

What you will want to do is record the number next to the row and column number of your grid. In the picture above you will see a tag has the number 173 and another has the number 203. I place the sticker (tag) on my grid the 1st tag at 0,0 and record 173. The next tag at 0,1 and record the number 203, I continue until I have all 15 intersections covered with a NFC tag.

Soon we will record those numbers in the sketch (Near line 184 to 190)

//Map//My Gird is 3 x 5 (0,0 to 2,4) - I am using the "Checksum" of the RFID tags

int codes[ROWS][COLS] = {



  {143,133,187,177,183},};  //Map of NFC codes 67 is location 0,0 183 is location 2,4

From this you can see the rows and columns of your grid.

Step 5: Once You Have Your Grid....

We will move the RFID reader to the bottom of your robot,

We will connect it to the MEGAs SPI bus, So,

MISO to pin 50,

MOSI to pin 51,

SCK to pin 52,

SS to pin 53,

RST will be connected to D5

The prototype robot I have doesn't have great mounting options on the bottom. It's mostly flat, and that turned out to be a plus for mounting it. I ended up using a lot of electrical tape to hold it in place.

I found that it was better to mount the reader close to the center of the wheels. My early tests (and the videos) have the sensor a little bit more forward. It caused the robot to not spin quite far enough because it could read the next tag too soon. Have the sensor a little more centered does seem to correct that issue.

Since you will most likely have a different robot, mounting will most likely be different. Electrical tape works surprisingly good thou.

Step 6: Adding the 3x4 Keypad and LCD

If you haven't already done so, Grab the library from

There is also a good tutorial on how a matrix keypad works.

Here is another good tutorial:

The basic idea is similar to how we made a grid map of NFC tags. We are going to make a "map" of what the keypad physical looks like in the memory of the Arduino. The biggest difference is we use 7 digital inputs to read the button pushed.

When we call the keypad routine, we are scanning those inputs to and see if a "PIN" from the "ROWS" gets shorted to a "PIN" from the "COLUMNS" - using that information, we look at our map to tell us which key was pushed.

This key of keypad is very common in hundreds of electronic devices.

Wiring it up to the MEGA - so one of the pictures above shows a 4x4 keypad matrix, We are using a 3x4 keypad. The reason I've included it is because I couldn't find a picture of the pin numbers. And this one has the same pin layout, only we don't have a pin 8 ours stops at pin 7.

So on the Keypad

Pin 1 will connect to Pin 49

Pin 2 will connect to Pin 47

Pin 3 will connect to PIn 45

Pin 4 will connect to Pin 43

Pin 5 will connect to Pin 41

Pin 6 will connect to Pin 39

Pin 7 will connect to Pin 37

I made a small stand out of foam board and used electric tape to tape the keypad to it.

The stand is about the same size as a standard servo, it fits nicely in the servo hole in my robot. Since it is very unlikely you have the same robot, you'll need to come up with your own way to mount the keypad.

The Parallax 16x02 LCD - As I said in the parts list, I used this LCD because I had it, it was serial (rs232/ttl), didn't need any additional libraries. It is 9600 baud, And very simple to use, Just plug it into pin 1 of the mega. It needs 5 volts.

I had mentioned the tinkerkit LCD, and while I have not tried it with this, it should work just fine, running the modified Sparkfun firmware I linked to earlier. It should just be plug in and use it.

(I'm trying to remember) I don't think I used any Parallax command codes, but if I did they are easy enough to


I had a small "L" bracket and used that mount one side of the LCD to the top of the robot, problem, it moves around a bit, but is usable.

Step 7: Installing the HMC5883L Compass.

To keep the compass from getting interference from the motors I made an antenna mast out of foam board.

At the base (attached to the robot) are two brackets made out of foam board, this helps keep the whole thing stable. I cut to long strips, and glued them together, and near the top, glued another small bracket that holds the compass module.

The compass is a I2C device, so it only needs two wires, voltage and a ground.

The compass.h, and compass.cpp are semi-custom libraries based on code from the "Official Arduino Robot", actually, the Official Arduino Robot uses a different compass. The Duinopeak Clone of the official robot uses the HMC5883L.

The Duinopeak robot is based off the Official Robot, but technically my code is based off the Duinopeak code.

Confused! Don't worry - We are almost ready to run the robot.

The most important thing here is the compass must be as level as you can possible make it. There is a calibration routine that can be run at the start up of the robot. Sometimes it helps, sometimes not so much.

Keeping it level always helps!

Step 8: Almost There - It's Code Time!

You will find the code here:

There are two sketches in the repository, one that is a early version, that doesn't use a compass - the first video in this instructable shows how that one works. The second sketch has the compass working (more or less). The line numbers here are for the 1st sketch, they will be slightly different if you are using the compass - but are pretty close to where they were.

Near Line 181 you'll fine something like this in the code:

<p>#define ROWS 3</p><p>#define COLS 5<br></p><p>//Map</p><p>//My Gird is 3 x 5 (0,0 to 2,4) - I am using the "Checksum" of the RFID tags</p><p>int codes[ROWS][COLS] = {</p><p>  {67,121,127,117,107},</p><p>  {137,147,157,103,97},</p><p>  {143,133,187,177,183},};</p><p>  //Map of NFC codes 67 is location 0,0 183 is location 2,4</p>

This is where you'll insert your NFC ID numbers that you previously recorded. You can make more rows or columns as need.

Near line 202 you'll find some speed settings (These numbers are PWM numbers and not true speed numbers)

<p>int leftspeed = 50;</p><p>int rightspeed = 50;</p><p>int turnDelay = 2000;</p><p>int forwardSpeed = 75;</p>

You may or may not need to modify these based on your motors, power and gear ratios.

At line 207 you'll find:

<p>BittyBot bot(44,46,36,38,40,42); //Left Enable, Right Enable, Pin1 for Left, Pin2 for Left, Pin 1 for Right, Pin 2 for Right</p>

See the next section for usage. The basics of this however are the PIN numbers of where your L298 motor is hooked up.

At line 218 to 226 you'll see the setup for the keyboard matrix, you shouldn't need to change this if you are using the same keypad and pins I am using. However if you need to make changes - this is where to do it.

Step 9: A Custom Library (BittyBot2)

My robot is called a Bitty Bot Rover - mine is a prototype (I still use it even thou there have been many improvements to the design). It is one of the better designs I've seen in a low cost robotics platform.

A small group of people were given these and asked to make changes, and software this was in late 2014.

One thing I thought was needed was a library for the motors. It's a simple library that contains the basics Forward, Backward, Left, Right, etc. The advantage here is the robot can be doing other things (updating sensors, printing to screen, etc) while it's moving. There are of course other ways to do this. And I'm not saying mine is the best (in fact it probably needs some work). However it's simple, and it works well for me, and for this project.

There are a couple of things you need to know. The library works like most other libraries, and needs to be put in the library directory for your Arduino IDE.

Next: In the RFID_Indoor_robot_navigation.ino sketch find this line:

BittyBot bot(44,46,36,38,40,42); //Left Enable, Right Enable, Pin1 for Left, Pin2 for Left, Pin 1 for Right, Pin 2 for Right

It should be line 207. This is the important line to change for your robot.

What it's saying is we are using 6 wires to control the L298 motor driver. On the Arduino Mega 2560 pin 44, and 46 are both PWM pins. So we are using the Enable pins of the L298 for speed control.

Pin 1 for Left is IN1 on the L298 Board, Pin 2 for Left is IN2, Pin1 for Right is IN3 and Pin 2 for is IN4

Typical that is all that needs to be changed, however we want to test your robot to see if it goes forward correctly.

There is an example in the library called (forwardback.ino) Load that sketch, and you'll see the same

BittyBot bot(44,46,36,38,40,42);

Line it should be line 6 (near the top this time). You'll want to populate it with your motor settings.

Run the sketch if your robot goes (mostly forward) for a short distance, and then goes (mostly backward) for about the same short distance you have the correct settings. And can proceed to load your robot with the RFID_indoor_robot_navigation.ino sketch.

If it doesn't act as expected, try to flip your pin numbers; IE: Left P1 becomes Left P2, and Left P2 becomes Left P1 (in my case, we would flip 36, 38 so it would look like this:

BittyBot bot(44,46,38,36,40,42);

** You can also modify the forwardback.ino sketch to include turning left and right


while (bot.IsRunning()) {

Serial.println("Bot Running");




while(bot.IsRunning()) {

Serial.println("Bot Running");



IF your robot doesn't move at all, make sure the ENABLE PINs are connected to a PWM pin on your Arduino.

IF it still doesn't move try to increase the speed in the sketch, each motor is a little different.

Some other things in the library include:




bot.IsRunning(); is a flag one means the robot should be moving, not that it is moving, a zero says the robot should be stopped (and it should be)

bot.update(); This checks to see if the time has expired, and stops the motors It is important to use this function often.

(bot.calibrate()) was commented out, at one time I was using a hall effect sensor to count wheel rotations, the wheels had to start in the same spot each time, and that is what calibrate did. It worked, but I found it didn't work as well as I liked.

This library works very much like 'Blink_without_delay' example, with the big change to run motors.

Some known issues:

PWM is used on the ENABLE PINS (Yes, that could be a big problem).

IT uses 6 wires, where 4 wires would do the same job. (Yes, we can get motor direction and speed control using just 4 wires, and only 2 PWM pins)

For people who are only using 4 wires:

Which is another simple library I wrote, but it just uses four wires (2 PWM, and 2 DIGITAL) hooked to the L298. With this library, leave the jumper connections on the L298 boards enable pins.

This library was written for use with a Robot called the Bitty Bot Compact Rover, which is a very small robot based on the UNO board.

You will have to make a number of changes to the RFID_indoor_navigation.ino sketch to use the library, but it shouldn't be too hard to do. Since this library is based off the BittyBot2 library.

I'm not going into it completely here But here is what you need to know:


#include "BittyBot2.h" to #include "CompactRover.h"

BittyBot bot(xx,xx,xx,xx,xx,xx); to CompactRover bot(Left Pin, LEFT PWM, Right PIN, Right PWM)

Left PIN = IN1, LEFT PWM = IN2, Right PIN = IN3, Right PWM = IN4 - you probably should run the forwardback.ino example. This is a more advanced way to control your motors, so troubleshooting will be more difficult.

The next thing to know is you need to add a speed to your forward, back, right, left calls. IE:

bot.forward(TimeON, PWM);

Speed is the wrong thing to call PWM, but at the time it seemed right. Otherwise the CompactRover library works very much like the BittyBot2 library.

Some Issues with using 4 wire:

It is harder to troubleshoot.

Step 10: The Updated Video.

This is the updated video, and a brief explanation of how it works.

If you are using the compass sketch - the robot will ask a few questions at the start.


If you want to calibrate the compass, hit "1" if not any other key.

Next it will ask for a Row and Column to go to - if you tell it somewhere off the map, it will say "Out of Bounds"

Following that it will ask which direction it's facing?

1=U, 2=R, 3=D, 4=L

1=Up, 2=Right, 3=Down, 4=Left

Location 0,0 is considered to be at the Top Left of the map, and Location 2,4 is considered to be the Lower Right.

(IF you have more locations, your last grid point will be the lower right).

The robot, starts a short count down, reads the NFC tag it's sitting on, and proceeds to the target location you told it to goto.

The robot needs to know which direction it is facing in order to figure out where the next point it needs to go is at.

It's all about the math at this point.

IF TargetRow > CurrentRow = Move Down

IF TargetRow < CurrentRow = Move UP

IF TargetColumn > CurrentColumn = Move Right

IF TargetColumn < CurrentColumn = Move Left

IF TargetColumn equals CurrentColumn && TargetRow equals CurrentRow we are at target and Stop!

We are always looking for the CurrentRow and CurrentColumn with the RFID scanner. And always updating the location with the map. The robot can get off, if it's told it's starting in the wrong direction. But as long as it's heading is the heading it thinks it's going it will get to it's target.

The robot is slow at this point. And is still a work in progress.

This repository has some of my test code, and some non-working examples

Step 11: Known Issues.

As a prove of concept this little robot works pretty good.

There are a couple of problems that I know of.

The biggest is if it thinks it facing one direction and it is really facing another direction it doesn't have any way to self correct (I haven't quite worked out how to do that yet).

The other issue is it's pretty slow, and when you look at the industrial robot from the early video, you see just how slow it really is. (I'm probably not going to do anything about the speed, but something to consider).

The compass can get off if there is a lot of metal or motor noise. It also needs to be very level to work correctly.

That about it for now. Thanks for getting to the end of this instructables I hope you enjoyed it as much as I enjoyed building the robot.

Automation Contest 2017

Participated in the
Automation Contest 2017