diff --git a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/user-manual-4.png b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/boards-manager.png similarity index 100% rename from content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/user-manual-4.png rename to content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/boards-manager.png diff --git a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/library-installation.png b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/library-installation.png new file mode 100644 index 0000000000..d126a054d3 Binary files /dev/null and b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/library-installation.png differ diff --git a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/library-repository.png b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/library-repository.png new file mode 100644 index 0000000000..92b1796d06 Binary files /dev/null and b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/library-repository.png differ diff --git a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/nearbydemo-serial-monitor.png b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/nearbydemo-serial-monitor.png new file mode 100644 index 0000000000..e7ea5f0377 Binary files /dev/null and b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/nearbydemo-serial-monitor.png differ diff --git a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/twr-portenta-serial.png b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/twr-portenta-serial.png new file mode 100644 index 0000000000..f832d2aa9f Binary files /dev/null and b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/twr-portenta-serial.png differ diff --git a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/twr-serial-plotter.gif b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/twr-serial-plotter.gif new file mode 100644 index 0000000000..3c1dbcc200 Binary files /dev/null and b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/twr-serial-plotter.gif differ diff --git a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/twr-stella-serial.png b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/twr-stella-serial.png new file mode 100644 index 0000000000..a0669bee84 Binary files /dev/null and b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/twr-stella-serial.png differ diff --git a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/user-manual-3.png b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/user-manual-3.png deleted file mode 100644 index 4ff31b5393..0000000000 Binary files a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/assets/user-manual-3.png and /dev/null differ diff --git a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/content.md b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/content.md index fa806f8cdb..ff7b294996 100644 --- a/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/content.md +++ b/content/hardware/04.pro/shields/portenta-uwb-shield/tutorials/01.user-manual/content.md @@ -26,22 +26,24 @@ This user manual provides a comprehensive overview of the Portenta UWB Shield, h - [Portenta UWB Shield (SKU: ASX00074)](https://store.arduino.cc/products/portenta-uwb-shield) (x1) - [Portenta C33 (SKU: ABX00074)](https://store.arduino.cc/products/portenta-c33) (x1) -- [Arduino Stella (SKU: ABX00131)](https://store.arduino.cc/products/stella) (x1) +- [Arduino Stella (SKU: ABX00131)](https://store.arduino.cc/products/stella) (x1) (optional, for Two-Way Ranging examples) - [USB-C® cable (SKU: TPX00094)](https://store.arduino.cc/products/usb-cable2in1-type-c) (x2) +- External antenna (x1) (optional, for Bluetooth® Low Energy functionality) ### Software Requirements -- [Arduino IDE 2.0+](https://www.arduino.cc/en/software) +- [Arduino IDE](https://www.arduino.cc/en/software) - [`PortentaUWBShield` library](https://github.com/Truesense-it/PortentaUWBShield) (designed for the Portenta UWB Shield) -- [`StellaUWB` library](https://github.com/Truesense-it/StellaUWB) (designed for the Arduino Stella) -- [`ArduinoBLE` library](https://github.com/arduino/ArduinoBLE) -- [Arduino Renesas Portenta Boards core](https://github.com/arduino/ArduinoCore-renesas) (required to work with the Portenta C33 board) +- [`StellaUWB` library](https://github.com/Truesense-it/StellaUWB) (optional, for Two-Way Ranging with Arduino Stella) +- [`ArduinoBLE` library](https://github.com/arduino-libraries/ArduinoBLE) (for Bluetooth® Low Energy examples) +- [Arduino Renesas Portenta Boards core](https://github.com/arduino/ArduinoCore-renesas) (required for the Portenta C33 microcontroller) +- [Arduino Mbed OS Stella Boards core](https://github.com/arduino/ArduinoCore-mbed) (optional, for Arduino Stella in Two-Way Ranging examples) -***The Portenta UWB Shield is not intended as a standalone device but as a shield to work alongside a Portenta family board. In this user manual, we will use the Portenta C33 as the main board and show how to use the Portenta UWB Shield with it.*** +***The Portenta UWB Shield is not intended as a standalone device but as a shield to work alongside a Portenta family board. In this user manual, we will use the Portenta C33 as the host board and demonstrate how to implement UWB functionality for real-time location services and precise ranging applications.*** ## Portenta UWB Shield Overview -Enhance your positioning and real-time location capabilities with the Portenta UWB Shield. Based on the Truesense DCU150 module, this versatile Ultra-Wideband (UWB) communication solution integrates with the Portenta C33 board via its High-Density connectors and functions as a base station for two-way ranging and real-time location services (RTLS). +Enhance your positioning and real-time location capabilities with the Portenta UWB Shield. Based on the Truesense [DCU150](https://ultrawideband.truesense.it/wp-content/uploads/2022/07/TRUESENSE-DCU150_Datasheet.pdf) Ultra-Wide Band (UWB) module, this versatile Ultra-Wideband (UWB) communication solution integrates with the Portenta C33 board via its High-Density connectors and functions as a base station for two-way ranging and real-time location services (RTLS). ![The Portenta UWB Shield](assets/front-page.png) @@ -108,7 +110,7 @@ In an UWB positioning system, devices typically operate in one of two roles: - **Anchors**: Fixed-position devices (like the Portenta UWB Shield with a Portenta C33) that provide reference points for the positioning system. A minimum of three anchors is typically needed for 2D positioning and four for 3D positioning. - **Tags**: Mobile devices that communicate with anchors to determine their position in space. Tags can be standalone devices like the Arduino Stella or integrated into smartphones, wearables, or other IoT devices. -#### Applications of UWB Technology +#### Applications of the Portenta UWB Shield with UWB Technology UWB's unique combination of precision, low latency, and security opens up numerous applications: @@ -150,7 +152,7 @@ Here's an overview of the shield's main components shown in the images: ### Board Libraries -The Portenta UWB Shield and the Arduino Stella use different libraries and board cores due to their different microcontrollers and onboard UWB modules: +The Portenta UWB Shield and Arduino Stella use different libraries and board cores due to their different microcontrollers and onboard UWB modules: #### Portenta UWB Shield Library @@ -160,37 +162,58 @@ The [`PortentaUWBShield` library](https://github.com/Truesense-it/PortentaUWBShi - Angle of Arrival (AoA) measurement for 2D and 3D positioning. - SPI and GPIO communication with the host board through dedicated level translators. -***The [Arduino Renesas Portenta Boards core](https://github.com/arduino/ArduinoCore-renesas) is required to work with the Portenta C33 board that hosts the UWB Shield in this User Manual.*** +***The [Arduino Renesas Portenta Boards core](https://github.com/arduino/ArduinoCore-renesas) is required to work with the Portenta C33 board that hosts the UWB Shield.*** #### Arduino Stella Library -For two-way ranging experiments between the Portenta UWB Shield and Arduino Stella, you'll also need the [`StellaUWB` library](https://github.com/Truesense-it/StellaUWB). This library provides similar functionality but is specifically optimized for the DCU040 module in the Stella board. +If you plan to use the Portenta UWB Shield with an Arduino Stella for two-way ranging, you will also need the [`StellaUWB` library](https://github.com/Truesense-it/StellaUWB) for the Arduino Stella. This library is specifically designed for the DCU040 module used in the Stella board. -***The Arduino mbed OS Boards core is required to work with Stella's nRF52840 microcontroller.*** +***The [Arduino Mbed OS Stella Boards core](https://github.com/arduino/ArduinoCore-mbed) is required to work with the Arduino Stella's nRF52840 microcontroller.*** #### Bluetooth® Communication -For examples that use Bluetooth® Low Energy communication (like the Nearby Demo), you'll also need the [`ArduinoBLE` library](https://github.com/arduino/ArduinoBLE). This library enables Bluetooth Low Energy communication functionality for device discovery and initial connection setup before UWB ranging begins. +For examples that use Bluetooth® Low Energy communication, you'll also need the [`ArduinoBLE` library](https://github.com/arduino/ArduinoBLE). This library enables Bluetooth® Low Energy functionality for device discovery and initial connection setup before UWB ranging begins. -#### Installing the Libraries and Board Cores +#### Installing the Libraries -To install the required libraries: +To install the required libraries, follow these steps: -1. Navigate to `Tools > Manage libraries...` or click the **Library Manager** icon in the left tab of the Arduino IDE. -2. In the Library Manager tab, search for the library name (`PortentaUWBShield`, `StellaUWB`, or `ArduinoBLE`). -3. Click "Install" to install the latest version of each library. +**Step 1: Download the library ZIP file** -![Installing the board's library in the Arduino IDE](assets/user-manual-3.png) +- Visit the library's GitHub repository using the links provided above +- Click the green Code button +- Select Download ZIP from the dropdown menu +- Save the ZIP file to your computer + +![Library repository on GitHub](assets/library-repository.png) + +**Step 2: Install the library in Arduino IDE** + +- Open the Arduino IDE +- Navigate to `Sketch > Include Library > Add .ZIP Library...` +- Browse to the location where you saved the ZIP file +- Select the ZIP file and click Open +- The library will be automatically installed and ready to use + +![Library installation on the Arduino IDE](assets/library-installation.png) + +**Step 3: Verify the library installation** + +- Go to `Sketch > Include Library` +- Scroll down to see if the library appears in the `Contributed libraries` list +- You can also check `File > Examples` to see if example sketches from the library are available + +#### Installing the Board Cores To install the required board cores: -1. Navigate to `Tools > Board > Boards Manager...` -2. For the Portenta C33: Search for "Arduino Renesas Boards" and install the latest version. -3. For the Arduino Stella (if using two-way ranging examples): Search for `Arduino mbed OS Boards` and install the latest version. +- Navigate to `Tools > Board > Boards Manager...` +- For the Portenta C33, search for `Arduino Renesas Portenta Boards` and install the latest version +- For the Arduino Stella (if using two-way ranging examples), search for `Arduino Mbed OS Stella Boards` and install the latest version -![Installing the board's core in the Arduino IDE](assets/user-manual-4.png) +![Boards manager on the Arduino IDE](assets/boards-manager.png) -***Important note: Make sure to install both the appropriate library and board core for your specific hardware. The Portenta UWB Shield with Portenta C33 requires the `PortentaUWBShield` library and Arduino Renesas Boards core. For examples involving Arduino Stella, you'll need the `StellaUWB` library and Arduino mbed OS Boards core. For examples involving Bluetooth® Low Energy communication, both devices will need the `ArduinoBLE` library installed.*** +***Important note: Make sure to install both the appropriate library and board core for your specific hardware. The Portenta UWB Shield with Portenta C33 requires the `PortentaUWBShield` library and `Arduino Renesas Portenta Boards` core, while the Arduino Stella requires the `StellaUWB` library and `Arduino Mbed OS Stella Boards` core.*** ### Pinout @@ -259,26 +282,39 @@ The `Nearby World` example demonstrates the core functionality of UWB technology 1. **Bluetooth® Low Energy connection setup**: The Portenta UWB Shield establishes a Bluetooth Low Energy connection with a compatible smartphone app. 2. **Configuration exchange**: The Bluetooth Low Energy connection is used to exchange necessary UWB configuration parameters. 3. **UWB ranging**: Once configured, the actual UWB ranging session begins, providing precise distance measurements. -4. **Real-time feedback**: Distance data is continuously updated and can be viewed on the IDE's Serial Monitor and the smartphone app. +4. **Real-time updates**: The system continuously calculates and displays distance measurements between the devices. -This process demonstrates the working principle of many UWB applications, where Bluetooth Low Energy is used primarily for discovery and configuration, while UWB handles the precise ranging. +This process demonstrates the working principle of many UWB applications, where Bluetooth® Low Energy is used primarily for discovery and configuration, while UWB handles the precise ranging. #### Uploading the Sketch -First, connect the Portenta UWB Shield to the Portenta C33 as described in the [Connecting the Shield section](#connecting-the-shield). Now, connect the Portenta C33 to your computer using a USB-C cable, open the Arduino IDE and connect the board to it. +**Step 1: Verify Board Selection** -***If you are new to the Portenta C33, please refer to the board's [user manual](https://docs.arduino.cc/tutorials/portenta-c33/user-manual/) for more detailed information.*** +Before uploading any code to the Arduino Stella, ensure you have selected the correct board: + +1. Connect the Portenta C33 to your computer using a USB-C cable +2. Open the Arduino IDE +3. **Critical**: Navigate to `Tools > Board > Arduino Renesas Portenta Boards > Portenta C33` +4. Verify the correct port is selected in `Tools > Port` + +**Step 2: Upload the Sketch** Copy and paste the example sketch below into a new sketch in the Arduino IDE: -```arduino +```arduino /** - Nearby Demo Example for Portenta UWB Shield - Name: portenta_uwb_nearby.ino + Nearby World Example for the Portenta UWB Shield + Name: portenta_uwb_shield_nearby_world.ino Purpose: This sketch demonstrates how to use the Portenta UWB Shield - to measure distance between the shield and a UWB-enabled smartphone. + to measure distance between the board and a UWB-enabled smartphone. + + Compatible with: + - NXP Trimensions AR (iOS) + - Qorvo Nearby Interaction (iOS) + - NXP Android demo + - Truesense Android demo - @author Pierpaolo Lento from Truesense, modified by the Arduino Product Experience Team + @author Arduino Product Experience Team @version 1.0 15/04/25 */ @@ -286,7 +322,7 @@ Copy and paste the example sketch below into a new sketch in the Arduino IDE: #include #include -// Track the number of connected Bluetooth® Low Energy clients +// Track the number of connected Bluetooth Low Energy clients uint16_t numConnected = 0; /** @@ -296,57 +332,55 @@ uint16_t numConnected = 0; void rangingHandler(UWBRangingData &rangingData) { Serial.print("- GOT RANGING DATA - Type: "); Serial.println(rangingData.measureType()); - + // Nearby interaction uses Double-sided Two-way Ranging method - if(rangingData.measureType()==(uint8_t)uwb::MeasurementType::TWO_WAY) { + if(rangingData.measureType() == (uint8_t)uwb::MeasurementType::TWO_WAY) { // Get the TWR (Two-Way Ranging) measurements RangingMeasures twr = rangingData.twoWayRangingMeasure(); // Loop through all available measurements - for(int j=0; jImportant note for Android devices: If Developer Mode is currently enabled on your Android device, please ensure all radio-related options remain at their default settings. We recommend keeping Developer Mode disabled for optimal UWB functionality. If you previously enabled it, consider disabling it for the most stable device operation.*** +***__Important note for Android devices:__ If Developer Options is currently enabled on your Android device, please ensure all radio-related options remain at their default settings. We recommend keeping Developer Options disabled for optimal UWB functionality. If you previously enabled it, consider disabling it for the most stable device operation.*** Install one of these apps on your smartphone and follow these steps: -1. Open the app on your smartphone. -2. Look for a device named `Portenta UWB Shield` in the app's device list. -3. Connect to the device. -4. Once connected, the app will begin an UWB ranging session. -5. Move your phone closer to and further from the Portenta UWB Shield. +1. Open the app on your smartphone +2. Look for a device named `Portenta UWB Shield` in the app's device list +3. Connect to the device +4. Once connected, the app will initiate a UWB ranging session +5. Move your phone closer to and further from the Portenta UWB Shield + +The smartphone app shows the connection status and continuously updates the distance measurement as you move the phone. Both the app and the Serial Monitor display synchronized measurements in millimeters. -You should see the distance measurements updating in real-time both on your smartphone app and in the IDE's Serial Monitor. The distances are shown in millimeters, providing centimeter-level accuracy characteristic of the UWB technology. +You should see the distance measurements updating in real-time both on your smartphone app and in the IDE's Serial Monitor. The distances are shown in millimeters, providing centimeter-level accuracy characteristic of UWB technology. ## NearbyDemo Example ### About the NearbyDemo Example -The NearbyDemo example sketch is a fundamental demonstration of the Portenta UWB Shield's core capabilities. This example showcases how to implement a direct distance measurement system between a stationary UWB device (the Portenta UWB Shield, acting as an UWB anchor) and a mobile UWB device (the UWB-enabled smartphone, acting as an UWB tag). +***__Before you begin__: Ensure you have selected `Tools > Board > Arduino Renesas Portenta Boards > Portenta C33` in the Arduino IDE.*** -This example sketch demonstrates the following: +The `NearbyDemo` example sketch demonstrates how to implement distance measurement between the Portenta UWB Shield with the Portenta C33 board and UWB-enabled smartphones using Apple's Nearby Interaction protocol or compatible Android implementations. This example showcases how Bluetooth® Low Energy is used for initial device discovery and configuration exchange, while UWB handles the precise distance measurements. -- **Hybrid communication protocol:** It shows the integration of Bluetooth® Low Energy for device discovery and configuration with UWB for precise distance measurements, a common pattern in production UWB applications. -- **Standards compatibility:** The implementation is compatible with Apple's Nearby Interaction API and similar Android standards, demonstrating how the Arduino ecosystem can interact with mainstream consumer devices. -- **Foundation for advanced applications:**: The ranging capability demonstrated is the building block for more sophisticated applications such as indoor positioning systems, geofencing, secure access and proximity-based automation. +This example demonstrates the following: -Some of the real-life applications for this example sketch are the following: +- **Hybrid communication protocol**: Integration of Bluetooth® Low Energy for device discovery and configuration with UWB for precise distance measurements +- **Standards compatibility**: Compatible with Apple's Nearby Interaction API and Android UWB implementations +- **Power-efficient design**: UWB subsystem only activates when a client connects, conserving battery life +- **Multi-client support**: Can handle connections from multiple smartphones simultaneously -- **Industrial automation:** Creating safety zones around machinery that can detect when workers approach with centimeter precision. -- **Smart buildings:** Enabling location-aware services within facilities where GPS is unavailable. -- **Healthcare:** Tracking the movement of patients, staff and equipment with high accuracy. -- **Retail:** Implementing contactless payment systems with a higher degree of security than current NFC solutions. -- **Consumer electronics:** Enabling precise "Find My Device" features and spatial awareness between gadgets. +Real-world applications for this example include: -Now, let's take a closer look at the sketch: +- **Asset tracking**: Precisely locate Portenta UWB Shield-based devices attached to valuable items using smartphones +- **Smart building automation**: Implement room-level presence detection for environmental control +- **Healthcare**: Track movement of equipment and personnel with smartphone-based monitoring +- **Retail analytics**: Analyze customer movement patterns using their smartphones +- **Consumer item finding**: Create smartphone-compatible tags for locating misplaced items + +Here's the complete code for the `NearbyDemo` example sketch: ```arduino /** - Nearby Demo Example for Portenta UWB Shield - Name: portenta_uwb_nearby.ino + Nearby World Example for the Portenta UWB Shield + Name: portenta_uwb_shield_nearby_world.ino Purpose: This sketch demonstrates how to use the Portenta UWB Shield - to measure distance between the shield and an UWB-enabled smartphone. + to measure distance between the board and a UWB-enabled smartphone. + + Compatible with: + - NXP Trimensions AR (iOS) + - Qorvo Nearby Interaction (iOS) + - NXP Android demo + - Truesense Android demo - @author Pierpaolo Lento from Truesense, modified by the Arduino Product Experience Team + @author Arduino Product Experience Team @version 1.0 15/04/25 */ @@ -459,7 +504,7 @@ Now, let's take a closer look at the sketch: #include #include -// Track the number of connected BLE clients +// Track the number of connected Bluetooth Low Energy clients uint16_t numConnected = 0; /** @@ -469,57 +514,55 @@ uint16_t numConnected = 0; void rangingHandler(UWBRangingData &rangingData) { Serial.print("- GOT RANGING DATA - Type: "); Serial.println(rangingData.measureType()); - + // Nearby interaction uses Double-sided Two-way Ranging method - if(rangingData.measureType()==(uint8_t)uwb::MeasurementType::TWO_WAY) { + if(rangingData.measureType() == (uint8_t)uwb::MeasurementType::TWO_WAY) { // Get the TWR (Two-Way Ranging) measurements RangingMeasures twr = rangingData.twoWayRangingMeasure(); // Loop through all available measurements - for(int j=0; j @@ -578,37 +627,31 @@ The `NearbyDemo` code follows an event-driven architecture that employs callback uint16_t numConnected = 0; ``` -The code includes two essential libraries: +The example sketch uses two important libraries for its operation: - `ArduinoBLE`: Provides Bluetooth® Low Energy functionality for device discovery and initial connection. -- `PortentaUWBShield`: The core library that enables interaction with the UWB hardware on the Portenta UWB Shield. +- `PortentaUWBShield`: The core library that enables interaction with the onboard UWB module of the Portenta UWB Shield. + +The `numConnected` variable tracks how many Bluetooth® Low Energy clients are currently connected to the Portenta UWB Shield. -The `numConnected` variable tracks how many Bluetooth Low Energy clients are currently connected to the Portenta UWB Shield. +- **Ranging Data Handler** -1. **Ranging Data Handler** +The heart of the UWB functionality resides in the ranging callback: ```arduino void rangingHandler(UWBRangingData &rangingData) { - // ... - if(rangingData.measureType()==(uint8_t)uwb::MeasurementType::TWO_WAY) { + if(rangingData.measureType() == (uint8_t)uwb::MeasurementType::TWO_WAY) { RangingMeasures twr = rangingData.twoWayRangingMeasure(); - // ... - if(twr[j].status==0 && twr[j].distance!=0xFFFF) { - Serial.print("Distance: "); - Serial.println(twr[j].distance); - } + // Process measurements... } } ``` -This callback function is the heart of the UWB functionality: +This function processes incoming distance measurements, validates the data integrity, and outputs results to the IDE's Serial Monitor. The validation checks ensure only valid measurements are displayed (`status = 0` and `distance ≠ 0xFFFF`). -- It's triggered whenever new ranging data is received from the UWB subsystem. -- It checks if the measurement type is *Two-Way Ranging (TWR)*. -- It validates the measurement (`status = 0` indicates a valid measurement, while `distance = 0xFFFF` is a reserved value indicating an invalid distance). -- It extracts the distance measurements in millimeters and prints them to the IDE's Serial Monitor. +- **Connection Management** -1. **Connection Management** +The connection callbacks manage the UWB subsystem lifecycle efficiently: ```arduino void clientConnected(BLEDevice dev) { @@ -617,62 +660,41 @@ void clientConnected(BLEDevice dev) { } numConnected++; } - -void clientDisconnected(BLEDevice dev) { - UWBSession sess = UWBNearbySessionManager.find(dev); - sess.stop(); - numConnected--; - if(numConnected==0) { - UWB.end(); - } -} ``` -These functions handle Bluetooth® Low Energy connection events: +This power-saving approach ensures the UWB hardware only activates when needed, extending battery life in portable applications. -- `clientConnected` initializes the UWB subsystem when the first client connects. -- `clientDisconnected` shuts down the UWB subsystem when no clients are connected. - -This approach saves power by only running the shield's UWB hardware when it's needed. - -4. **Session Management** +- **Session Management** ```arduino void sessionStarted(BLEDevice dev) { - Serial.println("Session started!"); -} - -void sessionStopped(BLEDevice dev) { - Serial.println("Session stopped!"); + Serial.println("- Session started!"); } ``` -These callbacks track the UWB session state: +These functions provide feedback about the session lifecycle, helping developers understand the connection state during debugging. -- A session begins after the Bluetooth® Low Energy connection is established and the UWB configuration is exchanged. -- A session ends when the UWB communication is terminated, either by the client disconnecting or other factors. +- **Setup and Initialization** -5. **Setup and Initialization** +The setup function registers all callbacks and starts Bluetooth® Low Energy advertising: ```arduino void setup() { - // ... + // Register all callbacks UWB.registerRangingCallback(rangingHandler); UWBNearbySessionManager.onConnect(clientConnected); - UWBNearbySessionManager.onDisconnect(clientDisconnected); - UWBNearbySessionManager.onSessionStart(sessionStarted); - UWBNearbySessionManager.onSessionStop(sessionStopped); + // ... other callbacks - UWBNearbySessionManager.begin("Portenta UWB Shield"); + // Start advertising with device name + UWBNearbySessionManager.begin("TS_DCU150"); } ``` -The setup function: +The device name `TS_DCU150` appears in smartphone apps when scanning for available UWB devices. -- Registers all the callback functions with the UWB subsystem. -- Initializes the Bluetooth® Low Energy advertising with the name `Portenta UWB Shield`. This name is what will appear in the smartphone app's device list. +- **Main Loop** -1. **Main Loop** +The main loop maintains the Bluetooth® Low Energy connection: ```arduino void loop() { @@ -681,81 +703,135 @@ void loop() { } ``` -The main loop is quite simple: +The `poll()` function processes Bluetooth® Low Energy events while the actual UWB ranging occurs asynchronously through callbacks. -- It calls the `UWBNearbySessionManager.poll()` function to process Bluetooth® Low Energy events. -- The actual UWB ranging happens asynchronously through the callback system. - -This event-driven architecture allows the system to respond quickly to UWB and Bluetooth Low Energy events without blocking the main program flow. +### Testing with Smartphones + +To test this example with a UWB-enabled smartphone: + +1. Upload the sketch to your Portenta C33 +2. Open the IDE's Serial Monitor at 115200 baud +3. Install a compatible app on your smartphone: + +- **For iOS**: NXP® Trimensions AR or Qorvo Nearby Interaction +- **For Android**: Truesense or NXP® UWB demo apps + +4. Connect to the device named "Portenta UWB Shield" in the app +5. Move your phone to see distance measurements update in real-time + +The smartphone app displays the connection status and real-time distance to the Portenta UWB Shield. Once connected, both the app and the IDE's Serial Monitor will show synchronized distance measurements as you move the phone. The distance measurements are displayed in millimeters, providing centimeter-level accuracy. For example, a reading of "Distance: 80" indicates approximately 8 cm between devices. + +***__Important note__: If the connection fails or no measurements appear, verify that your smartphone has UWB enabled and that the Portenta C33 is powered on and running the sketch.*** ### Extending the Example Sketch -The `NearbyDemo` example sketch provides a great foundation that you can build upon for more complex projects. Some possible extensions of this sketch include the following: +The `NearbyDemo` example sketch provides a great foundation that you can build upon for more complex projects. Some possible extensions of this example sketch include the following: -- **Adding visual feedback:** Using LEDs or displays to indicate distance ranges. -- **Implementing proximity alerts:** Triggering actions when devices come within a certain distance. -- **Data logging:** Recording distance measurements for analysis and visualization. -- **Integrating with other sensors:** Combining UWB data with other environmental sensors for context-aware applications. +- **Visual feedback**: Add LED patterns based on distance thresholds +- **Audio alerts**: Implement buzzer feedback for proximity warnings +- **Motion detection**: Combine accelerometer data with ranging for activity monitoring +- **Data logging**: Record distance measurements for analysis +- **Custom device names**: Modify the advertising name for multiple device deployments -***Note: If you want to try this example yourself, please follow the same steps described in the [Nearby World Example](#nearby-world-example) section. The process for uploading the sketch and testing it with a smartphone is the same.*** +The event-driven architecture makes it easy to add features without disrupting the core ranging functionality. ## Two-Way Ranging Example ### About the Two-Way Ranging Example -The Two-Way Ranging example demonstrates direct UWB communication between two Arduino devices: the Portenta UWB Shield (acting as a Controlee/Responder) and the Arduino Stella (acting as a Controller/Initiator). This example showcases the fundamental distance measurement capabilities of UWB technology in a dedicated device-to-device setup without requiring external UWB-enabled consumer devices such as smartphones. +**📋 Hardware Setup Reminder:** -***Note: In UWB communication, the terms "Controller" and "Controlee" refer to specific roles within a ranging session. A __Controller__ (also called an Initiator) is the device that initiates and controls the ranging process, sending the initial signal and managing the timing of exchanges. A __Controlee__ (also called a Responder) is the device that responds to the Controller's signals. These terms are used interchangeably in UWB documentation: Controller/Initiator and Controlee/Responder refer to the same roles. In positioning systems, Controllers/Initiators often correspond to mobile "tags" while Controlees/Responders often serve as stationary "anchors".*** +- **For the Arduino Stella:** Select `Tools > Board > Arduino Mbed OS Stella Boards > Arduino Stella` on the Arduino IDE +- **For the Portenta C33 board and the UWB Shield:** Select `Tools > Board > Arduino Renesas Portenta Boards > Portenta C33` on the Arduino IDE + +The Two-Way Ranging example demonstrates direct UWB communication between two Arduino devices: the Arduino Stella (acting as a Controller/Initiator) and the Portenta UWB Shield (acting as a Controlee/Responder). This example showcases the fundamental distance measurement capabilities of UWB technology in a dedicated device-to-device setup without requiring external UWB-enabled consumer devices such as smartphones. + +***__Important note__: In UWB communication, the terms "Controller" and "Controlee" refer to specific roles within a ranging session. A __Controller__ (also called an Initiator) is the device that initiates and controls the ranging process, sending the initial signal and managing the timing of exchanges. A __Controlee__ (also called a Responder) is the device that responds to the Controller's signals. These terms are used interchangeably in UWB documentation: Controller/Initiator and Controlee/Responder refer to the same roles. In positioning systems, Controllers/Initiators often correspond to mobile "tags" while Controlees/Responders often serve as stationary "anchors".*** This example demonstrates the following: - **Direct device-to-device communication:** Unlike the `NearbyDemo` example, which requires a smartphone, this example establishes direct UWB communication between two UWB-enabled Arduino devices. - **Controller-Controlee architecture:** It shows how to configure one device as a Controller (initiator of the ranging) and another as a Controlee (responder). - **Double-Sided Two-Way Ranging (DS-TWR):** This technique provides higher accuracy in distance measurements by accounting for clock drift between devices. -- **Simple MAC addressing:** The implementation shows how to use short MAC addresses for device identification in UWB networks. +- **Visual feedback system**: Both devices provide LED feedback to indicate connection status and distance measurements. +- **Real-time distance visualization**: The Portenta C33 displays both raw measurements and smoothed moving average for analysis. Some of the real-life applications for this example include: -- **Multi-node positioning systems:** Creating networks of UWB nodes for advanced indoor positioning. -- **Robot navigation:** Enabling precise distance measurements between robots or between robots and fixed stations. -- **Asset tracking:** Building custom tracking solutions with multiple Arduino-based UWB anchors. -- **Proximity detection systems:** Creating safety systems that can detect precise distances between industrial equipment and personnel. -- **Interactive installations:** Enabling position-based interactive exhibits in museums or public spaces. +- **Multi-node positioning systems**: Creating networks of UWB nodes for advanced indoor positioning. +- **Robot navigation**: Enabling precise distance measurements between robots or between robots and fixed stations. +- **Asset tracking**: Building custom tracking solutions with multiple Arduino-based UWB anchors. +- **Proximity detection systems**: Creating safety systems that can detect precise distances between industrial equipment and personnel. +- **Access control systems**: Implementing secure entry systems based on precise proximity detection. +- **Interactive installations**: Enabling position-based interactive exhibits in museums or public spaces -Here's the code for the Portenta UWB Shield, which acts as the Controlee (Responder) in this Two-Way Ranging scenario: +Here's the code for the Arduino Stella, which acts as the Controller (Initiator) in this Two-Way Ranging scenario. + +**📋 Board Selection Check:** Ensure `Arduino Stella` is selected in the Arduino IDE before uploading this code. ```arduino /** - Two-Way Ranging Controlee Example for Portenta UWB Shield - Name: portenta_uwb_twr_controlee.ino - Purpose: This sketch configures the Portenta UWB Shield as a Controlee (Responder) - for Two-Way Ranging with an Arduino Stella configured as Controller. + Two-Way Ranging Controller Example for Arduino Stella + Name: stella_uwb_twr_controller.ino + Purpose: This sketch configures the Arduino Stella as a Controller (Initiator) + for Two-Way Ranging with a Portenta UWB Shield configured as Controlee. + The LED provides visual feedback based on measured distance. - @author Pierpaolo Lento from Truesense, modified by the Arduino Product Experience Team + @author Arduino Product Experience Team @version 1.0 15/04/25 */ // Include required UWB library -#include +#include + +// Pin definitions +#define LED_PIN p37 // Stella's built-in LED for status indication + +// Distance and timing parameters +#define MAX_DISTANCE 300 // Maximum distance to consider (cm) +#define MIN_BLINK_TIME 50 // Fastest blink rate (ms) +#define MAX_BLINK_TIME 1000 // Slowest blink rate (ms) +#define TIMEOUT_MS 2000 // Connection timeout (ms) + +// System state variables +unsigned long lastBlink = 0; +unsigned long lastMeasurement = 0; +bool ledState = false; +int currentBlinkInterval = MAX_BLINK_TIME; +long lastDistance = MAX_DISTANCE; /** Processes ranging data received from UWB communication. + Updates LED feedback based on measured distance. @param rangingData Reference to UWB ranging data object. */ void rangingHandler(UWBRangingData &rangingData) { - Serial.print("- GOT RANGING DATA - Type: "); - Serial.println(rangingData.measureType()); - if(rangingData.measureType()==(uint8_t)uwb::MeasurementType::TWO_WAY) { + if (rangingData.measureType() == (uint8_t)uwb::MeasurementType::TWO_WAY) { // Get the TWR (Two-Way Ranging) measurements - RangingMeasures twr=rangingData.twoWayRangingMeasure(); - + RangingMeasures twr = rangingData.twoWayRangingMeasure(); + // Loop through all available measurements - for(int j=0;j MAX_DISTANCE) { + currentBlinkInterval = MAX_BLINK_TIME; + } else { + // Map distance to blink interval + currentBlinkInterval = map(lastDistance, + 0, MAX_DISTANCE, + MIN_BLINK_TIME, MAX_BLINK_TIME); + } + + // Display the distance measurement in centimeters + Serial.print("- Distance (cm): "); + Serial.println(lastDistance); } } } @@ -765,106 +841,147 @@ void setup() { // Initialize serial communication at 115200 bits per second Serial.begin(115200); - #if defined(ARDUINO_PORTENTA_C33) - // Only the Portenta C33 has an RGB LED - pinMode(LEDR, OUTPUT); - digitalWrite(LEDR, LOW); - #endif + // Configure LED pin + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, HIGH); // Start with LED off - // Define MAC addresses for this device and the target - // This device (Controlee) has address 0x2222 - // Target device (Controller) has address 0x1111 - uint8_t devAddr[]={0x22,0x22}; - uint8_t destination[]={0x11,0x11}; - UWBMacAddress srcAddr(UWBMacAddress::Size::SHORT,devAddr); - UWBMacAddress dstAddr(UWBMacAddress::Size::SHORT,destination); + Serial.println("- Arduino Stella - Two-Way Ranging Controller started..."); + // Define MAC addresses for this device and the target + // This device (Controller) has address 0x2222 + // Target device (Controlee) has address 0x1111 + uint8_t devAddr[] = {0x22, 0x22}; + uint8_t destination[] = {0x11, 0x11}; + UWBMacAddress srcAddr(UWBMacAddress::Size::SHORT, devAddr); + UWBMacAddress dstAddr(UWBMacAddress::Size::SHORT, destination); + // Register the callback and start UWB UWB.registerRangingCallback(rangingHandler); UWB.begin(); - Serial.println("- Starting UWB ..."); - + + Serial.println("- Starting UWB..."); + // Wait until UWB stack is initialized - while(UWB.state()!=0) + while (UWB.state() != 0) { delay(10); + } - // Configure the UWB session - Serial.println("- Starting session ..."); - UWBSession session1; - session1.sessionID(0x11223344); - session1.sessionType(uwb::SessionType::RANGING); - - // Set application parameters - if(!session1.appParams.addOrUpdateParam(AppConfigId::NO_OF_CONTROLEES,1)) - Serial.println("- Could not add to app params!"); - if(!session1.appParams.destinationMacAddr(dstAddr)) - Serial.println("- Could not add to app params!"); - - // Apply default values for measurement repetition rate and antenna config - session1.applyDefaults(); - - // Configure ranging parameters - session1.rangingParams.deviceMacAddr(srcAddr); - session1.rangingParams.deviceRole(uwb::DeviceRole::RESPONDER); - session1.rangingParams.deviceType(uwb::DeviceType::Controlee); - session1.rangingParams.multiNodeMode(uwb::MultiNodeMode::UNICAST); - session1.rangingParams.rangingRoundUsage(uwb::RangingMethod::DS_TWR); - session1.rangingParams.scheduledMode(uwb::ScheduledMode::TIME_SCHEDULED); - - // Add the session to the manager and start it - UWBSessionManager.addSession(session1); - session1.init(); - session1.start(); + // Setup and start the UWB session using simplified UWBTracker + Serial.println("- Starting session..."); + UWBTracker myTracker(0x11223344, srcAddr, dstAddr); + UWBSessionManager.addSession(myTracker); + myTracker.init(); + myTracker.start(); + + // Signal initialization complete with triple LED flash + Serial.println("- Initialization complete!"); + for (int i = 0; i < 3; i++) { + digitalWrite(LED_PIN, LOW); // LED ON + delay(100); + digitalWrite(LED_PIN, HIGH); // LED OFF + delay(100); + } } void loop() { - // Toggle the LED to show the system is running - #if defined(ARDUINO_PORTENTA_C33) - // Only the Portenta C33 has an RGB LED - digitalWrite(LEDR, !digitalRead(LEDR)); - #else - Serial.println(millis()); - #endif - - // Small delay using FreeRTOS scheduler - vTaskDelay(configTICK_RATE_HZ/4); + unsigned long currentTime = millis(); + + // Handle LED feedback based on connection status and distance + if (currentTime - lastMeasurement > TIMEOUT_MS) { + // No connection detected - rapid blink warning + if (currentTime - lastBlink >= 100) { + lastBlink = currentTime; + ledState = !ledState; + digitalWrite(LED_PIN, ledState ? LOW : HIGH); + } + } else { + // Normal operation - distance-based blink rate + if (currentTime - lastBlink >= currentBlinkInterval) { + lastBlink = currentTime; + ledState = !ledState; + digitalWrite(LED_PIN, ledState ? LOW : HIGH); + } + } + + // Small delay to prevent CPU overload + delay(10); } ``` -Here's the code for the Arduino Stella, which acts as the Controller (Initiator) in this Two-Way Ranging scenario: +Here's the code for the Portenta UWB Shield, which acts as the Controlee (Responder) in this Two-Way Ranging scenario: + +**📋 Board Selection Check:** Ensure `Portenta C33` is selected in the Arduino IDE before uploading this code. ```arduino /** - Two-Way Ranging Controller Example for Arduino Stella - Name: stella_uwb_twr_controller.ino - Purpose: This sketch configures the Arduino Stella as a Controller (Initiator) - for Two-Way Ranging with a Portenta UWB Shield configured as Controlee. + Two-Way Ranging Controlee Example for Portenta UWB Shield + Name: portenta_uwb_twr_controlee.ino + Purpose: This sketch configures the Portenta UWB Shield as a Controlee (Responder) + for Two-Way Ranging with an Arduino Stella configured as Controller. + Includes distance visualization and moving average calculation. - @author Pierpaolo Lento from Truesense, modified by the Arduino Product Experience Team + @author Arduino Product Experience Team @version 1.0 15/04/25 */ // Include required UWB library -#include +#include + +// Moving average configuration +#define SAMPLES 10 // Number of samples for moving average +long distances[SAMPLES] = {0}; // Circular buffer for distance measurements +int sample_index = 0; // Current position in circular buffer + +// LED and status configuration +#define NEARBY_THRESHOLD 300 // Distance threshold for green LED (cm) +#define CONNECTION_TIMEOUT 2000 // Time before considering tag lost (ms) +#define LED_BLINK_INTERVAL 500 // Red LED blink interval (ms) + +// System state variables +unsigned long lastMeasurement = 0; +unsigned long lastLedBlink = 0; +bool ledState = false; /** Processes ranging data received from UWB communication. + Calculates moving average and provides visual feedback. @param rangingData Reference to UWB ranging data object. */ void rangingHandler(UWBRangingData &rangingData) { - Serial.print("- GOT RANGING DATA - Type: "); - Serial.println(rangingData.measureType()); - if(rangingData.measureType()==(uint8_t)uwb::MeasurementType::TWO_WAY) { + if (rangingData.measureType() == (uint8_t)uwb::MeasurementType::TWO_WAY) { // Get the TWR (Two-Way Ranging) measurements - RangingMeasures twr=rangingData.twoWayRangingMeasure(); - + RangingMeasures twr = rangingData.twoWayRangingMeasure(); + // Loop through all available measurements - for(int j=0;j CONNECTION_TIMEOUT) ? LOW : HIGH); + + // Blink red LED to show system is running + if (currentTime - lastLedBlink >= LED_BLINK_INTERVAL) { + lastLedBlink = currentTime; + ledState = !ledState; + digitalWrite(LEDR, ledState ? HIGH : LOW); + } + #else + // For boards without RGB LED, print heartbeat + if (currentTime - lastLedBlink >= LED_BLINK_INTERVAL) { + lastLedBlink = currentTime; + Serial.println("- System running..."); + } + #endif + + // Small delay to prevent CPU overload + delay(10); } ``` +***__Important note:__ Both devices must be programmed and powered on before you will see any distance measurements. The ranging session only begins when both the Controller (Arduino Stella) and Controlee (Portenta UWB Shield) are running their respective sketches.*** + +Once both devices are running, the Arduino Stella's Serial Monitor will display the distance measurements: + +![Arduino Stella Serial Monitor output showing distance measurements](assets/twr-stella-serial.png) + +Similarly, the Portenta UWB Shield's Serial Monitor will show both raw and averaged distance measurements: + +![Portenta UWB Shield Serial Monitor output showing distance and average measurements](assets/twr-portenta-serial.png) + +The output format from the Portenta C33 board is optimized for visualization, showing both the immediate distance readings and the calculated moving average. + ### Key Components of the Example Sketch -The Two-Way Ranging example demonstrates a more direct approach to UWB communication compared to the `NearbyDemo`. Let's analyze the key components of both example sketches: +The Two-Way Ranging example uses simplified helper classes (`UWBTracker` and `UWBRangingControlee`) that make device configuration easier while maintaining the same functionality. Let's analyze the key components: -1. **Libraries and MAC Addressing** +- **Libraries and MAC Addressing** Both devices use their respective UWB libraries: +- The Arduino Stella uses `StellaUWB.h` (for the DCU040 module) - The Portenta UWB Shield uses `PortentaUWBShield.h` (for the DCU150 module) -- The Stella uses `StellaUWB.h` (for the DCU040 module) -Both sketches configure MAC addresses for identification: +MAC address configuration remains critical for communication: ```arduino -// On Portenta UWB Shield -uint8_t devAddr[]={0x22,0x22}; -uint8_t destination[]={0x11,0x11}; +// On Arduino Stella (Controller) +uint8_t devAddr[] = {0x22, 0x22}; // This device +uint8_t destination[] = {0x11, 0x11}; // Target device -// On Arduino Stella -uint8_t devAddr[]={0x11,0x11}; -uint8_t destination[]={0x22,0x22}; +// On Portenta UWB Shield (Controlee) +uint8_t devAddr[] = {0x11, 0x11}; // This device +uint8_t destination[] = {0x22, 0x22}; // Target device ``` -***Important note: Notice how the MAC addresses are reversed between the two devices; this is critical for proper communication. In UWB communication, each device must know both its own address (`devAddr`) and the address of the device it is communicating with (`destination`). The Portenta UWB Shield identifies itself as `0x2222` and expects to communicate with `0x1111`, while the Arduino Stella identifies itself as `0x1111` and expects to communicate with `0x2222`. If these addresses don't match correctly, the devices won't be able to establish a ranging session. The prefix `0x` indicates these are hexadecimal values, which is a common notation in programming for representing memory addresses and identifiers.*** - -The MAC addresses used in this example are short (2-byte) addresses for simplicity, but UWB also supports extended (8-byte) addresses for larger networks where unique identification is required. For basic two-device setups, these short addresses are enough, but for multi-node positioning systems, you may want to use extended addressing to avoid conflicts. +***__Important note:__ The MAC addresses are reversed between the two devices. The Arduino Stella identifies itself as `0x2222`and expects to communicate with `0x1111`, while the Portenta UWB Shield identifies itself as `0x1111` and expects to communicate with `0x2222`. Both devices must use the same session ID (`0x11223344`) to establish communication.*** -2. **Setup and Initialization** +- **Simplified Session Setup** -The setup process for UWB communication differs between the two devices due to their different roles in the ranging session: +The new code uses helper classes that simplify the UWB session configuration: -**Portenta UWB Shield (Controlee/Responder):** +**Arduino Stella (Controller/Initiator):** ```arduino -// Configure the UWB session -UWBSession session1; -session1.sessionID(0x11223344); // Unique identifier for this session -session1.sessionType(uwb::SessionType::RANGING); - -// Set application parameters -if(!session1.appParams.addOrUpdateParam(AppConfigId::NO_OF_CONTROLEES,1)) - Serial.println("could not add to app params"); -if(!session1.appParams.destinationMacAddr(dstAddr)) - Serial.println("could not add to app params"); - -// Apply default values for measurement repetition rate and antenna config -session1.applyDefaults(); - -// Configure ranging parameters -session1.rangingParams.deviceMacAddr(srcAddr); -session1.rangingParams.deviceRole(uwb::DeviceRole::RESPONDER); -session1.rangingParams.deviceType(uwb::DeviceType::Controlee); -session1.rangingParams.multiNodeMode(uwb::MultiNodeMode::UNICAST); -session1.rangingParams.rangingRoundUsage(uwb::RangingMethod::DS_TWR); -session1.rangingParams.scheduledMode(uwb::ScheduledMode::TIME_SCHEDULED); - -// Add the session to the manager and start it -UWBSessionManager.addSession(session1); -session1.init(); -session1.start(); +UWBTracker myTracker(0x11223344, srcAddr, dstAddr); +UWBSessionManager.addSession(myTracker); +myTracker.init(); +myTracker.start(); ``` -**Arduino Stella (Controller/Initiator):** +**Portenta UWB Shield (Controlee/Responder):** ```arduino -// Configure the UWB session -UWBSession session1; -session1.sessionID(0x11223344); -session1.sessionType(UWBD_RANGING_SESSION); - -// Set application parameters -if(!session1.appParams.addOrUpdateParam(UWB_SET_APP_PARAM_VALUE(NO_OF_CONTROLEES,1))) - Serial.println("could not add to app params"); -if(!session1.appParams.destinationMacAddr(dstAddr)) - Serial.println("could not add to app params"); - -// Apply default values for measurement repetition rate and antenna config -session1.applyDefaults(); - -// Configure ranging parameters -session1.rangingParams.deviceMacAddr(srcAddr); -session1.rangingParams.deviceRole(kUWB_DeviceRole_Initiator); -session1.rangingParams.deviceType(kUWB_DeviceType_Controller); -session1.rangingParams.multiNodeMode(kUWB_MultiNodeMode_UniCast); -session1.rangingParams.rangingRoundUsage(kUWB_RangingRoundUsage_DS_TWR); -session1.rangingParams.scheduledMode(kUWB_ScheduledMode_TimeScheduled); - -// Add the session to the manager and start it -UWBSessionManager.addSession(session1); -session1.init(); -session1.start(); +UWBRangingControlee myControlee(0x11223344, srcAddr, dstAddr); +UWBSessionManager.addSession(myControlee); +myControlee.init(); +myControlee.start(); ``` -***Important note: The session configuration is more detailed for the Portenta UWB Shield because it explicitly defines all the ranging parameters. The Arduino Stella uses the simplified `UWBTracker` class, which automatically sets up the device as a Controller/Initiator with appropriate defaults. However, both devices must use the same session ID (`0x11223344` in this example) to communicate with each other. This session ID is a shared identifier for the ranging session between these devices.*** +These helper classes automatically configure the appropriate ranging parameters for their respective roles, making the setup process more straightforward. -Let's examine some of the key configuration parameters: +- **Enhanced Visual Feedback** -- `sessionID`: A unique 32-bit identifier (`0x11223344`) must match between devices in the same session. -- `deviceRole`: Defines whether the device is a Responder (Controlee) or Initiator (Controller). -- `multiNodeMode`: Set to UniCast for direct device-to-device communication. -- `rangingRoundUsage`: Set to DS_TWR (Double-Sided Two-Way Ranging) for the highest accuracy. -- `scheduledMode`: `TimeScheduled` mode allows the Controller to manage the timing of ranging exchanges. +Both devices in this example provide visual feedback to help users understand the system status and distance measurements at a glance. Each device uses its LED capabilities to indicate different operational states. -The initialization follows a specific sequence on both devices: +**Arduino Stella LED Behavior:** -- Register the ranging callback. -- Start the UWB subsystem. -- Configure the session parameters. -- Initialize the session (apply the configuration). -- Start the session (begin the ranging process). +The Arduino Stella uses its built-in LED to provide distance-based feedback through variable blink rates: -This process ensures both devices are properly configured before ranging begins, establishing a synchronized communication channel for precise distance measurements. +- **Close range (0 to 50 cm)**: Very fast blinking for immediate proximity alert +- **Medium range (50 to 150 cm)**: Medium blinking for moderate distances +- **Far range (150 to 300 cm)**: Slow blinking indicating increasing distance +- **Very far (>300 cm)**: Very slow blinking for maximum range +- **No connection**: Rapid blinking (100 ms intervals) as a warning signal +- **Startup**: Triple flash to indicate successful initialization -1. **Ranging Data Handler** +This variable blink rate creates an intuitive feedback system where users can gauge distance without looking at the serial output. -Both devices use nearly identical callback functions to process ranging data: +**Portenta C33 RGB LED Behavior:** -```arduino -void rangingHandler(UWBRangingData &rangingData) { - // ... - if(rangingData.measureType()==(uint8_t)uwb::MeasurementType::TWO_WAY) { - RangingMeasures twr=rangingData.twoWayRangingMeasure(); - for(int j=0;j Board > Arduino Renesas Portenta Boards > Portenta C33` +- Upload the Controlee/Responder sketch to the Portenta C33 board -You should see distance measurements on both Serial Monitors. Try moving the devices closer together and further apart to see the distance values change in real time. +2. **For the Arduino Stella:** -**Tips for optimal performance:** +- Select `Tools > Board > Arduino Mbed OS Stella Boards > Arduino Stella` +- Upload the Controller/Initiator sketch to the Arduino Stella -- For best results, position the devices so their antennas have a clear line-of-sight to each other. -- Keep the devices at least 20 cm away from large metal objects, as these can reflect UWB signals and interfere with measurements. -- Maintain the devices in a similar orientation (parallel to each other) for more consistent results, as antenna positioning affects signal strength. -- Start testing at distances between 0.5 to 3 meters, as extremely close or far distances might produce less reliable measurements. +***__Important note__: If you encounter compilation errors, verify that you have selected the correct board for each device before uploading.*** -The distances are reported in millimeters, providing centimeter-level accuracy. For example, a reading of `- Distance: 1234` indicates the devices are approximately 1.234 meters apart. +**Testing:** + +Once both devices are programmed, you can begin testing the ranging system: + +1. Open the IDE's Serial Monitor for the Portenta C33 board at 115200 baud +2. For best visualization, use `Tools > Serial Plotter` instead of the `Serial Monitor` +3. Move the devices closer and further apart +4. Observe the LED feedback on both devices + +***If you don't see any measurements, verify that both devices are powered on and running their respective sketches. The system requires both the Controller and Controlee to be active for ranging to occur.*** + +**Visual Feedback During Operation:** + +When the system is working correctly, both devices provide LED feedback: + +- **Arduino Stella LED:** Blinks faster as devices get closer (fast at 50 cm, slow at 300 cm) +- **Portenta C33 Red LED:** Blinks continuously to show system is active +- **Portenta C33 Blue LED:** OFF when connected, ON when connection is lost +- **Portenta C33 Green LED:** ON when Stella is within 300 cm, OFF when further away + +**Serial Output Visualization:** + +The Serial Plotter provides real-time visualization of the distance measurements: + +![Serial Plotter showing real-time distance measurements and moving average](assets/twr-serial-plotter.gif) + +The graph shows two lines: + +- **Blue line:** Raw distance measurements in centimeters +- **Red line:** Smoothed moving average for trend analysis + +Example readings: `Distance(cm):125,Average(cm):123` indicates the devices are approximately 1.25 meters apart. ### Extending the Two-Way Ranging Example -This basic example can be extended in several ways for more advanced applications: +This enhanced example provides a foundation for more advanced applications: + +- **Access control systems**: Use the distance threshold to trigger door locks or security systems +- **Safety zones**: Create multiple distance thresholds for industrial safety applications +- **Data logging**: Add SD card storage to record distance measurements over time +- **Multi-node networks**: Extend to support multiple tags communicating with one base station +- **Position calculation**: Combine multiple base stations for 2D/3D positioning through triangulation +- **Alert systems**: Add buzzer or additional LEDs for specific distance-based alerts -- **Adding multiple nodes:** Modify the example sketch to support multiple anchors or tags for triangulation and full positioning. -- **Integrating additional sensors:** Combine UWB ranging with IMU data for more robust positioning. -- **Implementing position calculation:** Add algorithms to convert distance measurements to coordinates. -- **Creating a visualization interface:** Develop a graphical interface to display the relative positions of devices. -- **Adding data communication:** Use UWB not just for ranging but also for data exchange between devices. +The visual feedback and data processing capabilities demonstrated in this example can be adapted to various real-world applications requiring precise distance measurement and proximity detection. ## Support