Esp32+dw3000 DS TWR sample code

We were earlier working with DW1000 libraries and examples as part of Github link those were provided by Qorvo forum. We were using the combination of ESP32 with DW1000. In this, we were using DS_TWR (Double Sided TWR), and it was working out well for our application.
We now are trying to move our application to combination of ESP32 with DW3000. For this, we referred to the sample codes provided at

           https://github.com/Makerfabs/Makerfabs-ESP32-UWB-DW3000/tree/main/Dw3000 (this link was referred to us by Qorvo forum),

these sample codes provided in above link are for SS_TWR (Single Sided TWR) only and not for DS_TWR.

Can you guide us to DS_TWR code for ESP32 using DW3000?

If you have single sided working and known code for DS then it shouldn’t be too hard to make the change yourself.
Do two SS ranges, one in each direction. Ignore the clock rate corrections. Average the two results or use the formula in the back of the user manual (the DW1000 one at least).
A refinement that is normally made is that the 2nd message (Reply from the anchor) is also used as the initial request for the 2nd range.

I am attaching here my anchor and TAG code

Anchor

#include <Ndw3000.h>

#define ANCHOR_ADD “81:17:5B:D5:A9:9A:E2:9C”

static uint8_t Address[] = {0x81, 0x17, 0x5B, 0xD5,0xA9, 0x9A,0xE2, 0x9C};
static uint16_t Address1 = 0x8117;
// connection pins
const uint8_t PIN_RST = 27; // reset pin
const uint8_t PIN_IRQ = 34; // irq pin
const uint8_t PIN_SS = 4; // spi select pin

uint16_t Adelay = 16539;//16965;
float average =0;
uint16_t Average_Counter = 0;
unsigned char Ranging_Done = 0;
volatile int Enable_receive_Blink = 1;
volatile int Transmit_blink_en = 1;
String T ;
String Prv_Tag_ID;
byte Prv_SeqNum_ID ;
String Data;
const int numReadings = 10;
float readings [numReadings];
int readIndex = 0;
float total = 0.0;
byte seqnum;

/* Default communication configuration. We use default non-STS DW mode. */
extern void test_run_info(unsigned char *data);

/* Example application name */
#define APP_NAME “DS TWR RESP v1.0”

/* Default communication configuration. We use default non-STS DW mode. /
static dwt_config_t config = {
5, /
Channel number. /
DWT_PLEN_128, /
Preamble length. Used in TX only. /
DWT_PAC8, /
Preamble acquisition chunk size. Used in RX only. /
9, /
TX preamble code. Used in TX only. /
9, /
RX preamble code. Used in RX only. /
1, /
0 to use standard 8 symbol SFD, 1 to use non-standard 8 symbol, 2 for non-standard 16 symbol SFD and 3 for 4z 8 symbol SDF type /
DWT_BR_6M8, /
Data rate. /
DWT_PHRMODE_STD, /
PHY header mode. /
DWT_PHRRATE_STD, /
PHY header rate. /
(129 + 8 - 8), /
SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. /
DWT_STS_MODE_OFF, /
STS disabled /
DWT_STS_LEN_64, /
STS length see allowed values in Enum dwt_sts_lengths_e /
DWT_PDOA_M0 /
PDOA mode off */
};

/* Inter-ranging delay period, in milliseconds. */
#define RNG_DELAY_MS 1000

/* Default antenna delay values for 64 MHz PRF. See NOTE 1 below. */
#define TX_ANT_DLY 16385
#define RX_ANT_DLY 16385

/* Frames used in the ranging process. See NOTE 2 below. /
static uint8_t rx_poll_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘W’, ‘A’, ‘V’, ‘E’, 0x21, 0, 0 };
static uint8_t tx_resp_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘V’, ‘E’, ‘W’, ‘A’, 0x10, 0x02, 0, 0, 0, 0 };
static uint8_t rx_final_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘W’, ‘A’, ‘V’, ‘E’, 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/
Length of the common part of the message (up to and including the function code, see NOTE 2 below). /
#define ALL_MSG_COMMON_LEN 10
/
Index to access some of the fields in the frames involved in the process. /
#define ALL_MSG_SN_IDX 2
#define FINAL_MSG_POLL_TX_TS_IDX 10
#define FINAL_MSG_RESP_RX_TS_IDX 14
#define FINAL_MSG_FINAL_TX_TS_IDX 18
/
Frame sequence number, incremented after each transmission. */
static uint8_t frame_seq_nb = 0;

/* Buffer to store received messages.

  • Its size is adjusted to longest frame that this example code is supposed to handle. */
    #define RX_BUF_LEN 24
    static uint8_t rx_buffer[RX_BUF_LEN];

/* Hold copy of status register state here for reference so that it can be examined at a debug breakpoint. */
static uint32_t status_reg = 0;

/* Delay between frames, in UWB microseconds. See NOTE 1 below. */
#ifdef RPI_BUILD
#define POLL_RX_TO_RESP_TX_DLY_UUS 550
#endif //RPI_BUILD
#ifdef STM32F429xx
#define POLL_RX_TO_RESP_TX_DLY_UUS 450
#endif //STM32F429xx
#ifdef NRF52840_XXAA
#define POLL_RX_TO_RESP_TX_DLY_UUS 650
#endif //NRF52840_XXAA

#define POLL_RX_TO_RESP_TX_DLY_UUS 450
#define RESP_TX_TO_FINAL_RX_DLY_UUS 450
#define FINAL_RX_TIMEOUT_UUS 450
/* Preamble timeout, in multiple of PAC size. See NOTE 6 below. */
#define PRE_TIMEOUT 5

/* Timestamps of frames transmission/reception. */
static uint64_t poll_rx_ts;
static uint64_t resp_tx_ts;
static uint64_t final_rx_ts;

