Connect the uwb using a esp32 dev board and arduino ide

Hello, I have been unable to get my eps32 dev board to communicate with the uwb bu03

I copied and pasted the code provided. Below is the response from the serial monitor.

Thank you

Sending AT+SETCFG command...

Sending AT+SAVE command...

Sending AT+GETCFG command...
1 Like

Welcome…

A few little thing while we wait for the guru’s to give some feedback.
Any photos of your write hook up can help. Also the code snippets to setup and send commands.

Having a quick look at the guide I see it uses 2 UARTS, 1 for the AT Commands on pings TX1, RX1 (PA9/10). then the UART for that data PA2/3.
So for that AT command it will be PA9/10. Check the cross over. Normally you would connect RX-TX and TX to RX, but sometimes its could be RX-RX and TX-TX, no harm in trying a swap over (from the photos it looks like the normal RX-TX).
Check the baud rate, its should be 115200

2 Likes

Thank you for your help! This is our wiring. The code is exactly cut and pasted from the arduino ide version posted in the tutorial. We tried switching the rx/tx going rx to rx, tx to tx with not luck.

1 Like

To me it looks like you have the UART Pins for data output connected, but to use the AT commands you need to use the UART Pins for AT Commands (the other side)

1 Like

Thank you! The picture I took was my last shot at hooking this up in desperation, I tried using the other pins. With the correct connections as you pointed out, I again hooked up to AT command pins with the same result in the code. Please let me know if you have any other suggestions. Do I need to declare rx/tx pins on the esp32 dev board in the code?

full code with serial monitor result:

void setup() {

  // Initialize USB Serial for debugging

  Serial.begin(115200);

  while (!Serial) {

    ; // Wait for USB serial port to connect

  }

  Serial.println("Starting board configuration...");

  

  // Initialize hardware UART on pins 0 (RX) and 1 (TX) for UWB communication

  Serial1.begin(115200);

  

  delay(2000); // Give some time for everything to get ready

  

  // Send configuration command

  Serial.println("Sending AT+SETCFG command...");

  Serial1.print("AT+SETCFG=0,0,1,1\\r\\n");

  delay(1000);

  

  // Check for response

  if (Serial1.available()) {

    String response = Serial1.readString();

    Serial.println(response);

  }

    delay(3000);

  

  // Save configuration

  Serial.println("Sending AT+SAVE command...");

  Serial1.print("AT+SAVE\\r\\n");

  delay(3000);

  

  // Check for response

  if (Serial1.available()) {

    String response = Serial1.readString();

    Serial.println(response);

  }


  // Get current configuration to verify

  Serial.println("Sending AT+GETCFG command...");

  Serial1.print("AT+GETCFG\\r\\n");

  delay(100);

  

  // Check for response

  if (Serial1.available()) {

    String response = Serial1.readString();

    Serial.println(response);

  }

  }

void loop() {

}

Serial Monitor result:

Sending AT+SETCFG command…

Sending AT+SAVE command…

Sending AT+GETCFG command…

I prefer to do that as then I know exactly what pins its using. Please not I am not an Arduino user, so I cant tell you the commands.

From your code above

     // Initialize hardware UART on pins 0 (RX) and 1 (TX) for UWB communication
     Serial1.begin(115200);
	

t seems its trying to use GPIO pin 0/1, which to me makes no sense at all.
Normally Serial 0 is the main programing/debug serial port the also goes via the USB, which would be your serial 0.

So maybe something like

Serial1.begin(115200, SERIAL_8N1, RXPIN, TXPIN); 

where RXPIN and TXPIN would be you gpio for where you want it. (GPIO 16/17 by the look of your wiring) but that seems to be labeled as UART2 RX/TX. In theory that should be OK as long as UART2 is not currently enabled.

Hey Michael, are you currently following the steps from the below tutorial?

If you are, I think the pins you’re using are incorrect. Based on the pinouts for the dev board below, you would be using UART 2 in your setup which probably is not the default configuration:

Could you try using the pins labelled GPIO1 and GPIO3 in the diagram above. Since they’re labelled as UART0 they’re more likely to be the default UART pins.

Hi Jane, thank you for the reply! We are following the steps in the tutorial. I tried with the other pins this morning. With the rx going to the tx I received the error below. When I ran the rx to rx and tx to tx is loaded, but I received the same message as befor in the serial monitor. Thank you again for your help!

If using UART0 then you most likely need to remove the connections during flashing as the USB->UART for programming will be via UART0

After you flash the device you can try to re-connect, but you wont be able to monitor the serial output. I would use UART1 or 2 and device the pins you what to use as RX/TX.

Hello all,

