DWM1000 Ranging issues

Good Day,

I need to develop a local position system for a robot. Decided to use the DWM1000, I currently have 4 tags that are statuinary and one anchor that is mobile. The anchor that is mobile is connected to an MCU. My question is can I run the system in default mode or do I need to connect each tag to their own MCU?


The DWM1000 doesn’t have a processor and so you need to add one and communicate with the radio over SPI.

Or did you mean the DWM1001 which does have a processor as part of the module?

Thannks for the response.

I meant DWM1000, and you answered my question I think. So each module will need it’s own processor, do you have any cheap recommendations of what processor to use? We cannot use Adruino.

I’ve used LPC1768’s from NXP using the mbed platform.
Just about anything with an SPI bus will work so whatever you have familiarity with is a good plan.

I’m a little confused as to how this module works with SPI. Is there specific messages that I have to see over SPI ? or do I rewrite the Register bits through SPI and a response is sent back?

The DWM1000 is just a DW1000 chip on a module that includes the required capacitors, clocks and antenna. You have to drive it in exactly the same way you would any other dumb peripheral, by reading and writing registers.

Some registers only have one block of data (e.g. the status register) and so you always want to read from the start of that register. Other registers have lots of sub-fields, for those you normally want to start the read/write at an offset. When starting a read/write cycle you always send a register address byte but then there are one or two optional bytes with the offset to use.

The basic sequence is:

Chip select low
Write the register address byte: bit 7 = write flag, bit 6 = offset follows, bits 5-0 = register address.
If there is a offset 
  If the offset > 0x7f
    Write 0x80 | low 7 bits of offset
    Write remaining bits of offset right shifted 7 places.
    write the offset.

For a write cycle write as many data bytes as required. Ignore the returned values.
For a read cycle write a 0x00 byte for each byte required, save the returned values.

Chip select high.

The DW1000 user manual gives details of all the registers.

You can also set the interrupt pin to signal when certain conditions arise (e.g. a radio packet has been received) in order to notify your processor that it needs to go and read things. As with just about all other devices exactly which conditions generate an interrupt can be set by using the mask register.

e.g. my code to read the status register is:

uint64_t DW1000::getStatus()
    return readRegister40(DW1000_SYS_STATUS, 0);

uint64_t DW1000::readRegister40(uint8_t reg, uint16_t subaddress)
    uint64_t result = 0;
    readRegister(reg, subaddress, (uint8_t*)&result, 5);
    return result;

void DW1000::readRegister(uint8_t reg, uint16_t subaddress, uint8_t *buffer, int length)
    setupTransaction(reg, subaddress, false);
    for(int i=0; i<length; i++)                 
        buffer[i] = spi.write(0x00);

void DW1000::setupTransaction(uint8_t reg, uint16_t subaddress, bool write)
    reg |=  (write * DW1000_WRITE_FLAG); 
    if (subaddress > 0) {
        spi.write(reg | DW1000_SUBADDRESS_FLAG);
        if (subaddress > 0x7F) {
            spi.write((uint8_t)(subaddress & 0x7F) | DW1000_2_SUBADDRESS_FLAG);
            spi.write((uint8_t)(subaddress >> 7));
        } else {
    } else {