#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define LCD_ADDRESS 0x27 // Alamat I2C, sesuaikan jika perlu
#define LCD_COLUMNS 16
#define LCD_ROWS 2
LiquidCrystal_I2C lcd(LCD_ADDRESS, LCD_COLUMNS, LCD_ROWS);
// Pin assignments
enum PinAssignments {
dtPinA = 2, // DT
clkPinB = 3, // CLK
swButton = 8, // SW
buttonMenu = 4 // button menu
};
volatile int encoderPos = 0;
unsigned int lastReportedPos = 1; // change management
static boolean rotating = false; // debounce management
// Interrupt service routine vars
boolean A_set = false;
boolean B_set = false;
const float pi = 3.14;
const float R = 2; // circle radius
const int N = 20; // number of steps on Rotary Encoder (in 1 rotation = 360 degrees = 20 Step)
float distance = 0;
float circumference = 0;
float trackDistance = 0;
int menuDirection;
void setup() {
lcd.begin(LCD_COLUMNS, LCD_ROWS); // Inisialisasi LCD I2C dengan kolom dan baris
lcd.print("Initializing..."); // Tampilkan pesan sementara
lcd.backlight(); // Nyalakan lampu latar (jika ada)
pinMode(dtPinA, INPUT_PULLUP);
pinMode(clkPinB, INPUT_PULLUP);
pinMode(swButton, INPUT_PULLUP);
pinMode(buttonMenu, INPUT_PULLUP);
// Attach interrupt
attachInterrupt(digitalPinToInterrupt(dtPinA), doEncoderA, CHANGE);
attachInterrupt(digitalPinToInterrupt(clkPinB), doEncoderB, CHANGE);
}
void loop() {
measuringDirection();
rotating = true; // reset the debouncer
if (lastReportedPos != encoderPos) {
// Lintasan = Keliling x Putaran
circumference = 2 * pi * R;
trackDistance = circumference * encoderPos;
distance = trackDistance / N;
displayUpdate();
lastReportedPos = encoderPos;
}
if (digitalRead(swButton) == LOW) {
encoderPos = 0;
displayUpdate();
}
}
// Interrupt on A changing state
void doEncoderA() {
if (rotating) delay(1); // wait a little until the bouncing is done
if (digitalRead(dtPinA) != A_set) {
A_set = !A_set;
if (A_set && !B_set) {
if (menuDirection == 1) {
encoderPos += 1;
}
}
rotating = false; // no more debouncing until loop() hits again
}
}
// Interrupt on B changing state
void doEncoderB() {
if (rotating) delay(1);
if (digitalRead(clkPinB) != B_set) {
B_set = !B_set;
if (B_set && !A_set) {
if (menuDirection == 0) {
encoderPos += 1;
}
}
rotating = false;
}
}
// Button Direction
void measuringDirection() {
if (digitalRead(buttonMenu) == LOW) {
encoderPos = 0;
menuDirection++;
if (menuDirection > 1) {
menuDirection = 0;
}
delay(300);
displayUpdate();
}
}
// Display menu
void displayUpdate() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Distance: ");
lcd.setCursor(0, 1);
lcd.print(distance);
lcd.print(" cm");
}