Software/Arduino Core/Connectivity

Bluetooth LE

Bluetooth Low Energy on the MAYA-W476 module through the BluetoothMaya beacon library or the ArduinoBLE library.

intermediate2 min read

The MAYA-W476 module on the OV5640-W and TFT-W carriers has a Bluetooth LE controller reached over USART6 using the HCI H4 protocol. Two libraries use it. BluetoothMaya advertises a non-connectable beacon. ArduinoBLE, the standard Arduino library with an Ohm Lab HCI transport added, provides connectable GATT services. Only one of the two may be used in a sketch.

Module bring-up

The Bluetooth controller runs on the same firmware image the WiFi bring-up loads. Starting WiFi is what loads it, so every Bluetooth sketch starts an access point first, even when the network is not used:

cpp
#include <NeuroN6.h>
#include <MayaW476.h>
#include <ArduinoBLE.h>

void setup() {
  NeuroN6_StreamUsbOnlyStart();                   // USB console, no camera
  MayaW476.beginAP("NeuroN6-Setup", password);    // loads the module firmware
  BLE.begin();
}

The two libraries do not share the module's bring-up, so the WiFi access point in a Bluetooth-only sketch exists only to load the firmware. It is still a real network, and the examples derive its password from the chip ID rather than using a fixed value.

Beacon

cpp
#include <BluetoothMaya.h>

void setup() {
  NeuroN6_StreamUsbOnlyStart();
  MayaW476.beginAP("NeuroN6-Setup", password);
  BluetoothMaya.begin("Neuro-N6", /*bringUpModule=*/false);
}

void loop() {
  delay(3000);
  BluetoothMaya.printDiag();
}

The board appears as "Neuro-N6" in a phone scanner such as nRF Connect. The beacon is not connectable.

Connectable peripheral

The BlePeripheral example, under File > Examples > BluetoothMaya, uses ArduinoBLE to advertise a service with two characteristics: one a client can write, one the board increments each second and notifies.

cpp
BLEService                   svc      ("19B10000-E8F2-537E-4F6C-D104768A1214");
BLEByteCharacteristic        ctrlChar ("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
BLEUnsignedIntCharacteristic countChar("19B10002-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);

void setup() {
  NeuroN6_StreamUsbOnlyStart();
  MayaW476.beginAP("NeuroN6-Setup", password);
  BLE.begin();

  BLE.setLocalName("Neuro-N6");
  BLE.setDeviceName("Neuro-N6");
  BLE.setAdvertisedService(svc);
  svc.addCharacteristic(ctrlChar);
  svc.addCharacteristic(countChar);
  BLE.addService(svc);
  BLE.advertise();
}

void loop() {
  BLEDevice central = BLE.central();
  if (central) {
    while (central.connected()) {
      if (ctrlChar.written()) { /* handle the byte */ }
      countChar.writeValue(millis() / 1000);
    }
  }
}

The ArduinoBLE API is unchanged from other platforms. Its documentation applies.

Bluetooth alongside video

The WiFiAccessPoint example runs an access point, a BLE peripheral, the camera, the panel and the speaker together. Two adjustments are required when Bluetooth shares loop() with Vision.run():

  • BLE.poll() is used rather than a blocking wait on central.connected(), which would freeze the video for the duration of a connection.
  • The connection interval and supervision timeout are widened, because the sketch services Bluetooth once per video frame, less often than a phone expects. The example uses an interval of 30 to 100 ms and a timeout of 6 seconds, and polls for a 5 ms window per frame so that a connecting phone's initial requests are answered promptly.

Both radios share one 2.4 GHz antenna and alternate between WiFi and Bluetooth.

Licence

ArduinoBLE is LGPL-2.1. Statically linking it into a firmware image carries a relinking obligation. See Licensing.