Arduino WiFi Indoor Positioning

Arduino WiFi Indoor Positioning cover

Locating people and objects as they move around a known, controllable environment is a common problem in many scenarios:

A few commercial solutions exists on the market, but they require you to invest thousands of dollars in proprietary technology.

This project will show you how you can implement your own indoor positioning system using open source Arduino hardware and free software with a minimal economic commitment, without writing any custom code!

What is Indoor Positioning?

As stated from Wikipedia, an Indoor Positioning System is a network of devices used to locate objects where GPS is not an option.

In the context of this project, indoor positioning refers to the ability of a device (an Arduino board) to recognize in which room/zone it is in a known environment.  For example: if you map your house, it can tell that you're in the kitchen, or in the bedroom, but it won't tell you how far from the front door you are.

How does it work?

To implement an indoor positioning system you need a number of hotspots (or repeaters) that emit a radio signal. Your device will hear the strength of those signals and use a machine learning model to detect in which location it currently is.

The system stays independent from the kind of radio you use. It can work with:

For the purpose of this project, we'll use WiFi because:

  1. you can find several Arduino boards equipped with WiFi
  2. if you live in an urban area, there are chances you are already surrounded by WiFi routers

How much accurate is Indoor Positioning?

It's hard to assess how accurate such an Indoor Positioning System can be.

It depends on a variety of factors:

Out of the box, you can expect a resolution of few meters.

Since the cost of hotspots can be as low as a few dollars (if you choose the ESP32s, for example), you can always add as much hotspots as your project requires to get the accuracy you need.


Now that the theory is done, let's move to the practice!

Prepare your environment

There is a single strict requirement to follow this project: an Arduino WiFi board and a basic knowledge on how to use it (load a sketch, open the Serial monitor).

You can find many on the market: any will do the job (ESP32, Arduino MKR WiFi 1010, Arduino MKR WiFi 1010...).

Map your area

The first step to implement your own WiFi Indoor Positioning System is to map the area you want to "navigate".

By mapping I mean you will walk around all the places you want to be able to detect, with the purpose to characterize each location. Each location will be defined by a set of {BSSID, RSSI} pairs, so we need to record these sets in as many points as possible to create a robust model.


What does BSSID mean? It stands for Basic Service Set Identifier and is the name of the access point. This name can be the network name (SSID), the MAC address, or any other unique identifier for the given access point.


What does RSSI mean? It stands for Received Signal Strength Indication and is a number indicating how strong a received signal is. The stronger the signal, the higher the RSSI.


Load the following sketch on your board.

See source

Filename: CollectOverWiFi.ino

/**
* Collect RTLS training data
* using WiFi
*/
#include <eloquent_rtls.h>
#include <eloquent_rtls/wifi.h>
#include <eloquent_rtls/collect.h>

using eloq::rtls::Collect;
using eloq::rtls::wifiScanner;

Collect collector(wifiScanner);


/**
 *
 */
void setup() {
    delay(3000);
    Serial.begin(115200);
    Serial.println("__RTLS WIFI__");

    wifiScanner.identifyBySSID();
    // or
    // wifiScanner.identifyByMAC();

    // set lower bound for RSSI
    wifiScanner.discardWeakerThan(-85);

    // print collection instructions
    collector.setup();
}


/**
 *
 */
void loop() {
    // collect data
    collector.loop();
}
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

The sketch is a WiFi scanner that prints to the Serial monitor the visible networks along with their RSSI in a format that is suitable for further processing.

For every location you want to be able to recognize:

  1. position yourself in the center and enter the name of the location. The detected hotspots will appear on the Serial monitor
  2. start moving around, go to the corners of the room / space, walk along the walls, then go back to the center
  3. after a decent amount of time, enter "stop" to stop the scanning (you should record at least 10-15 lines for each location)
  4. repeat the process for each room/space you want to map
    rtls-wifi.jpg 143.17 KB

When you're done, you will have a text similar to the following on your Serial Monitor.

