#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <EEPROM.h>
#define SCREEN_WIDTH 128 // Lebar layar OLED, dalam piksel
#define SCREEN_HEIGHT 64 // Tinggi layar OLED, dalam piksel
#define OLED_RESET -1 // Pin reset # (atau -1 jika menggunakan pin reset Arduino)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Definisikan koneksi pin
const int fuelPotPin = A0;
const int speedPotPin = A1;
const int rpmPotPin = A2;
const int buttonPin = 4;
const int switchPin1 = 5; // Pin untuk tombol ganti mode Speed -> Trip A/B
const int switchPin2 = 6; // Pin untuk tombol reset Trip A/B
// Definisikan alamat EEPROM untuk menyimpan data
#define ADDR_KM_TRAVELED 0
#define ADDR_KM_TRIP_A 4
#define ADDR_KM_TRIP_B 8
// Variabel untuk mode dan pembacaan sensor
int mode = 0; // 0: Fuel, 1: Speed, 2: RPM, 3: Trip A, 4: Trip B
float fuelLevelRaw = 0;
float fuelLevelSmoothed = 0;
float fuelLevelStable = 0;
float lastFuelLevelSmoothed = 0;
const float alpha = 0.05; // Faktor untuk perataan (smoothing)
const int stabilityThreshold = 10; // Ambang batas untuk stabilitas
int speed = 0;
int lastSpeed = 0;
unsigned long kmTraveled = 0;
unsigned long kmTripA = 0;
unsigned long kmTripB = 0;
unsigned long lastTime = 0;
int rpm = 0; // Deklarasi variabel rpm
void setup() {
pinMode(fuelPotPin, INPUT);
pinMode(speedPotPin, INPUT);
pinMode(rpmPotPin, INPUT);
pinMode(buttonPin, INPUT_PULLUP);
pinMode(switchPin1, INPUT_PULLUP);
pinMode(switchPin2, INPUT_PULLUP);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
// Animasi teks saat Arduino dihidupkan
animateStartingText();
// Begin EEPROM without specifying size
EEPROM.begin(); // Initialize EEPROM
// Read values from EEPROM on startup
EEPROM.get(ADDR_KM_TRAVELED, kmTraveled);
EEPROM.get(ADDR_KM_TRIP_A, kmTripA);
EEPROM.get(ADDR_KM_TRIP_B, kmTripB);
// Display initial screen after animation
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("Initializing...");
display.display();
delay(1000); // Delay before starting main loop
}
void loop() {
if (digitalRead(buttonPin) == LOW) {
mode = (mode + 1) % 5; // Berpindah antara mode (0-4)
delay(300); // Delay untuk mencegah bounce pada tombol
}
if (digitalRead(switchPin1) == LOW) {
if (mode == 1) {
mode = 3; // Ganti ke mode Trip A
} else if (mode == 3) {
mode = 4; // Ganti ke mode Trip B
} else if (mode == 4) {
mode = 1; // Kembali ke mode Speed
}
delay(300); // Delay untuk mencegah bounce pada tombol
}
if (digitalRead(switchPin2) == LOW) {
if (mode == 3) {
kmTripA = 0; // Reset Trip A
} else if (mode == 4) {
kmTripB = 0; // Reset Trip B
}
// Reset juga nilai km total jika diperlukan
resetKilometers();
delay(300); // Delay untuk mencegah bounce pada tombol
}
switch (mode) {
case 0:
displayFuelLevel();
break;
case 1:
displaySpeed();
break;
case 2:
displayRPM();
break;
case 3:
displayTripA();
break;
case 4:
displayTripB();
break;
}
delay(100); // Delay antar update layar
}
void animateStartingText() {
// Frame 1: "CRF 150L"
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20, 20);
display.println("CRF 150L");
display.display();
delay(1000);
// Frame 2: Geser ke kiri dengan gambar roda
for (int i = 0; i < 120; ++i) {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(20 - i, 20);
display.println("CRF 150L");
// Gambar roda sebagai efek
display.drawLine(110 - i, 40, 120 - i, 40, SSD1306_WHITE);
display.drawCircle(110 - i, 40, 5, SSD1306_WHITE);
display.drawCircle(120 - i, 40, 5, SSD1306_WHITE);
display.display();
delay(20);
}
// Frame 3: "Memuat..."
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(40, 30);
display.println("Memuat...");
display.display();
delay(1000); // Delay sebelum masuk ke tampilan utama
}
void displayFuelLevel() {
fuelLevelRaw = analogRead(fuelPotPin);
// Perataan dengan moving average eksponensial (EMA)
fuelLevelSmoothed = alpha * fuelLevelRaw + (1 - alpha) * fuelLevelSmoothed;
// Update nilai stabil hanya jika perubahan nilai halus
if (abs(fuelLevelSmoothed - lastFuelLevelSmoothed) < stabilityThreshold) {
fuelLevelStable = fuelLevelSmoothed;
}
lastFuelLevelSmoothed = fuelLevelSmoothed;
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.print("Fuel Level");
// Tampilkan tingkat bahan bakar sebagai bar
int barWidth = map(fuelLevelStable, 0, 1023, 0, 128); // Skala lebar layar
display.fillRect(0, 20, barWidth, 20, SSD1306_WHITE); // Gambar bar terisi
display.drawRect(0, 20, 128, 20, SSD1306_WHITE); // Gambar border
display.display();
}
void displaySpeed() {
speed = analogRead(speedPotPin) * (100.0 / 1023.0); // Konversi contoh ke kecepatan km/jam
unsigned long currentTime = millis();
// Hitung jarak yang ditempuh jika kecepatan di atas 0
if (speed > 0 && lastSpeed > 0) {
unsigned long deltaTime = currentTime - lastTime;
kmTraveled += (speed * deltaTime) / 3600; // Konversi ke km (3600000 = 1000 * 60 * 60)
kmTripA += (speed * deltaTime) / 3600; // Update Trip A
kmTripB += (speed * deltaTime) / 3600; // Update Trip B
}
lastSpeed = speed;
lastTime = currentTime;
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 10);
display.print("Speed: ");
display.print(speed);
display.print(" km/h");
display.setTextSize(1);
display.setCursor(0, 40);
if (mode == 1) {
display.print("Total Km: ");
display.print(kmTraveled);
} else if (mode == 3) {
display.print("Trip A: ");
display.print(kmTripA);
} else if (mode == 4) {
display.print("Trip B: ");
display.print(kmTripB);
}
display.display();
}
void displayRPM() {
rpm = analogRead(rpmPotPin) * (8000.0 / 1023.0); // Konversi contoh ke RPM
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 10);
display.print("RPM: ");
display.print(rpm);
display.display();
}
void displayTripA() {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 10);
display.print("Trip A: ");
display.print(kmTripA);
display.display();
}
void displayTripB() {
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 10);
display.print("Trip B: ");
display.print(kmTripB);
display.display();
}
void resetKilometers() {
kmTraveled = 0;
kmTripA = 0;
kmTripB = 0;
// Simpan nilai km ke EEPROM
EEPROM.put(ADDR_KM_TRAVELED, kmTraveled);
EEPROM.put(ADDR_KM_TRIP_A, kmTripA);
EEPROM.put(ADDR_KM_TRIP_B, kmTripB);
}