I'm trying to achieve ranging and messaging between two UWB DW1000 ESP32 boards. I am using examples from the Decawave DW1000 library for Arduino for this purpose.
I'm pretty out of my depth so the extent of my prototyping has been cobbling together examples from the library with lots and lots of trail and error.
Board A (anchor) is running the RangingAnchor code from the Decawave DW1000 library.
Board B (tag), I have tried both the RangingTag code from the library as well as the BasicReceive code from the examples and when the complimentary code runs on Board A, everything functions as desired.
I tried combining the RangingTag and BasicReceive examples into one sketch. This results in the ranging function being broken until I remove the following line.
DW1000.attachReceivedHandler(handleReceived);
The problem is that this line is required for the messaging function to work correctly.
I'm not sure what I'm doing wrong so any advice or direction would be greatly appreciated.
RangingTag code
/*
For ESP32 UWB or ESP32 UWB Pro
*/
#include <SPI.h>
#include "DW1000Ranging.h"
#define SPI_SCK 18
#define SPI_MISO 19
#define SPI_MOSI 23
#define UWB_RST 27 // reset pin
#define UWB_IRQ 34 // irq pin
#define UWB_SS 21 // spi select pin
void setup()
{
Serial.begin(115200);
delay(1000);
//init the configuration
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
DW1000Ranging.initCommunication(UWB_RST, UWB_SS, UWB_IRQ); // Reset, CS, IRQ pin
//define the sketch as anchor. It will be great to dynamically change the type of module
DW1000Ranging.attachNewRange(newRange);
DW1000Ranging.attachNewDevice(newDevice);
DW1000Ranging.attachInactiveDevice(inactiveDevice);
//Enable the filter to smooth the distance
//DW1000Ranging.useRangeFilter(true);
//we start the module as a tag
DW1000Ranging.startAsTag("7D:00:22:EA:82:60:3B:9C", DW1000.MODE_LONGDATA_RANGE_LOWPOWER);
pinMode(13,OUTPUT);
digitalWrite(13, HIGH);
Serial.print("CODE is uploaded");
}
void loop()
{
DW1000Ranging.loop();
}
void newRange()
{
Serial.print("from: ");
Serial.print(DW1000Ranging.getDistantDevice()->getShortAddress(), HEX);
Serial.print("\t Range: ");
Serial.print(DW1000Ranging.getDistantDevice()->getRange());
Serial.print(" m");
Serial.print("\t RX power: ");
Serial.print(DW1000Ranging.getDistantDevice()->getRXPower());
Serial.print(" dBm");
Serial.println("\t It works on Tag");
}
void newDevice(DW1000Device *device)
{
Serial.print("ranging init; 1 device added ! -> ");
Serial.print(" short:");
Serial.println(device->getShortAddress(), HEX);
}
void inactiveDevice(DW1000Device *device)
{
Serial.print("delete inactive device: ");
Serial.println(device->getShortAddress(), HEX);
}
BasicReceive
#include <SPI.h>
#include <DW1000.h>
// connection pins
const uint8_t PIN_RST = 27; // reset pin
const uint8_t PIN_IRQ = 34; // irq pin
const uint8_t PIN_SS = 21; // spi select pin
// DEBUG packet sent status and count
volatile boolean received = false;
volatile boolean error = false;
volatile int16_t numReceived = 0; // todo check int type
String message;
void setup() {
// DEBUG monitoring
Serial.begin(115200);
// initialize the driver
DW1000.begin(PIN_IRQ, PIN_RST);
DW1000.select(PIN_SS);
Serial.println(F("DW1000 initialized ..."));
// general configuration
DW1000.newConfiguration();
DW1000.setDefaults();
DW1000.setDeviceAddress(6);
DW1000.setNetworkId(10);
DW1000.enableMode(DW1000.MODE_LONGDATA_RANGE_LOWPOWER);
DW1000.commitConfiguration();
Serial.println(F("Committed configuration ..."));
// DEBUG chip info and registers pretty printed
/* char msg[128];
DW1000.getPrintableDeviceIdentifier(msg);
Serial.print("Device ID: "); Serial.println(msg);
DW1000.getPrintableExtendedUniqueIdentifier(msg);
Serial.print("Unique ID: "); Serial.println(msg);
DW1000.getPrintableNetworkIdAndShortAddress(msg);
Serial.print("Network ID & Device Address: "); Serial.println(msg);
DW1000.getPrintableDeviceMode(msg);
Serial.print("Device mode: "); Serial.println(msg);
*/
// attach callback for (successfully) received messages
DW1000.attachReceivedHandler(handleReceived);
//DW1000.attachReceiveFailedHandler(handleError);
//DW1000.attachErrorHandler(handleError);
// start reception
receiver();
}
void handleReceived() {
// status change on reception success
received = true;
}
void handleError() {
error = true;
}
void receiver() {
DW1000.newReceive();
DW1000.setDefaults();
// so we don't need to restart the receiver manually
DW1000.receivePermanently(true);
DW1000.startReceive();
}
void loop() {
// enter on confirmation of ISR status change (successfully received)
if (received) {
numReceived++;
// get data as string
DW1000.getData(message);
Serial.print("#"); Serial.print(numReceived); Serial.println(message);
//Serial.print("FP power is [dBm] ... "); Serial.println(DW1000.getFirstPathPower());
//Serial.print("RX power is [dBm] ... "); Serial.println(DW1000.getReceivePower());
//Serial.print("Signal quality is ... "); Serial.println(DW1000.getReceiveQuality());
received = false;
}
}
My combination of the above
/*
For ESP32 UWB or ESP32 UWB Pro
*/
#include <SPI.h>
#include "DW1000Ranging.h"
#include "DW1000.h"
#define SPI_SCK 18
#define SPI_MISO 19
#define SPI_MOSI 23
const uint8_t PIN_RST = 27; // reset pin
const uint8_t PIN_IRQ = 34; // irq pin
const uint8_t PIN_SS = 21; // spi select pin
// DEBUG packet sent status and count
volatile boolean received = false;
volatile boolean error = false;
volatile int16_t numReceived = 0; // todo check int type
String message;
void setup()
{
Serial.begin(115200);
delay(1000);
//init the configuration
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
DW1000Ranging.initCommunication(PIN_RST, PIN_SS, PIN_IRQ); // Reset, CS, IRQ pin
//define the sketch as anchor. It will be great to dynamically change the type of module
//DW1000Ranging.attachNewRange(newRange);
//DW1000Ranging.attachNewDevice(newDevice);
DW1000Ranging.attachInactiveDevice(inactiveDevice);
//Enable the filter to smooth the distance
//DW1000Ranging.useRangeFilter(true);
//we start the module as a tag
DW1000Ranging.startAsTag("7D:00:22:EA:82:60:3B:9C", DW1000.MODE_LONGDATA_RANGE_LOWPOWER);
pinMode(13,OUTPUT);
digitalWrite(13, HIGH);
Serial.print("CODE is uploaded");
//Code for messages
DW1000.begin(PIN_IRQ, PIN_RST);
DW1000.select(PIN_SS);
// general configuration
DW1000.newConfiguration();
DW1000.setDefaults();
DW1000.setDeviceAddress(6);
DW1000.setNetworkId(10);
DW1000.enableMode(DW1000.MODE_LONGDATA_RANGE_LOWPOWER);
DW1000.commitConfiguration();
DW1000.attachReceivedHandler(handleReceived);
//DW1000.attachReceiveFailedHandler(handleError);
//DW1000.attachErrorHandler(handleError);
// start reception
receiver();
}
void handleReceived() {
// status change on reception success
received = true;
}
void handleError() {
error = true;
}
void receiver() {
DW1000.newReceive();
DW1000.setDefaults();
// so we don't need to restart the receiver manually
DW1000.receivePermanently(true);
DW1000.startReceive();
}
void loop()
{
DW1000Ranging.loop();
if (received) {
numReceived++;
// get data as string
DW1000.getData(message);
Serial.print("#"); Serial.print(numReceived); Serial.println(message);
//Serial.print("FP power is [dBm] ... "); Serial.println(DW1000.getFirstPathPower());
//Serial.print("RX power is [dBm] ... "); Serial.println(DW1000.getReceivePower());
//Serial.print("Signal quality is ... "); Serial.println(DW1000.getReceiveQuality());
received = false;
}
}
void newRange()
{
Serial.print("from: ");
Serial.print(DW1000Ranging.getDistantDevice()->getShortAddress(), HEX);
Serial.print("\t Range: ");
Serial.print(DW1000Ranging.getDistantDevice()->getRange());
Serial.print(" m");
Serial.print("\t RX power: ");
Serial.print(DW1000Ranging.getDistantDevice()->getRXPower());
Serial.print(" dBm");
Serial.println("\t It works on Tag");
}
void newDevice(DW1000Device *device)
{
Serial.print("ranging init; 1 device added ! -> ");
Serial.print(" short:");
Serial.println(device->getShortAddress(), HEX);
}
void inactiveDevice(DW1000Device *device)
{
Serial.print("delete inactive device: ");
Serial.println(device->getShortAddress(), HEX);
}