UWB Feather

Getting started with the UWB Feather.
Note: Work on creating the example documentation is still in progress.

To get started, install the PlatformIO package and board files as shown below and follow the guide to get started. To use the DWM1000 install the thotro/arduino-dw1000 library.

To put the board into programming mode, double press the reset button. The RGB LED will fade blue slowly if a connection is successful.

Install the PIO repository & board package

Add UWB Feather board support

Download the board file from https://dl.prototypingcorner.io/pio/boards/prototypingcorner_uwb_feather.json and place this in your PlatformIO core directory /boards directory (see the PIO guide if you get stuck)

{
    "build": {
      "arduino": {
          "ldscript": "flash_with_bootloader.ld"
      },
      "core": "prototypingcorner",
      "cpu": "cortex-m0plus",
      "extra_flags": "-DARDUINO_ARCH_SAMD -DARDUINO_SAMD_ZERO -DARM_MATH_CM0PLUS -D__SAMD21G18A__",
      "f_cpu": "48000000L",
      "hwids": [
        [
          "0x1209",
          "0x8192"
        ]
      ],
      "mcu": "samd21g18a",
      "system": "samd",
      "usb_product": "Prototyping Corner UWB Feather",
      "variant": "uwb_feather"
    },
    "debug": {
      "jlink_device": "ATSAMD21G18",
      "openocd_chipname": "at91samd21g18",
      "openocd_target": "at91samdXX",
      "svd_path": "ATSAMD21G18A.svd"
    },
    "frameworks": [
      "arduino"
    ],
    "platforms": [
      "atmelsam"
    ],
    "name": "Prototyping Corner UWB Feather",
    "upload": {
      "disable_flushing": true,
      "maximum_ram_size": 32768,
      "maximum_size": 262144,
      "native_usb": true,
      "offset_address": "0x2000",
      "protocol": "sam-ba",
      "protocols": [
        "sam-ba",
        "blackmagic",
        "jlink",
        "atmel-ice"
      ],
      "require_upload_port": true,
      "use_1200bps_touch": true,
      "wait_for_upload_port": true
    },
    "url": "https://prototypingcorner.io/l/uwb_feather",
    "vendor": "Prototyping Corner"
  }
  

Add the prototypingcorner samd package

Next you’ll need to modify the atmelsam package list to add the prototyping corner package repository. In the PlatformIO core directory go to platforms/atmelsam and open the platform.json file.

Here add https://dl.prototypingcorner.io/pio/packages/manifest.json to the packageRepositories list (as shown above) to add the Prototyping Corner package repository.

Then add support for the framework by pasting the below snippet into the packages list as shown above.

"framework-arduino-samd-prototypingcorner": {
    "type": "framework",
    "optional": true,
    "version": "~1.6.2"
},

That’s it, head on over the the PIO boards page and you should see the UWB feather show up

Getting updates

Board support is still a work in progress, luckily if you need to update just run this PIO command (press F1 from within VSCode to get the command window up)

PlatformIO: Update platforms & packages

This will automatically pull and install the latest version of the UWB Feather package.

Configuration.h

The following is the pin assignment. Note in future releases this will be included in the support package.

#ifndef CONFIGURATION_H
#define CONFIGURATION_H
#include <Arduino.h>

#define DW1000_RST      2
#define DW1000_IRQ      3
#define DW1000_CS       4

#define LED_RED         26
#define LED_GREEN       31
#define LED_BLUE        30

#define BATTERY_VOLT    25
#define BATTERY_CHARGE  27

#endif

Main.cpp

The following is example code use to test the module. It shows how to use the RGB LED, measure voltage and monitor charge status. View the full project on the GitHub repository

/**
 * UWB Feather feature test
 * Short set of testing program onboard features of the UWB feather
 */

#include <Arduino.h>
#include "DW1000Ranging.h"

// Decawave DW1000 pins
#define DW1000_RST      2
#define DW1000_IRQ      3
#define DW1000_CS       4

