Program ESP32 Menerima Data Untuk Menghidupkan LED Melalui Bluetooth Low Energy

T. Ezandi Trinanda
5 min readAug 30, 2021

Library yang digunakan berkomunikasi melalui Bluetooth Low Energy (BLE) di sini adalah ESP32 BLE Arduino yang ditulis oleh Neil Kolban dan Dariusz Krempa sebagai maintener-nya. Library ini sudah termasuk dalam dalam paket saat menginstal board ESP32 pada Arduino IDE, jika belum library dapat diinstal pada ESP32 BLE Arduino.

Role atau peran ESP32 yang digunakan pada program ini adalah client atau central device, yaitu perangkat yang memberikan perintah dan permintaan, dan menerima respon. Peran client biasanya mencari perangkat yang bisa terkoneksi dan menyambungkan ke perangkat server yang diinginkan. Setelah tersambung, barulah setelah itu kedua perangkat bertukar informasi. Untuk ESP32 yang berperan sebagai server pada program ini dapat dilihat pada ESP32 BLE Server Mengirim Data ke ESP32 BLE Client.

Kode yang digunakan merupakan modifikasi dari kode example yang tersedia pada library ESP32 BLE Arduino yang ditulis oleh Neil Kolban dan Dariusz Krempa sebagai maintener-nya. Library ini sudah termasuk dalam dalam paket saat menginstal board ESP32 pada Arduino IDE, jika belum library dapat diinstal pada ESP32 BLE Arduino.

Rangkaian ESP32

Gambar rangkaian breadboard ESP32 menerima data untuk menghidupkan LED
Gambar skema rangkaian untuk menghidupkan LED

Kode ESP32 Client Menerima Data Melalui BLE

