Hello all, i'm trying to build a tracking system using 3 anchors that will track one tag all using the Decawave DWM1000 chip. The tag collects the distance from the 3 anchors and the results will be used for trilateration. I have no problem getting this initial setup working, my issue is that the tag needs to provide output to a computer and as a result, I can't have it communicate through the serial port as this would be a wired connection. My solution is to build a receiver that will communicate with the tag and collect the distance results. I tried to implement the send and receive routines as demonstrated in the examples from this library. However I'm having trouble building a receiver that will accept the data from the tag as I keep getting a garbled output. If anyone has any experience with this, I would love some input on the Arduino code, because I have seemed to hit a roadblock. I am using Arduino pro mini and the latest version of the Arduino IDE if that helps. Cheers!
Here is the code I am working with. Apologies for the messy code, I've been modifying these frequently. The goal of these sketches was first to just pass a string that says hello from the tag to the receiver and extend that to sending over an anchor ID and range.
Here is the code for the receiver:
/**
*
* @todo
* - move strings to flash (less RAM consumption)
* - fix deprecated convertation form string to char* startAsAnchor
* - give example description
*/
#include <SPI.h>
//#include <DW1000.h>
#include "DW1000Ranging.h"
// connection pins
const uint8_t PIN_RST = 9; // reset pin
const uint8_t PIN_IRQ = 2; // irq pin
const uint8_t PIN_SS = SS; // 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);
// 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();
//Enable the filter to smooth the distance
//DW1000Ranging.useRangeFilter(true);
//we start the module as an anchor
//DW1000Ranging.startAsAnchor("82:17:5B:D5:A9:9A:E2:9F", DW1000.MODE_LONGDATA_RANGE_ACCURACY,0);
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("Received message ... #"); Serial.println(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;
}
if (error) {
Serial.println("Error receiving a message");
error = false;
//DW1000.getData(message);
//Serial.print("Error data is ... "); Serial.println(message);
}
}
Here is the code for the tag that will be doing the sending:
/**
#include <SPI.h>
#include "DW1000Ranging.h"
// connection pins
const uint8_t PIN_RST = 9; // reset pin
const uint8_t PIN_IRQ = 2; // irq pin
const uint8_t PIN_SS = SS; // spi select pin
// DEBUG packet sent status and count
boolean sent = false;
volatile boolean sentAck = false;
volatile unsigned long delaySent = 0;
int16_t sentNum = 0; // todo check int type
DW1000Time sentTime;
String message;
//variables
int tagID;
float tagRange;
float tagPower;
float Range1;
float Power1;
float Range2;
float Power2;
float Range3;
float Power3;
void setup() {
Serial.begin(115200);
delay(1000);
//init the configuration
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);
DW1000.newConfiguration();
DW1000.setDefaults();
DW1000.setDeviceAddress(5);
DW1000.setNetworkId(10);
//Enable the filter to smooth the distance
//DW1000Ranging.useRangeFilter(true);
char msg[128];
DW1000Ranging.startAsTag("7D:00:22:EA:82:60:3B:9C", DW1000.MODE_LONGDATA_RANGE_LOWPOWER);
DW1000.commitConfiguration();
// start a transmission
transmitter();
}
void handleSent() {
// status change on sent success
sentAck = true;
}
void transmitter() {
// transmit some data
//Serial.print("Transmitting packet ... #"); Serial.println(sentNum);
DW1000.newTransmit();
DW1000.setDefaults();
//place range data in String msg
//float message = tagRange;
message = "hello";
DW1000.setData(message);
// delay sending the message for the given amount
DW1000Time deltaTime = DW1000Time(10, DW1000Time::MILLISECONDS);
DW1000.setDelay(deltaTime);
DW1000.startTransmit();
delaySent = millis();
}
void loop() {
DW1000Ranging.loop();
// transmit some data
//Serial.print("Transmitting packet ... #"); Serial.println(sentNum);
DW1000.newTransmit();
DW1000.setDefaults();
//place range data in String msg
//float message = tagRange;
message = "hello";
DW1000.setData(message);
// delay sending the message for the given amount
DW1000Time deltaTime = DW1000Time(10, DW1000Time::MILLISECONDS);
DW1000.setDelay(deltaTime);
DW1000.startTransmit();
delaySent = millis();
//rangeSort();
if (!sentAck) {
return;
}
sentAck = false;
transmitter();
}
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.println(" dBm");
}
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);
}
void rangeSort()
{
tagID = (int) DW1000Ranging.getDistantDevice()->getShortAddress(),HEX;
tagRange = (float) DW1000Ranging.getDistantDevice()->getRange();
tagPower = (float) DW1000Ranging.getDistantDevice()->getRXPower();
if (tagID == 1) {
Range1 = tagRange;
Power1 = tagPower;
}
else if (tagID == 2) {
Range2 = tagRange;
Power2 = tagPower;
}
else if (tagID == 3) {
Range3 = tagRange;
Power3 = tagPower;
}
}
void print() {
Serial.println(Range1);
Serial.println(Power1);
Serial.println(Range2);
Serial.println(Power2);
Serial.println(Range3);
Serial.println(Power3);
}