Hello,
I have an application that needs to advertise only once then sleep for a long period in BLE 1 Mbps. From time to time it needs also to advertise in CODED_PHY (ext advertisement) instead of the standard 1 Mbps BLE. I am using the SD140 on nRF52811. Up to now, I implemented a simple function that is called by a timer handler on a regular basis. This function initializes the advertising, start it wait (long enough) and stops the advertising. It also toggles an IO (debug pulse) at different steps to understand how the code runs and allow to measure timings.
I noticed that the duration between the advertising_start() and the effective time the packet is transmitted is variable. My code is certainly sub optimal as it uses an active wait (nrf_delay()) for 11 ms between advertising_start and advertising_stop. During this time the circuit consumes about 5mA which is a lot for my application. So I am looking for simple way to reduce the power consumption by avoiding this active wait state or doing thin in a more clever way.
The current code extract is the following (loosely based on the ble_App_beacon example):
#define STARTUP_DURATION_MS 11
....
static void tx_BLE_packet(enum adv_speeds speed, uint8_t mask)
{
cur_adv_speed = speed; //enum adv_speeds {legacy1Mbps, coded_phy};
debug_pulse(400);
advertising_init();
debug_pulse(800);
advertising_start();
debug_pulse(400);
nrf_delay_ms(STARTUP_DURATION_MS);
debug_pulse(400);
advertising_stop();
}
Screenshots taken using the very good Nordic power profiler kit are instructive. The current consumption is depicted along time axis, nicely showing the chip activity and the 3 advertising packets (one on each RF advertising channel, 37, 38 and 39). The debug pulses are visible on the bottom of the screenshot In this first screenshot, one can see that once advertising_start() is called, it takes about 10 ms for the packet to start. :

The 2nd screenshot is taken after the system has run on its own for maybe one minute or two. The very same code is running. Here one can see that the effective packet transmission is starting only 1.8 ms after entering in my function. So the long "tail" of waiting after the packet has been transmitted is here pure waste of time and DC power:

These 2 measurements show that the startup time of the stack seems very variable for whatever reason. I've also seen packets being transmitted so late that the last advertisement transmission was cut-out by the advertisement_stop() command and not transmitted at all. IN some cases the last packet was "damaged". Obviously the stack can startup in 1.8 ms, but for some reasons, it doesn't do it always so fast. In some cases it takes up to 10 ms to start. Why?
Obviously my solution needs enhancement. I see following possibilities to optimize the system:
- Configure the stack to advertise only once then stop advertising. This would allow going to sleep mode quicker. As I have understood, there is a parameter m_adv_params.duration that could be set to 1 to advertise only once, but I get a crash if I use it. (BLE_GAP_EVT_ADV_SET_TERMINATED) So currently it is kept set to 0. Any pointer to working code using this feature?
- Replace nRF_delay_ms() by some more clever waiting routing consuming less current. How to implement this knowing that the function tx_BLE_packet is already called from within a timer handler? (looks like nested timers)
- Detect that the advertisement has been effectively transmitted (how?) and immediately send the advertising_stop() command afterwards. This would not save current at the packet start, but would allow at least to save the current "tail" and avoid cutting into the advertisement packets too early.
I don't know which is the most promising path to follow. Maybe somebody has yet another idea. Any help will be appreciated.
Have a nice day
