Project Overview & Difficulty Rating

Difficulty: Intermediate | Time: 45 Minutes | Target Board: Arduino Nano 33 BLE Sense Rev2 (ABX00069)

The Arduino Nano 33 BLE Sense is a densely packed development board built around the Nordic Semiconductor nRF52840 SoC. Unlike standard microcontrollers that require external breakout boards for sensing, the Sense variant integrates a 9-axis IMU (LSM9DS1), a BME680 environmental sensor, an APDS9960 gesture/proximity sensor, and an HTS221 temperature/humidity sensor directly on the internal I2C bus. This project focuses on the Rev2 variant (ABX00069), which updated the onboard sensor suite and power management compared to the original Rev1 (ABX00031).

In this build, we will configure the board to act as a Bluetooth Low Energy (BLE) peripheral. It will poll the onboard LSM9DS1 accelerometer, calculate the magnitude of the acceleration vector, and broadcast it to a connected central device (like a smartphone running nRF Connect) while simultaneously exposing the external I2C pins for future expansion.

Hardware Bill of Materials & Pin Mapping

Before writing firmware, verify your hardware matches the exact variants below. Using a clone board with a different nRF52840 module footprint often results in radio initialization failures.

Component Exact Variant / Part Number Notes
Microcontroller Arduino Nano 33 BLE Sense Rev2 (ABX00069) Ensure it says "Rev2" on the silkscreen. Rev1 uses different sensor libraries.
Power Source 3.7V LiPo Battery (500mAh - 1000mAh) Must have a JST-PH 2.0mm connector. Do not exceed 4.2V fully charged.
Testing Tool Smartphone with nRF Connect for Mobile Required to sniff BLE advertising packets and verify characteristic reads.
Wiring Silicone jumper wires (26 AWG) Used only if breaking out external I2C or adding a LiPo voltage divider.

Pin Mapping Table

While the onboard sensors communicate via an internal I2C bus that is not directly exposed to the user pins, the external headers provide access to the primary I2C bus, power, and analog inputs. Below is the mapping for external connections.

Board Pin Function External Connection Target Voltage Level
A4 (SDA) External I2C Data OLED Display / External Sensor SDA 3.3V
A5 (SCL) External I2C Clock OLED Display / External Sensor SCL 3.3V
A0 Analog Input LiPo Voltage Divider (100k/100k) 0 - 3.3V
3V3 Regulated Output External 3.3V peripherals (Max 200mA) 3.3V
GND Common Ground All external peripherals 0V
Pro-Tip: The onboard 3.3V regulator on the Rev2 can supply roughly 200mA. If you are adding an external I2C OLED display (which typically draws 20-30mA) and a high-draw external sensor, monitor your total current budget. The nRF52840 itself can peak at 15mA during BLE transmission bursts.

Complete Firmware: BLE IMU & Environmental Logger

The following C++ code targets the Arduino Nano 33 BLE Sense Rev2. It requires the ArduinoBLE and Arduino_LSM9DS1 libraries, both available via the Arduino Library Manager. The code includes explicit error handling for sensor and radio initialization failures, preventing silent hangs in the field.


#include <ArduinoBLE.h>
#include <Arduino_LSM9DS1.h>

// --- Pin Definitions ---
#define LED_PIN LED_BUILTIN
#define EXT_SDA_PIN A4
#define EXT_SCL_PIN A5

// --- BLE UUIDs (Custom 128-bit) ---
const char* bleServiceUUID = "19B10000-E8F2-537E-4F6C-D104768A1214";
const char* bleCharUUID = "19B10001-E8F2-537E-4F6C-D104768A1214";

BLEService imuService(bleServiceUUID);
BLEFloatCharacteristic imuChar(bleCharUUID, BLERead | BLENotify);

