Problems receiving frames

Hello all,

being new to the community, I would like to introduce myself. I am Adrian from TU Dresden and I work with the DWM1000 module for a thesis I write to achieve ranging and positioning.

I use an Atmel microcontroller for interfacing with the DWM1000 via SPI (AtMega 328p).

Now, I am running into problems, when I try to receive packets on one side, when sending on the other.

This is how I configure my transmitter for a blink message:

  • set TFLEN in TX_FCTRL to 12 bytes (blink message)
  • set PRF in TX_FCTRL to 2 (64MHz PRF)
  • set TXPSR and PE in TX_FCTRL to 3 and 0 respectively (preamble length of 4096)

After that, my TX_FCTRL reads: 0x00000E000C

This is then 110 kbps mode.

-> start transmission by setting TXSTART in SYS_CTRL

If I wait a little and read out the SYS_STATUS register after sending, it reads: 0x00008000F2

This means:






are all set. Especially the TX* bits are indicative of sending all the parts of the message.

This tells me, that sending was successful. Right?

Now to receiving end, which gives me the problems.

This is how I configure the registers:

  • DRX_TUNE2 is set to 0x373B0296, which is a PAC size of 64 at 64 MHz PRF, suitable for a preamble length of 4096
  • RXM110K was set in SYS_CFG, because I use 110 kbps mode for my testing. There is no particular reason for choosing this mode, I just thought it is more stable than faster modes.

SYS_CFG register reads: 0x00400000

-> then I start reception by setting RXENAB in the SYS_CTRL register. After this, I periodically read out the SYS_STATUS register to look for bits that change.

The problem is: when I transmit, there is no change in the status register. I always get: 0x0000820002

This indicates a timeout on the receiver (RXRFTO is set):
“This event status bit is set to indicate that a receive frame wait timeout has occurred.”

I wonder why that happens, because I set no timeout interval. I would be happy for any suggestions on solving this issue.

Thank you in advance,


Hey man,

First of all, the sender seems to work since the TXFRS bit is set. In the receiver chechk the RXWTOE bit in SYS_CFG register, and make sure that it is not set. I also assume that you dont have frame filtering enabled :wink:
As far as I remember, the default setup of DWM1000 allow you to start a transmission and reception, so also you can try without setting up the lower baud-rates and preambles. You have a good approach with constant checking the Sys_STATUS register, it should give you some information even if the frame wasnt received properly (just preamble detection, at least you know there was something in the air).


Great! Thanks for the advice of just leaving the settings at default. This actually just worked!

On the receiver, I first got a SYS_STATUS reading of


which is some idle state. Then, after sending on the other DWM module, I get


which is leading edge detection error, unfortunately. If I send again, I get


where B indicates SFD detection and completion of LDE processing, and 2 indicates RXDFR is set: Receiver Data Frame Ready.

That looks promising to me!

Now just check what is the approx. rate of bad frames. You can proceed to right chip configuration, tx power settings etc. Keep us updated about the results :slight_smile:


How do I do that?

Also, I want to receive more than only one frame.

If I check my SYS_STATUS register, I get the confirmation, that I received a packet. Every time I read the status register, I also set RXENAB again (once a second), but it does not clear the bits in the status register that it is supposed to clear. So, the bits remain set in the status register.

Consequently, I wanted to clear them manually (which I did) for seeing new packets arrive. When I clear them and I send another message, no change in the status register appers. It seems like, after the DWM1000 receives one message, it locks up. What can I do to make it receive another frame? Do I have to reset anything, except setting RXENAB?

Actually, I have to go to IDLE mode first by setting TRXOFF. If I then set RXENAB, it clears the status flags. Do I have to do that every time I receive a frame or is there another way?

Any idea on the above?

However, I can now send and receive arbitrary content. Also, TX timestamping works.

My problem now is: The RX timestamp always reads zero! What can be the cause of this? I thought that RX timestamping does not need to be enabled.

Well, I think the solution for all your problems is to read the User manual carefully. “The LDERUNE bit is enabled by default, which means that the microcode (the LDE algorithm) that has been
loaded in RAM will execute on every frame reception, which in turn will calculate accurate frame time-of-
arrival. However the DW1000 needs to load this microcode on power-on from a special ROM area in the
DW1000. This is done by enabling the LDELOAD bit as part of DW1000 initialisation (because after powering
up the DW1000 (or after exiting SLEEP or DEEPSLEEP states) the LDE RAM is empty). This should be done
before the receiver is enabled if it is important to timestamp this received frame. If the LDE code is not
being loaded before the receiver is enabled then the LDERUNE (LDE run enable) control in Sub-Register
0x36:04 – PMSC_CTRL1 must be turned off (set to zero).”


t seems, I have overlooked the very important section 2 of the user manual. Thanks for pointing this out.

I now followed chapter 2 thoroughly and I have RX timestamps now! Also, I have set all the preferred settings for the default mode.

