Range failed when clock@MCU is 32MHz

Hi,
I am novice. I use the code of DecaRangeRTLS_ARM_2p10.zip for range. The mcu clock is 72 MHz in the anchor source code and the range work good. But when i change the mcu clock to 32 MHz, the range is fail(only tag_poll can be receive, response send fail and final can not be receive). I want to know which parameters need to be modified when i change the mcu clock to other value.
We designed the SCH and PCB file. And the buyer bought dw1000 chip in Li Chuang mall( https://www.szlcsc.com/?c=1Z ).
Thank you.
Best regards

Hi rain

The first thing to adjust is the SPI clock speeds. The SPI clock speed needs to be low enough (<3MHz) in slow mode and fast enough (~16-20 MHz) to handle quick communication with the DW1000. Typically the SPI clock speed depends on the system clock so you will probably have to adjust the clock devider to ensure optimal clock speeds. See port_set_dw1000_slowrate and port_set_dw1000_fastrate in src/platform/port.c.

If ranging still does not work, it could be the MCU is to slow to perform ranging at the required speed. You can lower the ranging interval by increasing the RX_RESPONSE_TURNAROUND macro in src/application/instance.c.

It might be interesting to look at the DW1000 examples, this explains a bit more about how the TWR works and how MCU timing impacts the ranging. The TREK1000 source code is a bit more complicated. See e.g the POLL_TX_TO_RESP_RX_DLY_UUS macro and note 4 in example 05a: TWR initiator of the DW1000 examples. These are designed to run on the same hardware as the TREK1000.

Note that we can’t assure the TREK demo will work correctly when using a 32MHz clock, though technically it should be possible we haven’t tested this afaik.

Hi, seppe
Thank you !
It is cause of the problem that the spi speed is too low. It work good when i set the spi speed to 16MHz and the value of RX_RESPONSE1_TURNAROUND_6M81 to 1000.
I have another question that is there any source_code instructions detailed about the constant of the instancesetreplydelay function, such as 330.0f,RX_RESPONSE1_TURNAROUND_6M81 and 21539 and so on. I think the DecaRangeRTLS_ARM_Source_Code_Guide.pdf file is simply for me to look at the source_code.

#define RX_RESPONSEX_TURNAROUND (50) //takes about 100 us for response to come back
#define RX_RESPONSE1_TURNAROUND (200) //takes about 200 us for the 1st response to come back (from A0)
#define RX_RESPONSE1_TURNAROUND_6M81 (300) //takes about 100 us for response to come back
#define RX_RESPONSE1_TURNAROUND_110K (300) //takes about 100 us for response to come back

void instancesetreplydelay(int delayus) //delay in us
{
int instance = 0;

int margin = 3000; //2000 symbols
int respframe = 0;
int respframe_sy = 0; //// 

//configure the rx delay receive delay time, it is dependent on the message length
float msgdatalen = 0;
float preamblelen = 0;
int sfdlen = 0;
int x = 0;

//Set the RX timeouts based on the longest expected message - the Final message
//Poll = 13, Response = 20, Final = 44 bytes
//msgdatalen = TAG_FINAL_MSG_LEN + FRAME_CRTL_AND_ADDRESS_S + FRAME_CRC; //// should be changed for tag   for test
msgdatalen = ANCH_RESPONSE_MSG_LEN + FRAME_CRTL_AND_ADDRESS_S + FRAME_CRC;

x = (int) ceil(msgdatalen*8/330.0f); //// rounding up, i.e. ceil(1.5) = 2

msgdatalen = msgdatalen*8 + x*48;

//add some margin so we don't timeout too soon
margin = 0; //(TAG_FINAL_MSG_LEN - TAG_POLL_MSG_LEN);

x = (int) ceil(margin*8/330.0f);

margin = margin*8 + x*48;

//assume PHR length is 172308ns for 110k and 21539ns for 850k/6.81M
if(instance_data[instance].configData.dataRate == DWT_BR_110K)

{
msgdatalen *= 8205.13f;
msgdatalen += 172308; // PHR length in nanoseconds

	margin *= 8205.13f;

}
else if(instance_data[instance].configData.dataRate == DWT_BR_850K)
{
msgdatalen *= 1025.64f;
msgdatalen += 21539; // PHR length in nanoseconds

	margin *= 1025.64f;

}
else
{
msgdatalen *= 128.21f;
msgdatalen += 21539; // PHR length in nanoseconds

	margin *= 128.21f;
}

//SFD length is 64 for 110k (always)
//SFD length is 8 for 6.81M, and 16 for 850k, but can vary between 8 and 16 bytes
sfdlen = dwnsSFDlen[instance_data[instance].configData.dataRate];

switch (instance_data[instance].configData.txPreambLength)

{
case DWT_PLEN_4096 : preamblelen = 4096.0f; break;
case DWT_PLEN_2048 : preamblelen = 2048.0f; break;
case DWT_PLEN_1536 : preamblelen = 1536.0f; break;
case DWT_PLEN_1024 : preamblelen = 1024.0f; break;
case DWT_PLEN_512 : preamblelen = 512.0f; break;
case DWT_PLEN_256 : preamblelen = 256.0f; break;
case DWT_PLEN_128 : preamblelen = 128.0f; break;
case DWT_PLEN_64 : preamblelen = 64.0f; break;
}

//preamble  = plen * (994 or 1018) depending on 16 or 64 PRF
if(instance_data[instance].configData.prf == DWT_PRF_16M)
{
	preamblelen = (sfdlen + preamblelen) * 0.99359f;
}
else
{
	preamblelen = (sfdlen + preamblelen) * 1.01763f;
}

respframe_sy = (16 + (int)((preamblelen + ((msgdatalen + margin)/1000.0))/ 1.0256)) ;

//this is the delay used for the delayed transmit (when sending the response, and final messages)
instance_data[instance].pollTx2FinalTxDelay = convertmicrosectodevicetimeu (delayus);
//the anchor to anchor ranging consist of A0 ranging to A1 and A2 and A1 ranging to A2
//as there are less messages the ranging time is shorter (thus divide by 2)
instance_data[instance].pollTx2FinalTxDelayAnc = convertmicrosectodevicetimeu (delayus/2 + 100);

//this is the delay the anchors 1, 2, etc.. will send the response back at...
//anchor 2 will have the delay set to 2 * fixedReplyDelayAnc
//andhor 3 will have the delay set to 3 * fixedReplyDelayAnc and so on...
//this delay depends on how quickly the tag can receive and process the message from previous anchor
//(and also the frame length of course)
respframe = (int)(preamblelen + (msgdatalen/1000.0)); //length of response frame (micro seconds)
if(instance_data[instance].configData.dataRate == DWT_BR_110K)
{
	//set the frame wait timeout time - total time the frame takes in symbols
	instance_data[instance].fwtoTime_sy = respframe_sy + RX_RESPONSE1_TURNAROUND_110K + 400; //add some margin because of the resp to resp RX turn on time

	instance_data[instance].fwtoTimeAnc_sy = respframe_sy; //add some margin so we don't timeout too soon
	instance_data[instance].fixedReplyDelayAnc = convertmicrosectodevicetimeu (respframe + RX_RESPONSE1_TURNAROUND_110K);
	instance_data[instance].fixedReplyDelayAncP = (uint32) (((uint64) convertmicrosectodevicetimeu (preamblelen)) >> 8) + 16;

	instance_data[instance].ancRespRxDelay = RX_RESPONSE1_TURNAROUND_110K ;
}
else
{
	//set the frame wait timeout time - total time the frame takes in symbols
	instance_data[instance].fwtoTime_sy = respframe_sy + RX_RESPONSE1_TURNAROUND_6M81; //add some margin because of the resp to resp RX turn on time

	instance_data[instance].fwtoTimeAnc_sy =  respframe_sy;
	instance_data[instance].fixedReplyDelayAnc = convertmicrosectodevicetimeu (respframe + RX_RESPONSE1_TURNAROUND_6M81);
	instance_data[instance].fixedReplyDelayAncP = (uint32) (((uint64) convertmicrosectodevicetimeu (preamblelen)) >> 8) + 16;

	instance_data[instance].ancRespRxDelay = RX_RESPONSE1_TURNAROUND_6M81 ;
}

}

Thank you.
Best regards