Thank you again for all your help. We decided to purchase an arduino r4 and were able to get throught the provided tutorial and have the distance between the the anchor and tag! Although this may seem basic… The students would now like to do something with the distance data. Are there any examples of how we could illuminate some LEDs bas on a distance range? For example, it the distance is between the anchor and tag is between 5 and 10 meters apart turn on an LED. Thanks again for all your efforts, it is really appreciated!

1 Like

Hey @Michael309401,

Absolutely you can.

There aren’t any tutorials specifically on that, but it wouldn’t be too hard to configure.

You would want to wire up your Arduino to an LED like so:

And use code similar, if not exactly like, the following (Note: I’ve not had time to test this).

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
   // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

bool decodeUwbDistances(uint8_t* data, int dataLen, float* distances) {
  // Initialize all distances to -1 (equivalent to None)
  for (int i = 0; i < 8; i++) {
    distances[i] = -1.0;
  }
  
  if (dataLen < 35) {
    return false;
  }
  
  // Check for header pattern
  if (data[0] != 0xaa || data[1] != 0x25 || data[2] != 0x01) {
    return false;
  }
  
  // Extract distance data (skip header, process 4-byte chunks)
  for (int i = 0; i < 8; i++) {  // 8 base stations (0-7)
    int byteOffset = 3 + (i * 4);  // Each distance is 4 bytes
    if (byteOffset + 3 < dataLen) {
      // Read as little-endian 32-bit integer
      uint32_t distanceRaw = data[byteOffset] | 
                            (data[byteOffset + 1] << 8) | 
                            (data[byteOffset + 2] << 16) | 
                            (data[byteOffset + 3] << 24);
      
      // Convert to meters
      if (distanceRaw > 0) {
        distances[i] = distanceRaw / 1000.0;
      } else {
        distances[i] = -1.0;  // No signal/not visible
      }
    }
  }
  
  return true;
}

void printDistances(float* distances, bool validData) {
  if (!validData) {
    Serial.println("Invalid data received");
    return;
  }
  
  Serial.println("Base Station Distances:");
  for (int i = 0; i < 8; i++) {

  if (distances[i] > 0) {
    Serial.print("  BS");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(distances[i], 3);
    Serial.println("m");

    // turn LEDs on if  the distance is between 5m and 10m
    if (distances[i] >= 5.0 && distances[i] <= 10.0) {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(5000);  // wait 5 seconds, then continue loop
      digitalWrite(LED_BUILTIN, LOW); // optional: ensure off after the wait
    }

  } else {
    Serial.print("  BS");
    Serial.print(i);
    Serial.println(": Not visible");
  }
  Serial.println("------------------------------");
}

void loop() {
  static uint8_t buffer[256];
  static int bufferIndex = 0;
  static bool messageStarted = false;
  
  // Check if anything is available in buffer
  while (Serial1.available()) {
    uint8_t incomingByte = Serial1.read();
    
    // searches for the start of message
    if (!messageStarted && incomingByte == 0xAA) {
      messageStarted = true;
      bufferIndex = 0;
      buffer[bufferIndex++] = incomingByte;
    } else if (messageStarted) {
      buffer[bufferIndex++] = incomingByte;
      
      // Check if we have a complete message (35+ bytes expected)
      if (bufferIndex >= 35) {
        // Print raw data
        Serial.print("Raw data: b'");
        for (int i = 0; i < bufferIndex; i++) {
          if (buffer[i] >= 32 && buffer[i] <= 126) {
            Serial.print((char)buffer[i]);
          } else {
            Serial.print("\\x");
            if (buffer[i] < 16) Serial.print("0");
            Serial.print(buffer[i], HEX);
          }
        }
        Serial.println("'");
        
        // Decode distances
        float distances[8];
        bool validData = decodeUwbDistances(buffer, bufferIndex, distances);
        printDistances(distances, validData);
        
        // Reset for next message
        messageStarted = false;
        bufferIndex = 0;
      }
      
      // Prevent buffer overflow
      if (bufferIndex >= 256) {
        messageStarted = false;
        bufferIndex = 0;
      }
    }
  }
}

Hi Jane. Thank you so much again for your help. The studnets will be exicited to try the code you provided and will defininetly help expand their and my knowledge, as this level of coding is out of area of expertise… I will let you know how we are making out. Thanks again!

1 Like

No worries, @Michael309401, as I said I haven’t had the chance to test it but I’ll be happy to refine it as we go.

Happy Holidays.

As a comment… once you have the distance measuing device feeding values back, one way to to print those to the terminal window. Then have it detect someone at the start of the “detect zone” and record that value. Next have it detect someone at the end of the “detect zone” and record that value.

Now that you know the two values that the unit will feed you for the start and end…

psedude code

 if ((measuredDistance >= StartRange)  && (measuredDistance <= EndRange)) {
   // Do something.
  // eg make a pin go high to trigger something...
}

the reason I like this apprach is it is very practical. So if the unit is not calibrated to give the correct “meters” it can still be used to detect a range; and you/the students can see how testing the range first can help “tune” what you want to do.

1 Like

Thanks Jane. Students have headed home for the holiday, so I’m sure they will be back at it when we return. I again really appreciate your help!

Mike

They did have a few minutes yesterday to test the code and said they were getting an error with one of the brackets in the loop. I did not have a chance to see it so I’m not sure. But again, I really appreciate the help!

1 Like

Thank Michael. I will pass it along to the students. I really appreciate your help and insight as we’re working through this. Happy holidays!

Mike

Whoops, you’re correct, @Michael309401,

I missed a closing curly bracket in the for loop. The perils of coding in Markdown. Fixed below.

Happy Holidays <3

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
   // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED_BUILTIN, OUTPUT);
}