// RGB LED pins
#define LED_RED         26
#define LED_GREEN       31
#define LED_BLUE        30

// Battery sense pins
#define BATTERY_VOLT    25
#define BATTERY_CHARGE  27

/** Pulse a pin for a set amount of time */
void pulse(int pin, int interval) {
  digitalWrite(pin, HIGH);
  delay(interval);
  digitalWrite(pin, LOW);
  delay(interval);
}

/** Calculate the battery voltage on battery pin */
float getBatteryVoltage() {
  float measuredvbat = analogRead(BATTERY_VOLT);
  measuredvbat *= 2;    // we divided by 2, so multiply back
  measuredvbat *= 3.3;  // Multiply by 3.3V, our reference voltage
  measuredvbat /= 1024; // convert to voltage
  return measuredvbat;
}

void setup() {
  /** Wait for the serial monitor to be open before starting the program */
  Serial.begin(9600);
  while(!Serial);
  Serial.println("Starting...");

  /** Setup our pins */
  pinMode(LED_RED, OUTPUT);
  pinMode(LED_GREEN, OUTPUT);
  pinMode(LED_BLUE, OUTPUT);
  pinMode(BATTERY_CHARGE, INPUT);

  /** Test the RGB LED */
  Serial.println("Testing RGB LED...");
  Serial.println("RED");
  pulse(LED_RED, 1000);

  Serial.println("GREEN");
  pulse(LED_GREEN, 1000);

  Serial.println("BLUE");
  pulse(LED_BLUE, 1000);

  /** 
   * Test the DWM1000 module 
   * Device ID will print out:
   * Device ID: DECA - model: 1, version: 3, revision: 0
   * if connectivity to the DWM1000 was successful
   */
  Serial.println("Testing DWM1000 module");
  DW1000Ranging.initCommunication(DW1000_RST, DW1000_CS, DW1000_IRQ);
  DW1000Ranging.startAsTag("7D:00:22:EA:82:60:3B:9C", DW1000.MODE_LONGDATA_RANGE_ACCURACY);
  delay(1000);
  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);

  /** Test the battery */
  Serial.println("Testing battery...");
  Serial.println("Running battery test for 20 seconds");

  long millisNow = millis();
  // For 20 seconds display the reading on the BATTERY_VOLT and BATTERY_CHARGE pins
  // BATTERY_VOLT will float around 4.3V if there is no battery plugged in
  while(millis() < millisNow + 20000) {
    // Calculate the battery voltage
    Serial.print("VBat: "); Serial.println(getBatteryVoltage());

    // The BATTERY_CHARGE signal is active low, so dont forget to invert it
    Serial.print("Charge: "); Serial.println( ! digitalRead(BATTERY_CHARGE) ); 
    
    delay(500);
  }

  Serial.println("Testing complete");
}

void loop() { /** Nothing to loop */ }

Using the DWM1000

Create a new DW1000Ranging instance using the pin definitions from configuration.h. Don’t forget to install the thotro/arduino-dw1000 using either the PIO library manager or downloading it to the lib folder.

DW1000Ranging.initCommunication(PIN_RST, PIN_SS, PIN_IRQ);

Further reading

Here is some links to papers that utilize the DW1000 IC and may be useful for integrating this module

Decawave Application Notes
This is a great resource for everything to do with the DW1000, everyone working with this board should take a look at what information is available here
https://www.decawave.com/application-notes/

Decawave UWB Clock Drift Correction and Power Self-Calibration
https://www.mdpi.com/1424-8220/19/13/2942/htm

UWB Positioning
https://www.decawave.com/wp-content/uploads/2018/12/Ultra-Wideband-Wireless-Positioning-Systems_2014-03-27.pdf

Still to come

Work that on its way:
– New DW1000 library (to replace thotro/arduino-dw1000)
– Create library for easy of use (i.e. charge status interrupt, LED control)
– Examples!
– Multilateration code samples

Questions?

For any help with getting started contact hi@prototypingcorner.io, or take a look at our product forums (coming soon)