Portenta C33 + UWB Shield BLE Communication with React Native App Sep 18, 2025 | 16 minutes read 8 Likes React Native BLE IntegrationThis project demonstrates wireless communication between the Arduino Portenta C33 microcontroller equipped with a UWB (Ultra-Wideband) Shield and a mobile application built with React Native. The Portenta C33 acts as a Bluetooth Low Energy (BLE) peripheral that advertises a custom UWB service. Through this service, a smartphone can connect, send commands, and receive responses in real time.On the hardware side, the Portenta C33 manages BLE communication using the ArduinoBLE library and prepares for data exchange with the UWB shield over SPI (Serial Peripheral Interface). The device exposes two main characteristics:Command Characteristic (Write-only): The phone sends commands such as turning the LED on/off or requesting UWB data.Data Characteristic (Notify): The device responds with status updates or measurement results, which are instantly sent back to the phone.On the software side, the React Native application uses the react-native-ble-plx library to scan for nearby BLE devices, establish a connection with the Portenta C33, and interact with the UWB service. The app provides a user-friendly interface for scanning, connecting, sending commands, and monitoring device responses.This project highlights how modern microcontrollers and mobile applications can work together to create low-power, wireless, and interactive systems. While the current implementation demonstrates basic functionality with LED control and dummy UWB responses, it provides a foundation to integrate real UWB distance measurement data for applications such as indoor positioning, navigation, and smart IoT systems. Hardware and Software Requirements Hardware Requirements :Portenta UWB Shield Portenta C33 USB-C cable Software Requirements :Arduino IDE 2.0+Portenta UWB Shield library (for the Portenta UWB Shield)Arduino Renesas Portenta Boards core (for the Portenta C33) System OverviewThe system consists of two main components: the embedded hardware platform and the mobile application interface. Embedded Hardware (Portenta C33 + UWB Shield):The Portenta C33 microcontroller acts as the central controller. It communicates with the UWB shield over the SPI bus and simultaneously provides a Bluetooth Low Energy (BLE) interface to external devices. Using the ArduinoBLE library, the microcontroller advertises a custom UWB BLE service with two characteristics—command and data. Commands received from the phone (e.g., LED control, UWB request) are processed by the Portenta, and the results are sent back through the data characteristic as BLE notifications. Mobile Application (React Native App)A cross-platform React Native application enables the user to interact with the hardware. The app uses the react-native-ble-plx library to scan for nearby BLE devices, connect to the Portenta C33, and exchange data. It allows users to send commands such as turning the LED on/off or requesting UWB measurements, and it displays real-time responses received from the microcontroller. Communication Flow: The user interacts with the React Native app.The app sends a command to the Portenta C33 over BLE.The Portenta C33 processes the command and either controls the LED or communicates with the UWB shield to gather data.The result is then sent back as a BLE notification to the mobile app, where it is displayed to the user.This architecture demonstrates a complete IoT pipeline, where embedded hardware with wireless communication integrates seamlessly with a mobile application to provide a user-friendly, interactive, and extensible system. System Architecture : The system consists of the following elements The React Native mobile app connects via Bluetooth Low Energy (BLE).The Portenta C33 handles BLE services and communicates with the UWB shield via SPI.Commands flow from the app → Portenta → UWB shield, and responses flow back. Hardware SetupThe hardware setup for this project consists of the Arduino Portenta C33, the Portenta UWB Shield, and connectivity with a computer and mobile phone. This setup enables the microcontroller to communicate with the shield over SPI and with the smartphone via Bluetooth Low Energy (BLE).1. Required ComponentsArduino Portenta C33 boardPortenta UWB Shield (compatible with Portenta family boards)USB-C cable (for powering and programming the C33)Computer with Arduino IDE installedSmartphone (Android/iOS) with Bluetooth enabled and the React Native app installed 2. AssemblyAlign the Boards Place the Portenta UWB Shield directly below the Portenta C33.Ensure that the high-density connectors of the UWB Shield and Portenta C33 are perfectly aligned.Gently press the boards together until the connectors are fully seated.Make sure the boards are flush and there is no gap between them.Plug a USB-C cable into the Portenta C33.Connect the other end to your computer for power and programming Powering the SystemDuring development, the Portenta C33 is powered directly through the USB-C connection. For standalone use, you can power the device with: An external power source via the Portenta’s power pins, orA battery pack compatible with the Portenta family. ConnectionsPortenta C33 ↔ UWB Shield → Communication through SPI bus. Portenta C33 ↔ Smartphone → Wireless link using the built-in BLE module (no extra wiring required). Portenta C33 ↔ Computer → USB-C for programming and serial debugging. Verification StepsConnect the hardware to your PC. Open Arduino IDE and select Portenta C33 as the target board. Upload the provided BLE sketch. Open the Serial Monitor at 115200 baud → You should see the message:BLE advertising as Portenta-UWB 5. On your smartphone:Open the React Native app.Start scanning for devices.You should see Portenta-UWB in the device list.Connect to it and test with commands (e.g., LED:ON, LED:OFF) Arduino Code ` #include #include #include #define UWB_SERVICE_UUID "12345678-1234-5678-1234-56789abcdef0" #define CMD_CHAR_UUID "12345678-1234-5678-1234-56789abcdef1" #define DATA_CHAR_UUID "12345678-1234-5678-1234-56789abcdef2" BLEService uwbService(UWB_SERVICE_UUID); BLECharacteristic cmdChar(CMD_CHAR_UUID, BLEWrite, 64); BLECharacteristic dataChar(DATA_CHAR_UUID, BLENotify, 64); void onCmdWritten(BLEDevice central, BLECharacteristic characteristic) { String cmd = ""; int len = characteristic.valueLength(); for (int i = 0; i < len; i++) { cmd += (char)characteristic.value()[i]; } Serial.print("CMD from phone: "); Serial.println(cmd); if (cmd == "LED:ON") { digitalWrite(LED_BUILTIN, HIGH); dataChar.writeValue("OK:LED_ON"); } else if (cmd == "LED:OFF") { digitalWrite(LED_BUILTIN, LOW); dataChar.writeValue("OK:LED_OFF"); } else if (cmd.startsWith("UWB:")) { String resp = "UWB_RESP:dummy"; dataChar.writeValue(resp.c_str()); } else { dataChar.writeValue("ERR:UNKNOWN_CMD"); } } void setup() { Serial.begin(115200); while (!Serial); pinMode(LED_BUILTIN, OUTPUT); if (!BLE.begin()) { Serial.println("Failed to init BLE!"); while (1); } BLE.setLocalName("Portenta-UWB"); BLE.setAdvertisedService(uwbService); uwbService.addCharacteristic(cmdChar); uwbService.addCharacteristic(dataChar); BLE.addService(uwbService); cmdChar.setEventHandler(BLEWritten, onCmdWritten); BLE.advertise(); Serial.println("BLE advertising as Portenta-UWB"); SPI.begin(); } void loop() { BLE.poll(); } ` import React, { useEffect, useState } from "react"; import { View, Text, Button, FlatList, TouchableOpacity, PermissionsAndroid, Platform, } from "react-native"; import { BleManager } from "react-native-ble-plx"; import { Buffer } from "buffer"; const manager = new BleManager(); const UWB_SERVICE_UUID = "12345678-1234-5678-1234-56789abcdef0"; const CMD_CHAR_UUID = "12345678-1234-5678-1234-56789abcdef1"; const DATA_CHAR_UUID = "12345678-1234-5678-1234-56789abcdef2"; export default function App() { const [devices, setDevices] = useState([]); const [connectedDevice, setConnectedDevice] = useState(null); const startScan = async () => { setDevices([]); if (Platform.OS === "android" && Platform.Version >= 23) { await PermissionsAndroid.requestMultiple([ PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN, PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT, ]); } manager.startDeviceScan(null, null, (error, device) => { if (error) { console.log("Scan error:", error); return; } if (device && device.name) { setDevices((prev) => { if (!prev.find((d) => d.id === device.id)) { return [...prev, device]; } return prev; }); } }); setTimeout(() => manager.stopDeviceScan(), 10000); }; useEffect(() => { startScan(); return () => manager.destroy(); }, []); const connectToDevice = async (device) => { try { const connected = await manager.connectToDevice(device.id); await connected.discoverAllServicesAndCharacteristics(); setConnectedDevice(connected); console.log(" Connected to:", connected.name); connected.monitorCharacteristicForService( UWB_SERVICE_UUID, DATA_CHAR_UUID, (error, char) => { if (error) { console.log("Notify error:", error); return; } if (char?.value) { const msg = Buffer.from(char.value, "base64").toString("utf-8"); console.log(" From board:", msg); } } ); } catch (error) { console.log("Connection error:", error); } }; const sendCommand = async (cmd) => { if (!connectedDevice) return; try { await connectedDevice.writeCharacteristicWithResponseForService( UWB_SERVICE_UUID, CMD_CHAR_UUID, Buffer.from(cmd, "utf-8").toString("base64") ); console.log(" Sent:", cmd); } catch (error) { console.log("Write error:", error); } }; return ( Nearby BLE Devices item.id} renderItem={({ item }) => ( connectToDevice(item)}> {item.name || "Unnamed"} ({item.id}) )} /> {connectedDevice && ( Connected to {connectedDevice.name} sendCommand("LED:ON")} /> sendCommand("LED:OFF")} /> sendCommand("UWB:REQ")} /> )} ); } Portenta UWB BLE project: Connect hardware & mobile Learn MoreThe Way ForwardPerformance optimization in Magento 2 is essential for a fast, smooth shopping experience. By identifying bottlenecks and applying development enhancements like caching, code optimization, and database tuning, you can drastically improve site speed. Regular monitoring and best practices keep your store running efficiently. A well-optimized Magento store boosts user satisfaction, SEO, and sales. Free Consultation Hardware and Software RequirementsMobile Application (React Native App)React Native BLE IntegrationLopa DasSep 18 2025With over 13 years of experience, Lopa Das is a seasoned professional at iFlair Web Technologies Pvt Ltd, specializing in web and mobile app development. Her technical expertise spans across Laravel, PHP, CodeIgniter, CakePHP, React, Vue.js, Nuxt.js, iOS, Android, Flutter, and React Native. Known for her exceptional skills in team handling, client communication, presales, and risk analysis, Lopa ensures seamless project execution from start to finish. Her proficiency in Laravel CRM, Next.js, and mobile app development makes her a valuable asset in delivering robust, scalable solutions.You may also like React Native + Arduino Portenta C33 UWB: Detecting and Listing Nearby Devices Using Mobile Data Read More Sep 18 2025 Solving Performance Issues in React Apps with Advanced Rendering Techniques Read More Sep 05 2025 Unlocking the Power of n8n Automation Workflows Read More Aug 27 2025 React Native: Location Integration & Club Filtering Read More Aug 04 2025 How to Create a Design and Deploy with React and Strapi Headless CMS Read More Jun 17 2025 Understanding PropTypes in React Read More Jun 16 2025