I am using DWM1001 modules to locate goods within a warehouse. Currently, I use the example program from Decawave/dwm1001-examples repository to obtain distance information between tags and anchors.
Here’s the encountering:
Initiator (Tag):
// ss_init_main.c
int ss_init_run(void) {
// Code to send poll message and wait for response
tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0);
dwt_writetxfctrl(sizeof(tx_poll_msg), 0, 1);
dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);
// Poll for reception of a frame or error/timeout
while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR))) {};
// Process the received response message
if (status_reg & SYS_STATUS_RXFCG) {
uint32 frame_len;
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);
frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFLEN_MASK;
if (frame_len <= RX_BUF_LEN) {
dwt_readrxdata(rx_buffer, frame_len, 0);
}
// Check that the frame is the expected response
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 timestamps and calculate distance
poll_tx_ts = dwt_readtxtimestamplo32();
resp_rx_ts = dwt_readrxtimestamplo32();
clockOffsetRatio = dwt_readcarrierintegrator();
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);
rtd_init = resp_rx_ts - poll_tx_ts;
rtd_resp = resp_tx_ts - poll_rx_ts;
tof = ((rtd_init - rtd_resp * (1.0f - clockOffsetRatio)) / 2.0f) * DWT_TIME_UNITS;
distance = tof * SPEED_OF_LIGHT;
printf("Distance: %f\n", distance);
}
} else {
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR);
dwt_rxreset();
}
}
Responder (Anchor):
// ss_resp_main.c
int ss_resp_run(void) {
dwt_rxenable(DWT_START_RX_IMMEDIATE);
// Poll for reception of a frame or error/timeout
while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR))) {};
if (status_reg & SYS_STATUS_RXFCG) {
uint32 frame_len;
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);
frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
if (frame_len <= RX_BUF_LEN) {
dwt_readrxdata(rx_buffer, frame_len, 0);
}
if (memcmp(rx_buffer, rx_poll_msg, ALL_MSG_COMMON_LEN) == 0) {
uint32 resp_tx_time;
int ret;
// Retrieve poll reception timestamp
poll_rx_ts = get_rx_timestamp_u64();
resp_tx_time = (poll_rx_ts + (POLL_RX_TO_RESP_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;
dwt_setdelayedtrxtime(resp_tx_time);
resp_tx_ts = (((uint64)(resp_tx_time & 0xFFFFFFFEUL)) << 8) + TX_ANT_DLY;
resp_msg_set_ts(&tx_resp_msg[RESP_MSG_POLL_RX_TS_IDX], poll_rx_ts);
resp_msg_set_ts(&tx_resp_msg[RESP_MSG_RESP_TX_TS_IDX], resp_tx_ts);
tx_resp_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
dwt_writetxdata(sizeof(tx_resp_msg), tx_resp_msg, 0);
dwt_writetxfctrl(sizeof(tx_resp_msg), 0, 1);
ret = dwt_starttx(DWT_START_TX_DELAYED);
if (ret == DWT_SUCCESS) {
while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS)) {};
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);
frame_seq_nb++;
} else {
dwt_rxreset();
}
}
} else {
dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);
dwt_rxreset();
}
return(1);
}
When using multiple anchors, only the anchor closest to the tag responds during the tag poll. This results in inaccurate positioning because other anchors’ distance measurements are not considered.
Here’s a simplified version of my code:
However, the issue arises because only the nearest anchor to the tag responds, which leads to inaccurate positioning.
Question: How can I modify my approach or code to ensure that multiple anchors’ distance measurements are used to accurately determine the tag’s position within the warehouse?
Any examples or methods to improve the accuracy of positioning using DWM1001 with multiple anchors would be highly appreciated.