/* Hold copies of computed time of flight and distance here for reference so that it can be examined at a debug breakpoint. /
static double tof;
static double distance;
/
Values for the PG_DELAY and TX_POWER registers reflect the bandwidth and power of the spectrum at the current

  • temperature. These values can be calibrated prior to taking reference measurements. See NOTE 2 below. */
    extern dwt_txconfig_t txconfig_options;
    unsigned char msg11[90];
    uint16_t add = 0;
    void setup() {
    // DEBUG monitoring
    Serial.begin(115200);

/* Display application name on LCD. */
test_run_info((unsigned char )APP_NAME);
/
Configure SPI rate, DW3000 supports up to 38 MHz /
/
Reset DW IC */
spiBegin(PIN_IRQ, PIN_RST);
spiSelect(PIN_SS);

Sleep(2); // Time needed for DW3000 to start up (transition from INIT_RC to IDLE_RC



while (!dwt_checkidlerc()) /* Need to make sure DW IC is in IDLE_RC before proceeding */ { };

if (dwt_initialise(DWT_DW_INIT) == DWT_ERROR)
{
    test_run_info((unsigned char *)"INIT FAILED     ");
    while (1) { };
}

/* Configure DW IC. See NOTE 15 below. */
/* if the dwt_configure returns DWT_ERROR either the PLL or RX calibration has failed the host should reset the device */
if (dwt_configure(&config))
{
    test_run_info((unsigned char *)"CONFIG FAILED     ");
    while (1) { };
}

/* Configure the TX spectrum parameters (power, PG delay and PG count) */
dwt_configuretxrf(&txconfig_options);

/* Apply default antenna delay value. See NOTE 1 below. */
dwt_setrxantennadelay(RX_ANT_DLY);
dwt_settxantennadelay(TX_ANT_DLY);

/* Next can enable TX/RX states output on GPIOs 5 and 6 to help debug, and also TX/RX LEDs
 * Note, in real low power applications the LEDs should not be used. */
dwt_setlnapamode(DWT_LNA_ENABLE | DWT_PA_ENABLE);
  // Enabling LEDs here for debug so that for each TX the D1 LED will flash on DW3000 red eval-shield boards.

dwt_setleds(DWT_LEDS_ENABLE | DWT_LEDS_INIT_BLINK);
}

void loop() {

    /* Activate reception immediately. */
    dwt_rxenable(DWT_START_RX_IMMEDIATE);


    /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
    while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR)))
    { };
    if (status_reg & SYS_STATUS_RXFCG_BIT_MASK)
    {
        uint16_t frame_len;

        /* Clear good RX frame event in the DW IC status register. */
  //      dwt_writesysstatuslo(DWT_INT_RXFCG_BIT_MASK);
      /* Clear good RX frame event in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG_BIT_MASK);
        /* A frame has been received, read it into the local buffer. */
      
        frame_len = dwt_read32bitreg(RX_FINFO_ID) & RXFLEN_MASK;
        if (frame_len <= RX_BUF_LEN)
        {
            dwt_readrxdata(rx_buffer, frame_len, 0);
        }

        /* Check that the frame is a poll sent by "DS TWR initiator" 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_poll_msg, ALL_MSG_COMMON_LEN) == 0)
        {
            uint32_t resp_tx_time;
            int ret;

            /* Retrieve poll reception timestamp. */
            poll_rx_ts = get_rx_timestamp_u64();

            /* Set send time for response. See NOTE 9 below. */
            resp_tx_time = (poll_rx_ts + (POLL_RX_TO_RESP_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;
            dwt_setdelayedtrxtime(resp_tx_time);

            /* Set expected delay and timeout for final message reception. See NOTE 4 and 5 below. */
            dwt_setrxaftertxdelay(RESP_TX_TO_FINAL_RX_DLY_UUS);
            dwt_setrxtimeout(FINAL_RX_TIMEOUT_UUS);
            /* Set preamble timeout for expected frames. See NOTE 6 below. */
            dwt_setpreambledetecttimeout(PRE_TIMEOUT);

            /* Write and send the response message. See NOTE 10 below.*/
            tx_resp_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
            dwt_writetxdata(sizeof(tx_resp_msg), tx_resp_msg, 0); /* Zero offset in TX buffer. */
            dwt_writetxfctrl(sizeof(tx_resp_msg), 0, 1);          /* Zero offset in TX buffer, ranging. */
            ret = dwt_starttx(DWT_START_TX_DELAYED | DWT_RESPONSE_EXPECTED);

            /* If dwt_starttx() returns an error, abandon this ranging exchange and proceed to the next one. See NOTE 11 below. */
            if (ret == DWT_ERROR)
            {
               // continue;
            }

      

    /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
    while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR)))
    { };
            /* Increment frame sequence number after transmission of the response message (modulo 256). */
            frame_seq_nb++;

            if (status_reg & SYS_STATUS_RXFCG_BIT_MASK)
            {
      
                          /* Clear good RX frame event in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG_BIT_MASK| SYS_STATUS_TXFRS_BIT_MASK);

                /* A frame has been received, read it into the local buffer. */
              //  frame_len = dwt_getframelength();
                frame_len = dwt_read32bitreg(RX_FINFO_ID) & RXFLEN_MASK;
                if (frame_len <= RX_BUF_LEN)
                {
                    dwt_readrxdata(rx_buffer, frame_len, 0);
                }

                /* Check that the frame is a final message sent by "DS TWR initiator" example.
                 * As the sequence number field of the frame is not used in this example, it can be zeroed to ease the validation of the frame. */
                rx_buffer[ALL_MSG_SN_IDX] = 0;
                if (memcmp(rx_buffer, rx_final_msg, ALL_MSG_COMMON_LEN) == 0)
                {
                    uint32_t poll_tx_ts, resp_rx_ts, final_tx_ts;
                    uint32_t poll_rx_ts_32, resp_tx_ts_32, final_rx_ts_32;
                    double Ra, Rb, Da, Db;
                    int64_t tof_dtu;

                    /* Retrieve response transmission and final reception timestamps. */
                    resp_tx_ts = get_tx_timestamp_u64();
                    final_rx_ts = get_rx_timestamp_u64();

                    /* Get timestamps embedded in the final message. */
                    final_msg_get_ts(&rx_buffer[FINAL_MSG_POLL_TX_TS_IDX], &poll_tx_ts);
                    final_msg_get_ts(&rx_buffer[FINAL_MSG_RESP_RX_TS_IDX], &resp_rx_ts);
                    final_msg_get_ts(&rx_buffer[FINAL_MSG_FINAL_TX_TS_IDX], &final_tx_ts);

                    /* Compute time of flight. 32-bit subtractions give correct answers even if clock has wrapped. See NOTE 12 below. */
                    poll_rx_ts_32 = (uint32_t)poll_rx_ts;
                    resp_tx_ts_32 = (uint32_t)resp_tx_ts;
                    final_rx_ts_32 = (uint32_t)final_rx_ts;
                    Ra = (double)(resp_rx_ts - poll_tx_ts);
                    Rb = (double)(final_rx_ts_32 - resp_tx_ts_32);
                    Da = (double)(final_tx_ts - resp_rx_ts);
                    Db = (double)(resp_tx_ts_32 - poll_rx_ts_32);
                    tof_dtu = (int64_t)((Ra * Rb - Da * Db) / (Ra + Rb + Da + Db));

                    tof = tof_dtu * DWT_TIME_UNITS;
                    distance = tof * SPEED_OF_LIGHT;
                    /* Display computed distance on LCD. */
                    sprintf(dist_str, "DIST: %3.2f m", distance);
                    test_run_info((unsigned char *)dist_str);

                    /* as DS-TWR initiator is waiting for RNG_DELAY_MS before next poll transmission
                     * we can add a delay here before RX is re-enabled again
                     */
                    Sleep(RNG_DELAY_MS - 10); // start couple of ms earlier
                }
            }
            else
            {
                /* Clear RX error/timeout events in the DW IC status register. */
                dwt_write32bitreg(SYS_STATUS_ID,SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR);
            }
        }
    }
    else
    {
        /* Clear RX error/timeout events in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID,SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR);
    }

}

Tag:

#include <Ndw3000.h>

#define ANCHOR_ADD “81:17:5B:D5:A9:9A:E2:9C”

static uint8_t Address[] = {0x81, 0x17, 0x5B, 0xD5,0xA9, 0x9A,0xE2, 0x9C};
static uint16_t Address1 = 0x8117;
// connection pins
const uint8_t PIN_RST = 27; // reset pin
const uint8_t PIN_IRQ = 34; // irq pin
const uint8_t PIN_SS = 4; // spi select pin

uint16_t Adelay = 16539;//16965;
float average =0;
uint16_t Average_Counter = 0;
unsigned char Ranging_Done = 0;
volatile int Enable_receive_Blink = 1;
volatile int Transmit_blink_en = 1;
String T ;
String Prv_Tag_ID;
byte Prv_SeqNum_ID ;
String Data;
const int numReadings = 10;
float readings [numReadings];
int readIndex = 0;
float total = 0.0;
byte seqnum;

extern void test_run_info(unsigned char *data);

/* Example application name and version to display on LCD screen. */
#define APP_NAME “DS TWR INIT v1.0”

/* Default communication configuration. We use default non-STS DW mode. /
static dwt_config_t config = {
5, /
Channel number. /
DWT_PLEN_128, /
Preamble length. Used in TX only. /
DWT_PAC8, /
Preamble acquisition chunk size. Used in RX only. /
9, /
TX preamble code. Used in TX only. /
9, /
RX preamble code. Used in RX only. /
1, /
0 to use standard 8 symbol SFD, 1 to use non-standard 8 symbol, 2 for non-standard 16 symbol SFD and 3 for 4z 8 symbol SDF type /
DWT_BR_6M8, /
Data rate. /
DWT_PHRMODE_STD, /
PHY header mode. /
DWT_PHRRATE_STD, /
PHY header rate. /
(129 + 8 - 8), /
SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. /
DWT_STS_MODE_OFF, /
STS disabled /
DWT_STS_LEN_64, /
STS length see allowed values in Enum dwt_sts_lengths_e /
DWT_PDOA_M0 /
PDOA mode off */
};

