Bluetooth peripheral mode
What this example shows
Use Inkplate 7SPECTRA as a display you control from a phone over Bluetooth LE. The sketch starts a Bluetooth LE service with a serial-style receive and transmit characteristic. Text the phone writes is passed to the run() function in the example's Peripheral.h, which draws on the display.
Pair the Inkplate with your phone in the phone's Bluetooth settings, then open a Bluetooth serial terminal app (the sketch's comments name Serial Bluetooth Terminal; a similar app works too) and pick the Inkplate from its device list. A command starts with # and ends with *. After the drawing commands, send #L(1)* to show the result on the screen; the sketch's comments say it equals display->display().
This example also uses the Bluetooth LE library (BLEDevice, BLEServer, BLEUtils, BLE2902) from arduino-esp32, which is not part of the Inkplate library and comes with the ESP32 board package.
Example code
The listing is the sketch file. The run() function and the command parser live in Peripheral.h, in the same example folder; open the complete example below to read it.
#include "Inkplate.h"
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include "Peripheral.h"
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E" // For data coming IN to Inkplate
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E" // For data coming OUT from Inkplate
BLEServer *pServer = NULL; // Pointer to BLEServer
BLECharacteristic *pTxCharacteristic; // Pointer to TX characteristic
bool deviceConnected = false; // Is client currently connected
bool oldDeviceConnected = false; // Store the previous connection
Inkplate inkplate;
#define BUFFER_SIZE 1000
char commandBuffer[BUFFER_SIZE + 1];
class MyServerCallbacks : public BLEServerCallbacks
{
void onConnect(BLEServer *pServer) {
deviceConnected = true;
Serial.println("Device connected");
};
void onDisconnect(BLEServer *pServer) {
deviceConnected = false;
Serial.println("Device disconnected");
}
};
class MyCallbacks : public BLECharacteristicCallbacks
{
void onWrite(BLECharacteristic *pCharacteristic) {
String rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0)
{
size_t len = rxValue.length();
if (len > BUFFER_SIZE)
{
len = BUFFER_SIZE;
}
memcpy(commandBuffer, rxValue.c_str(), len);
commandBuffer[len] = 0;
run(commandBuffer, len, &inkplate, pTxCharacteristic);
}
}
};
void setup() // Initialize everything
{
Serial.begin(115200);
inkplate.begin();
BLEDevice::init("Inkplate 7 SPECTRA");
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
pRxCharacteristic->setCallbacks(new MyCallbacks());
pService->start();
pServer->getAdvertising()->start();
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED)
{
Serial.println("BLE controller failed to start.");
}
else
{
Serial.println("The device started, now you can pair it with Bluetooth and send commands.");
}
}
void loop()
{
if (!deviceConnected && oldDeviceConnected)
{
delay(500); // Allow bluetooth stack some time
pServer->startAdvertising(); // Restart advertising
oldDeviceConnected = false;
}
if (deviceConnected && !oldDeviceConnected)
{
oldDeviceConnected = true;
}
}
Functions used
Inkplate()returns NoneCreates the Inkplate object. Inkplate 7SPECTRA has a single six-color mode, so the constructor takes no mode argument.
ReturnsConstructor; no return value.
inkplate.begin()returns voidInitializes the library, the peripherals and the frame buffer. Call it once in setup().
ReturnsNothing.
run(char commandBuffer[], size_t n, Inkplate *display, BLECharacteristic *pTxCharacteristic)returns voidDefined in the example's Peripheral.h. Looks for a command between # and * in the received text, runs the matching drawing function on the Inkplate object, and answers on the transmit characteristic when a command asks for it (the command `#?` replies OK).
ReturnsNothing.
Serial.begin(115200)returns voidArduino core function: starts the serial port at 115200 baud.
ReturnsNothing.
BLEDevice::init(name)returns voidBluetooth LE library of the ESP32 board package: starts Bluetooth LE with the device name the phone sees, here Inkplate 7 SPECTRA.
ReturnsNothing.
BLEDevice::createServer()returns BLEServer *Bluetooth LE library: creates the Bluetooth LE server.
ReturnsThe server.
pServer->setCallbacks(callbacks)returns voidBluetooth LE library: registers the object whose onConnect and onDisconnect functions run when a phone connects or disconnects. The sketch prints Device connected or Device disconnected.
ReturnsNothing.
pServer->createService(SERVICE_UUID)returns BLEService *Bluetooth LE library: creates the service with the UART service UUID defined at the top of the sketch.
ReturnsThe service.
pService->createCharacteristic(uuid, properties)returns BLECharacteristic *Bluetooth LE library: creates a characteristic. The sketch makes a transmit characteristic with PROPERTY_NOTIFY (data going out from Inkplate) and a receive characteristic with PROPERTY_WRITE (data coming in).
ReturnsThe characteristic.
pTxCharacteristic->addDescriptor(new BLE2902())returns voidBluetooth LE library: lets the phone turn notifications on and off for the transmit characteristic.
ReturnsNothing.
pRxCharacteristic->setCallbacks(new MyCallbacks())returns voidBluetooth LE library: registers the object whose onWrite function runs when the phone writes to the receive characteristic.
ReturnsNothing.
pCharacteristic->getValue()returns StringBluetooth LE library: returns the text the phone wrote. The sketch copies at most 1000 characters of it into a buffer and passes the buffer to run().
ReturnsThe received text.
pTxCharacteristic->setValue(value)returns voidBluetooth LE library, called inside run(): sets the value to send back to the phone.
ReturnsNothing.
pTxCharacteristic->notify()returns voidBluetooth LE library, called inside run(): sends the value to the connected phone.
ReturnsNothing.
pService->start()returns voidBluetooth LE library: starts the service.
ReturnsNothing.
pServer->getAdvertising()->start()returns voidBluetooth LE library: starts advertising, so the phone can find the Inkplate.
ReturnsNothing.
pServer->startAdvertising()returns voidBluetooth LE library: restarts advertising. The sketch calls it in loop() half a second after a phone disconnects, so a new one can connect.
ReturnsNothing.
esp_bt_controller_get_status()returns esp_bt_controller_status_tESP32 board package function: returns the state of the Bluetooth controller. The sketch compares it with ESP_BT_CONTROLLER_STATUS_ENABLED to report whether Bluetooth started.
ReturnsThe controller state.
Serial.println(text)returns size_tArduino core function: prints a line to the Serial Monitor.
ReturnsNumber of bytes printed.
delay(ms)returns voidArduino core function: waits for the given number of milliseconds.
ReturnsNothing.
What to expect
With the Serial Monitor at 115200 baud, the sketch prints once Bluetooth has started:
The device started, now you can pair it with Bluetooth and send commands.
It prints Device connected when a phone connects and Device disconnected when it leaves; if Bluetooth does not start, it prints BLE controller failed to start. instead. The screen shows nothing until the phone sends drawing commands followed by #L(1)*.
🔗Open the complete example
examples/Inkplate7SPECTRA/Advanced/Communications/Inkplate7SPECTRA_Bluetooth_Peripheral_Mode