void setup() {
  Serial.begin(115200);
  // Wait for serial monitor to connect (optional, remove for battery operation)
  while (!Serial) { delay(10); }
  
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);

  // 1. Initialize IMU
  if (!IMU.begin()) {
    Serial.println("Failed to initialize IMU!");
    // Blink rapidly to indicate IMU hardware fault
    while (1) {
      digitalWrite(LED_PIN, HIGH); delay(50);
      digitalWrite(LED_PIN, LOW); delay(50);
    }
  }
  Serial.println("IMU initialized successfully.");

  // 2. Initialize BLE Radio
  if (!BLE.begin()) {
    Serial.println("Failed to initialize BLE!");
    // Solid ON to indicate Radio fault
    digitalWrite(LED_PIN, HIGH);
    while (1) { delay(1000); }
  }
  Serial.println("BLE radio initialized.");

  // 3. Configure BLE Advertising
  BLE.setLocalName("Nano33_Sense_IMU");
  BLE.setAdvertisedService(imuService);
  imuService.addCharacteristic(imuChar);
  BLE.addService(imuService);
  
  // Set initial value
  imuChar.writeValue(0.0f);
  
  BLE.advertise();
  Serial.println("Advertising started. Waiting for central connection...");
}

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

  if (central) {
    Serial.print("Connected to central: ");
    Serial.println(central.address());
    digitalWrite(LED_PIN, HIGH);

    while (central.connected()) {
      if (IMU.accelerationAvailable()) {
        float x, y, z;
        IMU.readAcceleration(x, y, z);
        
        // Calculate magnitude of acceleration vector
        float magnitude = sqrt((x * x) + (y * y) + (z * z));
        
        // Transmit over BLE
        imuChar.writeValue(magnitude);
        
        // Optional: Print to serial for debugging
        // Serial.print("Accel Mag: "); Serial.println(magnitude);
      }
      // Polling rate control (50Hz)
      delay(20); 
    }

    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
    digitalWrite(LED_PIN, LOW);
  }
}

Debugging: First Three Things to Check When It Fails

Embedded BLE projects frequently fail silently or throw cryptic serial errors. If your board fails to connect or halts during setup, follow this ranked decision path based on the exact serial output.

Error 1: Failed to initialize IMU!

This exact string prints when the IMU.begin() function returns false, meaning the microcontroller cannot communicate with the LSM9DS1 chip on the internal I2C bus.

  1. Wrong Board Selected in IDE: This is the most common cause. If you compile for the "Arduino Nano 33 IoT" or the original "Nano 33 BLE" (non-Sense), the compiler maps the I2C pins incorrectly. Ensure Tools > Board is set specifically to Arduino Nano 33 BLE Sense.
  2. Missing or Outdated Library: Verify you have the Arduino_LSM9DS1 library installed via the Library Manager. Do not use generic LSM9DS1 libraries from third parties, as they do not account for the specific I2C pull-up resistor configuration on the Arduino PCB.
  3. I2C Bus Lockup (Brownout): If the board experienced a voltage drop during a previous write cycle, the LSM9DS1 might be stuck holding the SDA line low. Fix this by completely removing power (unplug USB and battery) for 30 seconds to drain the capacitors, then reconnect.

Error 2: Failed to initialize BLE!

This occurs when BLE.begin() fails. The nRF52840 radio peripheral is rejecting the initialization command.

  1. 3.3V Regulator Brownout: The nRF52840 requires current spikes of up to 15mA during radio initialization and transmission. If you are powering the board from an underpowered USB hub or a damaged cable, the voltage will sag below 3.0V, causing the radio to shut down. Plug directly into a wall-rated 2A USB adapter.
  2. Conflicting Radio Libraries: If you have included WiFiNINA.h or other networking libraries in your sketch (even if commented out in logic but included at the top), they can conflict with the SoftDevice memory allocation. Remove unused includes.
  3. Hardware Fault: If the board is a clone, the nRF52840 module might lack the proper SoftDevice bootloader flashed at the factory. This requires a J-Link debugger to re-flash the Nordic bootloader.