/* Inter-ranging delay period, in milliseconds. */
#define RNG_DELAY_MS 1000

/* Default antenna delay values for 64 MHz PRF. See NOTE 1 below. /
#define TX_ANT_DLY 16385
#define RX_ANT_DLY 16385
/

  • The first 10 bytes of those frame are common and are composed of the following fields:
  • - byte 0/1: frame control (0x8841 to indicate a data frame using 16-bit addressing).
    
  • - byte 2: sequence number, incremented for each new frame.
    
  • - byte 3/4: PAN ID (0xDECA).
    
  • - byte 5/6: destination address, see NOTE 3 below.
    
  • - byte 7/8: source address, see NOTE 3 below.
    
  • - byte 9: function code (specific values to indicate which message it is in the ranging process).
    
  • The remaining bytes are specific to each message as follows:
  • Poll message:
  • - no more data
    
  • Response message:
  • - byte 10: activity code (0x02 to tell the initiator to go on with the ranging exchange).
    
  • - byte 11/12: activity parameter, not used here for activity code 0x02.
    
  • Final message:
  • - byte 10 -> 13: poll message transmission timestamp.
    
  • - byte 14 -> 17: response message reception timestamp.
    
  • - byte 18 -> 21: final message transmission timestamp.
    
  • All messages end with a 2-byte checksum automatically set by DW IC.
    /
    /
    Frames used in the ranging process. See NOTE 2 below. /
    static uint8_t tx_poll_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘W’, ‘A’, ‘V’, ‘E’, 0x21 };
    static uint8_t rx_resp_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘V’, ‘E’, ‘W’, ‘A’, 0x10, 0x02, 0, 0 };
    static uint8_t tx_final_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘W’, ‘A’, ‘V’, ‘E’, 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    /
    Length of the common part of the message (up to and including the function code, see NOTE 2 below). /
    #define ALL_MSG_COMMON_LEN 10
    /
    Indexes to access some of the fields in the frames defined above. /
    #define ALL_MSG_SN_IDX 2
    #define FINAL_MSG_POLL_TX_TS_IDX 10
    #define FINAL_MSG_RESP_RX_TS_IDX 14
    #define FINAL_MSG_FINAL_TX_TS_IDX 18
    /
    Frame sequence number, incremented after each transmission. */
    static uint8_t frame_seq_nb = 0;

/* Buffer to store received response message.

  • Its size is adjusted to longest frame that this example code is supposed to handle. */
    #define RX_BUF_LEN 20
    static uint8_t rx_buffer[RX_BUF_LEN];

/* Hold copy of status register state here for reference so that it can be examined at a debug breakpoint. */
static uint32_t status_reg = 0;

/* Delay between frames, in UWB microseconds. See NOTE 4 below. /
/
Delay between frames, in UWB microseconds. See NOTE 1 below. /
#ifdef RPI_BUILD
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#endif //RPI_BUILD
#ifdef STM32F429xx
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#endif //STM32F429xx
#ifdef NRF52840_XXAA
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#endif //NRF52840_XXAA
/
Receive response timeout. See NOTE 5 below. */
#ifdef RPI_BUILD
#define RESP_RX_TIMEOUT_UUS 270
#endif //RPI_BUILD
#ifdef STM32F429xx
#define RESP_RX_TIMEOUT_UUS 210
#endif //STM32F429xx
#ifdef NRF52840_XXAA
#define RESP_RX_TIMEOUT_UUS 400
#endif //NRF52840_XXAA

#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#define RESP_RX_TIMEOUT_UUS 400
#define RESP_RX_TO_FINAL_TX_DLY_UUS 240
/* Preamble timeout, in multiple of PAC size. See NOTE 7 below. */
#define PRE_TIMEOUT 5

