#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Inisialisasi I2C LCD 16x2
LiquidCrystal_I2C lcd(0x27, 16, 2); // Alamat I2C bisa 0x27 atau 0x3F, tergantung modul
// Pin Setup
int Coil1 = 4;
int Coil2 = 5;
int Clutch = 6;
int Sensor = 7;
int DelayTrim = A2;
int ClutchLED = 8; // LED indikator untuk kopling
// Menu navigation buttons
int PlusRPM = 2;
int MinusRPM = 3;
int NextButton = 9; // Tombol untuk berpindah menu
// Variabel untuk RPM dan waktu
int RPMW = 3000; // RPM yang diinginkan
unsigned long RPM = 0; // RPM aktual
volatile bool PlusFlag = false;
volatile bool MinusFlag = false;
unsigned long PulseLength = 0;
volatile int Delay = 0;
int menuIndex = 0; // Indeks untuk mengontrol menu
int maxMenuIndex = 2; // Total jumlah menu
// Waktu untuk debounce tombol
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 200; // Delay untuk debounce
// Waktu untuk tampilan merk dagang dan loading bar
unsigned long displayStartTime = 0;
bool brandDisplayed = false;
bool loadingCompleted = false;
int loadingBarProgress = 0;
// Waktu blinking untuk Coil
unsigned long lastBlinkTime = 0;
bool coilState = false;
void setup() {
pinMode(Coil1, OUTPUT);
pinMode(Coil2, OUTPUT);
pinMode(Clutch, INPUT);
pinMode(Sensor, INPUT);
pinMode(PlusRPM, INPUT);
pinMode(MinusRPM, INPUT);
pinMode(NextButton, INPUT);
pinMode(ClutchLED, OUTPUT); // Set pin LED sebagai output
// Attach interrupts untuk tombol Plus dan Minus
attachInterrupt(digitalPinToInterrupt(PlusRPM), plus, FALLING);
attachInterrupt(digitalPinToInterrupt(MinusRPM), minus, FALLING);
// Mulai komunikasi serial
Serial.begin(9600);
// Inisialisasi LCD
lcd.init();
lcd.backlight();
// Simpan waktu mulai untuk menampilkan merk dagang
displayStartTime = millis();
}
void loop() {
// Tampilkan merk dagang dan loading bar selama 3 detik sebelum masuk ke menu utama
if (!brandDisplayed) {
if (millis() - displayStartTime < 4000) {
lcd.setCursor(1, 0);
lcd.print("RY Controller");
// Update loading bar setiap 300 ms
if (millis() - displayStartTime >= 300 * loadingBarProgress && loadingBarProgress <= 15) {
lcd.setCursor(0, 1);
lcd.print("[");
for (int i = 0; i < loadingBarProgress; i++) {
lcd.print(">"); // Progress bar
}
lcd.setCursor(15, 1);
lcd.print("]");
loadingBarProgress++;
}
} else {
brandDisplayed = true; // Setelah 3 detik, lanjutkan ke menu utama
lcd.clear(); // Bersihkan layar saat berpindah ke menu utama
}
return; // Keluar dari loop agar merk dagang tetap tampil selama 3 detik
}
// Baca nilai Delay dan hitung RPM
Delay = map(analogRead(DelayTrim), 0, 1023, 0, 500);
PulseLength = pulseIn(Sensor, LOW);
if (PulseLength > 0) {
RPM = 60000000 / PulseLength; // Hitung RPM aktual
} else {
RPM = 0;
}
// Tambah dan kurangi RPMW dengan flag interrupt
if (PlusFlag) {
PlusFlag = false;
RPMW += 1000;
if (RPMW > 7000) RPMW = 7000; // Batasi nilai maksimum
}
if (MinusFlag) {
MinusFlag = false;
RPMW -= 1000;
if (RPMW < 1000) RPMW = 1000; // Batasi nilai minimum
}
// Debouncing untuk tombol Next
if (digitalRead(NextButton) == HIGH && millis() - lastDebounceTime > debounceDelay) {
lastDebounceTime = millis();
menuIndex++;
if (menuIndex > maxMenuIndex) {
menuIndex = 0; // Reset menu ke awal jika melebihi jumlah menu
}
}
// Tampilan menu di LCD
lcd.clear();
switch (menuIndex) {
case 0:
// Menu RPM Real-time dan status kopling
lcd.setCursor(0, 0);
lcd.print("Real RPM: ");
lcd.print(RPM);
lcd.setCursor(0, 1);
lcd.print("Clutch: ");
if (digitalRead(Clutch) == HIGH) {
lcd.print("ON");
} else {
lcd.print("OFF");
}
break;
case 1:
// Menu Delay Trim
lcd.setCursor(0, 0);
lcd.print("PWM:");
lcd.setCursor(6, 0);
lcd.print( Delay);
lcd.print(" ms");
lcd.setCursor(5, 1);
lcd.print(" Next");
break;
case 2:
// Menu RPM Limit
lcd.setCursor(0, 0);
lcd.print("RPM Limit:");
lcd.print(RPMW);
lcd.setCursor(5, 1);
lcd.print(" Next");
break;
}
// Cek status kopling
int clutchState = digitalRead(Clutch);
// Logika blinking untuk Coil berdasarkan RPMW dan status kopling
if (clutchState == HIGH) { // Kopling ditekan
digitalWrite(ClutchLED, HIGH); // LED indikator menyala
if (RPM >= RPMW) {
unsigned long currentTime = millis();
if (currentTime - lastBlinkTime >= Delay) {
coilState = !coilState;
digitalWrite(Coil1, coilState);
digitalWrite(Coil2, coilState);
lastBlinkTime = currentTime;
}
} else {
digitalWrite(Coil1, LOW);
digitalWrite(Coil2, LOW);
}
} else { // Kopling dilepas
digitalWrite(ClutchLED, LOW); // LED indikator mati
digitalWrite(Coil1, LOW); // Matikan Coil1
digitalWrite(Coil2, LOW); // Matikan Coil2
}
delay(200); // Tambahkan sedikit jeda untuk keterbacaan tampilan
}
// Fungsi untuk interrupt RPMW
void plus() {
PlusFlag = true;
}
void minus() {
MinusFlag = true;
}