Pendahuluan
Di Seri 1 kita memakai DHT22 — sensor digital satu kabel data yang mudah untuk pemula. Di Seri 2, saatnya naik level ke I2C: bus dua kawat (SDA/SCL) yang bisa menghubungkan banyak perangkat sekaligus, dengan akurasi lebih baik.
Artikel ini fokus pada sensor BME280: mengukur suhu, kelembaban, dan tekanan udara dalam satu modul kecil. Kita baca datanya lewat I2C, lalu publish JSON ke broker MQTT — mengikuti pola NVS + WiFiManager (#12) dan broker pribadi (#16).
Ini lanjutan Jalur A (hardware & sensor) setelah deep sleep (#11) dan konfigurasi lapangan (#12).
Prasyarat: Sudah paham GPIO dasar (#3), DHT22 (#5), MQTT (#7). Untuk WiFi/NVS/broker auth, baca #12 dan #16.
Yang Kamu Butuhkan
- ESP32 DevKit
- Modul sensor BME280 (breakout I2C, 3.3V) — ±Rp 25.000–40.000 di marketplace lokal
- Kabel jumper female–female atau breadboard
- Broker MQTT — disarankan Mosquitto pribadi (boleh
test.mosquitto.orghanya untuk uji hardware)
DHT22 vs BME280 — Kenapa Upgrade?
| Aspek | DHT22 (Seri 1) | BME280 (Seri 2) |
|---|---|---|
| Protokol | Digital 1-wire (GPIO) | I2C (SDA + SCL) |
| Suhu | Cukup untuk hobby | Stabil, cocok monitoring & cuaca |
| Kelembaban | ±2–5% RH | ±3% RH |
| Tekanan udara | Tidak ada | Ada (hPa) — ketinggian, cuaca |
| Perangkat di satu bus | 1 pin per sensor | Banyak (alamat I2C berbeda) |
Apa itu I2C?
I2C (Inter-Integrated Circuit) memakai dua kabel data:
- SDA — data (Serial Data)
- SCL — clock (Serial Clock)
Setiap perangkat punya alamat 7-bit unik di bus yang sama. BME280 umumnya 0x76 atau 0x77 (tergantung jumper modul).
Analogi: I2C seperti lift apartemen — banyak penghuni (sensor), satu jalur (bus), setiap lantai punya nomor (alamat).
Komponen & Wiring I2C
Pin default I2C ESP32 DevKit (bisa diubah di kode):
ESP32 DevKit BME280
───────────── ──────
3.3V ─────── VCC
GND ─────── GND
GPIO 21 (SDA) ─────── SDA
GPIO 22 (SCL) ─────── SCL
- Modul breakout BME280 biasanya sudah punya pull-up kecil di PCB
- Pastikan modul 3.3V — jangan 5V langsung ke ESP32
- Jika
bme.begin()gagal, coba alamat0x77(beberapa modul pakai ini)
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 BME280 Library
- Adafruit Unified Sensor (dependency)
- PubSubClient (Nick O'Leary)
- WiFiManager (tzapu) — provisioning WiFi + MQTT
Board: esp32 by Espressif (v3.x). Library Wire, Preferences, dan WiFi sudah built-in.
Broker & topic: publish ke broker kamu (lihat #16).
Topic default: kodingindonesia/esp32/bme280/data
Payload JSON: {"suhu":28.5,"kelembaban":65.2,"tekanan":1013.25} — tekanan dalam hPa.
Catatan topic Seri 2: DHT22 memakai
.../dht22/data. BME280 punya subtopic sendiri.../bme280/dataagar hierarki MQTT tetap rapi.
Kode Lengkap: BME280 + I2C + WiFiManager + MQTT Auth
Pola NVS sama artikel #16 — tanpa hardcode WiFi/MQTT di sketch.
#include <Wire.h>
#include <WiFi.h>
#include <WiFiManager.h>
#include <Preferences.h>
#include <PubSubClient.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#define I2C_SDA 21
#define I2C_SCL 22
const char* NS_KINDO = "kindo";
const int MQTT_PORT = 1883;
Adafruit_BME280 bme;
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 initBME280() {
Wire.begin(I2C_SDA, I2C_SCL);
if (bme.begin(0x76)) return true;
if (bme.begin(0x77)) return true;
Serial.println("BME280 tidak ditemukan — cek wiring I2C");
return false;
}
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-BME280-" + 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 publishBME280() {
float suhu = bme.readTemperature();
float kelembaban = bme.readHumidity();
float tekanan = bme.readPressure() / 100.0F; // Pa → hPa
if (isnan(suhu) || isnan(kelembaban) || isnan(tekanan)) {
Serial.println("BME280 baca gagal");
return;
}
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);
if (!initBME280()) {
while (true) delay(1000);
}
delay(100);
if (!setupWiFiManager()) ESP.restart();
if (!koneksiMQTT()) ESP.restart();
publishBME280();
}
void loop() {
mqttClient.loop();
delay(10000);
publishBME280();
}
Penjelasan Bagian Kritis
Wire.begin(I2C_SDA, I2C_SCL)— inisialisasi bus I2C di pin 21/22bme.begin(0x76)/0x77— coba kedua alamat umum modul breakoutreadPressure() / 100.0F— library mengembalikan Pascal; dibagi 100 jadi hPasetBufferSize(512)— payload JSON 3 field butuh buffer cukup besarmqttClient.loop()— wajib sebelumpublish()
Uji Coba (Step-by-Step)
- Rakit wiring I2C, upload sketch, Serial Monitor 115200
- Pastikan tidak ada error
BME280 tidak ditemukan - Portal
KindoESP32-Setup— isi WiFi + kredensial broker (#16) - Serial:
Publish OKdengan JSON suhu, kelembaban, tekanan - Di laptop —
mosquitto_subatau MQTT Explorer:
mosquitto_sub -h 192.168.1.50 -p 1883 \
-u kindo_esp32 -P 'KindoMQTT2026!' \
-t "kodingindonesia/esp32/bme280/data" -v
Pro tip: Topic unik per unit, misalnya
kodingindonesia/anton/esp32/bme280/data.
Scanner I2C (Opsional)
Jika sensor tidak terdeteksi, upload sketch scanner untuk melihat alamat di bus:
#include <Wire.h>
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
Serial.println("Scan I2C...");
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.printf("Perangkat di 0x%02X\n", addr);
}
}
}
void loop() {}
Tips & Troubleshooting
- BME280 tidak ditemukan: Cek 3.3V, SDA/SCL tidak tertukar, coba
0x77, jalankan scanner I2C - Nilai tekanan aneh: Normal sekitar 950–1050 hPa di permukaan laut; bandingkan dengan cuaca lokal
- Portal WiFi tidak muncul: Reset WiFi tersimpan — tahan BOOT saat boot atau
wm.resetSettings(); buka manualhttp://192.168.4.1jika captive portal tidak redirect - Compile error WiFiManager: Update library tzapu ke 2.x; pastikan board esp32 v3.x
- MQTT gagal (rc=-2): Broker tidak terjangkau — cek IP host, firewall port 1883, ESP32 dan broker satu jaringan
- MQTT auth gagal (rc=5): Username/password salah — lihat troubleshooting broker #16
- Panjang kabel I2C: Untuk prototype breadboard <30 cm biasanya aman; kabel panjang butuh pull-up lebih kuat
- 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
- Portal AP
KindoESP32-Setupdefault tanpa password — untuk deploy lapangan, pertimbangkan password AP atau provisioning terbatas - Gunakan broker Mosquitto pribadi + auth (#16) — jangan andalkan
test.mosquitto.orguntuk data produksi
Langkah Selanjutnya (Seri 2)
- Artikel #14: OLED SSD1306 — tampilkan suhu/tekanan di layar (bus I2C sama, alamat berbeda dari BME280)
- Artikel #15: OTA update — update firmware tanpa kabel
- Gabung dengan deep sleep (#11) untuk node sensor hemat baterai + BME280
- Subscriber Python → MySQL (#18) untuk simpan histori tekanan & suhu
Dengan I2C dan BME280, hardware stack kamu siap untuk dashboard OLED dan capstone greenhouse Seri 2. Lanjutkan di halaman artikel Koding Indonesia.