/* Time-stamps of frames transmission/reception, expressed in device time units. */
static uint64_t poll_tx_ts;
static uint64_t resp_rx_ts;
static uint64_t final_tx_ts;

/* Values for the PG_DELAY and TX_POWER registers reflect the bandwidth and power of the spectrum at the current

  • temperature. These values can be calibrated prior to taking reference measurements. See NOTE 8 below. */
    extern dwt_txconfig_t txconfig_options;

unsigned char msg11[90];
uint16_t add = 0;
void setup() {
// DEBUG monitoring
Serial.begin(115200);

test_run_info((unsigned char *)APP_NAME);

/* Configure SPI rate, DW3000 supports up to 38 MHz /
/
Reset DW IC */
spiBegin(PIN_IRQ, PIN_RST);
spiSelect(PIN_SS);

Sleep(2); // Time needed for DW3000 to start up (transition from INIT_RC to IDLE_RC



while (!dwt_checkidlerc()) /* Need to make sure DW IC is in IDLE_RC before proceeding */ { };

if (dwt_initialise(DWT_DW_INIT) == DWT_ERROR)
{
    test_run_info((unsigned char *)"INIT FAILED     ");
    while (1) { };
}

/* Configure DW IC. See NOTE 2 below. */
/* if the dwt_configure returns DWT_ERROR either the PLL or RX calibration has failed the host should reset the device */
if (dwt_configure(&config))
{
    test_run_info((unsigned char *)"CONFIG FAILED     ");
    while (1) { };
}

/* Configure the TX spectrum parameters (power, PG delay and PG count) */
dwt_configuretxrf(&txconfig_options);

/* Apply default antenna delay value. See NOTE 1 below. */
dwt_setrxantennadelay(RX_ANT_DLY);
dwt_settxantennadelay(TX_ANT_DLY);

/* Set expected response's delay and timeout. See NOTE 4, 5 and 7 below.
 * As this example only handles one incoming frame with always the same delay and timeout, those values can be set here once for all. */
dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);
dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS);
dwt_setpreambledetecttimeout(PRE_TIMEOUT);

/* Next can enable TX/RX states output on GPIOs 5 and 6 to help debug, and also TX/RX LEDs
 * Note, in real low power applications the LEDs should not be used. */
dwt_setlnapamode(DWT_LNA_ENABLE | DWT_PA_ENABLE);
 dwt_setleds(DWT_LEDS_ENABLE | DWT_LEDS_INIT_BLINK);

}

void loop() {
/* Write frame data to DW IC and prepare transmission. See NOTE 9 below. /
tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0); /
Zero offset in TX buffer. /
dwt_writetxfctrl(sizeof(tx_poll_msg) + FCS_LEN, 0, 1); /
Zero offset in TX buffer, ranging. */

    /* Start transmission, indicating that a response is expected so that reception is enabled automatically after the frame is sent and the delay
     * set by dwt_setrxaftertxdelay() has elapsed. */
    dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);


   /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
    while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR)))
    { };
    /* Increment frame sequence number after transmission of the poll message (modulo 256). */
    frame_seq_nb++;

    if (status_reg & SYS_STATUS_RXFCG_BIT_MASK)
    {
        uint16_t frame_len;

        /* Clear good RX frame event and TX frame sent in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID,SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_TXFRS_BIT_MASK);

        /* A frame has been received, read it into the local buffer. */

       frame_len = dwt_read32bitreg(RX_FINFO_ID) & RXFLEN_MASK;
        if (frame_len <= RX_BUF_LEN)
        {
            dwt_readrxdata(rx_buffer, frame_len, 0);
        }

        /* Check that the frame is the expected response from the companion "DS 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_t final_tx_time;
            int ret;

            /* Retrieve poll transmission and response reception timestamp. */
            poll_tx_ts = get_tx_timestamp_u64();
            resp_rx_ts = get_rx_timestamp_u64();

            /* Compute final message transmission time. See NOTE 11 below. */
            final_tx_time = (resp_rx_ts + (RESP_RX_TO_FINAL_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;
            dwt_setdelayedtrxtime(final_tx_time);

            /* Final TX timestamp is the transmission time we programmed plus the TX antenna delay. */
            final_tx_ts = (((uint64_t)(final_tx_time & 0xFFFFFFFEUL)) << 8) + TX_ANT_DLY;

            /* Write all timestamps in the final message. See NOTE 12 below. */
            final_msg_set_ts(&tx_final_msg[FINAL_MSG_POLL_TX_TS_IDX], poll_tx_ts);
            final_msg_set_ts(&tx_final_msg[FINAL_MSG_RESP_RX_TS_IDX], resp_rx_ts);
            final_msg_set_ts(&tx_final_msg[FINAL_MSG_FINAL_TX_TS_IDX], final_tx_ts);

            /* Write and send final message. See NOTE 9 below. */
            tx_final_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
            dwt_writetxdata(sizeof(tx_final_msg), tx_final_msg, 0); /* Zero offset in TX buffer. */
            dwt_writetxfctrl(sizeof(tx_final_msg) + FCS_LEN, 0, 1); /* Zero offset in TX buffer, ranging bit set. */

            ret = dwt_starttx(DWT_START_TX_DELAYED);
            /* If dwt_starttx() returns an error, abandon this ranging exchange and proceed to the next one. See NOTE 13 below. */
            if (ret == DWT_SUCCESS)
            {

                    /* Poll DW IC until TX frame sent event set. See NOTE 6 below. */
                    while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS_BIT_MASK))
                    { };

                    /* Clear TXFRS event. */
                    dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS_BIT_MASK);
                /* Increment frame sequence number after transmission of the final message (modulo 256). */
                frame_seq_nb++;
            }
        }
    }
    else
    {
        /* Clear RX error/timeout events in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID,SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR | SYS_STATUS_TXFRS_BIT_MASK);
    }

    /* Execute a delay between ranging exchanges. */
    Sleep(RNG_DELAY_MS);

}

In my above code i didnot get last frame from tag to calculate distance on anchor

Your timeout delays are not much longer or in one case the same as your delay times. Try increasing them. Also make sure your delay times are achievable, if you set one as lower than the actual time taken to process the message and queue up the reply then the transmission will be scheduled for 18 seconds time.

I just had the same error, just try to increase the PRE_TIMEOUT define. I’ve increase it to 50 and now i can range the distance

I changed Timeout as well but still not working

If you share your code properly like ino file I can control it easily for you. By the way, I guess you changed the library(Ndw3000.h) too.

