Hello everyone,
Someone has been able to reach 200m with the right code to use long range that says Colas71? I have achieved some improvement but not so much, with ble legacy around 20 or 22m as someone said in the post and with LE_Coded between 55 or 60m, better but still far from the 200m. By the way I think that it is not commented in the post but I suppose that apart from using a smartphone that supports Ble 5 long range you are using the app "nRF connect" to establish the connection, in my case if in connect I set LE Coded in "Set initial preferred PHY" it works but only occasionally, the thing is that I don't care about the connection because what I need is to generate beacons where the information is coded in the uuid so I adapted the code of Colas71 to generate an ibeacon.
/*--------INCLUDES--------*/
#include "ble/BLE.h"
/*------------------------*/
using namespace mbed; // Enable us to call mbed functions without "mbed::"
/*------------GLOBAL VARIABLES-------------*/
const static char DEVICE_NAME[] = "LR Beacon"; // Device name when detected on Bluetooth
static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE);
static const uint16_t MAX_ADVERTISING_PAYLOAD_SIZE = 59; // Advertising payload parameter
const ble::phy_set_t CodedPHY(ble::phy_t::LE_CODED); // Creating a Coded Phy set
/*-----------------------------------------*/
/*------------------------------Bluetooth Device class------------------------------*/
class BeaconDemo : ble::Gap::EventHandler {
public:
BeaconDemo(BLE &ble, events::EventQueue &event_queue) :
_ble(ble),
_event_queue(event_queue),
_adv_data_builder(_adv_buffer) { }
void start() {
_ble.gap().setEventHandler(this);
_ble.init(this, &BeaconDemo::on_init_complete);
_event_queue.dispatch_forever();
}
private:
/** Callback triggered when the ble initialization process has finished */
void on_init_complete(BLE::InitializationCompleteCallbackContext *params) {
if (params->error != BLE_ERROR_NONE) {
Serial.println("Ble initialization failed.");
return;
}
Serial.println("Ble initialized.");
start_advertising();
}
void start_advertising() {
/* Create advertising parameters and payload */
ble::AdvertisingParameters adv_parameters(
//ble::advertising_type_t::CONNECTABLE_UNDIRECTED,
ble::advertising_type_t::CONNECTABLE_NON_SCANNABLE_UNDIRECTED,
ble::adv_interval_t(ble::millisecond_t(500)),
ble::adv_interval_t(ble::millisecond_t(1000)),
false
);
adv_parameters.setPhy(ble::phy_t::LE_CODED, ble::phy_t::LE_CODED); // Set Advertising radio modulation to LE_CODED Phy (=Long Range)
adv_parameters.setTxPower(8); // Set radio output power to 8dbm (max)
_ble.gap().setPreferredPhys(&CodedPHY, &CodedPHY); // Set preferred connection phy to LE_CODED (=long range)
_adv_data_builder.setFlags();
static const uint8_t ibeacon_raw[] = {0x00, 0x4C, 0x02, 0x15, 0xE2, 0x0A, 0x39, 0xF4, 0x73, 0xF5, 0x4B, 0xC4, 0xA1, 0x2F, 0x17, 0xD1, 0xAD, 0x07, 0xA9, 0x61, 0x11, 0x22, 0x33, 0x44, 0xC8};
_adv_data_builder.setManufacturerSpecificData(ibeacon_raw);
/* Setup advertising */
ble_error_t error = _ble.gap().setAdvertisingParameters(
ble::LEGACY_ADVERTISING_HANDLE,
adv_parameters
);
if (error) {
Serial.println("_ble.gap().setAdvertisingParameters() failed");
return;
}
error = _ble.gap().setAdvertisingPayload(
ble::LEGACY_ADVERTISING_HANDLE,
_adv_data_builder.getAdvertisingData()
);
if (error) {
Serial.println("_ble.gap().setAdvertisingPayload() failed");
return;
}
/* Start advertising */
error = _ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
if (error) {
Serial.println("_ble.gap().startAdvertising() failed");
return;
}
}
private:
/* Event handler */
void onDisconnectionComplete(const ble::DisconnectionCompleteEvent&) {
_ble.gap().startAdvertising(ble::LEGACY_ADVERTISING_HANDLE);
}
private:
BLE &_ble;
events::EventQueue &_event_queue;
uint8_t _adv_buffer[ble::LEGACY_ADVERTISING_MAX_SIZE];
ble::AdvertisingDataBuilder _adv_data_builder;
};
/** Schedule processing of events from the BLE middleware in the event queue. */
void schedule_ble_events(BLE::OnEventsToProcessCallbackContext *context) {
event_queue.call(Callback<void()>(&context->ble, &BLE::processEvents));
}
/*====================== MAIN CODE ======================*/
void setup(){
/* Setup Debugging */
Serial.begin(9600);
while(!Serial);
/* Low Power */
digitalWrite(LED_PWR, LOW); // Turn off power LED
digitalWrite(PIN_ENABLE_SENSORS_3V3, LOW); // Turn off sensors
NRF_POWER->DCDCEN = 0x00000001; // Enable DCDC
/* */
BLE &ble = BLE::Instance(); // Create the BLE object in order to use BLE_API function
ble.onEventsToProcess(schedule_ble_events); // Set event schedule
BeaconDemo demo(ble, event_queue);
demo.start(); // Start Bluetooth Long Range
}
void loop(){}
Basically is to add the CONNECTABLE_NON_SCANNABLE_UNDIRECTED option to the advertisement and set phy to LE_Coded and tx power to 8 dBi, then generate the ibeacon
I am using a One Plus 6T that as it shows the capture has all the options for Ble 5, in addition I attach the captures of the beacons one with legacy beacon to around 22m and the other with long range beacon to around 60m, both with a rssi near the limit of range.


