If you are trying to build an edge-AI or IoT telemetry project and your code throws initialization errors, you are likely hitting the silicon swap. The Arduino Nano 33 BLE Sense Rev2 is a 3.3V logic, nRF52840-powered sensor hub, but it is not pin-for-pin or IC-for-IC identical to the original 2019 release. Due to global supply chain shifts, Arduino updated the Rev2 with new Bosch and Renesas sensors. This guide targets the Rev2 variant specifically, providing a complete BLE telemetry build, exact pin mappings, and the debugging framework you need when the new sensors refuse to talk.

The Hardware: What Changed in the Rev2?

Before writing a single line of firmware, you must verify which board variant is on your bench. The original Nano 33 BLE Sense used an STMicroelectronics LSM9DS1 for motion and an HTS221 for environmental data. The Rev2 completely changed the motion and environmental ICs. If you copy-paste a tutorial from 2021, your I2C bus scans will fail because the I2C addresses and register maps are entirely different.

Table 1: Arduino Nano 33 BLE Sense Rev1 vs Rev2 Sensor Specifications
Sensor Domain Rev1 IC (Legacy) Rev2 IC (Current) Rev2 I2C Address Rev2 Library Requirement
IMU (Accel/Gyro) LSM9DS1 BMI270 (Bosch) 0x68 (SDO low) Arduino_BMI270_BMM150
Magnetometer LSM9DS1 (Integrated) BMM150 (Bosch) 0x10 Arduino_BMI270_BMM150
Temp / Humidity HTS221 HS3003 (Renesas) 0x44 Arduino_HS300x
Barometric Pressure LPS22HB LPS22HB (ST) 0x5C Arduino_LPS22HB
Proximity / Gesture APDS9960 APDS9960 (Broadcom) 0x39 Arduino_APDS9960

Parts List & Pin Mapping

This build creates a low-power BLE telemetry node that reads the BMI270 IMU and HS3003 environmental sensor, packaging the data into a custom BLE GATT service. Because the nRF52840 handles BLE natively in its SoftDevice stack, we do not need an external radio module.

Exact Parts List

  • Microcontroller: Arduino Nano 33 BLE Sense Rev2 (Official SKU: ABX00069). Current retail: ~$48.00 USD.
  • Power: 3.7V LiPo battery (e.g., Adafruit 4237, 500mAh) with JST-PH 2.0 connector, OR a standard Micro-USB data cable.
  • Debugging (Optional but recommended): Segger J-Link EDU Mini or Raspberry Pi running OpenOCD for SWD recovery.
  • Headers: 2x 15-pin male headers (included in the box, requires soldering).

nRF52840 Pin Mapping & Internal Routing

The Nano 33 BLE Sense routes several sensors to internal I2C buses. Understanding which physical nRF52840 pins map to the Arduino IDE labels is critical when you need to debug bus lockups.

Table 2: Critical Pin Mapping for Nano 33 BLE Sense Rev2
Arduino Pin Label nRF52840 Port/Pin Function / Internal Routing Notes & Constraints
A4 (SDA) P1.01 External I2C Data 3.3V logic only. No internal pull-ups enabled by default.
A5 (SCL) P1.00 External I2C Clock 3.3V logic only. Max capacitance ~400pF.
Internal I2C P0.14 (SDA) / P0.15 (SCL) Onboard Sensors (BMI270, HS3003, etc.) Not broken out to headers. Accessed via Wire1 or core abstractions.
VDD_ENV P1.14 (Internal) Sensor Power Enable Must be HIGH to power onboard sensors. Handled by pinMode(PIN_ENABLE_SENSORS_3V3, OUTPUT).
SWDIO / SWCLK P0.09 / P0.10 Serial Wire Debug (Test pads on bottom) Required to unbrick the nRF52840 if the bootloader is corrupted.

Step-by-Step Build & Firmware

Follow these steps to flash the telemetry firmware. This code targets the Rev2 hardware specifically, utilizing the BMI270 and HS3003.

  1. Install the Core: Open the Arduino IDE Boards Manager and install the Arduino Mbed OS Nano Boards core (version 4.0.8 or newer).
  2. Install Libraries: Via the Library Manager, install ArduinoBLE, Arduino_BMI270_BMM150, and Arduino_HS300x.
  3. Solder Headers: Solder the 15-pin headers. Bench tip: Use flux-cored 63/37 Sn/Pb or SAC305 lead-free at 350°C. The castellated edge pads on the nRF52840 module wick heat quickly; dwell for 2-3 seconds per pin to ensure a fillet.
  4. Flash the Firmware: Select Arduino Nano 33 BLE as the board (the IDE core covers both Sense and Rev2 variants). Upload the code below.
Difficulty Rating: Intermediate. Time: 45 minutes. Prerequisite: Familiarity with BLE GATT services and I2C bus concepts.
#include <ArduinoBLE.h>
#include <Arduino_BMI270_BMM150.h>
#include <Arduino_HS300x.h>

// Pin definitions and BLE UUIDs
#define BLE_DEVICE_NAME "Nano33Rev2_Telemetry"
#define BLE_SERVICE_UUID "19B10000-E8F2-537E-4F6C-D104768A1214"
#define BLE_CHAR_UUID "19B10001-E8F2-537E-4F6C-D104768A1214"

// Internal power enable pin for Rev2 sensors
#define PIN_ENABLE_SENSORS_3V3 (32u)

BLEService telemetryService(BLE_SERVICE_UUID);
BLECharacteristic telemetryChar(BLE_CHAR_UUID, BLERead | BLENotify, 24);

