#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
#include <AccelStepper.h>
const int stepsPerRevolution = 200;
const float wheelDiameter = 5.0;
const float distancePerStep = (wheelDiameter * PI) / stepsPerRevolution;
const int buzzerPin = 12;
const int motorStepPin = 2;
const int motorDirPin = 3;
/* Display */
LiquidCrystal_I2C lcd(0x27, 16, 2);
// AccelStepper Setup
AccelStepper stepper(1, motorStepPin, motorDirPin); // 1 = Easy Driver interface
/* Keypad setup */
const byte ROW_NUM = 4; // Jumlah baris pada keypad
const byte COLUMN_NUM = 4; // Jumlah kolom pada keypad
byte pin_rows[ROW_NUM] = {11, 10, 9, 8}; // Sesuaikan dengan koneksi keypad ke Arduino
byte pin_column[COLUMN_NUM] = {7, 6, 5, 4}; // Sesuaikan dengan koneksi keypad ke Arduino
char keys[ROW_NUM][COLUMN_NUM] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
Keypad keypad = Keypad(makeKeymap(keys), pin_rows, pin_column, ROW_NUM, COLUMN_NUM);
long targetDistance = 0; // Nilai default 0 cm
long currentDistance = 0;
bool isPaused = true; // Diubah menjadi true agar motor tidak bergerak sebelum perintah start
bool isBuzzerOn = false;
void handleKeypadInput(char key);
void startMeasurement(int z);
void togglePause();
void cancelMeasurement();
void resetMeasurement();
void moveStepperMotor(bool isClockwise); // Menambahkan parameter untuk menentukan arah putaran motor
void stopMotor();
void playBuzzer();
void updateLCD(); // Deklarasi fungsi updateLCD
void setup() {
pinMode(buzzerPin, OUTPUT);
// AccelStepper speed and acceleration setup
stepper.setMaxSpeed(1500); // Not too fast or you will have missed steps
stepper.setAcceleration(200); // Same here
lcd.begin(16, 2);
lcd.setCursor(0, 0);
lcd.print("Panjang: cm");
lcd.setCursor(0, 1);
lcd.print("Current: cm"); // Mengubah nilai awal current menjadi 0 cm
}
void loop() {
char key = keypad.getKey();
if (key) {
handleKeypadInput(key);
}
if (!isPaused && currentDistance < targetDistance) {
moveStepperMotor(true); // Motor berputar CW
} else {
stopMotor();
if (!isPaused && currentDistance >= targetDistance && !isBuzzerOn) {
playBuzzer();
isBuzzerOn = true;
}
}
}
void updateLCD() {
lcd.setCursor(9, 1);
lcd.print(" cm"); // Menghapus tampilan sebelumnya
lcd.setCursor(9, 1);
lcd.print(currentDistance);
}
void handleKeypadInput(char key) {
switch(key) {
case 'A':
startMeasurement(targetDistance);
playBuzzer(); // Menambahkan bunyi bip saat tombol start ditekan
break;
case 'B':
togglePause();
break;
case 'C':
cancelMeasurement();
break;
case 'D':
resetMeasurement();
break;
default:
if (isdigit(key)) {
targetDistance = (targetDistance * 10 + (key - '0')); // Mengubah targetDistance sesuai input keypad
lcd.setCursor(9, 0);
lcd.print(" cm"); // Menghapus tampilan sebelumnya
lcd.setCursor(9, 0);
lcd.print(targetDistance);
}
}
}
void startMeasurement(int z) {
int calculatedMove = ((z * 160)/8);
stepper.moveTo(calculatedMove);
stepper.runToPosition();
currentDistance = z;
isPaused = false;
isBuzzerOn = false;
lcd.setCursor(9, 1);
lcd.print(" cm"); // Menghapus tampilan sebelumnya
lcd.setCursor(9, 1);
lcd.print(currentDistance);
}
void togglePause() {
isPaused = !isPaused;
}
void cancelMeasurement() {
stopMotor();
isPaused = true; // Diubah menjadi true agar motor tidak bergerak setelah dibatalkan
}
void resetMeasurement() {
stopMotor();
currentDistance = 0;
targetDistance = 0; // Mengembalikan nilai default 0 cm
isPaused = true; // Diubah menjadi true agar motor tidak bergerak setelah direset
isBuzzerOn = false;
lcd.setCursor(9, 0);
lcd.print(" cm"); // Menghapus tampilan sebelumnya
lcd.setCursor(9, 0);
lcd.print(targetDistance);
lcd.setCursor(9, 1);
lcd.print(" cm"); // Menghapus tampilan sebelumnya
lcd.setCursor(9, 1);
lcd.print(currentDistance);
}
void moveStepperMotor(bool isClockwise) {
if (!isPaused) { // Motor hanya akan bergerak jika tidak di-pause
if (isClockwise) {
stepper.setSpeed(1000); // Kecepatan putaran CW
} else {
stepper.setSpeed(-1000); // Kecepatan putaran CCW
}
stepper.runSpeed();
currentDistance += distancePerStep; // Menambahkan perhitungan perputaran motor ke currentDistance
updateLCD(); // Memperbarui tampilan LCD setelah perubahan currentDistance
}
}
void stopMotor() {
stepper.setCurrentPosition(0); // Mengatur posisi motor menjadi 0
stepper.stop();
}
void playBuzzer() {
tone(buzzerPin, 1000, 50);
delay(50);
noTone(buzzerPin); // Menghentikan bunyi buzzer
}