This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Advertise on one channel at a time - app_timer problem

Hi DevZone

I want to make a little beacon app, that advertises on channel 37 then waits 700 ms, advertises on channel 38, waits 700 and advertises on channel 39. The below is what i have implemented, yet it doesn't work. It seems like the timeout handler is never called and therefor it is never starting advertising.

static void timers_init(void)
{
	uint32_t err_code;
	APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
	
	err_code = app_timer_create(&channel_timer_id, APP_TIMER_MODE_REPEATED, channel_timeout_handler);
	APP_ERROR_CHECK(err_code);	
}

My timeout handler which switches the channel_mode

static void channel_timeout_handler(void *p_context)
{
	SEGGER_RTT_printf(0, "Channel timeout handler %d\n, channel_mode");
	
	if(m_channel_mode == 37)
	{
		m_channel_mode = 38;
	}
	else if(m_channel_mode == 38)
	{
		m_channel_mode = 39;
	}
	else if(m_channel_mode == 39)
	{
		m_channel_mode = 37;
	}
	
	advertising_stop();
	advertising_init(m_channel_mode);
	advertising_start();
}

And here is my advertising_init where i set what channel it advertises on

static void advertising_init(uint8_t channel_mode)
{
	
		SEGGER_RTT_printf(0, "Advertising init\n");
    uint32_t      err_code;
    ble_advdata_t advdata;		
		ble_gap_adv_ch_mask_t ch_mask; // channel mask
		
	
	  uint8_t flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
	
		ble_uuid_t adv_uuids[] = 	
		{
				{BLE_CUSTOM_16UUID, 		BLE_UUID_TYPE_BLE}
		};

    // Build and set advertising data.
    memset(&advdata, 0, sizeof(advdata));
    advdata.name_type             = BLE_ADVDATA_NO_NAME;
		advdata.include_appearance		= false;
		advdata.flags 								= flags;
		
    err_code = ble_advdata_set(&advdata, NULL);
    APP_ERROR_CHECK(err_code);
		

		// Prepare the Manufacturer specific data packet
		ble_gap_addr_t gap_addr;
		sd_ble_gap_address_get(&gap_addr);
		ble_advdata_manuf_data_t manuf_data;
		
		manuf_data.company_identifier           = 0x028C; // 0x028C; // NanoLink Aps company ID
		//www.bluetooth.org/.../company-identifiers
		
		manuf_data.data.p_data									= gap_addr.addr;
		manuf_data.data.size                    = sizeof(gap_addr.addr);
		
    advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
    advdata.uuids_complete.p_uuids  = adv_uuids;
		
		advdata.p_manuf_specific_data   = &manuf_data;

    err_code = ble_advdata_set(&advdata, NULL);
    APP_ERROR_CHECK(err_code);
	
    // Initialize advertising parameters (used when starting advertising).
    memset(&m_adv_params, 0, sizeof(m_adv_params));	
		
		m_adv_params.type					= BLE_GAP_ADV_TYPE_ADV_NONCONN_IND;
		m_adv_params.p_peer_addr	= NULL;
		m_adv_params.fp					  = BLE_GAP_ADV_FP_ANY;
		m_adv_params.interval			= NON_CONNECTABLE_ADV_INTERVAL;
		m_adv_params.timeout			= 0;
		m_adv_params.p_whitelist	= NULL;
				
		SEGGER_RTT_printf(0, "channel mode %d\n", channel_mode);
		if(channel_mode == 37)
		{
			ch_mask.ch_37_off				 = 0;
			ch_mask.ch_38_off				 = 1;
			ch_mask.ch_39_off 			 = 1;
			m_adv_params.channel_mask = ch_mask;
		}
		else if(channel_mode == 38)
		{
			ch_mask.ch_37_off				 = 1;
			ch_mask.ch_38_off				 = 0;
			ch_mask.ch_39_off 			 = 1;
			m_adv_params.channel_mask = ch_mask;
		}
		else if(channel_mode == 39)
		{
			ch_mask.ch_37_off				 = 0;
			ch_mask.ch_38_off				 = 1;
			ch_mask.ch_39_off 			 = 1;
			m_adv_params.channel_mask = ch_mask;
		}
}

And my main looks like this:

