program Arduino untuk pengisian air otomatis dengan fitur lengkap dan advance, termasuk sensor level air, sensor aliran, pompa, LCD, dan opsi kalibrasi.
Program Pengisian Air Otomatis Lanjut dengan Arduino
Program ini dirancang untuk sistem pengisian air otomatis yang cerdas, mampu mengisi tangki hingga level yang ditentukan, memantau aliran, dan menyediakan antarmuka pengguna melalui LCD dan tombol. Fitur kalibrasi volume memungkinkan akurasi yang lebih baik.
Komponen yang Dibutuhkan
Arduino Uno/Mega
Sensor Level Air Ultrasonik (HC-SR04): Untuk mendeteksi ketinggian air.
Sensor Aliran Air (YF-S201): Untuk mengukur volume air yang mengalir.
Relay Modul 1 Channel: Untuk mengontrol pompa air.
Pompa Air DC (sesuai kebutuhan)
LCD I2C 16x2 atau 20x4: Untuk menampilkan informasi.
Push Button (3 buah): Untuk navigasi menu dan pengaturan.
Resistor (untuk pull-down jika diperlukan)
Kabel Jumper
Power Supply Eksternal (untuk pompa jika diperlukan)
Skema Pengkabelan (Contoh)
Sensor Ultrasonik (HC-SR04):
VCC ke 5V
GND ke GND
Trig ke Pin Digital 9
Echo ke Pin Digital 10
Sensor Aliran Air (YF-S201):
VCC ke 5V
GND ke GND
Signal ke Pin Digital 2 (Interrupt 0)
Relay:
VCC ke 5V
GND ke GND
IN ke Pin Digital 4
LCD I2C:
SDA ke SDA (Analog Pin A4 pada Uno)
SCL ke SCL (Analog Pin A5 pada Uno)
VCC ke 5V
GND ke GND
Push Button:
Button UP ke Pin Digital 5
Button SELECT ke Pin Digital 6
Button DOWN ke Pin Digital 7
Hubungkan sisi lain setiap tombol ke GND (gunakan internal pull-up atau eksternal pull-down resistor 10K).
Library yang Dibutuhkan
Pastikan Anda telah menginstal library berikut di Arduino IDE Anda:
LiquidCrystal_I2C
: Untuk LCD I2C. Anda dapat menginstalnya melalui Sketch > Include Library > Manage Libraries... cari "LiquidCrystal I2C".NewPing
: Untuk sensor ultrasonik HC-SR04. Cari "NewPing" di Library Manager.
Kode Program
#include <LiquidCrystal_I2C.h>
#include <NewPing.h>
#include <EEPROM.h> // Untuk menyimpan data kalibrasi di EEPROM
// --- Pengaturan Sensor Level Air (Ultrasonik) ---
#define TRIGGER_PIN 9
#define ECHO_PIN 10
#define MAX_DISTANCE 200 // Jarak maksimum dalam cm yang diharapkan dari sensor ke dasar tangki
#define TANK_HEIGHT 30 // Tinggi tangki sebenarnya dalam cm
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
// --- Pengaturan Sensor Aliran Air ---
#define FLOW_SENSOR_PIN 2 // Pin interrupt (Interrupt 0 pada Arduino Uno)
volatile unsigned long pulseCount = 0;
float calibrationFactor = 4.5; // Faktor kalibrasi default (pulses per mL). Sesuaikan!
unsigned long startTime = 0;
float totalVolumeML = 0.0; // Total volume terakumulasi dalam mL
// --- Pengaturan Pompa ---
#define PUMP_PIN 4
// --- Pengaturan LCD ---
#define LCD_ADDR 0x27 // Alamat I2C LCD (biasanya 0x27 atau 0x3F)
#define LCD_COLS 16
#define LCD_ROWS 2
LiquidCrystal_I2C lcd(LCD_ADDR, LCD_COLS, LCD_ROWS);
// --- Pengaturan Tombol ---
#define BUTTON_UP_PIN 5
#define BUTTON_SELECT_PIN 6
#define BUTTON_DOWN_PIN 7
// --- Variabel State ---
enum MenuState {
STATE_HOME,
STATE_SET_TARGET_LEVEL,
STATE_CALIBRATE_FLOW,
STATE_FILLING,
STATE_CALIBRATING_RUN
};
MenuState currentMenuState = STATE_HOME;
float targetLevelPercentage = 80.0; // Level target dalam persen (default 80%)
float currentLevelPercentage = 0.0;
// --- Variabel Kalibrasi ---
#define CALIBRATION_VOLUME_ML 1000 // Volume air yang digunakan untuk kalibrasi (1 Liter)
#define CALIBRATION_EEPROM_ADDR 0 // Alamat EEPROM untuk menyimpan faktor kalibrasi
// --- Fungsi Interrupt untuk Sensor Aliran ---
void flowISR() {
pulseCount++;
}
// --- Fungsi Baca Jarak Ultrasonik ---
float getDistanceCm() {
delay(50); // Beri waktu sensor untuk stabil
unsigned int uS = sonar.ping_cm();
if (uS == 0) { // Jika tidak ada echo atau di luar jangkauan
return MAX_DISTANCE;
}
return uS;
}
// --- Fungsi Konversi Jarak ke Persen Level ---
float getLevelPercentage(float distanceCm) {
// Jarak dari sensor ke permukaan air adalah 'distanceCm'
// Ketinggian air = TANK_HEIGHT - distanceCm
// Level persen = (Ketinggian air / TANK_HEIGHT) * 100
float waterHeight = TANK_HEIGHT - distanceCm;
if (waterHeight < 0) waterHeight = 0; // Pastikan tidak negatif
float level = (waterHeight / TANK_HEIGHT) * 100.0;
if (level > 100) level = 100; // Pastikan tidak lebih dari 100%
return level;
}
// --- Fungsi Kontrol Pompa ---
void turnPumpOn() {
digitalWrite(PUMP_PIN, HIGH);
lcd.setCursor(0, 1);
lcd.print("Pompa: ON ");
}
void turnPumpOff() {
digitalWrite(PUMP_PIN, LOW);
lcd.setCursor(0, 1);
lcd.print("Pompa: OFF ");
totalVolumeML = 0; // Reset volume setelah pengisian selesai/dihentikan
}
// --- Fungsi Tampilan LCD ---
void displayHome() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Level: ");
lcd.print(currentLevelPercentage, 1);
lcd.print("% ");
lcd.print("Trgt: ");
lcd.print(targetLevelPercentage, 0);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print("Mode: Home ");
}
void displaySetTargetLevel() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Set Level: ");
lcd.print(targetLevelPercentage, 0);
lcd.print("% ");
lcd.setCursor(0, 1);
lcd.print("< Up Sel Down >");
}
void displayCalibrateFlow() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Kalibrasi Flow");
lcd.setCursor(0, 1);
lcd.print("Vol: ");
lcd.print(CALIBRATION_VOLUME_ML);
lcd.print("mL ");
}
void displayFilling() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Isi: ");
lcd.print(currentLevelPercentage, 1);
lcd.print("% ");
lcd.print("Vol:");
lcd.print(totalVolumeML, 0);
lcd.print("mL");
lcd.setCursor(0, 1);
lcd.print("Menunggu...");
}
void displayCalibratingRun() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Kalibrasi...");
lcd.setCursor(0, 1);
lcd.print("Pulses: ");
lcd.print(pulseCount);
}
// --- Fungsi Baca Tombol ---
bool readButton(int pin) {
return digitalRead(pin) == LOW; // Asumsi tombol terhubung ke GND
}
// --- Setup ---
void setup() {
Serial.begin(9600);
// Inisialisasi LCD
lcd.init();
lcd.backlight();
lcd.print("Sistem Air Otomatis");
delay(2000);
// Pin mode
pinMode(PUMP_PIN, OUTPUT);
digitalWrite(PUMP_PIN, LOW); // Pastikan pompa mati saat start
pinMode(BUTTON_UP_PIN, INPUT_PULLUP);
pinMode(BUTTON_SELECT_PIN, INPUT_PULLUP);
pinMode(BUTTON_DOWN_PIN, INPUT_PULLUP);
// Interrupt untuk sensor aliran
attachInterrupt(digitalPinToInterrupt(FLOW_SENSOR_PIN), flowISR, RISING);
// Muat faktor kalibrasi dari EEPROM
EEPROM.get(CALIBRATION_EEPROM_ADDR, calibrationFactor);
if (calibrationFactor < 1.0 || calibrationFactor > 10.0) { // Batasan untuk nilai wajar
calibrationFactor = 4.5; // Setel ke default jika nilai tidak valid
EEPROM.put(CALIBRATION_EEPROM_ADDR, calibrationFactor);
}
Serial.print("Faktor Kalibrasi Dimuat: ");
Serial.println(calibrationFactor);
displayHome();
}
// --- Loop ---
void loop() {
// Baca level air secara kontinu (kecuali saat kalibrasi)
if (currentMenuState != STATE_CALIBRATING_RUN) {
float distance = getDistanceCm();
currentLevelPercentage = getLevelPercentage(distance);
Serial.print("Jarak: ");
Serial.print(distance);
Serial.print("cm, Level: ");
Serial.print(currentLevelPercentage);
Serial.println("%");
}
// Handle Menu State
switch (currentMenuState) {
case STATE_HOME:
displayHome();
if (readButton(BUTTON_SELECT_PIN)) {
delay(200); // Debounce
currentMenuState = STATE_SET_TARGET_LEVEL;
displaySetTargetLevel();
} else if (readButton(BUTTON_UP_PIN)) { // Akses Kalibrasi dari Home
delay(200);
currentMenuState = STATE_CALIBRATE_FLOW;
displayCalibrateFlow();
}
break;
case STATE_SET_TARGET_LEVEL:
displaySetTargetLevel();
if (readButton(BUTTON_UP_PIN)) {
delay(200);
targetLevelPercentage = min(100.0, targetLevelPercentage + 5.0);
displaySetTargetLevel();
}
if (readButton(BUTTON_DOWN_PIN)) {
delay(200);
targetLevelPercentage = max(0.0, targetLevelPercentage - 5.0);
displaySetTargetLevel();
}
if (readButton(BUTTON_SELECT_PIN)) {
delay(200);
currentMenuState = STATE_HOME; // Kembali ke home setelah set
displayHome();
}
break;
case STATE_CALIBRATE_FLOW:
displayCalibrateFlow();
if (readButton(BUTTON_SELECT_PIN)) {
delay(200);
// Mulai proses kalibrasi
currentMenuState = STATE_CALIBRATING_RUN;
pulseCount = 0; // Reset pulse count
totalVolumeML = 0; // Reset total volume
turnPumpOn();
startTime = millis();
displayCalibratingRun();
} else if (readButton(BUTTON_DOWN_PIN)) {
delay(200);
currentMenuState = STATE_HOME;
displayHome();
}
break;
case STATE_CALIBRATING_RUN:
displayCalibratingRun();
// Kalibrasi berjalan sampai tombol SELECT ditekan atau waktu habis (misal 30 detik untuk keamanan)
// Disarankan untuk mengisi volume yang ditentukan secara manual dan kemudian menekan SELECT.
if (readButton(BUTTON_SELECT_PIN) || (millis() - startTime > 30000 && pulseCount > 0)) { // 30 detik timeout jika lupa tekan
delay(200);
turnPumpOff();
if (pulseCount > 0) {
calibrationFactor = (float)pulseCount / CALIBRATION_VOLUME_ML;
EEPROM.put(CALIBRATION_EEPROM_ADDR, calibrationFactor);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Kalibrasi Selesai!");
lcd.setCursor(0, 1);
lcd.print("Faktor: ");
lcd.print(calibrationFactor, 2);
Serial.print("Faktor Kalibrasi Baru: ");
Serial.println(calibrationFactor, 2);
delay(3000);
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Kalibrasi Gagal!");
lcd.setCursor(0, 1);
lcd.print("Tidak ada pulsa.");
delay(3000);
}
currentMenuState = STATE_HOME;
displayHome();
}
break;
case STATE_FILLING:
displayFilling();
// Hitung volume air yang mengalir
totalVolumeML = (float)pulseCount / calibrationFactor;
// Logika pengisian
if (currentLevelPercentage < targetLevelPercentage) {
if (digitalRead(PUMP_PIN) == LOW) { // Jika pompa mati, nyalakan
turnPumpOn();
}
} else {
turnPumpOff(); // Matikan pompa jika level sudah tercapai
currentMenuState = STATE_HOME;
displayHome();
}
// Tombol SELECT untuk menghentikan pengisian secara manual
if (readButton(BUTTON_SELECT_PIN)) {
delay(200);
turnPumpOff();
currentMenuState = STATE_HOME;
displayHome();
}
break;
}
// Logika otomatis pengisian dari mode HOME
if (currentMenuState == STATE_HOME) {
if (currentLevelPercentage < (targetLevelPercentage - 2.0)) { // Mulai mengisi jika di bawah target (dengan histeresis)
currentMenuState = STATE_FILLING;
pulseCount = 0; // Reset pulse count sebelum memulai pengisian baru
totalVolumeML = 0;
turnPumpOn();
displayFilling();
}
}
// Debounce umum untuk semua tombol
delay(100);
}
Penjelasan Kode dan Fitur Lanjutan
Pengaturan Komponen:
#define
: Digunakan untuk pin dan konstanta. Memudahkan perubahan jika Anda menggunakan pin yang berbeda atau ukuran tangki yang lain.NewPing
: Library ini khusus untuk HC-SR04, memberikan pembacaan jarak yang lebih stabil dan fitur debounce.LiquidCrystal_I2C
: Untuk antarmuka LCD. Pastikan alamat I2C LCD Anda benar (0x27
atau0x3F
).
Sensor Level Air (Ultrasonik):
Fungsi
getDistanceCm()
membaca jarak dari sensor ke permukaan air.Fungsi
getLevelPercentage()
mengkonversi jarak tersebut menjadi persentase level air di dalam tangki, berdasarkanTANK_HEIGHT
yang Anda definisikan. Penting untuk mengukur tinggi tangki Anda dengan akurat.
Sensor Aliran Air:
Menggunakan Interrupt: Sensor aliran terhubung ke pin interrupt (
FLOW_SENSOR_PIN
). Setiap kali ada pulsa dari sensor, fungsiflowISR()
akan dipanggil secara otomatis dan cepat, meningkatkan akurasi penghitungan pulsa.calibrationFactor
: Ini adalah kunci untuk akurasi pengukuran volume. Nilai ini menunjukkan berapa banyak pulsa yang dihasilkan sensor untuk setiap mililiter air. Ini harus dikalibrasi.totalVolumeML
: Menghitung volume air yang telah mengalir berdasarkanpulseCount
dancalibrationFactor
.
Kontrol Pompa:
Menggunakan modul Relay untuk mengontrol pompa DC, yang biasanya membutuhkan tegangan dan arus lebih tinggi daripada yang bisa disediakan langsung oleh pin Arduino.
Fungsi
turnPumpOn()
danturnPumpOff()
untuk memudahkan kontrol.
LCD dan Antarmuka Pengguna:
LiquidCrystal_I2C
: Menampilkan informasi level air, target, volume, dan status sistem.enum MenuState
: Mengelola status menu yang berbeda (HOME
,SET_TARGET_LEVEL
,CALIBRATE_FLOW
,FILLING
,CALIBRATING_RUN
). Ini membuat navigasi menu lebih terstruktur.Fungsi
displayX()
: Setiap fungsi bertanggung jawab untuk menampilkan informasi yang relevan dengan state menu saat ini.Tombol
UP
,DOWN
,SELECT
: Untuk navigasi dan pengaturan. TombolSELECT
juga digunakan untuk memulai/menghentikan kalibrasi dan pengisian manual.
Fitur Canggih:
Kalibrasi Aliran Air (Flow Calibration):
Memungkinkan Anda mengkalibrasi sensor aliran untuk akurasi yang lebih baik.
Anda akan diminta untuk menyiapkan volume air tertentu (misal: 1 liter = 1000mL) dan membiarkan pompa mengisi volume tersebut.
Selama kalibrasi, sistem akan menghitung total pulsa yang dihasilkan.
calibrationFactor = (float)pulseCount / CALIBRATION_VOLUME_ML;
: Faktor kalibrasi dihitung berdasarkan pulsa yang terdeteksi dan volume air yang diketahui.Penyimpanan EEPROM: Faktor kalibrasi yang dihitung disimpan di EEPROM Arduino (
EEPROM.put
/EEPROM.get
). Ini berarti nilai kalibrasi akan tetap tersimpan bahkan setelah Arduino dimatikan. Ini sangat penting untuk akurasi jangka panjang.
Target Level dalam Persentase: Lebih intuitif daripada menggunakan jarak atau volume absolut.
Histeresis untuk Pengisian: Dalam
STATE_HOME
, pompa akan mulai mengisi jika level air di bawahtargetLevelPercentage - 2.0%
. Ini mencegah pompa sering hidup/mati (chattering) jika level air berfluktuasi sedikit di sekitar target.Reset Volume Otomatis:
totalVolumeML
di-reset setiap kali pompa dimatikan (setelah pengisian selesai atau dihentikan manual).Debounce Tombol:
delay(200)
ataudelay(100)
setelah pembacaan tombol untuk mencegah pembacaan ganda karena pantulan mekanis tombol.Timeout Kalibrasi: Jika kalibrasi dimulai dan tidak ada tombol
SELECT
yang ditekan, ia akan berhenti otomatis setelah 30 detik untuk mencegah pompa berjalan terus-menerus.
Cara Penggunaan
Pasang Semua Komponen: Ikuti skema pengkabelan yang disebutkan.
Instal Library: Buka Arduino IDE, pergi ke Sketch > Include Library > Manage Libraries... dan cari "LiquidCrystal I2C" serta "NewPing" untuk menginstalnya.
Sesuaikan Parameter:
Ubah
LCD_ADDR
jika alamat I2C LCD Anda berbeda.Ubah
MAX_DISTANCE
dan terutamaTANK_HEIGHT
sesuai dengan tinggi tangki Anda yang sebenarnya (dari sensor ke dasar tangki saat kosong).Sesuaikan
CALIBRATION_VOLUME_ML
jika Anda ingin menggunakan volume kalibrasi yang berbeda (misal, 500mL atau 2000mL).
Unggah Kode: Unggah kode ke papan Arduino Anda.
Kalibrasi Sensor Aliran:
Setelah diunggah, Arduino akan booting ke mode
HOME
.Tekan tombol UP untuk masuk ke menu kalibrasi (
STATE_CALIBRATE_FLOW
).Siapkan wadah berukuran tepat (misal, botol 1 Liter jika
CALIBRATION_VOLUME_ML
= 1000).Tekan tombol SELECT untuk memulai kalibrasi. Pompa akan menyala.
Biarkan pompa mengisi wadah Anda hingga mencapai volume yang ditentukan (misal, 1 Liter).
Segera setelah volume tercapai, tekan tombol SELECT lagi untuk menghentikan kalibrasi.
LCD akan menampilkan "Kalibrasi Selesai!" dan faktor kalibrasi baru. Faktor ini akan disimpan di EEPROM.
Atur Level Target:
Dari mode
HOME
, tekan tombol SELECT untuk masuk ke menu "Set Level".Gunakan tombol UP dan DOWN untuk mengatur persentase level air yang Anda inginkan (misal, 80%).
Tekan tombol SELECT lagi untuk menyimpan pengaturan dan kembali ke
HOME
.
Operasi Otomatis:
Dalam mode
HOME
, sistem akan secara otomatis memantau level air.Jika level air turun di bawah target (dengan histeresis), pompa akan menyala secara otomatis untuk mengisi tangki.
Pompa akan mati ketika level air mencapai target.
Anda juga dapat menekan tombol SELECT kapan saja selama pengisian untuk menghentikannya secara manual.
Potensi Pengembangan Lanjut
Antarmuka Lebih Kaya: Gunakan LCD grafis atau antarmuka web (dengan modul ESP8266/ESP32) untuk visualisasi yang lebih baik.
Sensor Keamanan: Tambahkan sensor kebocoran, sensor level air maksimum/minimum fisik (float switch) sebagai redundansi.
Mode Manual: Tambahkan mode di mana pengguna dapat menyalakan/mematikan pompa secara manual.
Peringatan/Notifikasi: Buzzer, LED, atau bahkan notifikasi ke smartphone (dengan modul Wi-Fi) untuk level rendah, pengisian selesai, atau masalah.
Penjadwalan: Fitur untuk mengisi air pada waktu tertentu.
Riwayat Data: Menyimpan data pengisian atau konsumsi air.
Kontrol PID: Untuk pengisian yang lebih halus dan presisi, meskipun untuk pengisian tangki sederhana ini mungkin terlalu kompleks.
Program ini menyediakan dasar yang kuat untuk sistem pengisian air otomatis yang cerdas dan andal. Selamat mencoba!
Komentar
Posting Komentar