Pairwise ranging in a network

We’re thinking about writing some decawave software for an application we have in mind, but before I jump into that I was hoping I could get a quick sanity check on our intended use case.

Let’s say I have four nodes in a network, called A, B, C, D.

Is it possible to use A as a kind of gateway, and ask it to get

  • the range from A to each other node
  • the range from B to C
  • the range from C to D
  • the range from B to D

With the application we have in mind we could execute these sequentially, so I don’t think there would be any issue with interference, although we would like to be able to get the information as quickly as possible. The ideal answer would be that there is already a set of API functions that can tell A to instruct B to find range from C, and then return the value to A, and likewise for every other pair.

Does anything about that sound impossible or impractical?

Note that we don’t need the decawave network to be doing any positioning calculations, just pairwise ranging.


I have been looking for example code / API functions that can do this but I haven’t found anything so far.

I’m sure it would be possible with fully custom firmware but maybe not using the decawave userspace API. The only function that might get close is dwm_loc_get() which instructs a tag to get the range to all the anchors it can see. To do it for ALL of them using this function, seems like you’d have to

  1. Set node A as a tag, set others as anchors
  2. Get ranges from A to anchors.
  3. Set node B as tag, set others as anchors.
  4. Get ranges from B to anchors.
  5. Repeat for all nodes.

I don’t know if this is possible or reasonable. Perhaps switching modes takes too long to be practical?

Hi Colin

The PANS library has the concept of “tags” and “anchors”. Ranging happens between tags and one or more (up to 4) anchors and the tags triangulate their own location. Support for ranging between anchors is limited. It is only meant to be used for a more automated setup, not for continuous positioning.

What you are describing shouldn’t be to difficult to achieve in custom firmware though.

Is it possible to use the Decawave DWM1000 API instead of PANS?
Are there any examples/API functions capable of ranging between two devices based on some sort of device ID?

I’m working on an application to do that, using the API rather than PANS. We have a cloud of peer devices (i.e. no differentiation between anchors and tags) where each device measures the range to up to 10 of its nearest neighbours at intervals of around 1.5 seconds (all 10 in that time). BLE is used for initial discovery because TWR receive is very power hungry so you want it turned on for as little time as possible. To get our batteries to last more than 12 hours we also had to turn the DW1000 chip itself off for as much time as possible. Our aim is to support 200 devices within a large hall. DW1000 ranging is compatible with IEEE 802.15.4 and the packet structure includes source and destination addresses so there is no problem distinguishing who is trying to talk to who. So, yes, it is doable but the coding is very non-trivial. You have to become very familiar with the functions of the registers on the DW1000 (there are many of them) and be good at writing interrupt and time critical code. Having said that, most of my problems now are with the Nordic SoftDevice. The documentation suggests it easily handles both the BLE central and peripheral roles concurrently but there are massive performance problems so you have to override the scheduling of scanning and advertising.

That sounds like exactly what I’m looking for, and probably beyond my capabilities for the moment :). Would you be willing to share more information or any code? I understand you can’t if it’s a commercial application.

Having read a little more I 'm thinking about doing something like this:

Using the ss_twr_init and ss_twr_resp examples here: dwm1001-examples/examples at master · Decawave/dwm1001-examples · GitHub. Set up all nodes with both capabilities and have the ranging initiated based on either

  1. the value of a timer if I can make it accurate and fast enough, or
  2. the content of the user data registers managed using dwm_usr_data_write() and dwm_user_data_read().

I’m not totally sure of how the write function works but if it writes data to all nodes as I suspect then this seems like it could work.

So, for example, node A could be a controller responsible for timings. It writes something like “BC” to the user data, which instructs B to range to C and then write user data “BC-12.34”. Assuming all is well, A writes that response to UART. If no response, waits for a time out then sends the next instruction which might be “CD”. Nodes would range only once within a specified window, so B will not just keep transmitting if it misses the instruction “CD”, which is an instruction it should ignore anyway.

This notion does depend on a master node A but perhaps the logic could be extended to support secondary controllers, or possibly made completely decentralized. This already has the feature that all nodes should be aware of all information written to the network, so it is decentralized in that sense.

Haven’t written a line of code yet, still thinking about the options.

Edit: I should add that power draw is not a huge concern for me as the devices will be attached to things that have large (2000+ mAh) batteries attached and only need to operate for an hour or less.

Hi Colin,

I suggest having a look at the API examples on our website. These tend to be a bit more up-to-date than the DWM1001 examples on Github. Though they do not target the DWM1001 module explicitly, it is possible to just copy the deca_driver folder.

Thanks seppe. I have been looking there too, but as far as I can see there aren’t any examples that really relate to this question. Nevertheless I’m sure I’ll be referring back to them frequently when I get started.

Sorry Colin. I’ve asked whether I can show you any of the code and the feedback is no. The IP is split between two companies, the one I work for and the client, which makes it too difficult. We use 3200mAh batteries and get over 24 hours out of them but we were getting only about 10 hours until we resorted to things like turning the DW1000 off when not in use. Our typical duty cycle is about 20ms out of every 1.5s per TWR pair. If your design expects devices to be continually listening for instructions from A or a TWR operation from another device then you should do some power consumption feasibility tests early.

No problem, I’m grateful that you even asked the question! I work in a collaboration of three companies so I totally understand the IP issue.

I’ll be sure to keep an eye on power but there’s nothing stopping us increasing battery size if necessary so I’m not super concerned at this stage. If and when I start work I probably will end up having the radios turned off most of the time, and just setting up timing with a nice safe margin.