I am trying SS TWR - responder sets the delayed transmission. However, on initiator (tag) when I calculate rx timestamp - tx timestamp (round time) I always get same value. No matter what distance is. Timestamps are changing their values but diff remains the same. Any ideas?
Exactly the same difference or a very similar difference?
Exactly the same would be very odd. It is possible that the clock error between the two is just right to exactly cancel out the increase in time due to the change in range but that would be a very unusual coincidence.
Very similar is to be expected, the turn around time in the responder is orders of magnitude larger than the travel time and so at first glance the total time is going to the responder delay plus a tiny bit of noise. That tiny bit of noise is the range.
Once you have the timestamp difference subtract the responder time corrected for the difference in clock speeds, only after you’ve done that will you get a number that has anything to do with range.
Thanks @AndyA It turned out that I was getting high32 of 40 at short distances - that’s why I haven’t seen the difference. Subtracting lower32 gives me some values but now I need to compensate for clock drift. By the way do you know how to compensate for drift? I am running initiator and responder on two different MCUs. Does it matter or is it only different internal dw1000 clocks?
Assuming the MCU isn’t directly controlling the response time (which would be an unusual situation) it doesn’t matter if they are different.
The responder sends the response a fixed time after receiving the initiator message. As long as that fixed time is measured using the DW1000 clock via the timestamp registers and delayed/scheduled transmit functionality of the device (the normal way to do things) then the only clocks that matter are the ones for the DW1000.
Range = c * (Initiator Rx time - Initiator Tx time - Responder Delay)/2
Ideally the responder delay would be a perfect fixed value. However it will be wrong by the difference between the two devices clocks. This clock difference can be found by reading the Carrier recovery integration register, register 0x27:28. The DW1000 user manual section 7.2.40.11 gives details of how to convert this into an offset in ppm.
Once you have the offset you can scale the ideal delay by (1+clock offset) to give the effective delay in receiver time units. Note, the clock offset will generally be fairly small so this scale factor will be close to 1, the offset can be positive or negative depending on which clock is faster.
Other things you need to factor in:
The scheduled transmit function is setting the time that the signal will leave the chips control logic, not the time time it will leave the antenna. You need to subtract your transmit antenna delay from the scheduled time to get the signal to leave the antenna at the correct time.
The scheduled transmit ignores the low 9 bits of the transmit time, these will always be treated as 0. Which means when sending the response you need to include those 9 bits in the message you send back. When the initiator receives the message it should read those 9 bits from the message and add them to the received time. Technically that adjustment should also be scaled by the clock error but the effect is so insignificant it makes no difference.
Thanks a lot - you saved me lot of time. Now I have it working in a stable manner. I have changed from SS TWR to DS TWR though. However, I got a difference in distance of 10-20 cm more than actual distance (using standard antenna delay of 16436 - haven’t performed calibration . And the other thing I am not sure about is if I have to add or subtract the calculated clock offset from frequency offset value from 0x27:28. How can I know which clock is faster? If let’s say clock is faster on the device that is using delayed tx what will be sign for offset + or -?
I think I worked out the sign by trying both and finding which worked correctly
If you swap which is the responder and which is the initiator then you should get the same range, if you have the sign wrong then you’ll get very different numbers when you swap roles.
For reference my code is:
double getClockScale() {
int32_t offsetRaw = 0;
// I have my own driver so the syntax is a little different but this is read 3 bytes from the appropriate register.
readRegister(DW1000_DRX_CONF,DWDRX_CAR_INT,(uint8_t*)&offsetRaw,3);
// value is 21 bits, sign extend to 32 bits.
offsetRaw &= 0x001fffff;
if (offsetRaw & 0x00100000)
offsetRaw |= 0xffe00000;
if (channel >= 5)
return 1 - (offsetRaw * -0.5731e-9);
else
return 1 - (offsetRaw * -0.9313e-9);
}
I then do
remoteDelay = idealDelay*getClockScale();
Well I do something along those lines. I actually play some tricks and measure the clock error on both the responder and the initiator and use the average after flipping the sign on one of them.
If you are using DS-TWR you don’t need to do any clock error correction. As long as your delays are symmetrical the clock errors cancel out and you get the correct value without needing to correct it.