Bluetooth Low Energy (BLE) proximity detection is one of the most practical wireless sensing techniques in modern electronics. From retail asset tracking and indoor navigation to attendance systems and smart home automation, BLE beacons and proximity sensing have countless real-world applications. The Arduino Nano 33 BLE and Nano 33 BLE Sense are among the easiest ways to experiment with these technologies — combining the familiar Arduino IDE with a powerful Nordic nRF52840 SoC that supports BLE 5.0. This tutorial covers everything from broadcasting BLE beacons to measuring proximity using RSSI, with complete code examples.
Table of Contents
- BLE Basics: Advertising, GATT, and RSSI
- Arduino Nano 33 BLE Overview
- Broadcasting an iBeacon from Arduino
- Eddystone URL Beacon
- Proximity Detection Using RSSI
- BLE Scanner: Detect Nearby Devices
- Real-World Application Ideas
- Frequently Asked Questions
BLE Basics: Advertising, GATT, and RSSI
Bluetooth Low Energy operates very differently from classic Bluetooth. Instead of establishing persistent connections for streaming audio or serial data, BLE devices often operate in an advertising mode — periodically broadcasting small packets of data (advertising PDUs) that any scanner in range can receive without establishing a connection.
Key BLE concepts relevant to proximity and beacons:
- Advertising: A BLE peripheral broadcasts packets on channels 37, 38, and 39 (2.402, 2.426, and 2.480 GHz). The advertising interval determines how often packets are sent — typically 100 ms to 10 seconds for beacons.
- RSSI (Received Signal Strength Indicator): Measured in dBm (negative values). A stronger signal means the device is closer. Typical values: -40 dBm (very close, <30 cm), -70 dBm (~1–3 m), -90 dBm (edge of range, 5–10 m).
- TX Power: The transmitter’s output power in dBm. By knowing TX Power and measuring RSSI, you can estimate distance using path-loss models.
- GATT (Generic Attribute Profile): Used for connected BLE communication — services and characteristics. Not needed for simple beacon/proximity applications, which rely on advertising alone.
The Friis path-loss equation provides a rough distance estimate: distance = 10 ^ ((TX_Power – RSSI) / (10 * N)), where N is the path-loss exponent (typically 2 in free space, 2–4 in indoor environments).
Arduino Nano 33 BLE Overview
The Arduino Nano 33 BLE is built around the Nordic nRF52840 SoC — a 64 MHz ARM Cortex-M4F with hardware floating point, 1 MB flash, 256 KB RAM, BLE 5.0, NFC, and a USB 2.0 full-speed interface. The Nano 33 BLE Sense adds an onboard IMU (LSM9DS1), microphone (MP34DT05), temperature/humidity (HTS221), pressure (LPS22HB), colour and gesture sensor (APDS9960), and proximity sensor — all in the same tiny Nano form factor.
Key differences from older BLE Arduinos:
- Operates at 3.3 V (not 5 V) — use level shifters when interfacing with 5 V devices
- BLE 5.0 supports 2 Mbit/s PHY, extended advertising (up to 255 bytes), and long-range coded PHY
- The
ArduinoBLElibrary provides a clean, high-level API for both advertising and scanning - USB native (no USB-serial chip) — appears as a USB CDC device directly
Broadcasting an iBeacon from Arduino
The iBeacon format, originally defined by Apple, is the most widely recognized proximity beacon standard. An iBeacon advertising packet contains:
- UUID: A 16-byte (128-bit) identifier for your application or organization
- Major: 2-byte value (e.g., building or zone ID)
- Minor: 2-byte value (e.g., specific room or asset ID)
- TX Power: Expected RSSI at 1 meter (for distance calibration)
The ArduinoBLE library does not natively support iBeacon advertising format, so we construct the raw advertising payload manually:
#include <ArduinoBLE.h>
// Your iBeacon UUID (replace with your own)
const uint8_t beaconUUID[16] = {
0xE2, 0xC5, 0x6D, 0xB5, 0xDF, 0xFB, 0x48, 0xD2,
0xB0, 0x60, 0xD0, 0xF5, 0xA7, 0x10, 0x96, 0xE0
};
void setup() {
Serial.begin(9600);
if (!BLE.begin()) {
Serial.println("BLE init failed!");
while (1);
}
// Build iBeacon manufacturer data
uint8_t manufacturerData[25];
manufacturerData[0] = 0x4C; // Apple Company ID (LSB)
manufacturerData[1] = 0x00; // Apple Company ID (MSB)
manufacturerData[2] = 0x02; // iBeacon type
manufacturerData[3] = 0x15; // remaining length = 21
memcpy(&manufacturerData[4], beaconUUID, 16);
manufacturerData[20] = 0x00; // Major MSB
manufacturerData[21] = 0x01; // Major LSB = 1
manufacturerData[22] = 0x00; // Minor MSB
manufacturerData[23] = 0x02; // Minor LSB = 2
manufacturerData[24] = 0xBB; // TX Power at 1m = -69 dBm (0xBB = -69 signed)
BLE.setLocalName("ZboticBeacon");
BLE.setManufacturerData(manufacturerData, 25);
BLE.setAdvertisingInterval(160); // 100ms = 160 * 0.625ms
BLE.advertise();
Serial.println("iBeacon broadcasting...");
}
void loop() {
BLE.poll();
}
You can verify the beacon is broadcasting using the nRF Connect app (Android/iOS) — it will show your device name and decode the iBeacon UUID, major, and minor values.
Eddystone URL Beacon
Eddystone is Google’s open beacon format. The Eddystone-URL frame type broadcasts a short URL that can be resolved by nearby devices (Physical Web concept). It is simpler than iBeacon for web-oriented applications.
// Eddystone-URL frame for "https://zbotic.in"
void advertiseEddystoneURL() {
// Eddystone service UUID: 0xFEAA
uint8_t serviceData[] = {
0xAA, 0xFE, // Eddystone UUID
0x10, // Frame type = URL
0x00, // TX Power = 0 dBm
0x03, // URL scheme: https://
'z','b','o','t','i','c','.','i','n'
};
BLE.setAdvertisedServiceUuid("FEAA");
BLE.setAdvertisedServiceData(0xFEAA, serviceData, sizeof(serviceData));
BLE.advertise();
}
Note that the Physical Web / Eddystone-URL discovery in Android Chrome was deprecated by Google in 2018. However, Eddystone beacons are still useful in custom Android/iOS apps that explicitly scan for the 0xFEAA service UUID.
Proximity Detection Using RSSI
To detect whether a specific device is nearby (e.g., for a keyless entry system), scan for its BLE address or name and monitor RSSI. Smooth the RSSI with a running average to reduce noise:
#include <ArduinoBLE.h>
#define TARGET_NAME "MyPhone"
#define NEARBY_THRESHOLD -65 // dBm — device considered "nearby" if RSSI > this
float smoothedRSSI = -100.0;
const float alpha = 0.2; // EMA smoothing factor
void setup() {
Serial.begin(9600);
BLE.begin();
BLE.scan();
}
void loop() {
BLEDevice peripheral = BLE.available();
if (peripheral) {
if (String(peripheral.localName()) == TARGET_NAME) {
int rawRSSI = peripheral.rssi();
// Exponential Moving Average
smoothedRSSI = alpha * rawRSSI + (1 - alpha) * smoothedRSSI;
Serial.print("RSSI: ");
Serial.print(rawRSSI);
Serial.print(" dBm | Smoothed: ");
Serial.println(smoothedRSSI);
if (smoothedRSSI > NEARBY_THRESHOLD) {
Serial.println("Device NEARBY — unlock!");
// Trigger relay, servo, or LED here
} else {
Serial.println("Device FAR — lock.");
}
}
}
}
Practical threshold values for typical indoor environments:
- Very close (<0.5 m): RSSI > -50 dBm
- Near (0.5–2 m): RSSI -50 to -70 dBm
- Mid-range (2–5 m): RSSI -70 to -80 dBm
- Far (>5 m): RSSI < -80 dBm
Walls, people, and furniture cause significant RSSI variation. Always use averaging (EMA or Kalman filter) for stable proximity decisions.
BLE Scanner: Detect Nearby Devices
Use the Nano 33 BLE as a passive scanner to log all advertising devices in range — useful for crowd density estimation, occupancy detection, or security auditing:
#include <ArduinoBLE.h>
void setup() {
Serial.begin(9600);
BLE.begin();
BLE.scanForUuid(""); // Scan all devices
Serial.println("Scanning for BLE devices...");
}
void loop() {
BLEDevice peripheral = BLE.available();
if (peripheral) {
Serial.print("Found: ");
Serial.print(peripheral.address());
Serial.print(" | Name: ");
Serial.print(peripheral.localName());
Serial.print(" | RSSI: ");
Serial.print(peripheral.rssi());
Serial.println(" dBm");
}
}
You can log data to an SD card or transmit it via USB Serial to a Raspberry Pi for database storage and analysis. Adding a timestamp from an RTC module turns this into a full BLE device presence logger.
Real-World Application Ideas
Smart Attendance System
Equip each student or employee with a low-cost BLE tag (or use their smartphone’s BLE advertising). Deploy Arduino Nano 33 BLE scanners at entry points. When a known BLE address appears with sufficient RSSI, mark attendance in a server database via serial/Wi-Fi bridge.
Indoor Asset Tracking
Attach BLE beacon tags to valuable equipment. Place Nano 33 BLE scanners at key points in a building. By comparing RSSI values from multiple scanners (trilateration), you can estimate the position of each tagged asset to within 2–3 meters.
Proximity-Triggered Advertising
Deploy iBeacon transmitters in a retail store. Customer smartphones running your app detect beacon proximity and display contextually relevant product information or discounts — all triggered by physical location without GPS or internet.
BLE Keyless Lock
Scan for a specific phone’s Bluetooth address. When RSSI exceeds the “nearby” threshold and a PIN is verified over BLE GATT, trigger a servo or relay to unlock a door. When the phone moves away (RSSI drops), automatically re-lock.
Frequently Asked Questions
What is the maximum BLE range of the Arduino Nano 33 BLE?
The nRF52840 chip has a maximum TX power of +8 dBm and BLE 5.0 long-range coded PHY support. In practice with the onboard PCB antenna and default settings (0 dBm TX power), indoor range is approximately 10–20 meters. Reducing advertising interval and maximizing TX power (via BLE.setTxPower(8)) extends range to 30–50 meters in open space.
Can the Nano 33 BLE act as both an advertiser and a scanner simultaneously?
The nRF52840 supports concurrent advertising and scanning at the hardware level, but the current ArduinoBLE library does not expose this functionality easily. You need to use the Nordic nRF5 SDK or Mbed OS BLE stack for true simultaneous operation. A practical workaround is to alternate between advertising and scanning in short time slots using BLE.stopAdvertise() and BLE.stopScan().
How accurate is RSSI-based distance estimation?
RSSI-based distance estimation has ±1–3 meter accuracy in open space and ±3–6 meters indoors due to multipath reflections, interference, and body shadowing. For coarse zone detection (“in room” vs “out of room”), RSSI works reliably. For sub-meter accuracy, consider using BLE 5.1 Angle of Arrival (AoA) or Ultra-Wideband (UWB) technology instead.
Is the Arduino Nano 33 BLE compatible with iPhones?
Yes. iPhones run CoreBluetooth which fully supports BLE 4.x and 5.x. An iPhone can detect iBeacon advertising packets from the Nano 33 BLE when your app uses CoreLocation’s ranging APIs. For direct GATT connections, use the nRF Connect iOS app or build a custom Swift app using CoreBluetooth. Note: iOS does not expose the raw BLE MAC address for privacy reasons — use UUIDs for device identification.
What battery life can I expect from a Nano 33 BLE running as a beacon?
The Nano 33 BLE draws approximately 7 mA in active mode. In BLE advertising-only mode with the CPU in deep sleep, current can drop to under 50 µA between advertising events. A 1000 mAh LiPo with 100 ms advertising interval gives roughly 6–8 months of battery life when properly implementing sleep modes via the ArduinoLowPower library.
Build Your BLE Proximity System Today
The Arduino Nano 33 BLE makes BLE beacon broadcasting and proximity detection accessible to any maker or engineer. Whether you are building a retail presence system, a smart lock, or an indoor tracking solution, the combination of the nRF52840’s powerful BLE 5.0 stack and the familiar Arduino IDE makes development fast and rewarding.
Explore the Arduino Nano 33 BLE, Nano 33 BLE Sense, and all associated components at zbotic.in Arduino & Microcontrollers. Pan-India shipping with expert support for your next wireless project.
Add comment