Geert Roumen
Published © CC BY-NC-SA

Connect the micro:bit using Bluetooth to P5.js to Play Pong

This project will show how to connect a micro:bit to P5, to use it as a game-controller, or use your laptop or Android phone as a remote.

IntermediateProtip1 hour3,921
Connect the micro:bit using Bluetooth to P5.js to Play Pong

Things used in this project

Hardware components

micro:bit BBC:Microbit
×1
USB-A to Micro-USB Cable
USB-A to Micro-USB Cable
×1

Software apps and online services

P5 Sketch
Makecode

Story

Read more

Custom parts and enclosures

For this code to work there is no additional hardware necessary

But if you want, feel free to build an awesome steering wheel, balance board or some other cool way to make it cooler.

Code

bluetoothConnection.js

JavaScript
This code is to connect a micro:bit using BLE UART to p5.
/*
This code is to connect a micro:bit using BLE UART to p5.

API:

microBitConnect()

This function should be called by an user event, like  mousePressed() https://p5js.org/reference/#/p5/mousePressed
or KeyPressed() https://p5js.org/reference/#/p5/keyPressed

microBitDisconnect()

This function disconnects the microbit from the device running the p5 sketch.

microBitWriteString("string")

Writes a text to the microbit

microBitReceivedMessage(message)

This is a function that is called when the microBit sends a message to the device running P5


Example sketch.js

//This code sends the current key pressed to the microbit, and shows the last message of the microbit in the middle of the screen
function setup() {
  createCanvas(400, 400);
}
lastMessage = "";
function draw() {
  background(220);
  text(lastMessage,200,200);
}

function mousePressed(){
  microBitConnect()
}

function keyPressed(){
  microBitWriteString(key + "\n")
}
function microBitReceivedMessage(message){
  lastMessage = message;
}

*/

// https://lancaster-university.github.io/microbit-docs/resources/bluetooth/bluetooth_profile.html
// An implementation of Nordic Semicondutor's UART/Serial Port Emulation over Bluetooth low energy
const UART_SERVICE_UUID = "6e400001-b5a3-f393-e0a9-e50e24dcca9e";

// Allows the micro:bit to transmit a byte array
const UART_TX_CHARACTERISTIC_UUID = "6e400002-b5a3-f393-e0a9-e50e24dcca9e";

// Allows a connected client to send a byte array
const UART_RX_CHARACTERISTIC_UUID = "6e400003-b5a3-f393-e0a9-e50e24dcca9e";

let uBitDevice;
let rxCharacteristic;

async function microBitWriteString(string){
  if (!rxCharacteristic) {
    return;
  }

  try {
    let encoder = new TextEncoder();
    rxCharacteristic.writeValue(encoder.encode(string));
  } catch (error) {
    console.log(error);
  }
}

async function microBitConnect() {
  try {
    console.log("Requesting Bluetooth Device...");
    uBitDevice = await navigator.bluetooth.requestDevice({
      filters: [{ namePrefix: "BBC micro:bit" }],
      optionalServices: [UART_SERVICE_UUID]
    });

    console.log("Connecting to GATT Server...");
    const server = await uBitDevice.gatt.connect();

    console.log("Getting Service...");
    const service = await server.getPrimaryService(UART_SERVICE_UUID);

    console.log("Getting Characteristics...");
    const txCharacteristic = await service.getCharacteristic(
      UART_TX_CHARACTERISTIC_UUID
    );
    txCharacteristic.startNotifications();
    txCharacteristic.addEventListener(
      "characteristicvaluechanged",
      onTxCharacteristicValueChanged
    );
    rxCharacteristic = await service.getCharacteristic(
      UART_RX_CHARACTERISTIC_UUID
    );
  } catch (error) {
    console.log(error);
  }
}

function microBitDisconnect() {
  if (!uBitDevice) {
    return;
  }

  if (uBitDevice.gatt.connected) {
    uBitDevice.gatt.disconnect();
    console.log("Disconnected");
  }
}


function onTxCharacteristicValueChanged(event) {
  let receivedData = [];
  for (var i = 0; i < event.target.value.byteLength; i++) {
    receivedData[i] = event.target.value.getUint8(i);
  }
  const receivedString = String.fromCharCode.apply(null, receivedData);
  if (typeof microBitReceivedMessage !== 'undefined'){
    microBitReceivedMessage(receivedString);
  }else{
    console.log("microBitReceivedMessage is not defined")
  }
  console.log(receivedString);
}

Credits

Geert Roumen

Geert Roumen

6 projects • 10 followers
I’m a maker and interaction designer, bridging the digital and physical world. and make prototypes and do research in a playful way.
Thanks to Anna Wasson.

Comments