Getting started with Bluetooth Direction Finding

Hello, i have several questions regarding bluetooth direction finding.

My ultimate goal is to have a Real Time Location System with 6 locators (AoA) and 30 trackers.


For now, i want to:

  1. be able to calculate an angle of arrival using nordic's example code
  2. be able to receive CTE signals from 2 trackers on the same locator
  3. implement a CTE beacon on my company's products whose firmware is based on nRF5 sdk v17

My questions are the following:

1 - What is the difference between Central/Peripheral and Locator/Beacon example codes ? Which would be the best for my use case?

2 - What is the link between the antennas and the Q/I samples? How does antenna switching work?

static void cte_recv_cb(struct bt_le_per_adv_sync *sync, struct bt_df_per_adv_sync_iq_samples_report const *report)
{
	char le_addr[BT_ADDR_LE_STR_LEN];
	
	struct bt_le_per_adv_sync_info info;
	bt_le_per_adv_sync_get_info(sync, &info);
	bt_addr_le_to_str(&info.addr, le_addr, sizeof(le_addr));

	char output[361]; 
    int offset = 0;
	for(int iter = 0; iter < report->sample_count; iter++)
	    offset += sprintf(output + offset,"%d;%d;", report->sample[iter].i, report->sample[iter].q);
	sprintf(output + offset,"\n");
	printk("%s;%s", le_addr, output);
}

I am able to display Q/I samples using the code above. However I cant make sense out of those values.
I went through the theory and I understand how AoA works and how to calculate the angle from Q/I values:

  • arctan(Q/I) gives me the phase of the signal (φ) received for each antenna
  • I then calculate the phase difference between 2 antennas Δφ
  • I measure the distance between 2 antennas (on nordic's antenna matrix that would be d = 5 cm for adjacent antennas)
  • the measured angle would be  θ = arcsin(λ/2π x Δφ  x 1/d)

But the result I get is random values roughly between -0.05 and 0.05.
I think my problem is antenna switching.
I am using the default pattern for nordic's antenna matrix:
(0x2, 0x0, 0x5, 0x6, 0x1, 0x40xC, 0x9, 0xE, 0xD, 0x8, 0xA) => ANT11, ANT12, ANT1, ANT2, ANT10, ANT3, ANT9, ANT4, ANT8, ANT7, ANT6, ANT5
I have 45 values for 12 antennas  so i assume that the first value is for ANT11, the second is for ANT12, ... and when i get to the thirteenth value, it loops back to ANT11.
This was my supposition and my measured angles seem off.
After digging a bit on this forum someone said that the code doesn't loop through all of the antennas, so im not sure.

3 - How can I receive CTE signals from multiple trackers on one locator?

(fyi i use nRF52833 DevKit and nrf example codes not zephyr's)
I ran the DF central code on a DevKit with a antenna matrix and i ran the DF peripheral code on two other DevKits.
Instead of getting CTE signals for both kits, it seems that the central would connect to only one of them and then only receive CTE signals from that same peripheral.
I thought that's how the example code was supposed to work so i tried running the 'connectionless' code (aka Locator/Beacon) but i get the same behaviour.

4 - Lastly I want to know if it is possible to implement a beacon in nRF5 sdk. And is it possible to do this while using the softdevice.

I want my products that already run on nRF5 sdk v17 (with softdevice) to be locatable.
I've seen a code posted on this forum by the support team that consists of ble_app_beacon example
where BLE_GAP_ADV_SET_DATA_SIZE_MAX is replaced by BLE_GAP_ADV_SET_DATA_SIZE_EXTENDED_MAX_SUPPORTED
and BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED is replaced by BLE_GAP_ADV_TYPE_EXTENDED_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED
but when i ran this code, i didnt receive Q/I values on my locator.

Thanks in advance


  • Right now i have my antenna matrix sitting on a table and i am moving around it with my beacon devkit.
    i get my Q/I samples;
    i separate those samples according my antenna switching pattern;
    i calculate the phase with the formula 'phase = atan2(Q, I)';
    and finnaly, i calculate the difference between both waves and i display it on these graphs


    when i stand right in front of the antennas i get 0 rad phase difference as you can see in this graph which is logical since the signal reaches both antennas at the same time.

    in theory, if i am 'aligned' with the antennas, i should get +3.14 or -3.14 phase difference since the waves received by each antenna are in phase opposition

    however, when i move around, i cant get past 1rad phase difference (as shown in the other graph)

  • So how does the measured phase shift align with the modeled phase shift?

    It's impossible to comment on AoA measurement data if you don't have all the information about how they are taken. The better approach is making a simulation as you can then assess the validity of your measurements.

  • Hi again

    I'm reviving this ticket because i am still stuck
    Here is what i did.

    I configured the sample code to work with a 3 antenna switch pattern.
    As you can see the 1st signal 'looks' good. We can see the Ref period and some irregularities from antenna switching on the signal.

    Then i split the samples from each antenna  (2nd row of plots)

    I calculate the phase, and adjust to avoid having +/- pi jumps (3rd row of plots)

    I interpolate to take into account the time shift caused by the antenna switching (4th row of plots)

    But when i plot the phase difference, i get different results event if my beacon doesn't move.
    Here you can see the phases of ANT7 ANT8 and ANT9 in two different CTE signals after measuring the position of a static beacon






  • I am not sure I understand what you are trying to plot here.

    If you want to look at the samples you should do that with time on the X-axis and not the sample number, difficult to say what you are showing. This as the reference period has a different sampling interval than the rest of the samples.

    You would then use the reference period samples to predict the phase of the signal on the reference antenna for the entire sampling window. When you then start sampling the different antennas, you compare them to this predicted phase. For the samples with the reference antenna, the error should be 0. If it is not then the prediction is not good enough. The "error" on the other antennas will be the phase shift. If you do this then the phase will be around 0 so any phase shifts will be significantly easier to see than what seems to be in your graphs.

  • OK thx
    i wasnt using the reference period at all.
    i was switching between 3 antennas (ANT7 ANT8 ANT9) and using ANT8 as a phase reference.

    i will try what you suggested and see if i get better results

Related