// =============================================================
// Mesin Tancap Bulu Shuttlecock Otomatis - Versi Produksi Massal
// Fitur: LCD I2C, Tombol START / RESET / PAUSE, Buzzer, LED Indikator
// Dibuat oleh [Eko Andriyanto] - [08 april 2025 / V 1.0a]
// =============================================================
#include <AccelStepper.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// === INISIALISASI LCD I2C ===
LiquidCrystal_I2C lcd(0x27, 16, 2); // Alamat I2C bisa berbeda tergantung modul
// === PIN DEFINISI ===
const int stepPinBulu = 24;
const int dirPinBulu = 25;
const int relayPin = 2; // Relay tancap bulu
const int relayPneuPin = 3; // Relay pneumatik
const int relayMasukKayu = 6; // Relay masukkan kayu
const int startButton = 7; // Tombol START
const int resetButton = 8; // Tombol RESET (hapus jumlah putaran)
const int pauseButton = 9; // Tombol PAUSE / RESUME
const int ledOrange = 4; // Indikator proses OFF
const int ledGreen = 5; // Indikator proses ON
const int buzzerPin = 10; // Buzzer untuk notifikasi tombol
// === KONSTANTA ===
const int langkahPerPutaran = 1600; // 16 bulu x 100 langkah
const int langkahPerTancap = 100; // Langkah setiap tancapan
const int delayRelay = 500; // Delay ON/OFF relay bulu
const int delayPneu = 500; // Delay pneumatik
// === VARIABEL ===
AccelStepper stepperBulu(AccelStepper::DRIVER, stepPinBulu, dirPinBulu);
int posisiBulu = 0;
bool prosesAktif = false;
bool prosesPause = false;
bool lastStartState = HIGH;
bool lastPauseState = HIGH;
bool lastResetState = HIGH;
int putaranKe = 0;
void setup() {
Serial.begin(9600);
lcd.init();
lcd.backlight();
// Set mode pin
pinMode(relayPin, OUTPUT);
pinMode(relayPneuPin, OUTPUT);
pinMode(relayMasukKayu, OUTPUT);
pinMode(startButton, INPUT_PULLUP);
pinMode(resetButton, INPUT_PULLUP);
pinMode(pauseButton, INPUT_PULLUP);
pinMode(ledOrange, OUTPUT);
pinMode(ledGreen, OUTPUT);
pinMode(buzzerPin, OUTPUT);
// Matikan semua awal
digitalWrite(relayPin, LOW);
digitalWrite(relayPneuPin, LOW);
digitalWrite(relayMasukKayu, LOW);
digitalWrite(ledOrange, HIGH);
digitalWrite(ledGreen, LOW);
// Setup stepper
stepperBulu.setMaxSpeed(8000);
stepperBulu.setAcceleration(4000);
stepperBulu.setCurrentPosition(0);
tampilkanRunningText();
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Tekan START");
}
// Tampilkan animasi startup
void tampilkanRunningText() {
String teks = " Mesin Tancap Bulu Otomatis ";
for (int i = 0; i < teks.length() - 15; i++) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(teks.substring(i, i + 16));
delay(300);
}
}
// Buzzer bunyi singkat
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 ditekan ===
if (resetNow == LOW && lastResetState == HIGH) {
putaranKe = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Jumlah direset");
lcd.setCursor(0, 1);
lcd.print("Tekan START");
Serial.println("Jumlah putaran direset");
bunyiBuzzer();
delay(500);
}
lastResetState = resetNow;
// === PAUSE / RESUME ===
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 ");
Serial.println("PAUSE aktif");
} else {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Lanjut proses...");
lcd.setCursor(0, 1);
lcd.print("Tancap Bulu");
Serial.println("Lanjut dari PAUSE");
}
bunyiBuzzer();
delay(500);
}
lastPauseState = pauseNow;
// === START ditekan ===
if (startNow == LOW && lastStartState == HIGH && !prosesAktif) {
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);
}
// Masukkan kayu
digitalWrite(relayMasukKayu, HIGH);
delay(1000);
digitalWrite(relayMasukKayu, LOW);
delay(500);
// Status LED
digitalWrite(ledOrange, LOW);
digitalWrite(ledGreen, HIGH);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Proses Tancap");
}
lastStartState = startNow;
// === PROSES TANCAP ===
if (prosesAktif && !prosesPause) {
if (posisiBulu < langkahPerPutaran) {
digitalWrite(relayPin, HIGH);
delay(delayRelay);
digitalWrite(relayPin, LOW);
delay(delayRelay);
posisiBulu += langkahPerTancap;
stepperBulu.moveTo(posisiBulu);
stepperBulu.runToPosition();
Serial.print("Tancap ke posisi: ");
Serial.println(posisiBulu);
} else {
prosesAktif = false;
// Finishing step
digitalWrite(relayPin, HIGH);
delay(delayRelay);
digitalWrite(relayPin, LOW);
delay(delayRelay);
digitalWrite(relayPneuPin, HIGH);
delay(delayPneu);
digitalWrite(relayPneuPin, LOW);
delay(delayPneu);
putaranKe++;
digitalWrite(ledOrange, HIGH);
digitalWrite(ledGreen, LOW);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Jumlah ");
lcd.print(putaranKe);
lcd.print(" Done");
lcd.setCursor(0, 1);
lcd.print("Tekan START ");
Serial.print("Putaran selesai: ");
Serial.println(putaranKe);
}
}
}
Pneumatik memasukkan
Kayu
Pneumatik memasukkan
Bulu
Pneumatik mengeluarkan
Kok yang sudah jadi
START
RESET
PAUSE