Measuring distance with Bluetooth in indoor environment using Python
June 13, 2022Bluetooth ranging technology is very popular. There are many localization systems that exist based on beacons. Beacon technology usually estimates the distance between devices using the received signal strength (RSSI).
Bluetooth can be an excellent way to narrow down a search area at close distances when tracking something. This feature can be used in several fields. such as Secure Locks for Buildings and Automotive, Asset localization & tracking, Indoor navigation etc
GPS tracking isn’t excellent at giving accurate measurements of the close distance, especially in the indoor environment. On the other hand, Bluetooth is excellent in short ranges because the waves can go through walls. This might fill the gap that GPS tracking has when tracking devices in indoor spaces.
However, most calculations of the distance between two Bluetooth devices are estimates. It’s hard to determine the exact distance between two Bluetooth devices because many factors affect the calculations. Despite the challenges, there are methods to determine the distance between two Bluetooth devices with an accuracy of at least 80%.
The ranging method is simple to implement, and it has the formula to calculate the distance between two Bluetooth devices. As the name suggests, both devices need to be within Bluetooth range to estimate the distance.
This article will share a simple python script to determine nearby Bluetooth devices and their distance in meters.
This script scans for nearby Bluetooth devices and gets an approximation of the distance by using the well-known RSSI to distance formula.
Read more about how to calculate the distance
Requirments
- Bluetooth Low Energy USB dongle BleuIO (https://www.bleuio.com)
- Pyserial.
Instructions
- Get the script from GitHub at https://github.com/smart-sensor-devices-ab/python_bluetooth_device_distance_meter.git
- Connect the BleuIO to your computer. The script uses pyserial to connect to the Bluetooth USB dongle BleuIO.
- Update the script and write the correct COM port, where the dongle is connected.
- After connecting to the dongle, we put the dongle into the central role so that it can scan for nearby Bluetooth devices.
- Then we do a simple Gap scan using AT+GAPSCAN=3 command to scan for nearby Bluetooth devices for 3 seconds.
- After that, we read the output from the serial port and use our RSSI to distance formula to get the distance in meters.
- Finally, we sort the result by distance before printing it out on screen.
Here is the final script file.
import serial
import time
your_com_port = "COM18" # Change this to the com port your dongle is connected to.
connecting_to_dongle = True
print("Connecting to dongle...")
# Trying to connect to dongle until connected. Make sure the port and baudrate is the same as your dongle.
# You can check in the device manager to see what port then right-click and choose properties then the Port Settings
# tab to see the other settings
while connecting_to_dongle:
try:
console = serial.Serial(
port=your_com_port,
baudrate=57600,
parity="N",
stopbits=1,
bytesize=8,
timeout=0,
)
if console.is_open.__bool__():
connecting_to_dongle = False
except:
print("Dongle not connected. Please reconnect Dongle.")
time.sleep(5)
print("Connected to Dongle.")
# function to convert rssi to distance in meter
def rssiToDistance(rssi):
n=2
mp=-69
return round(10 ** ((mp - (int(rssi)))/(10 * n)),2)
#put the dongle in dual role, so we can scan for nearby device
console.write(str.encode("AT+CENTRAL"))
console.write("\r".encode())
print("Putting dongle in Central role.")
time.sleep(0.1)
# Scan for nearby devices for 3 seconds
console.write(str.encode("AT+GAPSCAN=3"))
console.write("\r".encode())
time.sleep(0.1)
print("Looking for nearby Bluetooth devices ...")
dongle_output2 = console.read(console.in_waiting)
time.sleep(3)
print("Scan Complete!")
filtered = []
# Filter out unncecssary outputs and keep only the list of devices (also remove index)
for dev in dongle_output2.decode().splitlines():
if len(dev)>20:
filtered.append(dev.split(maxsplit=1)[1])
# Get unique device by device id and add distance to each raw
seen = set()
out = []
for elem in filtered:
prefix = elem.split(' ')[1]
if prefix not in seen:
seen.add(prefix)
out.append(elem + " Distance: "+str(rssiToDistance(elem.split()[3]))+" meter")
# sort list by closest device
out.sort(key=lambda x:int(x.split()[3]),reverse=True)
# print(out)
for i in range(0, len(out)):
print (out[i])
time.sleep(0.1)
console.close()
Output
After running the script, we see a total 20 devices found nearby. The list shows their distance in meter from the central device.
6 thoughts on “Measuring distance with Bluetooth in indoor environment using Python”
Comments are closed.
What’s the speed of the data collection? Could it do (near) real time detection (even for just a single specific MAC address)?
Pretty cool either way! Congrats!
Speed of data collection depends how quick the device is advertising.
I would really love discussing this code a bit further with you. I have many questions regarding its implementation and theoretical application.
Mail us at support@smartsensordevices.com with your question. we can discuss further.
What kind of distance accuracy can be expected when using this method? <1m, 1-2m, 3+m?
The accurary depends on the distance and the environment, long distance in a indoor environment is more inaccurate.