setting tx_power_level


I'm following this tutorial. In challenge 1, I was asked to change the transmit power level of the device.

Challenge 1: Try to add and populate the "p_tx_power_level" field in "advdata" with a value of your own choice and see what happens in MCP. This field is meant to advertise the transmit power of your device. This enables other units to roughly estimate the distance to your device.

I add these two lines in the advertising_init() function but the device couldn't be discovered in MCP.

int8_t tx_power_level[] = {0, -20};
advdata.p_tx_power_level 					= tx_power_level;

I also tried following this question but no luck.

How can I change the current project to do challenge 1?

  • It's just a simple int8_t, not an array and you set advdata.p_tx_power_level the address of it (&).

    int8_t tx_power_level = 4;
    advdata.p_tx_power_level = &tx_power_level;
  • As Chris said and also:

    Edit - This is an answer to your question below and a response to your comment in the advertising tutorial. Your problem is that you have already squeezed 29 bytes into your advertising packet, dangerously close to the maximum allowed 31 bytes.

    Lets have a look at the content of your packet. First, this is what I see in my MCP with your code:

    image description

    Below I have used a nRF51 Dongle and Wireshark software to sniff the advertising packet to see what the packet contains:

    image description

    As you can see I have marked the Advertising Packet field at the top and the blue lines at the bottom represent the bytes in the packet. If you count the marked bytes you will find that it is already 29 of them. The rest of the bytes in the window are various link layer, address and CRC bytes (if you look closely you will, e.g., recognize the 6 Address bytes from the MCP in reverse order in the second line).

    Now, you can see that there are 4 main data fields in the advertising packet: Device Name, Appearance, Flags and 16-bit Service Class UUIDs.

    Have a look at the following screenshot:

    image description

    Here I have highlighted the Device Name field. Again you can see that the actual byte values are highlighted at the bottom and if you count them you will see that there are 8 of them. And why 8 when your name is just 6 bytes long? That is because the Device Name field in the advertising packet is structured this way:

    1. Length byte, value 7 (the length byte doesn't count it self), one single byte.
    2. Type byte, value 8, one single byte. (Here is a list of type bytes and you can recognize 0x08 that is «Shortened Local Name»).
    3. Actual name bytes, value "ThisIs", 6 bytes.

    Result = 8 bytes.

    Now that we understand the structure of the packet we can count all of the bytes:

    1. Device name field: 8 bytes
    2. Flag field: Length (1), type (1), flag(1) = 3 bytes
    3. 16-bit Service Class UUID: Length(1), type(1), UUID(2) = 4 bytes
    4. Manufacturer Specific: Lenght(1), type(1), company ID(2), data(10) = 14 bytes

    Result = 29 bytes!

    Now what happens if you add a TX power level field? Then you will add an additional Lenght byte, type byte and tx power level byte, i.e. 3 more bytes and you are up in a total of 32 bytes, 1 more than the allowed 31 bytes. So your solution will be to shorten your Device Name field or Manufacturer Specific data field with at least one byte.

    I know I should probably have added this in the tutorial, but I figured it was too much extra reading.

  • Hi,

    My code looks like this now. However, the device still didn't show up in the MCP.

    static void advertising_init(void) 
        uint32_t            err_code;
        ble_advdata_t       advdata;    // Struct containing advertising parameters
        uint8_t             flags       = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; // Defines how your device is seen (or not seen) by other devices
    	ble_uuid_t          adv_uuids[] = {
    																			{0x1234, BLE_UUID_TYPE_BLE}
    																		};    // Random example User Unique Identifier
    		//add tx_power_level variable
    		int8_t        tx_power_level = -20;
        ble_advdata_manuf_data_t manuf_data; // Variable to hold manufacturer specific data
    	uint8_t data[] 									= "SomeData!"; // Our data to adverise
    	manuf_data.company_identifier 	= 0x0059; //Nordics company ID					= data;						= sizeof(data);	 
    	// Populate the advertisement packet
        // Always initialize all fields in structs to zero or you might get unexpected behaviour
        memset(&advdata, 0, sizeof(advdata));
        advdata.name_type          = BLE_ADVDATA_SHORT_NAME;      
    	advdata.short_name_len  = 6;
        advdata.flags                   = flags;                                     // Must be included, but not discussed in this tutorial
        advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]); // Must be included, but not discussed in this tutorial
        advdata.uuids_complete.p_uuids  = adv_uuids;                                // Must be included, but not discussed in this tutorial
    	advdata.p_manuf_specific_data   = &manuf_data;                              // Load the manufacturer specific data into advertising packet
    	//adjust the transmit power of the device 	
    	advdata.p_tx_power_level 					= &tx_power_level;		
        // Set the advertisement and scan response packet. 
        err_code = ble_advdata_set(&advdata, NULL);
        APP_ERROR_CHECK(err_code);// Check for errors

    Is there anything else that I should do?