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();
    }
}
  • It is when i set the channel mask the problem occurs. If it sends on every channel it works just fine but as soon as i turn off some of the channels it only advertises periodically.

    While this code is inserted the problem occurs:

    	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 if i turn every channel on like this (which is the default) it works advertises continously.

    	ch_mask.ch_37_off = 0;
    	ch_mask.ch_38_off = 0;
    	ch_mask.ch_39_off	= 0;
    	m_adv_params.channel_mask = ch_mask;
    

    One way i can get it to advertise continously is to stop the advertising, initialize and then start it again, however as you also mentioned Endnode, this generates some crashes and advertising at random times.

  • The problem lays in the channel mask. If I turn off the radio notification it does the same thing, advertises on the selected channel for 5 seconds ish, then stops advertising for 10 seconds ish and so on. If I set it to advertise on two channels it will advertise for 10 seconds and then stop advertise for 5 seconds.

    So the problem is not within the radio notification, as i thought, but the channel mask.

    Is there a work-around this, so i can advertise continously but one channel at a time?

    I am sorry for the many updates in this thread..

  • Hey Mathias, it's obvious: your phone doesn't have multiple of 2.4GHz radios, just one. That needs tu8 tune to particular channel even for Rx. So what you see is convolution of advertising period and channel rolling with scannig period, duty cycle and channel rolling on phone side. You should use some real sniffer (and note that "cheap" sniffers such as the one from Nordic running on nRF51 DK and DONGLE will suffer from similar problems). Not saying it works perfectly, just that you might see false positives.

  • Hmm yep, I think you are right.

    But after some more testing and playing around, I can see in the sniffer (Both the one from Nordic and one from texas) that it only advertises on channel 37 when i do not stop the advertising and starting it again in my radio notification. That explains the behaviour in nRF connect after what you just enlightened me with.

    I just noticed that when i update the ch_mask the output is wrong when i output it in Segger RTT, though it switches correctly between the states.

    My output in the segger is:

     0> channel_mode == 37 37 
     0> channel mask in 37 118 
     0> channel_mode == 38 38 
     0> channel mask in 38 117 
     0> channel_mode == 39 39 
     0> channel mask in 39 115
    

    This is probably the problem. :-)

    Once again, thanks for your time! Much appreciated.

    Edit:

    I made the ch_mask global and static so i now get this output in SEGGER RTT:

     0> channel_mode == 37 37 
     0> channel mask in 37 6 
     0> channel_mode == 38 38 
     0> channel mask in 38 5 
     0> channel_mode == 39 39 
     0> channel mask in 39 3
    

    Which makes good sense in my eyes because 0b0110 = 6, 0b0101 = 5 and 0b0011 = 3.

    However with the same result, it only advertises on channel 37.

    I set the channel mask using: m_adv_params.channel_mask = ch_mask;, but as it appears that it does not update??...

  • Hi Mathias, I will try to modify SDK beacon example (the example I've already modified to use Radio Notifications and referenced here in this question) in order to use Channel list and test it with some professional sniffer such as Frontline. However not sure when...

Related