/*
Sistem Monitoring Lingkungan - ESP32
Sensor:
- DHT22 -> DATA pin ke GPIO 4
- Soil moisture (potentiometer simulasi) -> AOUT ke GPIO 34 (ADC1_CH6)
- MQ-2 analog -> AOUT ke GPIO 35 (ADC1_CH7)
- LCD I2C (SDA=21, SCL=22) -> 16x2 LCD via I2C module
Catatan:
- GPIO34 & GPIO35 adalah input-only ADC pada ESP32 (baik untuk sensor analog).
- Jika nilai soil kebalikan (putar kanan -> nilai kecil), tukar koneksi 3.3V/GND pada potentiometer.
- Untuk Thingspeak: isi WIFI_SSID, WIFI_PASS, THINGSPEAK_API_KEY dan uncomment bagian WiFi + HTTP.
*/
#include <Arduino.h>
#include <DHTesp.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// ===== PIN =====
#define DHT_PIN 4
#define SOIL_PIN 34 // ADC1_CH6
#define MQ2_PIN 35 // ADC1_CH7
// ===== SENSOR & LCD SETUP =====
DHTesp dht;
LiquidCrystal_I2C lcd(0x27, 16, 2); // Alamat 0x27 umum; kalau berbeda sesuaikan
// ===== Optional: Thingspeak / WiFi (uncomment jika diperlukan) =====
// #include <WiFi.h>
// #include <HTTPClient.h>
// const char* WIFI_SSID = "YOUR_SSID";
// const char* WIFI_PASS = "YOUR_PASSWORD";
// const char* THINGSPEAK_API_KEY = "YOUR_THINGSPEAK_WRITE_APIKEY";
// const char* THINGSPEAK_URL = "http://api.thingspeak.com/update";
// ===== SETTINGS =====
const unsigned long READ_INTERVAL_MS = 5000UL; // interval baca sensor dan tampil (ms)
unsigned long lastRead = 0;
void setup() {
Serial.begin(115200);
delay(100);
// init sensors + lcd
dht.setup(DHT_PIN, DHTesp::DHT22);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Starting...");
Serial.println("Starting IoT Monitoring - ESP32");
// Optional: wifi connect (uncomment to use)
/*
WiFi.begin(WIFI_SSID, WIFI_PASS);
Serial.print("Connecting WiFi");
int wl_count = 0;
while (WiFi.status() != WL_CONNECTED && wl_count < 20) {
delay(500);
Serial.print(".");
wl_count++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println();
Serial.print("Connected, IP: ");
Serial.println(WiFi.localIP());
} else {
Serial.println();
Serial.println("WiFi connect failed (timeout).");
}
*/
}
float readTemperature() {
TempAndHumidity th = dht.getTempAndHumidity();
if (isnan(th.temperature)) return NAN;
return th.temperature;
}
float readHumidity() {
TempAndHumidity th = dht.getTempAndHumidity();
if (isnan(th.humidity)) return NAN;
return th.humidity;
}
int readSoilRaw() {
// ADC range ESP32: 0 - 4095
int raw = analogRead(SOIL_PIN);
return raw;
}
int readMQ2Raw() {
int raw = analogRead(MQ2_PIN);
return raw;
}
void updateLCD(float temp, float hum, int soilRaw, int gasRaw) {
// hitung persentase sensor analog -> (optional mapping)
// Soil: 0..4095 -> 0..100% (asumsi higher = lebih lembab)
int soilPct = map(soilRaw, 0, 4095, 0, 100);
soilPct = constrain(soilPct, 0, 100);
// Gas: tampilkan raw atau dalam persen
int gasPct = map(gasRaw, 0, 4095, 0, 100);
gasPct = constrain(gasPct, 0, 100);
// Line 1: Temp & Humidity
lcd.setCursor(0,0);
if (!isnan(temp) && !isnan(hum)) {
char buf1[17];
// Contoh: "T:25.4C H:60%"
snprintf(buf1, sizeof(buf1), "T:%4.1fC H:%3.0f%%", temp, hum);
lcd.print(buf1);
} else {
lcd.print("T: --.-C H: --% ");
}
// Line 2: Soil & Gas
lcd.setCursor(0,1);
char buf2[17];
// contoh: "Soil:45% Gas:12%"
snprintf(buf2, sizeof(buf2), "Soil:%3d%% Gas:%3d%%", soilPct, gasPct);
lcd.print(buf2);
}
void sendToThingspeak(float temp, float hum, int soilRaw, int gasRaw) {
// Optional: kirim ke Thingspeak. Pastikan WiFi sudah connected.
/*
if (WiFi.status() != WL_CONNECTED) {
Serial.println("WiFi not connected, skip Thingspeak");
return;
}
HTTPClient http;
String url = String(THINGSPEAK_URL) + "?api_key=" + THINGSPEAK_API_KEY;
url += "&field1=" + String(temp);
url += "&field2=" + String(hum);
url += "&field3=" + String(soilRaw);
url += "&field4=" + String(gasRaw);
http.begin(url);
int httpCode = http.GET();
if (httpCode > 0) {
Serial.print("Thingspeak response: ");
Serial.println(httpCode);
} else {
Serial.print("Error sending to Thingspeak: ");
Serial.println(httpCode);
}
http.end();
*/
}
void printSerial(float temp, float hum, int soilRaw, int gasRaw) {
Serial.println("=== SENSOR READINGS ===");
if (!isnan(temp)) {
Serial.printf("Temperature: %.2f C\n", temp);
} else {
Serial.println("Temperature: NAN");
}
if (!isnan(hum)) {
Serial.printf("Humidity : %.2f %%\n", hum);
} else {
Serial.println("Humidity : NAN");
}
Serial.printf("Soil Raw : %d (0..4095)\n", soilRaw);
Serial.printf("MQ-2 Raw : %d (0..4095)\n", gasRaw);
Serial.println("=======================");
}
void loop() {
unsigned long now = millis();
if (now - lastRead < READ_INTERVAL_MS) return;
lastRead = now;
// Baca sensor
float temperature = readTemperature();
float humidity = readHumidity();
int soilRaw = readSoilRaw();
int gasRaw = readMQ2Raw();
// Serial output
printSerial(temperature, humidity, soilRaw, gasRaw);
// Update LCD
updateLCD(temperature, humidity, soilRaw, gasRaw);
// Optional: kirim ke Thingspeak
// sendToThingspeak(temperature, humidity, soilRaw, gasRaw);
}