Bluetooth on Arduino Nano 33 BLE Sense

Hi,

My question might be simple and maybe it has been answered in other threads, but my limited knowledge in regards to arduino, bluetooth, programming and electronics is making it hard for me to understand the level of discussion occuring in the other threads.

I’m studying a semester of Interaction Design where our latest module has been revolving around prototyping. My group and I have created a wearable device with LEDs attached to an Arduino Nano 33 BLE Sense.

We’ve programmed a sktech in Processing that is connected to the Arduino, so that the LED’s are controlled through the Processing-console.

To really get a feel of the wearable’s mobility we were talking about using a power-bank as power-source for the Arduino, and then instead of having the Arduino connected to the laptop through usb-cable having it connected through Bluetooth.

I was hoping that it would be as easy to connect the Arduino via bluetooth to the laptop, as pairing a speaker to a smartphone. You just power on the bluetooth and then search for bluetooth-units on the laptop and find the Arduino. Is this the case and I’m just missing a step somewhere? Because I can’t find the Arduino when searching for Bluetooth-devices.

Or do I need to dive deep into the BLE-world of Arduino and program every data-transfer?

Below you can find a rough schematic.
Index for schematic:

  1. Laptop that is running Processing-code that controlls the LED through serial communication.
  2. USB-cable between the Arduino Nano 33 BLE sense and the Laptop.
  3. The Arduino Nano 33 BLE sense
  4. The LED
  5. The power-bank that is now powering the LED.
  6. Bluetooth-symbol indicating that it has replaced the USB-Cable

you do… there are apps you can use that will let you manually read/write characteristics, that might be good enough for what you wanted to do

how complex was the Processing UI?

1 Like

Thanks for your reply! What apps do you suggest I exlpore? :slight_smile:

It’s not that complex. It 8 different images put as a background. The images are made in Adobe XD and we programmed it so it has the same “flow”. You go forward, backwards, skip images and stuff like that depending on where on the image you click. And then on certain clicks we trigger a Write-command that the Arduino reads.

Here are two extracts:

void draw() {
  background (0);
  image(slides[slide], 0, 0);

  if (slide == 0 && 
    mouseX > 50  && 
    mouseY > 300 &&  
    mouseX < 350  && 
    mouseY < 370 ) {
      slide = 2;  
      myPort.write('2');
   // the yellow mode-button

I mainly use BLE Scanner from bluepixel technologies on iOS. There are a quite a few others but the BLE Scanner is simple and clean. So, I start with that and then try a few others from time to time.

With BLE you do not need pairing. BLE apps can simply connect to devices. Pairing is an optional security feature in BLE and not supported by the ArduinoBLE library.

I suspect your processing code generates Serial writes. BLE works slightly different. You create services and characteristics. They can be like variables of a specific type. This makes the application code quite simple. No need to decode any serial messages.

If you post your Arduino code, we can provide some more specific tips on how to progress.

1 Like

Hi!

Sorry for a late reply! I had a 7 day-study-run with saturday dedicated for running tests-sessions on our prototype, and needed a day off yesterday.

And also thank you Klaus_K and J-M-L for your time!! :smiley:

Have I understood it correctly that then BLE Scanner would be the “peripheral device” and the computer and arduino be “central devices”?

You are correct in you suspicion, we’re using serial write!

The arduino currently only recieves serial communication from Processing (when a certain image appears on the UI in Processing a certain light shows on our Neopixel-ring connected to the arduino). We are working on adding communication back to processing from the Arduino with if the proximity-sensor is getting below a specific treshhold both the light in the LED-ring should change and an a specific image in Processing UI should appear.

Here’s our current “work-in-progress”-code. Sorry if it is messy!

#include <ArduinoBLE.h>
#include <Arduino_APDS9960.h>
#include <Adafruit_NeoPixel.h>
#define PIN        3
#define NUMPIXELS 12

Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
long timer = 0;
int i = 11;

void setup() {
  Serial.begin(9600);
  pixels.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
  pixels.setBrightness(10);
  timer = millis();
  if (!APDS.begin()) {
    Serial.println("Error initializing APDS9960 sensor!");
    //if (!BLE.begin()) {
    //Serial.println("starting BLE failed!");   -- Bluetooth-stuff

    //while (1);
    //}

  }
}

  void loop() {
    pixels.clear(); // cleans up the LED ring

    if (Serial.available() >= 0); //wait for signal
    {
      char mood = Serial.read();
      if (mood == '0')
      {
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(i, pixels.Color(255, 255, 255));
          pixels.show();//display leds
        }
      }
      if (mood == '1')
      {
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(i, pixels.Color(255, 0, 0));
          pixels.show();//display leds
        }
      }
      if (mood == '2')
      {
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(i, pixels.Color(255, 255, 0));
          pixels.show();//display leds
        }
      }
      if (mood == '3')
      {
        for (int i = 0; i < NUMPIXELS; i++)
          pixels.setPixelColor(i, pixels.Color(0, 255, 0));
        pixels.show();//display leds
      }

      if (mood == '4')
      {
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(i, pixels.Color(0, 0, 255));
          pixels.show();
          // if (millis() - timer > 1000) {
          // pixels.clear();
          //}
          //timer = millis();
        }
      }

      if (mood == '5')
      {
        for (int i = 0; i < NUMPIXELS; i++) {
          pixels.setPixelColor(i, pixels.Color(255, 255, 255));
          pixels.show();//display leds
        }
      }

      if (APDS.proximityAvailable()) {
        // read the proximity
        // - 0   => close
        // - 255 => far
        // - -1  => error
         int proximity = APDS.readProximity();

        if ((mood == '4') && (proximity < 50)) {
          Serial.println("9");
          delay(1000);

        }
      }
    }
  }

