// =============================================================
// Mesin Tancap Bulu Shuttlecock Otomatis - Auto Repeat Version
// Fitur: LCD I2C, Tombol START / RESET / PAUSE, Stepper Meja Otomatis
// Dibuat oleh [Eko Andriyanto] - [09 April 2025 / V 1.1]
// =============================================================
#include <AccelStepper.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// === INISIALISASI LCD I2C ===
LiquidCrystal_I2C lcd(0x27, 16, 2);
// === PIN DEFINISI ===
const int stepPinBulu = 23;
const int dirPinBulu = 22;
const int stepPinMeja = 27;
const int dirPinMeja = 26;
const int relaybulu = 2; // Relay masukkan bulu
const int relaykayu = 3; // Relay masukkan kayu
const int startButton = A1;
const int resetButton = A2;
const int pauseButton = A3;
const int ledOrange = 4;
const int ledGreen = 5;
const int buzzerPin = 10;
// === KONSTANTA ===
const int langkahPerPutaran = 1600;
const int langkahPerTancap = 100;
const int delayRelay = 500;
const int delayPneu = 500;
const int langkahMeja90 = 400; // Sesuaikan dengan stepper meja
// === VARIABEL ===
AccelStepper stepperBulu(AccelStepper::DRIVER, stepPinBulu, dirPinBulu);
AccelStepper stepperMeja(AccelStepper::DRIVER, stepPinMeja, dirPinMeja);
int posisiBulu = 0;
bool prosesAktif = false;
bool prosesPause = false;
bool lastStartState = HIGH;
bool lastPauseState = HIGH;
bool lastResetState = HIGH;
int putaranKe = 0;
void setup() {
lcd.init();
lcd.backlight();
pinMode(relaybulu, OUTPUT);
pinMode(relaykayu, OUTPUT);
pinMode(startButton, INPUT_PULLUP);
pinMode(resetButton, INPUT_PULLUP);
pinMode(pauseButton, INPUT_PULLUP);
pinMode(ledOrange, OUTPUT);
pinMode(ledGreen, OUTPUT);
pinMode(buzzerPin, OUTPUT);
// Set semua output awal ke kondisi aman
digitalWrite(relaybulu, LOW);
digitalWrite(relaykayu, LOW);
digitalWrite(ledOrange, HIGH);
digitalWrite(ledGreen, LOW);
digitalWrite(buzzerPin, LOW);
stepperBulu.setMaxSpeed(8000);
stepperBulu.setAcceleration(4000);
stepperBulu.setCurrentPosition(0);
stepperMeja.setMaxSpeed(1000);
stepperMeja.setAcceleration(500);
stepperMeja.setCurrentPosition(0);
tampilkanRunningText();
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Tekan START");
}
void tampilkanRunningText() {
String baris1 = " Mesin Tancap Bulu Otomatis ";
String baris2 = " Maju Teknik Art ";
int panjangScroll = max(baris1.length(), baris2.length());
for (int i = 0; i < panjangScroll - 15; i++) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(baris1.substring(i, min(i + 16, baris1.length())));
lcd.setCursor(0, 1);
lcd.print(baris2.substring(i, min(i + 16, baris2.length())));
delay(400);
}
}
void bunyiBuzzer() {
digitalWrite(buzzerPin, HIGH);
delay(100);
digitalWrite(buzzerPin, LOW);
}
void loop() {
bool startNow = digitalRead(startButton);
bool pauseNow = digitalRead(pauseButton);
bool resetNow = digitalRead(resetButton);
// === RESET / EMERGENCY STOP ===
if (resetNow == LOW && lastResetState == HIGH) {
putaranKe = 0;
posisiBulu = 0;
prosesAktif = false;
prosesPause = false;
stepperBulu.stop();
stepperMeja.stop();
digitalWrite(relaybulu, LOW);
digitalWrite(relaykayu, LOW);
digitalWrite(ledGreen, LOW);
digitalWrite(ledOrange, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Jumlah direset");
lcd.setCursor(0, 1);
lcd.print("Tekan START");
bunyiBuzzer();
delay(500);
}
lastResetState = resetNow;
// === PAUSE ===
if (pauseNow == LOW && lastPauseState == HIGH && prosesAktif) {
prosesPause = !prosesPause;
if (prosesPause) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("== PAUSED ==");
lcd.setCursor(0, 1);
lcd.print(" Lepas PAUSE ");
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Lanjut proses...");
lcd.setCursor(0, 1);
lcd.print("Tancap Bulu");
}
bunyiBuzzer();
delay(500);
}
lastPauseState = pauseNow;
// === START === (Hanya sekali)
if (!prosesAktif && startNow == LOW && lastStartState == HIGH) {
bunyiBuzzer();
prosesAktif = true;
posisiBulu = 0;
stepperBulu.setCurrentPosition(0);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Mulai dalam:");
for (int i = 3; i > 0; i--) {
lcd.setCursor(13, 0);
lcd.print(i);
lcd.setCursor(0, 1);
lcd.print("Bersiap... ");
delay(500);
}
digitalWrite(ledOrange, LOW);
digitalWrite(ledGreen, HIGH);
lcd.clear();
}
lastStartState = startNow;
// === PROSES BERULANG ===
if (prosesAktif && !prosesPause) {
lcd.setCursor(0, 0);
lcd.print("Running ");
lcd.setCursor(0, 1);
lcd.print("Kok: ");
lcd.print(putaranKe + 1);
lcd.print(" ");
if (posisiBulu < langkahPerPutaran) {
digitalWrite(relaybulu, HIGH);
delay(delayRelay);
digitalWrite(relaybulu, LOW);
delay(delayRelay);
posisiBulu += langkahPerTancap;
stepperBulu.moveTo(posisiBulu);
stepperBulu.runToPosition();
} else {
posisiBulu = 0;
stepperBulu.setCurrentPosition(0);
// Delay sedikit setelah selesai
delay(200);
digitalWrite(relaybulu, HIGH);
delay(500);
digitalWrite(relaybulu, LOW);
delay(500);
digitalWrite(relaykayu, HIGH);
delay(500);
digitalWrite(relaykayu, LOW);
delay(500);
putaranKe++;
stepperMeja.move(langkahMeja90);
stepperMeja.runToPosition();
}
}
}