BLE Week 3
Assignment: BLE p5 web app

I used the LED example (Examples » ArduinoBLE » Peripheral » LED + BLE-Week3-LED) as a starting point for this week's assignment. The example allows the user to turn a LED on and off from the p5 app.

I modified the code from the LED example to create a strobe light. The user drags a slider to control how fast the strobe light is:

Demo video:

Code:

Modified Arduino code:

Code
// while the central is still connected to peripheral:
while (central.connected()) {
  updateValue();
  delay(value * 100);
  analogWrite(A0, 255);

  updateValue();
  delay(value * 100);
  analogWrite(A0, 0);
}

p5 sketch:

Code
// The serviceUuid must match the serviceUuid of the device you would like to connect
const serviceUuid = "19b10000-e8f2-537e-4f6c-d104768a1214";
let myCharacteristic;
let input;
let slider;
let myBLE;

function setup() {
  myBLE = new p5ble();

  // Create a 'Connect' button
  const connectButton = createButton("Connect");
  connectButton.mousePressed(connectToBle);

  createButton("Strobe speed:");
  createButton("0ms");

  // Create slider
  slider = createSlider(0, 10, 5);
  slider.input(writeToBle);

  createButton("1000ms");
}

function connectToBle() {
  // Connect to a device by passing the service UUID
  myBLE.connect(serviceUuid, gotCharacteristics);
}

function gotCharacteristics(error, characteristics) {
  if (error) console.log("error: ", error);
  console.log("characteristics: ", characteristics);
  // Set the first characteristic as myCharacteristic
  myCharacteristic = characteristics[0];
}

function writeToBle() {
  const inputValue = slider.value();
  // Write the value of the input to the myCharacteristic
  myBLE.write(myCharacteristic, inputValue);
}

Thoughts:

  • The example code, and thus this app, doesn't handle any of the edge cases related to connectivity. Specifically, there should be UI states for before a device is connected and before the device's characteristics have been retrieved.
  • Dragging the slider results in the error: "DOMException: GATT operation already in progress." This error can be mostly prevented by debouncing the slider handler (sending on the trailing edge, to make sure the latest value is sent) and by checking whether the previous BLE command has finished before sending a new one.

Some helpful feedback I received after presenting this:

  • Adding a timeout can prevent the characteristic from being modified too often.
  • Is there a way to detect whether there's GATT in progress? Yes, in the Web Bluetooth API, a callback is fired when the GATT operation completes.