Ndw3000.h same as dw3000.h here i attached my code
not allowed me attch code here i will copy my anchor and tag code below

/*

  • Copyright (c) 2015 by Thomas Trojer thomas@trojer.net
  • Decawave DW3000 library for arduino.
  • Licensed under the Apache License, Version 2.0 (the “License”);
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at
  • http://www.apache.org/licenses/LICENSE-2.0
    
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an “AS IS” BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.
  • @file BasicConnectivityTest.ino
  • Use this to test connectivity with your DW3000 from Arduino.
  • It performs an arbitrary setup of the chip and prints some information.
  • @todo
    • move strings to flash (less RAM consumption)
    • make real check of connection (e.g. change some values on DW3000 and verify)
      */

#include “dw3000.h”

#define ANCHOR_ADD “81:17:5B:D5:A9:9A:E2:9C”

static uint8_t Address[] = {0x81, 0x17, 0x5B, 0xD5,0xA9, 0x9A,0xE2, 0x9C};
static uint16_t Address1 = 0x8117;
// connection pins
const uint8_t PIN_RST = 27; // reset pin
const uint8_t PIN_IRQ = 34; // irq pin
const uint8_t PIN_SS = 4; // spi select pin

uint16_t Adelay = 16539;//16965;
float average =0;
uint16_t Average_Counter = 0;
unsigned char Ranging_Done = 0;
volatile int Enable_receive_Blink = 1;
volatile int Transmit_blink_en = 1;
String T ;
String Prv_Tag_ID;
byte Prv_SeqNum_ID ;
String Data;
const int numReadings = 10;
float readings [numReadings];
int readIndex = 0;
float total = 0.0;
byte seqnum;

/* Default communication configuration. We use default non-STS DW mode. */
extern void test_run_info(unsigned char *data);

/* Example application name */
#define APP_NAME “DS TWR RESP v1.0”

/* Default communication configuration. We use default non-STS DW mode. /
static dwt_config_t config = {
5, /
Channel number. /
DWT_PLEN_128, /
Preamble length. Used in TX only. /
DWT_PAC8, /
Preamble acquisition chunk size. Used in RX only. /
9, /
TX preamble code. Used in TX only. /
9, /
RX preamble code. Used in RX only. /
1, /
0 to use standard 8 symbol SFD, 1 to use non-standard 8 symbol, 2 for non-standard 16 symbol SFD and 3 for 4z 8 symbol SDF type /
DWT_BR_6M8, /
Data rate. /
DWT_PHRMODE_STD, /
PHY header mode. /
DWT_PHRRATE_STD, /
PHY header rate. /
(129 + 8 - 8), /
SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. /
DWT_STS_MODE_OFF, /
STS disabled /
DWT_STS_LEN_64, /
STS length see allowed values in Enum dwt_sts_lengths_e /
DWT_PDOA_M0 /
PDOA mode off */
};

/* Inter-ranging delay period, in milliseconds. */
#define RNG_DELAY_MS 1000

/* Default antenna delay values for 64 MHz PRF. See NOTE 1 below. */
#define TX_ANT_DLY 16385
#define RX_ANT_DLY 16385

/* Frames used in the ranging process. See NOTE 2 below. /
static uint8_t rx_poll_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘W’, ‘A’, ‘V’, ‘E’, 0x21, 0, 0 };
static uint8_t tx_resp_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘V’, ‘E’, ‘W’, ‘A’, 0x10, 0x02, 0, 0, 0, 0 };
static uint8_t rx_final_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘W’, ‘A’, ‘V’, ‘E’, 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/
Length of the common part of the message (up to and including the function code, see NOTE 2 below). /
#define ALL_MSG_COMMON_LEN 10
/
Index to access some of the fields in the frames involved in the process. /
#define ALL_MSG_SN_IDX 2
#define FINAL_MSG_POLL_TX_TS_IDX 10
#define FINAL_MSG_RESP_RX_TS_IDX 14
#define FINAL_MSG_FINAL_TX_TS_IDX 18
/
Frame sequence number, incremented after each transmission. */
static uint8_t frame_seq_nb = 0;

/* Buffer to store received messages.

  • Its size is adjusted to longest frame that this example code is supposed to handle. */
    #define RX_BUF_LEN 24
    static uint8_t rx_buffer[RX_BUF_LEN];

/* Hold copy of status register state here for reference so that it can be examined at a debug breakpoint. */
static uint32_t status_reg = 0;

/* Delay between frames, in UWB microseconds. See NOTE 1 below. */
#ifdef RPI_BUILD
#define POLL_RX_TO_RESP_TX_DLY_UUS 550
#endif //RPI_BUILD
#ifdef STM32F429xx
#define POLL_RX_TO_RESP_TX_DLY_UUS 450
#endif //STM32F429xx
#ifdef NRF52840_XXAA
#define POLL_RX_TO_RESP_TX_DLY_UUS 650
#endif //NRF52840_XXAA

#define POLL_RX_TO_RESP_TX_DLY_UUS 450
#define RESP_TX_TO_FINAL_RX_DLY_UUS 450
#define FINAL_RX_TIMEOUT_UUS 450
/* Preamble timeout, in multiple of PAC size. See NOTE 6 below. */
#define PRE_TIMEOUT 50

/* Timestamps of frames transmission/reception. */
static uint64_t poll_rx_ts;
static uint64_t resp_tx_ts;
static uint64_t final_rx_ts;

/* Hold copies of computed time of flight and distance here for reference so that it can be examined at a debug breakpoint. /
static double tof;
static double distance;
/
Values for the PG_DELAY and TX_POWER registers reflect the bandwidth and power of the spectrum at the current

  • temperature. These values can be calibrated prior to taking reference measurements. See NOTE 2 below. */
    extern dwt_txconfig_t txconfig_options;
    unsigned char msg11[90];
    uint16_t add = 0;
    void setup() {
    // DEBUG monitoring
    Serial.begin(115200);

/* Display application name on LCD. */
test_run_info((unsigned char )APP_NAME);
/
Configure SPI rate, DW3000 supports up to 38 MHz /
/
Reset DW IC */
spiBegin(PIN_IRQ, PIN_RST);
spiSelect(PIN_SS);

Sleep(2); // Time needed for DW3000 to start up (transition from INIT_RC to IDLE_RC



while (!dwt_checkidlerc()) /* Need to make sure DW IC is in IDLE_RC before proceeding */ { };

if (dwt_initialise(DWT_DW_INIT) == DWT_ERROR)
{
    test_run_info((unsigned char *)"INIT FAILED     ");
    while (1) { };
}

/* Configure DW IC. See NOTE 15 below. */
/* if the dwt_configure returns DWT_ERROR either the PLL or RX calibration has failed the host should reset the device */
if (dwt_configure(&config))
{
    test_run_info((unsigned char *)"CONFIG FAILED     ");
    while (1) { };
}

/* Configure the TX spectrum parameters (power, PG delay and PG count) */
dwt_configuretxrf(&txconfig_options);

/* Apply default antenna delay value. See NOTE 1 below. */
dwt_setrxantennadelay(RX_ANT_DLY);
dwt_settxantennadelay(TX_ANT_DLY);

/* Next can enable TX/RX states output on GPIOs 5 and 6 to help debug, and also TX/RX LEDs
 * Note, in real low power applications the LEDs should not be used. */
dwt_setlnapamode(DWT_LNA_ENABLE | DWT_PA_ENABLE);
  // Enabling LEDs here for debug so that for each TX the D1 LED will flash on DW3000 red eval-shield boards.

dwt_setleds(DWT_LEDS_ENABLE | DWT_LEDS_INIT_BLINK);
}

