cancel
Showing results for 
Search instead for 
Did you mean: 

BLE scan and advertising issues

GHajj
Associate II

I am trying to make a simple BLE scan and advertising program which is supposed to advertise a set of changing data and scan for other devices. The advertising is completely non-connective and works as a dumb beacon, and so is the scanning.

The application is based on the HRS FreeRTOS example for the nucleo wb55, modified to remove the HRS-specific parts and with simple advertising and scanning added. After app_ble is done with all the initializing it goes on to create the advertising data and run aci_gap_set_discoverable with the correct settings (non-connectable, min advertising interval of 70 ms, maximum of 130, public address, no white-list) and add the advertising data using aci_gap_update_adv_data.

Then it runs aci_gap_start_observation_proc(0xA0, 0x60, 0x00, 0x00, 0x00, 0x00);, which should mean scan interval of 100 ms, scan window of 60 ms and no filters.

None of these commands return an error but seem to run just fine.

The scan packets are received through SVCCTL_App_Notification() and added to a FreeRTOS queue, and then handled by a separate thread.

The advertising data is currently not being updated in order to simplify the issue, but will be updated through filling a buffer with the new data and sending a flag to AdvUpdateProcess to send the new data to the BLE stack when possible.

Tested with only two devices running, either one or both seem to be unable to advertise. Sometimes one can find the other, sometimes neither can find the other one. The one that's advertising sometimes seems to be able to scan, as the function is called, but will not find the other device (i.e. the other device is not advertising) while the other device does find the first one.

Is there something I'm missing here? Does the stack not support both scanning and advertising at the "same time"? Do I have to make sure that the timing is configured in a specific manner?

Is there maybe a command to request the BLE stack status in order to debug?

When I had the advertising data update running there seemed to be some collision in the HCI layer due to the scan reports and advertising update happening simultaneously, but that seemingly disappeared when I stopped managing the data in the ISR directly.

Edit:

So I solved the issue somehow, I can't exactly recall what fixed it but I believe that reducing the amount of time spent in the event handler did something.

Now I have a tangentially related issue, and figured that editing it into this question may make sense.

There seems to be a timing issue where the devices can get out of sync and completely miss each other. Setting them to constantly scan (I have tried both long and short scan intervals) and periodically advertise, say with a minimum interval of 40 ms and maximum interval of 90 ms, does not seem to allow for enough time to return to scan after advertising.

Using an external device running a BLE packet sniffer I was able to see that a device (let's call it device A) advertised at a specific time but was not able to see the advertisement that another device (let's say B) transmitted 30 ms later.

This tells me that the BLE stack schedules the advertising and monitoring in a way that allows for dead time, where the device is neither advertising or monitoring. Is there any documentation or information concerning how the BLE controller handles this? If not, is there some other way to do what I want to do? I wanted to keep the devices dumb, so that they don't have to connect and communicate directly, but as it seems right now that may not be possible.

5 REPLIES 5
GHajj
Associate II

I figured that editing the main post would bump it up, but it doesn't seem to do that. So I guess I'll just write this here and hope it does something.

eleventen
Associate III

If I understand your application correctly, you are attempting to capture advertising messages from another device (Central mode) and advertise (Peripheral mode) at the same time.

I wasn't aware that this was explicitly permitted, but it certainly could work as long as you switch modes on your devices from the application. I don't expect that the stack has this capability, but I may be wrong about that. Generally, the radios are either listening or transmitting.

While I have no specific knowledge of the internals of the radio, I would suppose that you may have better luck if you relax your timing. The BLE protocol like long intervals for capturing advertising messages. If, for example, you advertised for five seconds and then randomly scheduled a one second interval for listening, you might see a little better behavior. The key is to make sure the devices are not synchronized. In fact, if you really wanted to get predictable performance, you could algorithmicly determine the advertising and listening intervals based on communication between the devices.

If you have a pricey BLE scanner, you should be able to see *all* advertising packets on every (three) channel. The cheaper scanners usually only read one channel at a time and follow conversations once devices initiate a connection. IOW, you won't see all advertisement packets via scanner in some circumstances but you can follow a conversation once it begins.

My understanding is that the BLE standard and the stack used both allow for multi-role devices, which allows me to use both the broadcaster and observer roles simultaneously. No mode-switching should be required, and also isn't. The stack has a scheduler that will decide when to scan and when to advertise, and deals with collisions in some predetermined but unknown manner. As you say, this will cause the radio to either listen or transmit at any given time, which is fine.

I believe the main issue is that there is no way to only advertise on one channel, and the stack is stuck in an essentially idle mode when waiting for the random 1-10 ms advertising delay for each channel. This means that while advertising a 40-byte message should be possible in about 300 µs, the devices spend about 15 ms not scanning during the advertising time. As I wanted shorter intervals to reduce the lag in the system (so say an advertising interval of around 100 ms) this quickly becomes impossible to deal with. I am not entirely sure how the maximum and minimum advertising intervals are supposed to work, but it seems like the stack either isn't following the standard or that the standard is pointless - the devices seemed to always advertise at a constant interval in the middle of min and max.

I spent a day or so thinking of other ways to deal with the issue, like using a random seed to give the devices unique advertising intervals, or making sure that the devices were only allowed to advertise in a predetermined order, or a bunch of other dumb ideas; but in the end I decided to abandon it and just use the openThread mesh instead. I wanted to keep going with BLE as it is more common and more standardized, but just gave up after a while. The BLE mesh library doesn't really seem to work, just running the example code doesn't even seem to work properly.

OpenThread even had a low-power example with freeRTOS, which made the development so much easier.

eleventen
Associate III

From what I've read, the Thread mesh protocols are pretty well dialed-in as compared to the BLE mesh. And, I think that in some sense that is what you are attempting to do, a kind of mesh, yes?

So, indeed, it seems like using Thread is a better pony to ride.

Thanks for the update.

KPrzy.1
Associate II

Dear Friend, Can You provide Your code of using freertos and simple beacon? I having difficulties run freertos heartrate example. It looks like my nucleo wb55 stack when i am trying to call appe_init function before or after freertos init. I am trying to understand what I am doing wrong there? I am using cubemx and after code generation appe_init() is not called anywhere...