int main(void)
{
	
    uint32_t err_code;
    // Initialize.
//  APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false); // Comment this when channel switching on
		timers_init(); // init timers
		//gap_params_init();
	
    err_code = bsp_init(BSP_INIT_LED, APP_TIMER_TICKS(100, APP_TIMER_PRESCALER), NULL);
    APP_ERROR_CHECK(err_code);
    ble_stack_init();
		//advertising_init(m_channel_mode); // 		

		err_code = app_timer_start(channel_timer_id, CHANNEL_TIMER_INTERVAL, NULL);
		APP_ERROR_CHECK(err_code);

	// Enter main loop.
    for (;; )
    {
        power_manage();
    }
}
  • Isn't it correct that my event_handler should get called when calling, where radio_notification_evt_handler is my event handler?

    err_code = ble_radio_notification_init(6, NRF_RADIO_NOTIFICATION_DISTANCE_5500US, radio_notification_evt_handler);
    APP_ERROR_CHECK(err_code)
    

    It doesn't seem so when i am debugging. And from my advertising_start i am getting error code Invalid data size, which is because advertising_set_data is never called where i setup the advertisement.

    Can anybody help me out?

  • Hi Mathias, see this example. You will fine source code which can be directly compiled with beacon example from SDK, it uses ble_radio_notification module and it works well.

  • Thanks :-) I have changed a bit in my code, and now it definitely interrupts at radio events.

    Though it doesn't change the advertising params as i would hope.

    This is my new handler which i am sure gets called because it toggles the LED2 on my board.

        void SWI1_IRQHandler(bool radio_evt)
    {
        if (radio_evt)
        {
          nrf_gpio_pin_toggle(BSP_LED_2); //Toggle the status of the LED on each radio notification event
    			advertising_reinit();
        }
    

    And here is my advertising_reinit(), where i set which channel i advertise on.

    static void advertising_reinit(void)
    {
    	  memset(&m_adv_params, 0, sizeof(m_adv_params));	
    		m_adv_params.type					= BLE_GAP_ADV_TYPE_ADV_NONCONN_IND;
    		m_adv_params.p_peer_addr	= NULL;
    		m_adv_params.fp					  = BLE_GAP_ADV_FP_ANY;
    		m_adv_params.interval			= NON_CONNECTABLE_ADV_INTERVAL;
    		m_adv_params.timeout			= 0;
    		m_adv_params.p_whitelist	= NULL;		
    		
    		if(channel_mode == 37)
    		{
    			channel_mode = 38;
    			ch_mask.ch_37_off = 0;
    			ch_mask.ch_38_off = 1;
    			ch_mask.ch_39_off	= 1;
    			m_adv_params.channel_mask = ch_mask;
    		}
    		else if(channel_mode == 38)
    		{
    			channel_mode = 39;
    			ch_mask.ch_37_off = 0;
    			ch_mask.ch_38_off = 1;
    			ch_mask.ch_39_off	= 1;
    			m_adv_params.channel_mask = ch_mask;
    		}
    		else if(channel_mode == 39)
    		{
    			channel_mode = 37;
    			ch_mask.ch_37_off = 0;
    			ch_mask.ch_38_off = 1;
    			ch_mask.ch_39_off	= 1;
    			m_adv_params.channel_mask = ch_mask;
    		}	
    }
    

    But it simply doesn't work. I am sorry for my ignorance, but i can't figure out why that wouldn't work

  • Hi,

    Few notes:

    1. If you do minor updates/corrections of single post or answer on the forum, please tick "minor edit" box, it prevents sending multiple notification emails to all followers;)
    2. I don't understand why are you stubbornly playing with IRQ handler. As far as I see there is nothing like that needed if you use SDk modules correctly, it notifies you through function handler provided in ble_radio_notification_init function call.
  • sorry about that, but i do not have such a check box?

    However, I call this in main:

    	err_code = ble_radio_notification_init(6, NRF_RADIO_NOTIFICATION_DISTANCE_800US, on_ble_radio_active_evt);
    	APP_ERROR_CHECK(err_code);
    

    which works and on_ble_radio_active_evt is triggered correctly, which calls advertising_init just as planned.

    In my advertising_init i have this code:

    	if(channel_mode == 37)
    	{
    		SEGGER_RTT_printf(0, "channel_mode == 37 %d \n", channel_mode);
    		channel_mode = 38;
    		ch_mask.ch_37_off = 0;
    		ch_mask.ch_38_off = 1;
    		ch_mask.ch_39_off	= 1;
    		m_adv_params.channel_mask = ch_mask;
    	}
    	else if(channel_mode == 38)
    	{
    		SEGGER_RTT_printf(0, "channel_mode == 38 %d \n", channel_mode);
    		channel_mode = 39;
    		ch_mask.ch_37_off = 0;
    		ch_mask.ch_38_off = 1;
    		ch_mask.ch_39_off	= 1;
    		m_adv_params.channel_mask = ch_mask;
    	}
    	else if(channel_mode == 39)
    	{
    		SEGGER_RTT_printf(0, "channel_mode == 39 %d \n", channel_mode);
    		channel_mode = 37;
    		ch_mask.ch_37_off = 0;
    		ch_mask.ch_38_off = 1;
    		ch_mask.ch_39_off	= 1;
    		m_adv_params.channel_mask = ch_mask;
    	}		
    

    I can see in RTT-viewer that it goes to channel 37 then 38 then 39 then 37 and so on.

    But when i look at the packages in wireshark using the sniffer it only advertises on channel 37.

    So i thought that i might have to stop the advertising, init the advertising and then advertising_start againg, which i tried as follows:

    static void on_ble_radio_active_evt(bool radio_active) {
    
        if (radio_active) 
    			{	
    				advertising_stop();
    				advertising_init();
    				advertising_start();
          }
    }
    

    But without any luck.. advertising_stop and advertising_startboth returns NRF_SUCCES..

    Got it to work... The problem was that i had the same mask for all possible channels.. Thank you very much for your help :-) Appreciated!

Related