bool decodeUwbDistances(uint8_t* data, int dataLen, float* distances) {
  // Initialize all distances to -1 (equivalent to None)
  for (int i = 0; i < 8; i++) {
    distances[i] = -1.0;
  }
  
  if (dataLen < 35) {
    return false;
  }
  
  // Check for header pattern
  if (data[0] != 0xaa || data[1] != 0x25 || data[2] != 0x01) {
    return false;
  }
  
  // Extract distance data (skip header, process 4-byte chunks)
  for (int i = 0; i < 8; i++) {  // 8 base stations (0-7)
    int byteOffset = 3 + (i * 4);  // Each distance is 4 bytes
    if (byteOffset + 3 < dataLen) {
      // Read as little-endian 32-bit integer
      uint32_t distanceRaw = data[byteOffset] | 
                            (data[byteOffset + 1] << 8) | 
                            (data[byteOffset + 2] << 16) | 
                            (data[byteOffset + 3] << 24);
      
      // Convert to meters
      if (distanceRaw > 0) {
        distances[i] = distanceRaw / 1000.0;
      } else {
        distances[i] = -1.0;  // No signal/not visible
      }
    }
  }
  
  return true;
}

void printDistances(float* distances, bool validData) {
  if (!validData) {
    Serial.println("Invalid data received");
    return;
  }
  
  Serial.println("Base Station Distances:");
  for (int i = 0; i < 8; i++) {

  if (distances[i] > 0) {
    Serial.print("  BS");
    Serial.print(i);
    Serial.print(": ");
    Serial.print(distances[i], 3);
    Serial.println("m");

    // turn LEDs on if  the distance is between 5m and 10m
    if (distances[i] >= 5.0 && distances[i] <= 10.0) {
      digitalWrite(LED_BUILTIN, HIGH);
      delay(5000);  // wait 5 seconds, then continue loop
      digitalWrite(LED_BUILTIN, LOW); // optional: ensure off after the wait
    }

  } else {
    Serial.print("  BS");
    Serial.print(i);
    Serial.println(": Not visible");
  }
  Serial.println("------------------------------");
  }
}

void loop() {
  static uint8_t buffer[256];
  static int bufferIndex = 0;
  static bool messageStarted = false;
  
  // Check if anything is available in buffer
  while (Serial1.available()) {
    uint8_t incomingByte = Serial1.read();
    
    // searches for the start of message
    if (!messageStarted && incomingByte == 0xAA) {
      messageStarted = true;
      bufferIndex = 0;
      buffer[bufferIndex++] = incomingByte;
    } else if (messageStarted) {
      buffer[bufferIndex++] = incomingByte;
      
      // Check if we have a complete message (35+ bytes expected)
      if (bufferIndex >= 35) {
        // Print raw data
        Serial.print("Raw data: b'");
        for (int i = 0; i < bufferIndex; i++) {
          if (buffer[i] >= 32 && buffer[i] <= 126) {
            Serial.print((char)buffer[i]);
          } else {
            Serial.print("\\x");
            if (buffer[i] < 16) Serial.print("0");
            Serial.print(buffer[i], HEX);
          }
        }
        Serial.println("'");
        
        // Decode distances
        float distances[8];
        bool validData = decodeUwbDistances(buffer, bufferIndex, distances);
        printDistances(distances, validData);
        
        // Reset for next message
        messageStarted = false;
        bufferIndex = 0;
      }
      
      // Prevent buffer overflow
      if (bufferIndex >= 256) {
        messageStarted = false;
        bufferIndex = 0;
      }
    }
  }
}

Hi Jane!

Thank you again for all you help! I hope you had a nice holiday. The students are making some progress.

Best regards,
Mike

1 Like