#include "BLEDevice.h"
//#include "BLEScan.h"
#define LEDPIN 4 // Digital pin yang tersambung ke LED//Deklarasi inputServer nilaiDelay secara global
String inputServer;
int nilaiDelay;
#define TUNGGU_SETELAH_TERIMA_PERINTAH 250 //Deklarasi konstanta Nilai Delay// Remote service server yang diinginkan.
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
// Characteristic dari the remote service yang ingin diakses.
static BLEUUID charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;
//Fungsi untuk mengontrol LED
void ledControl()
{
//Jika nilaiDelay kecil dari atau sama dengan 0 maka LED mati
if (nilaiDelay <= 0)
{
digitalWrite(LEDPIN, LOW);
}
else
{
//Hidupkan LED selama delay yang ditentukan
digitalWrite(LEDPIN, HIGH);
delay(nilaiDelay);
//Matikan LED
digitalWrite(LEDPIN, LOW);
}
}
void terimaData(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
if (connected) {
for (int i = 0; i < length; i++) {
// Serial.println(pData[i]);
inputServer = pData[i];
nilaiDelay = inputServer.toInt();
delay(TUNGGU_SETELAH_TERIMA_PERINTAH);
ledControl();
}
} else if (doScan) {
BLEDevice::getScan()->start(0);
}
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer() {BLEClient* pClient = BLEDevice::createClient();
// Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());pClient->connect(myDevice);// referensi ke layanan (service) yang di cari di server BLE.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {

pClient->disconnect();
return false;
}
// Referensi untuk karakteristik server BLE yang akan digunakan untuk berkomunikasi.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {

pClient->disconnect();
return false;
}
// Menerima data dari server
if (pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(terimaData);
connected = true;
}
/**
Scan untuk mencari server BLE dan temukan yang memiliki service UUID yang sama.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
Memanggil semua server yang dapat ditemukan.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
// We have found a device, let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
} // Server ditemukan
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {
// Serial.begin(115200);
pinMode(LEDPIN, OUTPUT);
BLEDevice::init("");//Pindai untuk mencari perangkat baru yang diinginkan.
//Aktifkan scan dengan kondisi true.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
// Scan server selama 5 detik
pBLEScan->start(5, false);
// Jika kondisi "doConnect" true maka server yang diinginkan telah ditemukan
// Sambung koneksi dengan server dan ubah kondisi "connected" menjadi true
if (doConnect == true) {
if (connectToServer()) {
}
doConnect = false;
}
} // End of setup.
void loop() {} // End of loop

Penjelasan Kode

Masukkan library yang diperlukan

#include “BLEDevice.h”

Menentukan atau mendefinisikan letak pin LED yang terkoneksi pada ESP32.

#define LEDPIN 4

Deklarasi variabel untuk menyimpan input atau data yang diterima dari server. Data yang diterima disimpan dalam tipe data String yang akan diubah menjadi tipe data integer agar dapat digunakan untuk menjadi delay.

String inputServer;
int nilaiDelay;

Deklarasi konstanta yang akan digunakan sebagai delay setelah membaca data dari sensor dan setelah mengirim data ke server.

#define TUNGGU_SETELAH_TERIMA_PERINTAH 250

Tentukan remote service UUID server yang diinginkan. Harus sama dengan UUID servernya.

static BLEUUID serviceUUID(“4fafc201–1fb5–459e-8fcc-c5c9c331914b”);

Characteristic UUID dari the remote service yang ingin diakses.

static BLEUUID charUUID(“beb5483e-36e1–4688-b7f5-ea07361b26a8”);

Fungsi ledControl() digunakan untuk mengeksekusi perintah yang diterima oleh server. Percabangan if digunakan untuk mengecek data yang disimpan pada nilaiDelay.

Jika ditemukan datanya berisi nilai kecil atau sama dengan 0 maka LED harus dalam keadaan mati atau LOW.

Selain dari nilai itu maka LED akan dihidupkan (HIGH) selama besar nilai yang ada pada nilaiDelay dengan cara menunda jalannya program dengan fungsi delay(). Kemudian LED dimatikan kembali.

void ledControl()
{
if (nilaiDelay <= 0)
{
digitalWrite(LEDPIN, LOW);
}
else
{
digitalWrite(LEDPIN, HIGH);
delay(nilaiDelay);
digitalWrite(LEDPIN, LOW);
}
}

Fungsi terimaData() berisi serangkaian kode untuk menerima data dari server. Data di

void terimaData(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
if (connected) {
for (int i = 0; i < length; i++) {
inputServer = pData[i];
nilaiDelay = inputServer.toInt();
delay(TUNGGU_SETELAH_TERIMA_PERINTAH);
ledControl();
}
} else if (doScan) {
BLEDevice::getScan()->start(0);
}
}

Di dalam fungsi connectToserver digunakan UUID untuk menyambungkan dengan server BLE . Untuk terhubung dengan server, ESP32 harus bertindak sebagai client, jadi ESP32 diberkikan peran sebagai client dengan membuat client dengan menggunakan fungsi createClient() dan kemudian terhubung ke alamat server BLE. Kemudian ESP32 mencari layanan dan karakteristik menggunakan UUID dan mencoba menghubungkannya. Ketika koneksi berhasil, fungsi mengembalikan nilai true dan jika tidak mengembalikan false.

bool connectToServer() {BLEClient*  pClient  = BLEDevice::createClient();
// Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());pClient->connect(myDevice);
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {

pClient->disconnect();
return false;
}
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {

pClient->disconnect();
return false;
}
// Menerima data dari server
if (pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(terimaData);
connected = true;
}

Di dalam fungsi MyAdvertisedDeviceCallbacks, server BLE yang dapat ditemukan dipanggil. Untuk dapat tersambung dengan server, client membutuhkan ID perangkat keras dari perangkat BLE yang ditemukan sehingga kami dapat membandingkannya dengan yang diinginkan. Jika perangkat yang diinginkan ditemukan, maka hentikan scan atau pencarian perangkat.

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {

void onResult(BLEAdvertisedDevice advertisedDevice) {
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
} // Server ditemukan
}
}; // MyAdvertisedDeviceCallbacks

Pada fungsi setup() digunakan fungsi pinMode() untuk menentukan fungsi pin yang digunakan pada LED bertindak sebagai output.

pinMode(LEDPIN, OUTPUT);

Kemudian beri inisial untuk nama perangkat yang digunakan dan hidupkan pemindaian aktif selama 5 detik.

BLEDevice::init("");//Pindai untuk mencari perangkat baru yang diinginkan.
//Aktifkan scan dengan kondisi true.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
// Scan server selama 5 detik
pBLEScan->start(5, false);

Jika kondisi “doConnect” true maka server yang diinginkan telah ditemukan, sambung koneksi dengan server dan ubah kondisi “connected” menjadi true

//
if (doConnect == true) {
if (connectToServer()) {
}
doConnect = false;
}

--

--