No, the smartphone will be the central/client and the Arduino will be the server/peripheral. In BLE the peripheral is the device that holds the data and usually is the small device running on a coin cell battery. The smartphone is the client, reading and writing data on the server.

I wrote an example you can use as a basis for your project. You can control it over BLE and Serial. I left prints and comments to show how the example works. You can use pixelTask to implement your Neopixel stuff. I only used the LEDs on the board for testing.

#include <ArduinoBLE.h>

//----------------------------------------------------------------------------------------------------------------------
// BLE UUIDs
//----------------------------------------------------------------------------------------------------------------------

#define BLE_UUID_PIXEL_SERVICE          "01430000-9743-472D-E4F5-3D58CDD61275"
#define BLE_UUID_PIXEL_MOOD             "01430001-9743-472D-E4F5-3D58CDD61275"

//----------------------------------------------------------------------------------------------------------------------
// BLE
//----------------------------------------------------------------------------------------------------------------------

#define BLE_DEVICE_NAME                 "Arduino Nano 33 BLE"
#define BLE_LOCAL_NAME                  "Arduino Nano 33 BLE"

BLEService pixelService( BLE_UUID_PIXEL_SERVICE );
BLEByteCharacteristic moodCharacteristic( BLE_UUID_PIXEL_MOOD, BLEWrite );

//----------------------------------------------------------------------------------------------------------------------
// I/O and App
//----------------------------------------------------------------------------------------------------------------------

#define BLE_LED_PIN                     LED_BUILTIN
#define PIXEL_LED_PIN                   LED_PWR

#define MOOD_NONE                       -1
int8_t mood = MOOD_NONE;

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

  pinMode( BLE_LED_PIN, OUTPUT );
  pinMode( PIXEL_LED_PIN, OUTPUT );
  digitalWrite( PIXEL_LED_PIN, LOW );

  if ( !setupBleMode() )
  {
    Serial.println( "Failed to initialize BLE!" );
    while ( 1 );
  }
  else
  {
    Serial.println( "BLE initialized. Waiting for clients to connect." );
  }
}

void loop()
{
  serialTask();
  bleTask();
  pixelTask();
}

void serialTask()
{
  if ( !Serial.available() )
  {
    return;
  }  
  char c = Serial.read();
  if ( c == '\n' || c == '\r' )
  {
    return; // Ignore CR and NL if send by Serial Monitor
  }
  mood = c;
}

void pixelTask()
{
  switch ( mood )
  {
    case 0:
    case '0':
      digitalWrite( PIXEL_LED_PIN, LOW );
      break;
    case 1:
    case '1':
      digitalWrite( PIXEL_LED_PIN, HIGH );
      break;
    case MOOD_NONE:
      break;
    default:
      Serial.print( "Unknown mood: " );
      Serial.println( mood, HEX );
      break;
  }
  mood = MOOD_NONE;
}

bool setupBleMode()
{
  if ( !BLE.begin() )
  {
    return false;
  }
  
  // set advertised local name and service UUID
  BLE.setDeviceName( BLE_DEVICE_NAME );
  BLE.setLocalName( BLE_LOCAL_NAME );
  BLE.setAdvertisedService( pixelService );

  // add characteristics
  pixelService.addCharacteristic( moodCharacteristic );

  // add service
  BLE.addService( pixelService );

  // set the initial value for the characeristics
  // not needed all characteristics are write only

  // set BLE event handlers
  BLE.setEventHandler( BLEConnected, blePeripheralConnectHandler );
  BLE.setEventHandler( BLEDisconnected, blePeripheralDisconnectHandler );

  // set service and characteristic specific event handlers
  moodCharacteristic.setEventHandler( BLEWritten, bleCharacteristicWrittenHandler );

  // start advertising
  BLE.advertise();

  return true;
}


void bleTask()
{
  #define BLE_UPDATE_INTERVAL 10
  static uint32_t previousMillis = 0;
  
  uint32_t currentMillis = millis();
  if ( currentMillis - previousMillis >= BLE_UPDATE_INTERVAL )
  {
    previousMillis = currentMillis;
    BLE.poll();
  }
}  


void bleCharacteristicWrittenHandler( BLEDevice central, BLECharacteristic bleCharacteristic )
{
  Serial.print( "BLE characteristic written. UUID: " );
  Serial.print( bleCharacteristic.uuid() );

  if ( bleCharacteristic.uuid() == (const char*) BLE_UUID_PIXEL_MOOD )
  {
    bleCharacteristic.readValue( mood );
    Serial.print( " Value: " );
    Serial.println( mood, HEX );
  }
}


void blePeripheralConnectHandler( BLEDevice central )
{
  digitalWrite( BLE_LED_PIN, HIGH );
  Serial.print( "Connected to central: " );
  Serial.println( central.address() );
}


void blePeripheralDisconnectHandler( BLEDevice central )
{
  digitalWrite( BLE_LED_PIN, LOW );
  Serial.print( "Disconnected from central: " );
  Serial.println( central.address() );
}

You can add more characteristics e.g. for Neopixel Brightness.
The switch case accepts character ‘0’ and value 0 because most BLE apps are happy to send numeric values.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.