Start scanning office...
{"__location":"office","SSID":-38,"PinguiniWifi":-74,"DIRECT-BA-HP DOMENICO":-75,"Linkem_ABCDEF":-77,"Wi-Fi_Casa":-77,"Wi-Fi_Ospiti":-77}
{"__location":"office","SSID":-41,"PinguiniWifi":-75,"Wi-Fi_Ospiti":-75,"Linkem_ABCDEF":-76,"Wi-Fi_Casa":-78,"DIRECT-BA-HP DOMENICO":-85}
{"__location":"office","SSID":-39,"PinguiniWifi":-75,"Wi-Fi_Ospiti":-76,"Linkem_ABCDEF":-77,"Wi-Fi_Casa":-77,"DIRECT-BA-HP DOMENICO":-83}
{"__location":"office","SSID":-48,"PinguiniWifi":-73,"DIRECT-BA-HP DOMENICO":-74,"Linkem_ABCDEF":-76,"Wi-Fi_Casa":-77,"Wi-Fi_Ospiti":-77}
Start scanning bedroom...
{"__location":"bedroom","Linkem_ABCDEF":-67,"SSID":-70,"PinguiniWifi":-71,"Vodafone-WiFi":-84,"DIRECT-BA-HP DOMENICO":-84,"PosteMobile_ABCDEF_2.4G":-85,"Vodafone-ABCDEF":-85,"Wi-Fi_Ospiti":-85}
{"__location":"bedroom","Linkem_ABCDEF":-65,"PinguiniWifi":-69,"SSID":-73,"DIRECT-BA-HP DOMENICO":-82,"Vodafone-WiFi":-84,"PosteMobile_ABCDEF_2.4G":-85,"Vodafone-ABCDEF":-85,"Wi-Fi_Casa":-85,"Wi-Fi_Ospiti":-85}
{"__location":"bedroom","Linkem_ABCDEF":-66,"PinguiniWifi":-71,"SSID":-74,"PosteMobile_ABCDEF_2.4G":-81,"Vodafone-WiFi":-81,"Vodafone-ABCDEF":-84}
{"__location":"bedroom","Linkem_ABCDEF":-66,"SSID":-70,"PinguiniWifi":-73,"Vodafone-ABCDEF":-83,"DIRECT-BA-HP DOMENICO":-84,"FASTWEB-ABCDEF":-85,"Vodafone-WiFi":-85,"Wi-Fi_Casa":-85,"Wi-Fi_Ospiti":-85}
Start scanning kitchen...
{"__location":"kitchen","PinguiniWifi":-51,"Wi-Fi_Casa":-69,"Wi-Fi_Ospiti":-69,"DIRECT-BA-HP DOMENICO":-73,"SSID":-74,"Vodafone-ABCDEF":-74,"Vodafone-WiFi":-74,"Linkem_ABCDEF":-85}
{"__location":"kitchen","PinguiniWifi":-51,"SSID":-68,"Wi-Fi_Casa":-69,"Wi-Fi_Ospiti":-70,"Vodafone-ABCDEF":-74,"Vodafone-WiFi":-74,"DIRECT-BA-HP DOMENICO":-75}
{"__location":"kitchen","PinguiniWifi":-51,"Wi-Fi_Casa":-66,"Wi-Fi_Ospiti":-67,"Vodafone-ABCDEF":-76,"Vodafone-WiFi":-76,"DIRECT-BA-HP DOMENICO":-83,"Wi-Fi_DiSavino":-85}
{"__location":"kitchen","PinguiniWifi":-52,"Wi-Fi_Casa":-65,"Wi-Fi_Ospiti":-65,"Vodafone-ABCDEF":-75,"Vodafone-WiFi":-75,"DIRECT-BA-HP DOMENICO":-77}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Train a machine learning model

Once you have mapped all your locations, paste the contents of the Serial monitor into the textarea below. If you don't see any complaint about syntax errors, hit the Train model button et voilà!

You fill find two code blocks when the training is done:

  1. Classifier.h is the classifier that will predict in which location you are
  2. FeaturesConverter.h will convert the scan results into a numeric feature vector that can be classified

Deploy

Now that you have those two files, create a new project and add them to it.

Then, add the main sketch below.

See source

Filename: PredictOverWiFi.ino

/**
* Collect RTLS training data
* using WiFi
*/
#include <eloquent_rtls.h>
#include <eloquent_rtls/wifi.h>
#include "Classifier.h"
#include "FeaturesConverter.h"

using eloq::rtls::wifiScanner;
using eloq::rtls::FeaturesConverter;

Classifier classifier;
FeaturesConverter converter(wifiScanner, classifier);


/**
 *
 */
void setup() {
    delay(3000);
    Serial.begin(115200);
    Serial.println("__RTLS WIFI__");

    wifiScanner.identifyBySSID();
    // or
    // wifiScanner.identifyByMAC();

    // set lower bound for RSSI
    wifiScanner.discardWeakerThan(-85);

    // print feature vector before predictions
    converter.verbose();

    Serial.println("Move around the mapped space...");
}


/**
 *
 */
void loop() {
    // scan & predict
    Serial.println(converter.predict());
    delay(1000);
}
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

Hit Upload and start moving around the space you mapped earlier: the predictions will appear on the Serial monitor.

rtls-prediction.jpg 396.68 KB

Subscribe to my newsletter

Join 1167 businesses and hobbysts skyrocketing their Arduino + ESP32 skills twice a month