Talk through what Bluetooth Low Energy (BLE) is, and how it compares/differs from serial, WiFi, and other ways of connecting.
nRF Connect is a good one for iOS, Anrdoid, and other OSes.
!! DOES NOT WORK !! will revisit at a later date
Write a program to scan for nearby BLE devices and detect if a specific device (like your phone) is nearby.
1. Find your Phone’s BLE MAC Address
2. Compile and upload arduino code
/*
Electronic Technologies for Art II
et4a.roberttwomey.com | rtwomey@ucsd.edu
ble-scanner
Scans for nearby BLE devices and detects a specific MAC address.
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
int scanTime = 5; //In seconds
BLEScan* pBLEScan;
// TARGET_DEVICE_MAC: Replace with your device's MAC address
// Format: "xx:xx:xx:xx:xx:xx" (lowercase)
String targetDeviceMac = "24:6f:28:ae:34:56";
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
// Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str());
// Convert found MAC to String for comparison
String currentMac = advertisedDevice.getAddress().toString().c_str();
// Check if the found device matches our target
if (currentMac == targetDeviceMac) {
Serial.println("***************************");
Serial.println("Target Device Found!");
Serial.printf("Device: %s \n", advertisedDevice.toString().c_str());
Serial.printf("RSSI: %d \n", advertisedDevice.getRSSI());
Serial.println("***************************");
}
}
};
void setup() {
Serial.begin(115200);
Serial.println("Scanning...");
BLEDevice::init("");
pBLEScan = BLEDevice::getScan(); //create new scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
pBLEScan->setInterval(100);
pBLEScan->setWindow(99); // less or equal setInterval value
}
void loop() {
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
Serial.print("Devices found: ");
Serial.println(foundDevices.getCount());
Serial.println("Scan done!");
pBLEScan->clearResults(); // delete results fromBLEScan buffer to release memory
delay(2000);
}
3. Activity
Control the onboard LED1 or LED2 using a BLE characteristic.
1. Compile and upload arduino code
/*
Electronic Technologies for Art II
et4a.roberttwomey.com | rtwomey@ucsd.edu
ble-led
Controls LED1 with BLE service.
Use a BLE scanner (such as nRF Connect) or
this p5js sketch: https://editor.p5js.org/robert.twomey/sketches/aXwz43amQ
Adapted from ESP32 Examples -> BLE -> Write
And NYU ITP https://itpnyu.github.io/p5ble-website/docs/write-one-char-callback
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
const int ledPin = 17;
class MyCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
String value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++) {
Serial.print(value[i]);
}
if (value != 0) { // any value other than 0
Serial.println("\nLED on\n");
digitalWrite(ledPin, HIGH); // will turn the LED on
} else { // a 0 value
Serial.println("\nLED off\n");
digitalWrite(ledPin, LOW); // will turn the LED off
}
Serial.println();
Serial.println("*********");
}
}
};
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
Serial.println("1- Download and install an BLE scanner app in your phone (nRF)");
Serial.println("2- Scan for BLE devices in the app");
Serial.println("3- Connect to MyESP32");
Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something");
Serial.println("5- See the magic =)");
BLEDevice::init("MyESP32"); // change this name
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic =
pService->createCharacteristic(CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
pAdvertising->start();
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
}
Be sure to change the device name (BLEDevice::init("MyESP32");)to be something special to you! (And so you don’t conflict with your classmates)
Compile and upload the program.
You can keep the serial port open to see what is happening from the dev board side. (Make sure Tools->USB CDC on Boot is set to Enabled)
1. Control with BLE scanner
2. Control with p5js
Use a p5js app to connect to and control the LED.
ON and OFF. (technically any non-zero value will turn the LED on)3. Activity
4. Extension
Use the onboard switch (SW1) to control an on-screen sketch.
1. Compile and upload arduino code
/*
Electronic Technologies for Art II
et4a.roberttwomey.com | rtwomey@ucsd.edu
ble-button
Reads from builting SW1 (IO12) and publishes to service.
Use a BLE scanner (such as nRF Connect) or
this p5js sketch: https://editor.p5js.org/robert.twomey/sketches/8wQxLraNL
NOTE: change your BLEDevice name from "MyESP32" to something of your own.
Adapted from ESP32 Examples -> BLE -> Server
And NYU ITP https://itpnyu.github.io/p5ble-website/docs/read-one-char-callback
*/
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define BUTTON_CHARACTERISTIC_UUID "19B10012-E8F2-537E-4F6C-D104768A1214"
const int ledPin = 18; // set ledPin to on-board LED2
const int buttonPin = 12; // set buttonPin to BTN1
int sensorPin = A0; // select the input pin for the potentiometer
// create switch characteristic and allow remote device to read and write
//BLEByteCharacteristic ledCharacteristic("19B10011-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
// create button characteristic and allow remote device to get notifications
// BLEIntCharacteristic buttonCharacteristic("19B10012-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLECharacteristic *pCharacteristic;
void setup() {
pinMode(ledPin, OUTPUT); // use the LED as an output
pinMode(buttonPin, INPUT); // use button pin as an input
Serial.begin(115200);
Serial.println("Starting BLE work!");
BLEDevice::init("MyESP32"); // change this name to a custom name
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic =
pService->createCharacteristic(BUTTON_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
// pService->createCharacteristic(CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE);
char txString[8];
dtostrf(0, 1, 2, txString);
pCharacteristic->setValue(txString); // set value to 0
pService->start();
// BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("Characteristic defined! Now you can read it in your phone!");
}
void loop() {
// put your main code here, to run repeatedly:
delay(2000);
// read the value from an analog sensor:
// int sensorValue = analogRead(sensorPin);
// char txString[8];
// dtostrf(sensorValue/4, 1, 2, txString);
// read value from digital button
// char txString[8];
// dtostrf(digitalRead(buttonPin), 1, 2, txString);
// Serial.println(txString);
// publish to characteristic
// pCharacteristic->setValue(txString);
int btn = digitalRead(buttonPin);
Serial.println(btn);
pCharacteristic->setValue(btn);
}
You can keep the serial port open to see what is happening.
Be sure to change the device name to be something special to you! (And so you don’t conflict with your classmates)
1. Debug with BLE scanner
2. Control with p5js
Use a p5js app to connect and read the unboard switch.
3. Activity
analogRead() and publish the value.
4. Extension