Pendahuluan
Di artikel BME280 (#13) kita sudah membaca suhu, kelembaban, dan tekanan lewat I2C, lalu mengirimnya ke broker MQTT. Data itu hanya terlihat di Serial Monitor atau aplikasi subscriber — tidak ada feedback langsung di hardware.
Artikel ini menambahkan layar OLED SSD1306 0,96″ (128×64 piksel) ke node yang sama. Pembaca sensor bisa melihat angka di lokasi tanpa membuka laptop. Karena OLED juga memakai I2C, BME280 dan OLED berbagi bus SDA/SCL — hanya alamat perangkat yang berbeda.
Ini lanjutan Jalur A (hardware & sensor) setelah deep sleep (#11), NVS (#12), dan BME280 (#13).
Prasyarat: Sudah paham GPIO dasar (#3), DHT22 (#5), MQTT (#7), dan I2C + BME280 (#13). Untuk WiFi/NVS/broker auth, baca #12 dan #16.
Yang Kamu Butuhkan
- ESP32 DevKit
- Modul sensor BME280 (I2C) — dari artikel #13
- Modul OLED 0,96″ SSD1306 (I2C, 128×64, 3.3V) — ±Rp 20.000–35.000
- Breadboard + kabel jumper
- Broker MQTT — disarankan Mosquitto pribadi (#16) (boleh
test.mosquitto.orghanya untuk uji hardware/OLED)
Mengapa OLED SSD1306?
| Aspek | Serial Monitor saja | + OLED SSD1306 |
|---|---|---|
| Feedback di lapangan | Butuh laptop/USB | Langsung di modul |
| Konsumsi daya | Minimal | ±20–40 mA saat layar menyala |
| Protokol | UART | I2C — satu bus dengan BME280 |
| Use case | Debug development | Panel sensor dinding, greenhouse, gudang |
Catatan daya: Untuk node deep sleep baterai (#11), matikan backlight OLED saat tidur atau pakai layar hanya saat ada interaksi — OLED boros dibanding ESP32 tidur.
Dua Perangkat, Satu Bus I2C
I2C mendukung banyak slave di kabel yang sama. Setiap modul punya alamat unik:
- BME280 — biasanya
0x76atau0x77 - SSD1306 OLED — biasanya
0x3C(kadang0x3D)
Karena alamat berbeda, BME280 dan OLED bisa dirakit paralel ke GPIO 21 (SDA) dan GPIO 22 (SCL) tanpa konflik.
Komponen & Wiring
Hubungkan kedua modul ke ESP32 (paralel di breadboard):
- Pastikan modul OLED 3.3V — beberapa modul punya jumper VCC/3V3
- Pin RST OLED boleh tidak di-wire jika library pakai
OLED_RESET -1 - Panjang kabel prototype <30 cm biasanya aman; untuk kabel panjang pertimbangkan pull-up 4.7kΩ di SDA/SCL
Install Library
Pastikan Arduino IDE dan board ESP32 sudah terpasang — ikuti tutorial install Arduino IDE & Board Manager (#2) jika belum.
Arduino IDE → Sketch → Include Library → Manage Libraries:
- Adafruit SSD1306
- Adafruit GFX Library (dependency OLED)
- Adafruit BME280 Library + Adafruit Unified Sensor
- PubSubClient (Nick O'Leary)
- WiFiManager (tzapu)
Board: esp32 by Espressif (v3.x). Library Wire, Preferences, dan WiFi sudah built-in.
Topic MQTT (sama #13): kodingindonesia/esp32/bme280/data
Payload JSON: {"suhu":28.5,"kelembaban":65.2,"tekanan":1013.25}
Kode Lengkap: BME280 + OLED + WiFiManager + MQTT
Sketch membaca BME280, menggambar suhu/kelembaban/tekanan di OLED, lalu publish JSON ke broker — pola NVS seperti #12 dan #16.
#include <Wire.h>
#include <WiFi.h>
#include <WiFiManager.h>
#include <Preferences.h>
#include <PubSubClient.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define I2C_SDA 21
#define I2C_SCL 22
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
const char* NS_KINDO = "kindo";
const int MQTT_PORT = 1883;
Adafruit_BME280 bme;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
WiFiClient espClient;
PubSubClient mqttClient(espClient);
Preferences prefs;
String mqttHost, mqttUser, mqttPass, topicSensor;
WiFiManagerParameter pHost("mqtt_host", "MQTT broker IP", "192.168.1.50", 64);
WiFiManagerParameter pUser("mqtt_user", "MQTT username", "kindo_esp32", 32);
WiFiManagerParameter pPass("mqtt_pass", "MQTT password", "", 48);
WiFiManagerParameter pTopic("mqtt_topic", "MQTT topic", "kodingindonesia/esp32/bme280/data", 64);
bool initI2C() {
Wire.begin(I2C_SDA, I2C_SCL);
delay(50);
return true;
}
bool initBME280() {
if (bme.begin(0x76)) return true;
if (bme.begin(0x77)) return true;
Serial.println("BME280 tidak ditemukan");
return false;
}
bool initOLED() {
if (display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) return true;
if (display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) return true;
Serial.println("OLED SSD1306 tidak ditemukan");
return false;
}
void tampilkanOLED(float suhu, float kelembaban, float tekanan) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(F("Koding Indonesia"));
display.println(F("BME280 + OLED"));
display.drawLine(0, 18, 128, 18, SSD1306_WHITE);
display.setCursor(0, 24);
display.printf("Suhu: %.1f C", suhu);
display.printf("\nRH: %.1f %%", kelembaban);
display.printf("\nTekanan: %.0f hPa", tekanan);
display.display();
}
void muatMqttDariNvs() {
prefs.begin(NS_KINDO, true);
mqttHost = prefs.getString("mqtt_host", "192.168.1.50");
mqttUser = prefs.getString("mqtt_user", "kindo_esp32");
mqttPass = prefs.getString("mqtt_pass", "");
topicSensor = prefs.getString("mqtt_topic", "kodingindonesia/esp32/bme280/data");
prefs.end();
}
void simpanMqttKeNvs() {
prefs.begin(NS_KINDO, false);
prefs.putString("mqtt_host", pHost.getValue());
prefs.putString("mqtt_user", pUser.getValue());
prefs.putString("mqtt_pass", pPass.getValue());
prefs.putString("mqtt_topic", pTopic.getValue());
prefs.end();
}
bool setupWiFiManager() {
WiFiManager wm;
wm.setConfigPortalTimeout(180);
wm.addParameter(&pHost);
wm.addParameter(&pUser);
wm.addParameter(&pPass);
wm.addParameter(&pTopic);
muatMqttDariNvs();
pHost.setValue(mqttHost.c_str(), 64);
pUser.setValue(mqttUser.c_str(), 32);
pPass.setValue(mqttPass.c_str(), 48);
pTopic.setValue(topicSensor.c_str(), 64);
if (!wm.autoConnect("KindoESP32-Setup")) return false;
simpanMqttKeNvs();
return true;
}
bool koneksiMQTT() {
mqttClient.setServer(mqttHost.c_str(), MQTT_PORT);
mqttClient.setBufferSize(512);
String clientId = "ESP32-OLED-" + String(random(0xffff), HEX);
if (!mqttClient.connect(clientId.c_str(), mqttUser.c_str(), mqttPass.c_str())) {
Serial.print("MQTT gagal, rc=");
Serial.println(mqttClient.state());
return false;
}
return true;
}
void bacaDanTampilkan() {
float suhu = bme.readTemperature();
float kelembaban = bme.readHumidity();
float tekanan = bme.readPressure() / 100.0F;
if (isnan(suhu) || isnan(kelembaban) || isnan(tekanan)) {
Serial.println("BME280 baca gagal");
return;
}
tampilkanOLED(suhu, kelembaban, tekanan);
char payload[128];
snprintf(payload, sizeof(payload),
"{\"suhu\":%.1f,\"kelembaban\":%.1f,\"tekanan\":%.2f}",
suhu, kelembaban, tekanan);
mqttClient.loop();
if (mqttClient.publish(topicSensor.c_str(), payload, false)) {
Serial.print("Publish OK → ");
Serial.println(payload);
} else {
Serial.println("Publish gagal");
}
}
void setup() {
Serial.begin(115200);
delay(500);
initI2C();
if (!initBME280() || !initOLED()) {
while (true) delay(1000);
}
tampilkanOLED(0, 0, 0);
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 24);
display.println(F("Menghubungkan..."));
display.display();
if (!setupWiFiManager()) ESP.restart();
if (!koneksiMQTT()) ESP.restart();
bacaDanTampilkan();
}
void loop() {
mqttClient.loop();
delay(5000);
bacaDanTampilkan();
}
Penjelasan Bagian Kritis
Wire.begin(21, 22)sekali — BME280 dan OLED berbagi objekWireyang samadisplay.begin(SSD1306_SWITCHCAPVCC, 0x3C)— coba0x3Djika layar kosongdisplay.display()— wajib dipanggil setelah menggambar; tanpa ini layar tidak berubahdisplay.clearDisplay()— hapus buffer sebelum menggambar frame baru (hindari ghosting)- Urutan init —
Wire.begin→ BME280 → OLED; jika salah satu gagal, hentikan agar mudah debug mqttClient.loop()— tetap dipanggil diloop()meski fokus artikel ini adalah layar
Uji Coba (Step-by-Step)
- Rakit BME280 + OLED paralel di breadboard, upload sketch, Serial Monitor 115200
- Pastikan OLED menampilkan teks
Menghubungkan...lalu angka sensor - Portal
KindoESP32-Setup— isi WiFi + kredensial broker (#16) - Verifikasi angka di OLED ≈ Serial Monitor / MQTT Explorer
- Subscribe topic di laptop:
mosquitto_sub -h 192.168.1.50 -p 1883 \
-u kindo_esp32 -P 'GANTI_PASSWORD_MQTT' \
-t "kodingindonesia/esp32/bme280/data" -v
Pro tip: Untuk demo, tiup hangat ke BME280 — suhu di OLED naik dalam 2–3 detik. Topic unik per unit, misalnya
kodingindonesia/anton/esp32/bme280/data.
Scanner I2C (Opsional)
Jika salah satu modul tidak terdeteksi, jalankan sketch Scan I2C dari artikel #13. Kamu harus melihat dua alamat (misalnya 0x76 + 0x3C).
Tips & Troubleshooting
- Layar putih/kosong: Cek alamat
0x3Cvs0x3D, wiring 3.3V, dan panggilandisplay.display() - Hanya BME280 terdeteksi: OLED mungkin modul SPI — pastikan beli varian I2C (4 pin: GND VCC SCL SDA)
- Teks terpotong: Resolusi 128×64 — pakai
setTextSize(1); untuk font besar kurangi jumlah baris - Ghosting/berbayang: Selalu
clearDisplay()sebelum menggambar ulang - BME280 gagal setelah pasang OLED: Cek beban 3.3V — dua modul + ESP32; gunakan USB port yang stabil
- Portal WiFi tidak muncul:
wm.resetSettings()atau bukahttp://192.168.4.1— sama seperti #12 - MQTT gagal (rc=-2): Broker tidak terjangkau — cek IP, firewall port 1883, satu jaringan WiFi
- MQTT auth (rc=5): Lihat troubleshooting broker #16
- Compile error WiFiManager: Update library tzapu ke 2.x; pastikan board esp32 v3.x
- Compile error GFX: Install Adafruit GFX versi terbaru sebelum SSD1306
- WiFi 2.4 GHz: ESP32 tidak support jaringan WiFi 5 GHz saja
Keamanan & Produksi
- Jangan commit password MQTT ke Git — simpan lewat portal WiFiManager + NVS seperti artikel #12
- OLED menampilkan data sensor di lokasi fisik — hindari menampilkan kredensial atau token di layar
- Gunakan broker Mosquitto pribadi + auth (#16) — jangan andalkan
test.mosquitto.orguntuk data produksi
Langkah Selanjutnya (Seri 2)
- OTA update firmware (#15) — update tanpa kabel USB (butuh #12 WiFiManager)
- Gabung deep sleep (#11) + BME280 + OLED untuk node lapangan (matikan OLED saat tidur)
- Subscriber Python → MySQL (#18) untuk histori + OLED sebagai panel lokal
- InfluxDB + Grafana (#19) — dashboard cloud selain layar OLED
- Capstone greenhouse (#39) — sensor + layar + pompa relay
Dengan OLED di bus I2C yang sama, node sensormu punya antarmuka lokal selain MQTT cloud. Lanjutkan di halaman artikel Koding Indonesia.
Komentar
Punya pertanyaan atau pengalaman? Tulis di bawah — komentar akan tampil setelah disetujui.
Belum ada komentar. Jadilah yang pertama!
Tulis komentar