void loop() {

    /* Activate reception immediately. */
    dwt_rxenable(DWT_START_RX_IMMEDIATE);


    /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
    while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR)))
    { };
    if (status_reg & SYS_STATUS_RXFCG_BIT_MASK)
    {
        uint16_t frame_len;

        /* Clear good RX frame event in the DW IC status register. */
  //      dwt_writesysstatuslo(DWT_INT_RXFCG_BIT_MASK);
      /* Clear good RX frame event in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG_BIT_MASK);
        /* A frame has been received, read it into the local buffer. */
      
        frame_len = dwt_read32bitreg(RX_FINFO_ID) & RXFLEN_MASK;
        if (frame_len <= RX_BUF_LEN)
        {
            dwt_readrxdata(rx_buffer, frame_len, 0);
        }

        /* Check that the frame is a poll sent by "DS TWR initiator" 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_poll_msg, ALL_MSG_COMMON_LEN) == 0)
        {
            uint32_t resp_tx_time;
            int ret;

            /* Retrieve poll reception timestamp. */
            poll_rx_ts = get_rx_timestamp_u64();

            /* Set send time for response. See NOTE 9 below. */
            resp_tx_time = (poll_rx_ts + (POLL_RX_TO_RESP_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;
            dwt_setdelayedtrxtime(resp_tx_time);

            /* Set expected delay and timeout for final message reception. See NOTE 4 and 5 below. */
            dwt_setrxaftertxdelay(RESP_TX_TO_FINAL_RX_DLY_UUS);
            dwt_setrxtimeout(FINAL_RX_TIMEOUT_UUS);
            /* Set preamble timeout for expected frames. See NOTE 6 below. */
            dwt_setpreambledetecttimeout(PRE_TIMEOUT);

            /* Write and send the response message. See NOTE 10 below.*/
            tx_resp_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
            dwt_writetxdata(sizeof(tx_resp_msg), tx_resp_msg, 0); /* Zero offset in TX buffer. */
            dwt_writetxfctrl(sizeof(tx_resp_msg), 0, 1);          /* Zero offset in TX buffer, ranging. */
            ret = dwt_starttx(DWT_START_TX_DELAYED | DWT_RESPONSE_EXPECTED);

            /* If dwt_starttx() returns an error, abandon this ranging exchange and proceed to the next one. See NOTE 11 below. */
            if (ret == DWT_ERROR)
            {
               // continue;
            }

      

    /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
    while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR)))
    { };
            /* Increment frame sequence number after transmission of the response message (modulo 256). */
            frame_seq_nb++;

            if (status_reg & SYS_STATUS_RXFCG_BIT_MASK)
            {
      
                          /* Clear good RX frame event in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG_BIT_MASK| SYS_STATUS_TXFRS_BIT_MASK);

                /* A frame has been received, read it into the local buffer. */
              //  frame_len = dwt_getframelength();
                frame_len = dwt_read32bitreg(RX_FINFO_ID) & RXFLEN_MASK;
                if (frame_len <= RX_BUF_LEN)
                {
                    dwt_readrxdata(rx_buffer, frame_len, 0);
                }

                /* Check that the frame is a final message sent by "DS TWR initiator" example.
                 * As the sequence number field of the frame is not used in this example, it can be zeroed to ease the validation of the frame. */
                rx_buffer[ALL_MSG_SN_IDX] = 0;
                if (memcmp(rx_buffer, rx_final_msg, ALL_MSG_COMMON_LEN) == 0)
                {
                    uint32_t poll_tx_ts, resp_rx_ts, final_tx_ts;
                    uint32_t poll_rx_ts_32, resp_tx_ts_32, final_rx_ts_32;
                    double Ra, Rb, Da, Db;
                    int64_t tof_dtu;

                    /* Retrieve response transmission and final reception timestamps. */
                    resp_tx_ts = get_tx_timestamp_u64();
                    final_rx_ts = get_rx_timestamp_u64();

                    /* Get timestamps embedded in the final message. */
                    final_msg_get_ts(&rx_buffer[FINAL_MSG_POLL_TX_TS_IDX], &poll_tx_ts);
                    final_msg_get_ts(&rx_buffer[FINAL_MSG_RESP_RX_TS_IDX], &resp_rx_ts);
                    final_msg_get_ts(&rx_buffer[FINAL_MSG_FINAL_TX_TS_IDX], &final_tx_ts);

                    /* Compute time of flight. 32-bit subtractions give correct answers even if clock has wrapped. See NOTE 12 below. */
                    poll_rx_ts_32 = (uint32_t)poll_rx_ts;
                    resp_tx_ts_32 = (uint32_t)resp_tx_ts;
                    final_rx_ts_32 = (uint32_t)final_rx_ts;
                    Ra = (double)(resp_rx_ts - poll_tx_ts);
                    Rb = (double)(final_rx_ts_32 - resp_tx_ts_32);
                    Da = (double)(final_tx_ts - resp_rx_ts);
                    Db = (double)(resp_tx_ts_32 - poll_rx_ts_32);
                    tof_dtu = (int64_t)((Ra * Rb - Da * Db) / (Ra + Rb + Da + Db));

                    tof = tof_dtu * DWT_TIME_UNITS;
                    distance = tof * SPEED_OF_LIGHT;
                    /* Display computed distance on LCD. */
                    sprintf(dist_str, "DIST: %3.2f m", distance);
                    test_run_info((unsigned char *)dist_str);

                    /* as DS-TWR initiator is waiting for RNG_DELAY_MS before next poll transmission
                     * we can add a delay here before RX is re-enabled again
                     */
                    Sleep(RNG_DELAY_MS - 10); // start couple of ms earlier
                }
            }
            else
            {
                /* Clear RX error/timeout events in the DW IC status register. */
                dwt_write32bitreg(SYS_STATUS_ID,SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR);
            }
        }
    }
    else
    {
        /* Clear RX error/timeout events in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID,SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR);
    }

}

Tag Code :slight_smile:

/*

  • Copyright (c) 2015 by Thomas Trojer thomas@trojer.net
  • Decawave DW3000 library for arduino.
  • Licensed under the Apache License, Version 2.0 (the “License”);
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at
  • http://www.apache.org/licenses/LICENSE-2.0
    
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an “AS IS” BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.
  • @file BasicConnectivityTest.ino
  • Use this to test connectivity with your DW3000 from Arduino.
  • It performs an arbitrary setup of the chip and prints some information.
  • @todo
    • move strings to flash (less RAM consumption)
    • make real check of connection (e.g. change some values on DW3000 and verify)
      */

#include “dw3000.h”

#define ANCHOR_ADD “81:17:5B:D5:A9:9A:E2:9C”

static uint8_t Address[] = {0x81, 0x17, 0x5B, 0xD5,0xA9, 0x9A,0xE2, 0x9C};
static uint16_t Address1 = 0x8117;
// connection pins
const uint8_t PIN_RST = 27; // reset pin
const uint8_t PIN_IRQ = 34; // irq pin
const uint8_t PIN_SS = 4; // spi select pin

uint16_t Adelay = 16539;//16965;
float average =0;
uint16_t Average_Counter = 0;
unsigned char Ranging_Done = 0;
volatile int Enable_receive_Blink = 1;
volatile int Transmit_blink_en = 1;
String T ;
String Prv_Tag_ID;
byte Prv_SeqNum_ID ;
String Data;
const int numReadings = 10;
float readings [numReadings];
int readIndex = 0;
float total = 0.0;
byte seqnum;

extern void test_run_info(unsigned char *data);

/* Example application name and version to display on LCD screen. */
#define APP_NAME “DS TWR INIT v1.0”

/* Default communication configuration. We use default non-STS DW mode. /
static dwt_config_t config = {
5, /
Channel number. /
DWT_PLEN_128, /
Preamble length. Used in TX only. /
DWT_PAC8, /
Preamble acquisition chunk size. Used in RX only. /
9, /
TX preamble code. Used in TX only. /
9, /
RX preamble code. Used in RX only. /
1, /
0 to use standard 8 symbol SFD, 1 to use non-standard 8 symbol, 2 for non-standard 16 symbol SFD and 3 for 4z 8 symbol SDF type /
DWT_BR_6M8, /
Data rate. /
DWT_PHRMODE_STD, /
PHY header mode. /
DWT_PHRRATE_STD, /
PHY header rate. /
(129 + 8 - 8), /
SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. /
DWT_STS_MODE_OFF, /
STS disabled /
DWT_STS_LEN_64, /
STS length see allowed values in Enum dwt_sts_lengths_e /
DWT_PDOA_M0 /
PDOA mode off */
};

