Hi, I'm new here so let me know if I forgot/can improve something. I really hope someone can help me here.
Situation:
I am currently building a Project that tries to combine the Ultra Wideband DW1000 Chip ranging capabilities with an E-Paper Display from Waveshare.
The DW1000 was pre bundled onto an ESP32-WROOM (bought from makerfabs.com).
Problem:
Over the last couple of weeks I worked out the individual aspects of the prototype with libraries I found online. Now, individually everything works fine. Like I can flash the ESPs with the ranging sketches and it will print out the values fine to the Serial Monitor. Just like that, the E-Paper Display also works great on its own. The Problem Im currently stuck on is combining everything into one working sketch.
AFAIK both modules use SPI to communicate and I think that might be the main direction I have to search in.
Main Libraries used:
- DW1000Ranging & DW1000 (modified ones for better anchor calibration)
- GxEPD
The DW1000 comes pre soldered to the board, but from the example codes I assume it uses:
#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 4 // spi select pin
... for SPI communication.
The E-Paper Display inits SPI with:
GxIO_Class io(SPI, /*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16); // arbitrary selection of 17, 16
GxEPD_Class display(io, /*RST=*/ 16, /*BUSY=*/ 4); // arbitrary selection of (16), 4
... I think.
Full (messy) Sketch:
//Epaper
// mapping suggestion for ESP32, e.g. LOLIN32, see .../variants/.../pins_arduino.h for your board
// NOTE: there are variants with different pins for SPI ! CHECK SPI PINS OF YOUR BOARD
// BUSY -> 4, RST -> 16, DC -> 17, CS -> SS(5), CLK -> SCK(18), DIN -> MOSI(23), GND -> GND, 3.3V -> 3.3V
// include library, include base class, make path known
#include <GxEPD.h>
// select the display class to use, only one
//#include <GxGDEP015OC1/GxGDEP015OC1.h> // 1.54" b/w
//#include <GxGDEH0154D67/GxGDEH0154D67.h> // 1.54" b/w
#include <GxGDEM029T94/GxGDEM029T94.h> // 2.9" b/w
//#include <GxGDEW042T2/GxGDEW042T2.h> // 4.2" b/w
#include GxEPD_BitmapExamples
// FreeFonts from Adafruit_GFX
#include <Fonts/FreeMonoBold9pt7b.h>
#include <Fonts/FreeMonoBold12pt7b.h>
#include <Fonts/FreeMonoBold18pt7b.h>
#include <Fonts/FreeMonoBold24pt7b.h>
#include <Fonts/Tiny3x3a2pt7b.h>
#include <GxIO/GxIO_SPI/GxIO_SPI.h>
#include <GxIO/GxIO.h>
#if defined(ESP32)
// for SPI pin definitions see e.g.:
// C:\Users\xxx\Documents\Arduino\hardware\espressif\esp32\variants\lolin32\pins_arduino.h
GxIO_Class io(SPI, /*CS=5*/ SS, /*DC=*/ 17, /*RST=*/ 16); // arbitrary selection of 17, 16
GxEPD_Class display(io, /*RST=*/ 16, /*BUSY=*/ 4); // arbitrary selection of (16), 4
#endif defined(ARDUINO_ARCH_SAMD)
//UWB Libraries
#include <SPI.h>
#include "DW1000Ranging.h"
#include "DW1000.h"
#define TAG_ADDR "7D:00:22:EA:82:60:3B:9C"
// #define DEBUG
#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 4 // spi select pin
//Datenstruktur für Anchors:
typedef struct _link
{
uint16_t anchor_addr;
float range;
float dbm;
struct _link *next;
} _link;
_link *uwb_data;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
Serial.println();
Serial.println("setup");
SPI.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
DW1000Ranging.initCommunication(UWB_RST, UWB_SS, UWB_IRQ); //Reset, CS, IRQ pin !!!!!!!!!!!!!!!!!!!!!!!!!!! if this is commented out, e-paper works
//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(TAG_ADDR, DW1000.MODE_LONGDATA_RANGE_LOWPOWER);
DW1000Ranging.startAsTag(TAG_ADDR, DW1000.MODE_SHORTDATA_FAST_LOWPOWER);
//DW1000Ranging.startAsTag(TAG_ADDR, DW1000.MODE_LONGDATA_FAST_LOWPOWER);
// DW1000Ranging.startAsTag(TAG_ADDR, DW1000.MODE_SHORTDATA_FAST_ACCURACY);
// DW1000Ranging.startAsTag(TAG_ADDR, DW1000.MODE_LONGDATA_FAST_ACCURACY);
// DW1000Ranging.startAsTag(TAG_ADDR, DW1000.MODE_LONGDATA_RANGE_ACCURACY);
uwb_data = init__link();
display.init(115200); // enable diagnostic output on Serial !!!!!!!!!!!!!!!!!!!!!!!! if this is commented out, UWB Ranging works --- it throws Guru Meditation Errors as long as line 87 (inside GxGDEM...) , which modifies the pinmode of _busy, isnt commented out
display.setRotation(3);
Serial.println("setup done");
}
long int runtime = 0;
void loop() {
// put your main code here, to run repeatedly:
DW1000Ranging.loop();
if ((millis() - runtime) > 6000)
{
//display_uwb(uwb_data);
//updateScreen();
Serial.println("60sec update triggered");
runtime = millis();
showGUI();
}
}
void showGUI() {
//display.fillScreen(GxEPD_WHITE);
//display.update();
display.setTextColor(GxEPD_BLACK);
display.setFont(&FreeMonoBold9pt7b);
display.setCursor(25, 25);
display.print("Short address: ");
// Serial.println(currentNearestName);
display.setCursor(5, 55);
display.setFont(NULL);
display.println("Informationen zum Kunstwerk");
// display.println(currentNearestDistance);
display.setCursor(80, 118);
display.setTextColor(GxEPD_WHITE, GxEPD_BLACK);
display.println("Nicht Gespeichert");
display.setCursor(2, 118);
display.println("Kurz(+)");
display.setCursor(240, 118);
display.println("Lang(-)");
display.fillRect(0, 40, 296, 2, GxEPD_BLACK);
display.fillRect(0, 110, 296, 2, GxEPD_BLACK);
display.update();
Serial.println("inGUI");
}
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");
fresh__link(uwb_data, DW1000Ranging.getDistantDevice()->getShortAddress(), DW1000Ranging.getDistantDevice()->getRange(), DW1000Ranging.getDistantDevice()->getRXPower());
//print__link(uwb_data);
}
void newDevice(DW1000Device *device)
{
Serial.print("ranging init; 1 device added ! -> ");
Serial.print(" short:");
Serial.println(device->getShortAddress(), HEX);
add__link(uwb_data, device->getShortAddress());
}
void inactiveDevice(DW1000Device *device)
{
Serial.print("delete inactive device: ");
Serial.println(device->getShortAddress(), HEX);
delete__link(uwb_data, device->getShortAddress());
}
//Data _link
_link *init__link()
{
#ifdef DEBUG
Serial.println("init__link");
#endif
_link *p = (_link *)malloc(sizeof(_link));
p->next = NULL;
p->anchor_addr = 0;
p->range = 0.0;
return p;
}
void add__link(_link *p, uint16_t addr)
{
#ifdef DEBUG
Serial.println("add__link");
#endif
_link *temp = p;
//Find _link end
while (temp->next != NULL)
{
temp = temp->next;
}
Serial.println("add__link:find _link end");
//Create a anchor
_link *a = (_link *)malloc(sizeof(_link));
a->anchor_addr = addr;
a->range = 0.0;
a->dbm = 0.0;
a->next = NULL;
//Add anchor to end of _link
temp->next = a;
return;
}
_link *find__link(_link *p, uint16_t addr)
{
#ifdef DEBUG
Serial.println("find__link");
#endif
if (addr == 0)
{
Serial.println("find__link:Input addr is 0");
return NULL;
}
if (p->next == NULL)
{
Serial.println("find__link:_link is empty");
return NULL;
}
_link *temp = p;
//Find target _link or _link end
while (temp->next != NULL)
{
temp = temp->next;
if (temp->anchor_addr == addr)
{
// Serial.println("find__link:Find addr");
return temp;
}
}
Serial.println("find__link:Can't find addr");
return NULL;
}
void fresh__link(_link *p, uint16_t addr, float range, float dbm)
{
#ifdef DEBUG
Serial.println("fresh__link");
#endif
_link *temp = find__link(p, addr);
if (temp != NULL)
{
temp->range = range;
temp->dbm = dbm;
return;
}
else
{
Serial.println("fresh__link:Fresh fail");
return;
}
}
void print__link(_link *p)
{
#ifdef DEBUG
Serial.println("print__link");
#endif
_link *temp = p;
while (temp->next != NULL)
{
//Serial.println("Dev %d:%d m", temp->next->anchor_addr, temp->next->range);
Serial.println(temp->next->anchor_addr, HEX);
Serial.println(temp->next->range);
Serial.println(temp->next->dbm);
temp = temp->next;
}
return;
}
void delete__link(_link *p, uint16_t addr)
{
#ifdef DEBUG
Serial.println("delete__link");
#endif
if (addr == 0)
return;
_link *temp = p;
while (temp->next != NULL)
{
if (temp->next->anchor_addr == addr)
{
_link *del = temp->next;
temp->next = del->next;
free(del);
return;
}
temp = temp->next;
}
return;
}
As I had no idea how to properly DEBUG this I experimented with the code in the sketch and corresponding Libraries. So far I observed that when I comment out either
- DW1000Ranging.initCommunication(UWB_RST, UWB_SS, UWB_IRQ);
or - display.init(115200);
either of them work individually. Otherwise I get:
Guru Meditation Error: Core 1 panic'ed (Interrupt wdt timeout on CPU1).
Core 1 register dump:
PC : 0x4008a716 PS : 0x00060d35 A0 : 0x8008996e A1 : 0x3ffbedbc
A2 : 0x3ffb7f54 A3 : 0x3ffb8890 A4 : 0x00000004 A5 : 0x00060d23
A6 : 0x00060d23 A7 : 0x00000001 A8 : 0x3ffb8890 A9 : 0x00000018
A10 : 0x3ffb8890 A11 : 0x00000018 A12 : 0x3ffc3414 A13 : 0x00060d23
A14 : 0x007bef68 A15 : 0x003fffff SAR : 0x0000001e EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x40085e74 LEND : 0x40085e79 LCOUNT : 0x00000000
Core 1 was running in ISR context:
EPC1 : 0x400e16d3 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x00000000
Backtrace:0x4008a713:0x3ffbedbc |<-CORRUPTED
Core 0 register dump:
PC : 0x4008a893 PS : 0x00060035 A0 : 0x80089597 A1 : 0x3ffbe8bc
A2 : 0x3ffbef68 A3 : 0xb33fffff A4 : 0x0000abab A5 : 0x00060023
A6 : 0x00060021 A7 : 0x0000cdcd A8 : 0x0000abab A9 : 0xffffffff
A10 : 0x3ffc3230 A11 : 0x00000000 A12 : 0x3ffc322c A13 : 0x00000007
A14 : 0x007bef68 A15 : 0x003fffff SAR : 0x0000001a EXCCAUSE: 0x00000006
EXCVADDR: 0x00000000 LBEG : 0x00000000 LEND : 0x00000000 LCOUNT : 0x00000000
Backtrace:0x4008a890:0x3ffbe8bc |<-CORRUPTED
ELF file SHA256: 0000000000000000
Rebooting...
Do I have to change something with the SPI configuration pins? I read mutliple SPI devices can share the same pins except the CS/SS pins. I tried that at one point, I think, but it didnt change the outcome. I only hope the libraries are compatible with each other and I am the problem and not the rest of the code. If someone can help me, give me a general direction or something I might be missing Id really appreciate it!