//Jika Anode Common, maka pin COM dihubungkan ke 5V
//Jika Cathode Common, makan pin COM dihubungkan ke GND
#include <WiFi.h> // Library untuk ESP32 (gunakan <ESP8266WiFi.h> untuk ESP8266)
#include <MQTT.h> // Library MQTT
#include <ESP32Servo.h> // Library Servo
#include <NusabotSimpleTimer.h> //Library NusabotSimpleTimer
// Object WiFi, MQTT,Timer dan SERVO
WiFiClient net;
MQTTClient client;
Servo servo;
NusabotSimpleTimer timer; //Function yang akan digunakan setiap kali melakukan publish
//Constanta array + Character + Variabel Array
// Konstanta untuk SSID dan password WiFi
const char ssid[] = "Wokwi-GUEST"; // Ganti dengan SSID WiFi Anda
const char pass[] = ""; // Ganti dengan password WiFi Anda (jika ada)
// Nomor pin GPIO untuk LED RGB
const int pinRed = 2;
const int pinGreen = 4;
const int pinBlue = 16;
const int pinLED = 13;
const int pinServo = 18;
const int pinPot = 33;
int pot, oldPot = 0; //Variabel global potensio dengan tipe data integer, Variabel data trakhir potensiometer dengan default 0
void setup() {
Serial.begin(9600); // Memulai komunikasi Serial untuk debugging
// Mengatur pin sebagai output
pinMode(pinRed, OUTPUT);
pinMode(pinGreen, OUTPUT);
pinMode(pinBlue, OUTPUT);
pinMode(pinLED, OUTPUT);
pinMode(pinPot, INPUT);
servo.attach(pinServo, 500, 2400); //Variabel+fungsi library servo + (Variabel pinServo + 500 + 2500/pwm)
WiFi.begin(ssid, pass); // Memulai koneksi ke jaringan WiFi
client.begin("broker.emqx.io", net); //Panggil variabel Client + fungsi begin + argumen(alamat broker + variabel wifi)
client.onMessage(subscribe); //fungsi Callback untuk menerima pesan yang di-subscribe
timer.setInterval(1000, publish); //fungsi untuk mengatur interval publish + (waktu(MiliDetik) + variabel publish)
connect(); //Memanggil fungsi connect
}
//Kebanyakan isi dari Void Loop Real Project IoT hanya seperti dibawah, Jika ada pemrosesan sensor dilakukan di fungsi tersendiri
void loop() {
client.loop(); //Fungsi untuk mengecek koneksi & penerimaan data
timer.run(); //Fungsinya untuk mengecek interval, apakah sudah sesuai waktunya atau belum (0,5 detik), Jika sudah lakukan Publish
//Fungsi khusus library MQTT untuk Memeriksa koneksi ke broker
if(!client.connected()){
connect();
}
delay(10); //Loop utama, tambahkan kode tambahan jika diperlukan
}
// Callback untuk menangani pesan yang diterima
//Membuat fungsi subscribe + parameter (tipe data, &variabel, tipe data, &variabel)
void subscribe(String &topic, String &data){
Serial.print("Topic: ");
Serial.println(topic);
Serial.print("Data: ");
Serial.println(data);
//FUNGSI UNTUK MENGONTROL NYALA MATI LED MERAH
//Samakan dengan client.subscribe/Topic & isi data
if(topic == "KONTROL/LED"){
if(data == "NYALA"){
digitalWrite(pinLED, HIGH);
}else if(data == "MATI"){
digitalWrite(pinLED, LOW);
}
}
if(topic == "KONTROL/SERVO1"){
int posServo = data.toInt(); //Konversi data(String) ke integer
servo.write(posServo); //Variabel servo+fungsi khusus(write) + (data hasil konversi ke integer)
Serial.println(posServo); //Menampilkan data subscribe + Hasil konversi
}
}
void publish(){
pot = analogRead(pinPot); //fungsi pembacaan nilai analog pot
//Percabangan agar tidak mengirim nilai data yang sama pada pembacaan sebelumnya
if(pot != oldPot/*Jika data pot sekarang tidak sama dengan pot sebelumnya, Maka...*/){
Serial.println(pot);
//Memanggil Object Client + fungsi publish library MQTT + (Topik + Payload(data dengan tipe data string) + Retain Message(bool/True or False) + QoS)
client.publish("SENSOR/POTENSIOMETER", String(pot), false, 1);
oldPot = pot;
}
}
// Custom Function + Variabel
// Fungsi untuk mengontrol LED RGB
void rgb(bool red, bool green, bool blue) {
digitalWrite(pinRed, red); // Kontrol pin merah
digitalWrite(pinGreen, green); // Kontrol pin hijau
digitalWrite(pinBlue, blue); // Kontrol pin biru
}
//Membuat fungsi baru dengan nama Connect
void connect(){
//Memanggil variabel Custom Function
// Menyalakan LED merah selama proses koneksi
rgb(1, 0, 0); // LED merah menyala
Serial.print("Menghubungkan ke WiFi");
while (WiFi.status() != WL_CONNECTED) { //Perulangan ESP32 untuk terhubung ke jaringan WiFi
Serial.print(".");
delay(500);
}
Serial.println("\nBerhasil terhubung ke WiFi"); // Jika terhubung, tampilkan pesan dan nyalakan LED hijau
rgb(0, 1, 0); // LED hijau menyala
//Fungsi untuk
//while(client.connect("clientid-Uniq","Username","password")){}
while(!client.connect("https://wokwi.com/projects/419962568402282497")){
delay(500);
}
rgb(0,0,1);
Serial.print("MQTT Connect");
client.subscribe("KONTROL/#", 1); //Memanggil Variabel + melakukan Fungsi Subscribe + argumen (Topik, QoS) setelah terhubung ke broker
}
/*
Library Nusabot Simple Timer berfungsi untuk mengeksekusi sebuah fungsi (function) secara berkala setiap beberapa detik, tanpa menggunakan delay.
Hal ini sangat berguna dalam skenario seperti melakukan publish data secara terjadwal.
Mengapa fungsi publish tidak diletakkan di 'void loop'?
- Jika publish dilakukan langsung di 'void loop', maka proses tersebut akan dieksekusi terlalu cepat dan berulang-ulang.
Hal ini dapat mengakibatkan pemborosan bandwidth karena banyaknya data serupa yang dikirim secara terus-menerus.
Akibatnya, data menjadi tidak efisien dan berpotensi menghasilkan data sampah.
Mengapa tidak menggunakan delay?
- Dalam proyek IoT yang bersifat real-time, penggunaan delay sebaiknya dihindari sama sekali, kecuali pada kondisi tertentu seperti:
1. Sebelum pengiriman data.
2. Sesudah pembacaan data sensor.
3. Saat menghubungkan perangkat ke WiFi atau broker MQTT.
- Delay akan menyebabkan ESP32 berhenti sementara (freeze) dan tidak menjalankan proses lain.
Jika pengiriman atau penerimaan data terjadi bersamaan dengan waktu delay, data tersebut dapat terlewat atau tidak sampai ke tujuan.
Sebagai solusinya, gunakan library Nusabot Simple Timer untuk mengatur eksekusi fungsi secara periodik tanpa menghambat proses lainnya.
https://github.com/nusabot-iot/NusabotSimpleTimer
*/