/* Inter-ranging delay period, in milliseconds. */
#define RNG_DELAY_MS 1000

/* Default antenna delay values for 64 MHz PRF. See NOTE 1 below. /
#define TX_ANT_DLY 16385
#define RX_ANT_DLY 16385
/

  • The first 10 bytes of those frame are common and are composed of the following fields:
  • - byte 0/1: frame control (0x8841 to indicate a data frame using 16-bit addressing).
    
  • - byte 2: sequence number, incremented for each new frame.
    
  • - byte 3/4: PAN ID (0xDECA).
    
  • - byte 5/6: destination address, see NOTE 3 below.
    
  • - byte 7/8: source address, see NOTE 3 below.
    
  • - byte 9: function code (specific values to indicate which message it is in the ranging process).
    
  • The remaining bytes are specific to each message as follows:
  • Poll message:
  • - no more data
    
  • Response message:
  • - byte 10: activity code (0x02 to tell the initiator to go on with the ranging exchange).
    
  • - byte 11/12: activity parameter, not used here for activity code 0x02.
    
  • Final message:
  • - byte 10 -> 13: poll message transmission timestamp.
    
  • - byte 14 -> 17: response message reception timestamp.
    
  • - byte 18 -> 21: final message transmission timestamp.
    
  • All messages end with a 2-byte checksum automatically set by DW IC.
    /
    /
    Frames used in the ranging process. See NOTE 2 below. /
    static uint8_t tx_poll_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘W’, ‘A’, ‘V’, ‘E’, 0x21 };
    static uint8_t rx_resp_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘V’, ‘E’, ‘W’, ‘A’, 0x10, 0x02, 0, 0 };
    static uint8_t tx_final_msg[] = { 0x41, 0x88, 0, 0xCA, 0xDE, ‘W’, ‘A’, ‘V’, ‘E’, 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    /
    Length of the common part of the message (up to and including the function code, see NOTE 2 below). /
    #define ALL_MSG_COMMON_LEN 10
    /
    Indexes to access some of the fields in the frames defined above. /
    #define ALL_MSG_SN_IDX 2
    #define FINAL_MSG_POLL_TX_TS_IDX 10
    #define FINAL_MSG_RESP_RX_TS_IDX 14
    #define FINAL_MSG_FINAL_TX_TS_IDX 18
    /
    Frame sequence number, incremented after each transmission. */
    static uint8_t frame_seq_nb = 0;

/* Buffer to store received response message.

  • Its size is adjusted to longest frame that this example code is supposed to handle. */
    #define RX_BUF_LEN 20
    static uint8_t rx_buffer[RX_BUF_LEN];

/* Hold copy of status register state here for reference so that it can be examined at a debug breakpoint. */
static uint32_t status_reg = 0;

/* Delay between frames, in UWB microseconds. See NOTE 4 below. /
/
Delay between frames, in UWB microseconds. See NOTE 1 below. /
#ifdef RPI_BUILD
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#endif //RPI_BUILD
#ifdef STM32F429xx
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#endif //STM32F429xx
#ifdef NRF52840_XXAA
#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#endif //NRF52840_XXAA
/
Receive response timeout. See NOTE 5 below. */
#ifdef RPI_BUILD
#define RESP_RX_TIMEOUT_UUS 270
#endif //RPI_BUILD
#ifdef STM32F429xx
#define RESP_RX_TIMEOUT_UUS 210
#endif //STM32F429xx
#ifdef NRF52840_XXAA
#define RESP_RX_TIMEOUT_UUS 400
#endif //NRF52840_XXAA

