Program ESP32 Mengirim Data Suhu dan Kelembapan melaui Bluetooth Low Energy

T. Ezandi Trinanda
6 min readAug 28, 2021

Library yang digunakan disini 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. Untuk proses pengiriman data suhu dan kelembapannya penulis terinspirasi dari GitHub — filipeflop/esp32-ble-dht11

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. Server untuk menerima data dari client ini dapat dilihat pada ESP32 BLE Server Menerima Data dari 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 maintainer-nya. Library ini sudah termasuk dalam dalam paket saat menginstal board ESP32 pada Arduino IDE, jika belum library dapat diinstal pada ESP32 BLE Arduino.

Gambar rangkaian breadboard ESP32 mengirim data suhu dan kelembapan
Gambar skema rangkaian ESP32 mengirim data suhu dan kelembapan
#include "BLEDevice.h"
#include "DHT.h"
#define DHTPIN 4 // Digital pin yang tersambung ke Sensor DHT22
#define DHTTYPE DHT22 // Type Sensor DHT22
// Membuat Objek baru dht dengan parameter DHTPIN dan DHTTYPE
DHT dht(DHTPIN, DHTTYPE);
#define TUNGGU_SETELAH_BACA_DATA 250// Deklarasi konstanta Nilai Delay
#define TUNGGU_SETELAH_KIRIM_DATA 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;
// Deklarasi variable h dan t secara global
float h = 0;
float t = 0;
// Fungsi untu baca Suhu
void bacaSuhudanKelembapan() {
t = dht.readTemperature();
h = dht.readHumidity();
}
void kirimData() {
bacaSuhudanKelembapan();
delay(TUNGGU_SETELAH_BACA_DATA);
if (connected) {
if (isnan(t) || isnan(h) <= -1) {
pRemoteCharacteristic->writeValue("Gagal membaca DHT sensor!", 1);
}
else {
char hString[8];
char tString[8];
dtostrf(t, 1, 2, tString);
dtostrf(h, 1, 2, hString);
pRemoteCharacteristic->writeValue(hString);
pRemoteCharacteristic->writeValue(tString);
//// cara pengiriman alternatif
// char dhtDataString[16];
// sprintf(dhtDataString, "%s%s", hString, tString);
// pRemoteCharacteristic->writeValue(dhtDataString);
delay(TUNGGU_SETELAH_KIRIM_DATA);
}
} else if (doScan) {
BLEDevice::getScan()->start(0);
}
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
}
};
bool connectToServer() {BLEClient* pClient = BLEDevice::createClient();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;
}
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;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {dht.begin();BLEDevice::init("");// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
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.
// This is the Arduino main loop function.
void loop() {
kirimData();} // End of loop

Penjelasan Kode

Masukkan library yang diperlukan

#include "BLEDevice.h"
#include "DHT.h"

Menentukan atau mendefinisikan letak pin DHT22 yang terkoneksi pada ESP32.

#define DHTPIN 4

Memilih tipe sensor DHT yang digunakan. Tipe yang digunakan pada rangkaian ini adalah DHT22.

#define DHTTYPE DHT22

Membuat objek DHT dari pin dan tipe yang ditentukan sebelumnya

DHT dht(DHTPIN, DHTTYPE);

Deklarasi variabel untuk menyimpan data suhu dan kelembapan dengan h untuk kelembapan dan t untuk suhu dengan tipe data float

float h = 0;
float t = 0;

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

#define TUNGGU_SETELAH_BACA_DATA 250
#define TUNGGU_SETELAH_KIRIM_DATA 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 bacaSuhudanKelembapan() untuk baca suhu dan kelembapan udara. Data suhu disimpan dalam variabel t dan data kelembapan udara disimpan dalam variabel h.

void bacaSuhudanKelembapan() {
t = dht.readTemperature();
h = dht.readHumidity();
}

Fungsi kirimData() digunakan untuk mengirim data. Pada fungsi ini dipanggil fungsi bacaSuhudanKelembapan() untuk dieksekusi. Tunggu setelah membaca data.

void kirimData() {
bacaSuhudanKelembapan();
delay(TUNGGU_SETELAH_BACA_DATA);

Percabangan if (connected)) digunakan untuk mengecek apakah client terkoneksi dengan server.

if (connected) {

Jika yang dibaca bukan berupa angka dan kecil atau sama dengan -1 maka pembacaan sensor dianggap gagal dan pesan error akan dikirim ke server.

if (isnan(t) || isnan(h) <= -1) {
pRemoteCharacteristic->writeValue("Gagal membaca DHT sensor!", 1);
}

Selain dari persyaratan diatas maka nilai kelembapan akan dikirim melalui perintah pRemoteCharacteristic->writeValue(hString);. Sedangkan nilai suhu akan dikirim dengan perintah pRemoteCharacteristic->writeValue(tString);. Tunggu setelah kirim data. Pada BLE, untuk mengirim data dengan tipe data float harus diubah terlebih dahulu ke tipe data String dengan cara membuat serangkaian karakter dan menyusunya dalam String. Untuk penjelasan lebih lengkap, dapat dilihat pada dtostrf() turn your floats into strings | Programming Electronics Academy.

else {
char hString[8];
char tString[8];
dtostrf(t, 1, 2, tString);
dtostrf(h, 1, 2, hString);
pRemoteCharacteristic->writeValue(hString);
pRemoteCharacteristic->writeValue(tString);

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;
}
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, sensor DHT diinisialisasikan.

dht.begin();

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;
}

Pada void loop akan dipanggil fungsi kirimData(); untuk diulang selama client terkoneksi dengan server

// This is the Arduino main loop function.
void loop() {
kirimData();} // End of loop

--

--