Range accuracy DW1000

Hi everyone,
I need to perform accurate ranging, but a lot of known problems arise, and I would like to know if some of these are solvable:

  • In LOS scenario:
    • antenna orientation makes computed distances varies about 10-15cm, this effect may be mitigated by using a, e.g., a PCB antenna, or by applying bias correction (Frii’s formula)?
    • which is the best way to perform antenna delay calibration? I simply tune it basing on a calibrate distance of 185 cm, but then after, in some positions ranging results quite incorrect (even maybe due to antenna orientation and RSL bias effect). In user manual it is recommended to set TX power to
      -41db/Mhz but actually I don’t know which is the hexadecimal value corresponding to this measure.
  • In NLOS scenario:
    • Frii formula for bias correction may mitigate for this effect or it is better to discrard the measure?
    • In order to detect a NLOS path I’m following the approach described in APS006 part 3, but many times it fails (actually I’m not using the undetected first path algorithm). Is there a more robust way to detect it?

Thank you

Antenna orientation - If you know the relative orientations then you model the effects and correct for this but it’s not trivial to do. There will be effects beyond just the antenna gain differences. Moving the antenna away from the rest of the PCB will minimize the impact on pattern caused by the rest of the electronics but won’t completely eliminate it. Other than that about the only other option available to you is to use a different antenna. No antenna is perfect but some designs are better than others.

Antenna delay calibration - If you are only using a single pair of devices then measuring the error at a fixed distance is a reasonable way to calculate it for the pair. But you have to assume the delay is split evenly between the two devices which is incorrect and so will result in errors as soon as you throw a 3rd device into the mix. If you use 3 or more units in a pattern (e.g. 3 in an equilateral triangle) then you can calculate accurate per unit delays. But in that situation you may need to take antenna orientation into account.
The transmit power to obtain -41dB/MHz will depend on antenna gains and the channel used.

Don’t forget that when you change the range you will also need to compensate for signal levels. You could use Frii’s formula but personally I found it more accurate to measure the effect rather than use a theoretical model.

In a NLOS situation you can attempt to compensate a little based on signal levels and lower your threshold to decrease the odds of a false direct path measurement. If you have a sufficiently advanced position algorithm you can de-weight suspected NLOS measurements to minimize their impact on position accuracy. But mostly you just have to accept that your accuracy will be less in a NLOS situation.

1 Like

Hi,

I am attempting to calculate the distance, but I am receiving incorrect results, and the distance is showing as negative. Here is the code for distance calculation:

static void rx_ok_cb(const dwt_cb_data_t *cb_data)
{
uint32 frame_len;

/* Clear good RX frame event in the DW1000 status register. */
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);

/* A frame has been received, read it into the local buffer. */
frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFLEN_MASK;

/* Clear local RX buffer to avoid having leftovers from previous receptions. This is not necessary but is included here to aid reading the RX
 * buffer. */
for (int i = 0 ; i < frame_len; i++ )
{
	rx_buffer[i] = 0;
}

if (frame_len <= RX_BUF_LEN)
{
	dwt_readrxdata(rx_buffer, frame_len, 0);
}

/* Check that the frame is the expected response from the companion "SS TWR responder" example.
 * As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */
rx_buffer[ALL_MSG_SN_IDX] = 0;
if (memcmp(rx_buffer, rx_resp_msg, ALL_MSG_COMMON_LEN) == 0)
{
	uint32 poll_tx_ts, resp_rx_ts, poll_rx_ts, resp_tx_ts;
	int32 rtd_init, rtd_resp;
	float clockOffsetRatio ;

	/* Retrieve poll transmission and response reception timestamps. See NOTE 9 below. */
	poll_tx_ts = dwt_readtxtimestamplo32();
	resp_rx_ts = dwt_readrxtimestamplo32();

	/* Read carrier integrator value and calculate clock offset ratio. See NOTE 11 below. */
	clockOffsetRatio = dwt_readcarrierintegrator() * (double)((FREQ_OFFSET_MULTIPLIER * HERTZ_TO_PPM_MULTIPLIER_CHAN_2) / 1.0e6) ;

	/* Get timestamps embedded in response message. */
	resp_msg_get_ts(&rx_buffer[RESP_MSG_POLL_RX_TS_IDX], &poll_rx_ts);
	resp_msg_get_ts(&rx_buffer[RESP_MSG_RESP_TX_TS_IDX], &resp_tx_ts);

	/* Compute time of flight and distance, using clock offset ratio to correct for differing local and remote clock rates */
	rtd_init = resp_rx_ts - poll_tx_ts;
	rtd_resp = resp_tx_ts - poll_rx_ts;

	tof = ((rtd_init - rtd_resp * (1.0f - (double)clockOffsetRatio)) / 2.0f) * DWT_TIME_UNITS;
	distance = (tof * SPEED_OF_LIGHT);
            }
     /* Set corresponding inter-frame delay. */
tx_delay_ms = DFLT_TX_DELAY_MS;

}…