#define POLL_TX_TO_RESP_RX_DLY_UUS 240
#define RESP_RX_TIMEOUT_UUS 400
#define RESP_RX_TO_FINAL_TX_DLY_UUS 240
/* Preamble timeout, in multiple of PAC size. See NOTE 7 below. */
#define PRE_TIMEOUT 50

/* Time-stamps of frames transmission/reception, expressed in device time units. */
static uint64_t poll_tx_ts;
static uint64_t resp_rx_ts;
static uint64_t final_tx_ts;

/* Values for the PG_DELAY and TX_POWER registers reflect the bandwidth and power of the spectrum at the current

  • temperature. These values can be calibrated prior to taking reference measurements. See NOTE 8 below. */
    extern dwt_txconfig_t txconfig_options;

unsigned char msg11[90];
uint16_t add = 0;
void setup() {
// DEBUG monitoring
Serial.begin(115200);

test_run_info((unsigned char *)APP_NAME);

/* Configure SPI rate, DW3000 supports up to 38 MHz /
/
Reset DW IC */
spiBegin(PIN_IRQ, PIN_RST);
spiSelect(PIN_SS);

Sleep(2); // Time needed for DW3000 to start up (transition from INIT_RC to IDLE_RC



while (!dwt_checkidlerc()) /* Need to make sure DW IC is in IDLE_RC before proceeding */ { };

if (dwt_initialise(DWT_DW_INIT) == DWT_ERROR)
{
    test_run_info((unsigned char *)"INIT FAILED     ");
    while (1) { };
}

/* Configure DW IC. See NOTE 2 below. */
/* if the dwt_configure returns DWT_ERROR either the PLL or RX calibration has failed the host should reset the device */
if (dwt_configure(&config))
{
    test_run_info((unsigned char *)"CONFIG FAILED     ");
    while (1) { };
}

/* Configure the TX spectrum parameters (power, PG delay and PG count) */
dwt_configuretxrf(&txconfig_options);

/* Apply default antenna delay value. See NOTE 1 below. */
dwt_setrxantennadelay(RX_ANT_DLY);
dwt_settxantennadelay(TX_ANT_DLY);

/* Set expected response's delay and timeout. See NOTE 4, 5 and 7 below.
 * As this example only handles one incoming frame with always the same delay and timeout, those values can be set here once for all. */
dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);
dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS);
dwt_setpreambledetecttimeout(PRE_TIMEOUT);

/* Next can enable TX/RX states output on GPIOs 5 and 6 to help debug, and also TX/RX LEDs
 * Note, in real low power applications the LEDs should not be used. */
dwt_setlnapamode(DWT_LNA_ENABLE | DWT_PA_ENABLE);
 dwt_setleds(DWT_LEDS_ENABLE | DWT_LEDS_INIT_BLINK);

}

void loop() {
/* Write frame data to DW IC and prepare transmission. See NOTE 9 below. /
tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0); /
Zero offset in TX buffer. /
dwt_writetxfctrl(sizeof(tx_poll_msg) + FCS_LEN, 0, 1); /
Zero offset in TX buffer, ranging. */

    /* Start transmission, indicating that a response is expected so that reception is enabled automatically after the frame is sent and the delay
     * set by dwt_setrxaftertxdelay() has elapsed. */
    dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);


   /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
    while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR)))
    { };
    /* Increment frame sequence number after transmission of the poll message (modulo 256). */
    frame_seq_nb++;

    if (status_reg & SYS_STATUS_RXFCG_BIT_MASK)
    {
        uint16_t frame_len;

        /* Clear good RX frame event and TX frame sent in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID,SYS_STATUS_RXFCG_BIT_MASK | SYS_STATUS_TXFRS_BIT_MASK);

        /* A frame has been received, read it into the local buffer. */

       frame_len = dwt_read32bitreg(RX_FINFO_ID) & RXFLEN_MASK;
        if (frame_len <= RX_BUF_LEN)
        {
            dwt_readrxdata(rx_buffer, frame_len, 0);
        }

        /* Check that the frame is the expected response from the companion "DS 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_t final_tx_time;
            int ret;

            /* Retrieve poll transmission and response reception timestamp. */
            poll_tx_ts = get_tx_timestamp_u64();
            resp_rx_ts = get_rx_timestamp_u64();

            /* Compute final message transmission time. See NOTE 11 below. */
            final_tx_time = (resp_rx_ts + (RESP_RX_TO_FINAL_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;
            dwt_setdelayedtrxtime(final_tx_time);

            /* Final TX timestamp is the transmission time we programmed plus the TX antenna delay. */
            final_tx_ts = (((uint64_t)(final_tx_time & 0xFFFFFFFEUL)) << 8) + TX_ANT_DLY;

            /* Write all timestamps in the final message. See NOTE 12 below. */
            final_msg_set_ts(&tx_final_msg[FINAL_MSG_POLL_TX_TS_IDX], poll_tx_ts);
            final_msg_set_ts(&tx_final_msg[FINAL_MSG_RESP_RX_TS_IDX], resp_rx_ts);
            final_msg_set_ts(&tx_final_msg[FINAL_MSG_FINAL_TX_TS_IDX], final_tx_ts);

            /* Write and send final message. See NOTE 9 below. */
            tx_final_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
            dwt_writetxdata(sizeof(tx_final_msg), tx_final_msg, 0); /* Zero offset in TX buffer. */
            dwt_writetxfctrl(sizeof(tx_final_msg) + FCS_LEN, 0, 1); /* Zero offset in TX buffer, ranging bit set. */

            ret = dwt_starttx(DWT_START_TX_DELAYED);
            /* If dwt_starttx() returns an error, abandon this ranging exchange and proceed to the next one. See NOTE 13 below. */
            if (ret == DWT_SUCCESS)
            {

                    /* Poll DW IC until TX frame sent event set. See NOTE 6 below. */
                    while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS_BIT_MASK))
                    { };

                    /* Clear TXFRS event. */
                    dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS_BIT_MASK);
                /* Increment frame sequence number after transmission of the final message (modulo 256). */
                frame_seq_nb++;
            }
        }
    }
    else
    {
        /* Clear RX error/timeout events in the DW IC status register. */
        dwt_write32bitreg(SYS_STATUS_ID,SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR | SYS_STATUS_TXFRS_BIT_MASK);
    }

    /* Execute a delay between ranging exchanges. */
    Sleep(RNG_DELAY_MS);

}