Now, I am starting to try out ranging. The current scheme is like this:

-The tag sends out a message, records the TX timestamp and switches to receive mode directly (WAIT4RESP set)
-The host receives the message and notes the RX timestamp
-The host adds a delay of 10ms to the RX timestamp, discards the lower 9 bit and writes the planned transfer time of the response to the TX_DLYE field

Now, the host calculates the actual delay. It takes the value written to the TX_DLYE field (with the 9 lower bits zeroed) and subtracts the RX timestamp value. This yields delay values which deviate slightly in the lower 9 bits. This is expected.

Then, the host sends out the delayed response to the tag. At the tag, I read the RX timestamp and subtract the TX timestamp of the first message.

My problem is, that when I subtract the calculated delay from that time of flight (plus delay) measured in the tag, the result varies by huge amounts (around ±0x100 counts). This somehow reflects the influence of the lower nine bits… Am I missing something here?

Also, I noticed that when I attach payload to the final message of the host, it only is sent in the NEXT frame. So, it is delayed by one frame. Do I have to do anything special when switching from RX to TX?

Kind regards,

The actual delay is calculated by taking the value written to TX_DLYE and adding the tx antenna delay. Or it can be read out from Tx timestamp value :slight_smile:


Ok, I see. However, this offset should be constant, right?

I changed my code quite a bit now and I get TOF readings every second. I only do one ranging. (tag->host, host->tag)

There are some strange things about the readings. The most striking one:

  • The readings of the time of flight increase with time. At some point, they seem to become more stable.

This is, how exactly my program works now:


  • fills TX_BUFFER with some random data.
  • writes the TXSTART and WAIT4RESP bits to SYS_CTRL
  • waits for the message to be sent by checking the SYS_STATUS register. (bits 4 through 7)
  • when it detects the successful transmission, it clears bits 4 through 7 in SYS_STATUS
  • then, TX timestamp is read out and stored
  • tag now waits for a frame to be received, checking SYS_STATUS bits 13, 14 and 15 (13 and 14 shall be set, while 15 should be zero)


  • has RXENAB set and waits for a message
  • waits for a frame, just like the tag is after sending
  • when a frame receive is detected, RX timestamp is read and stored
  • delay time is added to RX timestamp, lower 9 bits cleared and written to DX_TIME
  • actual delay is calculated by DX_TIME minus RX timestamp
  • configures a packet to be sent with some data, including the calculated actual delay time
  • sends out frame with TXSTART, TXDLYE and WAIT4RESP set
  • waits for the frame to be sent successfully


  • now receives that frame, extracts the delay
  • tag waits for successful (complete) receive and notes RX time
  • tag calculates time of flight and subtracts the delay

then, the process starts all over again.

Any idea, why the TOF times keep drifting towards higher numbers?

Kind regards,

“Actual delay is calculated by DX_TIME minus RX timestamp” good, but you forgot to add Anchors TXantenna delay.
The answer is simple. In the SingleSide-TWR (just two mesages) the crystal oscillator error is not subtracted from the measurement as in DoubleSide-TWR. It can be useful if you use really precise oscillators ( 1ppm or below), and keep the delayed send time as short as possible (500us is possible). You wait 10 ms whish is alot.


That makes sense. So, I changed to a double sided system. The drift is gone, I get very consistent readings which seem quite right (except for absolute offset, but I do not care yet).

Now, I want to make it run repeatedly (as fast as possible). This currently only works for varying numbers of measurements, before there are reception errors of different kinds.

Sometimes, I get “PHY Header receive” errors, sometimes “Receive SFD timeout”. So, I definitely have some packet loss, although the DW1000 modules are very close to each other.

The modules are in default configuration. I did the adjustments of chapter 2.5.5 of the user manual, too.


I noticed, that these errors only happen, if the modules are rellay close (below 1m). I guess, there is receiver saturation. Above 1m, there is nearly no packet loss at all.

Another problem is, that at larger distances I sometimes I get a “glitch” in my readings. The distance is then off by a fair amount. This only happens in a few measurements. What could cause those glitches? Could that be the leading edge detecting algorithm that fails in my environment? I am in a fairly small room now.

There can be few sources, but there are two most significant. If your modules are placed on the table lets say, 20-30 cm above it, then the difference between the straight line TOF and the reflected one from table is really small and latching algorithm is not able to select the proper signal. That kind of reflections (I call them
close reflections) affect the measurement slightly (see the attachement around 7000th sample.
The second kind of reflection is, when one of the foour messages go the reflected path, and the way differ so much from the last three that the turnaround time is shorter than delayed send time, and during later timestamp substractions and divisions the number is not even logic. I treat it as a gross error and remove it :slight_smile:


Thanks for the explanation and the support in general! It helped a lot for realizing the software algorithm on the AVR.

Especially the small quirks, that the DWM1000 module has, were not obvious to me at the beginning.