#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#include <DHT.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <WiFiClientSecure.h>
// WiFi credentials for Wokwi
#define WIFI_SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
// MQTT server details
const char* mqtt_server = "l25fdb81.ala.asia-southeast1.emqxsl.com";
const int mqtt_port = 8883;
const char* mqtt_user = "romi";
const char* mqtt_password = "1234";
// MQTT topics
const char* sensor_topic = "IOT/SENSORS";
const char* actuator_topic = "IOT/ACTUATORS";
// Define pins
#define DHTPIN 4 // Pin connected to DHT22
#define DHTTYPE DHT22 // DHT 22 (AM2302)
#define LDRPIN 34 // Pin connected to LDR (Analog)
#define PIRPIN 35 // Pin connected to PIR sensor
#define RELAY_POMPA_PIN 16
#define RELAY_LAMPU_PIN 17
#define BUTTON_PIN 12 // Pin for push button
// Initialize DHT sensor
DHT dht(DHTPIN, DHTTYPE);
// Initialize OLED display
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Create a WiFiClientSecure instance
WiFiClientSecure secureClient;
PubSubClient client(secureClient);
// For tracking button state
int displayMode = 0;
bool lastButtonState = HIGH;
bool currentButtonState = HIGH;
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
Serial.println("Starting setup...");
// Initialize DHT sensor
dht.begin();
Serial.println("DHT sensor initialized.");
// Initialize pins
pinMode(LDRPIN, INPUT);
pinMode(PIRPIN, INPUT);
pinMode(RELAY_POMPA_PIN, OUTPUT);
pinMode(RELAY_LAMPU_PIN, OUTPUT);
pinMode(BUTTON_PIN, INPUT_PULLUP);
Serial.println("Pins initialized.");
// Initialize OLED display
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
delay(2000); // Wait for initializing
display.clearDisplay();
Serial.println("OLED display initialized.");
// Set up WiFi
setup_wifi();
Serial.println("WiFi setup completed.");
// Load MQTT certificate
secureClient.setCACert(mqtt_cert);
Serial.println("MQTT certificate loaded.");
// Set MQTT server
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
Serial.println("MQTT server set.");
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
// Read sensor data
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
int ldrValue = analogRead(LDRPIN);
bool motionDetected = digitalRead(PIRPIN);
// Print sensor data to Serial Monitor
Serial.print("Temperature: ");
Serial.println(temperature);
Serial.print("Humidity: ");
Serial.println(humidity);
Serial.print("LDR Value: ");
Serial.println(ldrValue);
Serial.print("Motion Detected: ");
Serial.println(motionDetected);
// Publish sensor data to MQTT
publishSensorData(22, temperature);
publishSensorData(23, humidity);
publishSensorData(24, ldrValue);
publishSensorData(26, motionDetected ? 1 : 0);
// Control actuators
controlActuators(temperature);
// Update OLED display
updateDisplay(temperature, humidity, ldrValue, motionDetected);
delay(10000); // Delay between readings
}
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.print(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("ESP32Client", mqtt_user, mqtt_password)) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
// Handle incoming messages if needed
}
void publishSensorData(int sensor_id, float value) {
StaticJsonDocument<200> doc;
doc["sensor_id"] = sensor_id;
doc["value"] = value;
char jsonBuffer[512];
serializeJson(doc, jsonBuffer);
client.publish(sensor_topic, jsonBuffer);
Serial.print("Published sensor data: ");
Serial.print("Sensor ID: ");
Serial.print(sensor_id);
Serial.print(", Value: ");
Serial.println(value);
}
void controlActuators(float temperature) {
bool lampuStatus = digitalRead(RELAY_LAMPU_PIN);
bool pompaStatus = digitalRead(RELAY_POMPA_PIN);
if (temperature > 25 && !lampuStatus) {
digitalWrite(RELAY_LAMPU_PIN, HIGH);
publishActuatorData(13, 1);
Serial.println("Lampu turned ON.");
} else if (temperature <= 25 && lampuStatus) {
digitalWrite(RELAY_LAMPU_PIN, LOW);
publishActuatorData(13, 0);
Serial.println("Lampu turned OFF.");
}
}
void publishActuatorData(int actuator_id, int value) {
StaticJsonDocument<200> doc;
doc["actuator_id"] = actuator_id;
doc["value"] = value;
char jsonBuffer[512];
serializeJson(doc, jsonBuffer);
client.publish(actuator_topic, jsonBuffer);
Serial.print("Published actuator data: ");
Serial.print("Actuator ID: ");
Serial.print(actuator_id);
Serial.print(", Value: ");
Serial.println(value);
}
void updateDisplay(float temperature, float humidity, int ldrValue, bool motionDetected) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
switch(displayMode) {
case 0:
display.setCursor(0, 0);
display.println(F("SMART GREENHOUSE"));
break;
case 1:
display.setCursor(0, 0);
display.println(F("Suhu & Kelembaban"));
display.setCursor(0, 15);
display.print(F("Temp: "));
display.print(temperature);
display.println(F(" C"));
display.setCursor(0, 30);
display.print(F("Humi: "));
display.print(humidity);
display.println(F(" %"));
break;
case 2:
display.setCursor(0, 0);
display.println(F("Intensitas Cahaya"));
display.setCursor(0, 15);
display.print(F("Cahaya: "));
display.print(ldrValue);
display.println(F(" lx"));
break;
case 3:
display.setCursor(0, 0);
display.println(F("Motion Detected"));
display.setCursor(0, 15);
display.print(F("Motion: "));
display.print(motionDetected ? "YES" : "NO");
break;
}
display.display();
// Handle button press to change display mode
currentButtonState = digitalRead(BUTTON_PIN);
if (lastButtonState == HIGH && currentButtonState == LOW) {
displayMode++;
if (displayMode > 3) displayMode = 0;
delay(300); // Debounce delay
}
lastButtonState = currentButtonState;
}