void setup() {
  Serial.begin(115200);
  while (!Serial);

  // Enable power to onboard sensors
  pinMode(PIN_ENABLE_SENSORS_3V3, OUTPUT);
  digitalWrite(PIN_ENABLE_SENSORS_3V3, HIGH);
  delay(50); // Allow sensor rails to stabilize

  if (!BLE.begin()) {
    Serial.println("Fatal: BLE stack failed to initialize.");
    while (1);
  }

  if (!IMU.begin()) {
    Serial.println("Failed to initialize BMI270 IMU!");
    while (1);
  }

  if (!HS300x.begin()) {
    Serial.println("Failed to initialize HS3003 Temp/Humidity!");
    while (1);
  }

  BLE.setLocalName(BLE_DEVICE_NAME);
  BLE.setAdvertisedService(telemetryService);
  telemetryService.addCharacteristic(telemetryChar);
  BLE.addService(telemetryService);
  BLE.advertise();
  
  Serial.println("BLE Telemetry Node Active. Waiting for central...");
}

void loop() {
  BLEDevice central = BLE.central();

  if (central && central.connected()) {
    float x, y, z;
    float temp, humidity;
    
    if (IMU.accelerationAvailable() && IMU.readAcceleration(x, y, z)) {
      temp = HS300x.readTemperature();
      humidity = HS300x.readHumidity();
      
      // Pack data into a byte array for BLE transmission
      uint8_t payload[24];
      memcpy(&payload[0], &x, 4);
      memcpy(&payload[4], &y, 4);
      memcpy(&payload[8], &z, 4);
      memcpy(&payload[12], &temp, 4);
      memcpy(&payload[16], &humidity, 4);
      
      telemetryChar.writeValue(payload, 24);
      Serial.printf("Sent: AccX=%.2f, Temp=%.2fC\n", x, temp);
    }
  }
  delay(100); // Throttle to ~10Hz to save battery
}

Debugging: When the Sensors Fail to Initialize

The nRF52840 is a powerful chip, but its internal power management and I2C routing can trap beginners. If your serial monitor halts, follow this decision path.

The First 3 Things to Check When It Fails:
  1. VDD_ENV Power Rail: Did you include digitalWrite(PIN_ENABLE_SENSORS_3V3, HIGH)? The Rev2 sensors are physically unpowered at boot to save microamps. If this pin is LOW, the I2C bus will read all 0xFF or 0x00.
  2. Board Selection: Ensure you selected Arduino Nano 33 BLE and not the Nano ESP32 or Nano RP2040 Connect in the IDE dropdown. The Mbed OS core handles the internal I2C routing differently than standard AVR cores.
  3. Library Version Conflict: Check that you do not have the legacy Arduino_LSM9DS1 library actively included or conflicting in your sketch folder.

Exact Error String: Failed to initialize BMI270 IMU!

If your serial monitor prints this exact string and halts, the microcontroller successfully booted, BLE initialized, but the I2C handshake with the Bosch BMI270 failed. Here are the ranked causes:

  1. Cause 1: Using the Legacy Library (Most Common). You included <Arduino_LSM9DS1.h> instead of <Arduino_BMI270_BMM150.h>. The LSM9DS1 library looks for I2C address 0x6B. The BMI270 lives at 0x68. Fix: Swap the include and update the initialization call to IMU.begin().
  2. Cause 2: I2C Bus Lockup from External Devices. If you wired external 5V I2C devices to A4/A5 without level shifters, you may have back-powered the nRF52840 I2C pins, locking the internal bus state machine. Fix: Disconnect all external wires from A4/A5. Power cycle the board by removing USB and battery.
  3. Cause 3: Corrupted nRF52840 Bootloader / SoftDevice. If you previously flashed bare Zephyr or custom Nordic SDK firmware via SWD, you may have overwritten the Arduino bootloader or the Mbed OS flash partitions. The I2C peripheral drivers will fail to map. Fix: Use a Segger J-Link on the bottom SWD test pads to flash the Arduino Nano 33 BLE bootloader recovery image.

Scaling the Build: Extend or Simplify

Once your BLE telemetry is stable, you will likely want to adapt the node for a specific deployment. Here is how to modify the architecture without breaking the Rev2 hardware constraints.

How to Extend the Build

  • Add SPI SD Card Logging: The nRF52840 has ample flash, but for long-term logging, use the SPI headers. Map CS to D10, MOSI to D11, MISO to D12, and SCK to D13. Warning: The SPI bus shares internal routing with the APDS9960 gesture sensor. If you use high-speed SPI logging (>8MHz), you may see I2C ghosting on the gesture sensor. Drop SPI speed to 4MHz if both are active.
  • Implement Edge Impulse AI: The Rev2's BMI270 supports high-frequency sampling (up to 6.4kHz). You can feed this directly into an Edge Impulse model for predictive maintenance or gesture recognition, running inference locally on the Cortex-M4F DSP before sending only the classification result over BLE.

How to Simplify the Build

  • Drop BLE for Serial-Only Debugging: If you are just benchmarking sensor noise floors, strip out the ArduinoBLE library entirely. The BLE SoftDevice consumes roughly 1.5mA to 3mA of background current. Disabling it and running purely on USB Serial drops the quiescent board draw to under 8mA, making it easier to measure raw sensor power consumption with a bench multimeter.
  • Use Only the Environmental Sensor: If motion data is unnecessary, remove the BMI270 library. The HS3003 is highly accurate (±2% RH, ±0.2°C) and requires significantly less initialization overhead, freeing up flash space for larger data buffers.