Error 3: Device Not Found in nRF Connect App

The serial monitor says "Advertising started", but your phone cannot see "Nano33_Sense_IMU".

  1. Phone Bluetooth Cache: Mobile OS Bluetooth stacks aggressively cache MAC addresses. Toggle your phone's Bluetooth off and on, or clear the nRF Connect app cache.
  2. Advertising Timeout: By default, some BLE stacks stop advertising after 30 seconds to save power. Ensure you are scanning within the first half-minute of booting the board.

Extending and Simplifying the Build

Depending on your end application, you may need to scale this project up for production or down for a quick prototype.

How to Simplify the Build

If you only need a basic BLE beacon for presence detection and do not care about sensor data, strip out the Arduino_LSM9DS1 library entirely. Remove the IMU initialization and the loop() polling logic. Rely solely on BLE.advertise() with a custom manufacturer data payload. This reduces the firmware footprint by roughly 40KB and drops the active current draw from ~8mA to ~2mA, extending a 500mAh LiPo battery life from 2 days to over 10 days.

How to Extend the Build (Edge ML)

To evolve this from a simple data logger into an Edge Machine Learning device, integrate Edge Impulse. 1. Collect 3-axis raw accelerometer data (x, y, z) instead of the calculated magnitude. 2. Use the Edge Impulse CLI to sample gesture data (e.g., swipes, taps, circles). 3. Train a lightweight neural network or Dynamic Time Warping (DTW) model. 4. Export the trained model as an Arduino C++ library and replace the IMU.readAcceleration() block with the classifier's inference function. The nRF52840's Cortex-M4F DSP instructions handle 100Hz inference comfortably within a 10ms window.

Arduino Nano 33 BLE Sense FAQ

What is the exact difference between the Arduino Nano 33 BLE and the Nano 33 BLE Sense?

The standard Nano 33 BLE (ABX00030) only includes the nRF52840 microcontroller and an LSM9DS1 9-axis IMU. The Nano 33 BLE Sense adds a suite of environmental and proximity sensors: a BME680 (gas, pressure, humidity, temp), an HTS221 (temp/humidity), an APDS9960 (gesture, color, proximity), and an MP34DT05 digital microphone. If your project does not require environmental or audio sensing, the standard BLE board is cheaper and draws slightly less quiescent current.

Can I power the Arduino Nano 33 BLE Sense Rev2 directly with a 5V LiPo battery?

No. The onboard LiPo charging circuit and voltage regulation are designed strictly for 3.7V nominal (4.2V fully charged) single-cell lithium polymer batteries. Applying 5V directly to the battery pins will bypass the regulator and instantly destroy the nRF52840 SoC and the onboard sensors, which are strictly 3.3V tolerant. If you must use a 5V pack, wire it into the VIN pin, which routes through the onboard AP2112K-3.3 voltage regulator.

Why does the onboard nRF52840 get warm during continuous BLE advertising?

The nRF52840 integrates both the ARM Cortex-M4 processor and the 2.4GHz radio transceiver on a single silicon die. During continuous BLE advertising or high-throughput data streaming, the radio draws peak currents of 10-15mA. Because the chip is housed in a compact QFN package with limited thermal mass, the surface temperature can rise to 40-45°C (104-113°F) above ambient. This is within the Nordic Semiconductor operational specifications and is not indicative of a fault, provided you have adequate airflow.

How do I recover the Nano 33 BLE Sense if the bootloader is bricked?

If a failed firmware upload corrupts the bootloader, the board will no longer show up as a COM port. First, try the "double-tap" reset: quickly press the physical reset button on the board twice. This forces the microcontroller into the bootloader's ROM serial mode, indicated by the onboard LED pulsing slowly. If the double-tap fails, you will need an external SWD programmer (like a Segger J-Link) connected to the exposed SWDIO and SWCLK test pads on the bottom of the PCB to re-flash the official Arduino bootloader.