#include <Wire.h>
#include <U8g2lib.h>
// Inicjalizacja wyświetlaczy SH1106
U8G2_SH1106_128X64_NONAME_F_HW_I2C display1(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // Wyświetlacz 1
U8G2_SH1106_128X64_NONAME_F_HW_I2C display2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // Wyświetlacz 2
U8G2_SH1106_128X64_NONAME_F_HW_I2C display3(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // Wyświetlacz 3
// Adresy I2C wyświetlaczy
#define OLED_ADDR1 0x3C
#define OLED_ADDR2 0x3D
#define OLED_ADDR3 0x3E
// Dane pomiarowe
float oilPressure = 0.0;
float boostPressure = 0.0;
float intakeTemp = 0.0;
float boostPressureBar = 0;
float intakeTempBar = 0;
float internalTemp = 0.0;
float rpm = 0.0;
float speed = 0.0;
float fuelPressure = 0.0;
float throttlePosition = 0.0;
// Zmienna czasu
unsigned long lastUpdateTime = 0;
unsigned long lastSensorUpdateTime = 0;
// Pin przycisku
const int buttonPin = 7;
// Stan przycisku
bool buttonState = false;
bool lastButtonState = false;
int displayMode = 0; // 0 - ciśnienie oleju, 1 - temperatura, ..., 7 - pozycja pedału gazu
// Zmienne dla debounce
unsigned long lastButtonPressTime = 0;
unsigned long debounceDelay = 50; // 50 ms debounce delay
bool logoDisplayed = false; // Flaga, czy logo zostało wyświetlone
void setup() {
Wire.begin();
pinMode(buttonPin, INPUT_PULLUP); // Ustawienie przycisku jako wejście z pull-up
// Konfiguracja pierwszego wyświetlacza
Wire.beginTransmission(OLED_ADDR1);
if (Wire.endTransmission() == 0) {
display1.setI2CAddress(OLED_ADDR1 * 2);
display1.begin();
}
// Konfiguracja drugiego wyświetlacza (wyświetlenie logo VW na starcie)
Wire.beginTransmission(OLED_ADDR2);
if (Wire.endTransmission() == 0) {
display2.setI2CAddress(OLED_ADDR2 * 2);
display2.begin();
displayVWLogo(display2); // Wyświetlenie logo VW
}
// Konfiguracja trzeciego wyświetlacza
Wire.beginTransmission(OLED_ADDR3);
if (Wire.endTransmission() == 0) {
display3.setI2CAddress(OLED_ADDR3 * 2);
display3.begin();
}
}
void loop() {
unsigned long currentTime = millis();
// Obsługa przycisku (zmiana trybu wyświetlania)
buttonState = digitalRead(buttonPin) == LOW; // Sprawdzenie, czy przycisk jest wciśnięty
if (buttonState != lastButtonState) {
lastButtonState = buttonState;
if (buttonState && (currentTime - lastButtonPressTime > debounceDelay)) {
displayMode = (displayMode + 1) % 7; // Zmiana trybu wyświetlania
lastButtonPressTime = currentTime;
}
}
// Aktualizacja danych co 200 ms
if (currentTime - lastSensorUpdateTime >= 200) {
updateSensorData();
lastSensorUpdateTime = currentTime;
}
// Aktualizacja wyświetlaczy co 50 ms (dla płynności)
if (currentTime - lastUpdateTime >= 50) {
updateDisplays();
lastUpdateTime = currentTime;
}
}
void updateSensorData() {
// Generowanie losowych wartości dla symulacji
oilPressure = random(0, 30); // Losowe ciśnienie oleju (0-30)
boostPressure = random(0, 25) / 10.0; // Losowe ciśnienie doładowania (0-2.5)
intakeTemp = random(0, 70); // Losowa temperatura powietrza dolotowego (0-70)
internalTemp = random(-30, 40); // Losowa temperatura wewnętrzna (-30-40)
rpm = random(0, 6500); // Zmienia RPM o losową wartość
rpm = constrain(rpm, 0, 6500); // Ograniczenie do zakresu 1000-6500
speed = random(0, 150); // Losowa prędkość (0-150)
fuelPressure = random(0, 60); // Losowe ciśnienie paliwa (30-60)
throttlePosition = random(0, 100); // Losowa pozycja pedału gazu (0-100)
// Mapowanie wartości czujników do zakresu wyświetlania (0-124)
boostPressureBar = map(boostPressure, 0, 2.5, 0, 124);
intakeTempBar = map(intakeTemp, 0, 50, 0, 124);
// Ograniczanie wartości, aby uniknąć przepełnienia
boostPressureBar = constrain(boostPressureBar, 0, 124);
intakeTempBar = constrain(intakeTempBar, 0, 124);
}
void updateDisplays() {
// Wyświetlacz 1 - Wartości na ekranie
display1.firstPage();
do {
display1.setFont(u8g2_font_ncenB08_tr); // Używamy mniejszej czcionki dla tekstów
// W zależności od trybu, pokazujemy różne dane
switch (displayMode) {
case 0: // Ciśnienie oleju
display1.setCursor((128 - display1.getStrWidth("OIL PRESSURE")) / 20, 10); // Wyśrodkowanie
display1.drawStr(20, 10, "OIL PRESSURE");
char oilBuf[10];
sprintf(oilBuf, "%.1f BAR", oilPressure);
display1.setCursor((128 - display1.getStrWidth(oilBuf)) / 40, 30); // Wyśrodkowanie wartości
display1.drawStr(40, 30, oilBuf);
break;
case 1: // Temperatura wewnętrzna
display1.setCursor((128 - display1.getStrWidth("INTERNAL TEMP")) / 10, 10); // Wyśrodkowanie
display1.drawStr(10, 10, "INTERNAL TEMP");
char internalTempBuf[10];
sprintf(internalTempBuf, "%.1f C", internalTemp);
display1.setCursor((128 - display1.getStrWidth(internalTempBuf)) / 40, 30); // Wyśrodkowanie wartości
display1.drawStr(40, 30, internalTempBuf);
break;
case 2: // RPM
display1.setCursor((128 - display1.getStrWidth("RPM")) / 50, 10); // Wyśrodkowanie
display1.drawStr(50, 10, "RPM");
char rpmBuf[10];
sprintf(rpmBuf, "%d RPM", (int)rpm);
display1.setCursor((128 - display1.getStrWidth(rpmBuf)) / 30, 30); // Wyśrodkowanie wartości
display1.drawStr(30, 30, rpmBuf);
break;
case 3: // Prędkość
display1.setCursor((128 - display1.getStrWidth("SPEED")) / 50, 10); // Wyśrodkowanie
display1.drawStr(50, 10, "SPEED");
char speedBuf[10];
sprintf(speedBuf, "%d km/h", (int)speed);
display1.setCursor((128 - display1.getStrWidth(speedBuf)) / 40, 30); // Wyśrodkowanie wartości
display1.drawStr(40, 30, speedBuf);
break;
case 4: // Ciśnienie paliwa
display1.setCursor((128 - display1.getStrWidth("FUEL PRESSURE")) / 14, 10); // Wyśrodkowanie
display1.drawStr(14, 10, "FUEL PRESSURE");
char fuelPressureBuf[10];
sprintf(fuelPressureBuf, "%.1f BAR", fuelPressure);
display1.setCursor((128 - display1.getStrWidth(fuelPressureBuf)) / 40, 30); // Wyśrodkowanie wartości
display1.drawStr(40, 30, fuelPressureBuf);
break;
case 5: // Pozycja pedału gazu
display1.setCursor((128 - display1.getStrWidth("THROTTLE POSITION")) / 10, 10); // Wyśrodkowanie
display1.drawStr(10, 10, "THROTTLE POSITION");
char throttlePositionBuf[10];
sprintf(throttlePositionBuf, "%d %%", (int)throttlePosition);
display1.setCursor((128 - display1.getStrWidth(throttlePositionBuf)) / 40, 30); // Wyśrodkowanie wartości
display1.drawStr(40, 30, throttlePositionBuf);
break;
}
} while (display1.nextPage());
// Wyświetlanie na drugim wyświetlaczu - doładowanie
display2.firstPage();
do {
display2.setFont(u8g2_font_ncenB08_tr);
display2.drawStr(20, 10, "BOOST PRESSURE");
display2.drawFrame(0, 20, 124, 10); // Zmiana na długość 124
display2.drawBox(0, 20, boostPressureBar, 10); // Użycie przeskalowanej wartości
char buf[10];
sprintf(buf, "%.1f BAR", boostPressure);
display2.drawStr(40, 50, buf);
} while (display2.nextPage());
// Wyświetlanie na trzecim wyświetlaczu - temperatura powietrza dolotowego
display3.firstPage();
do {
display3.setFont(u8g2_font_ncenB08_tr);
display3.drawStr(20, 10, "INTAKE TEMP");
display3.drawFrame(0, 20, 124, 10); // Zmiana na długość 124
display3.drawBox(0, 20, intakeTempBar, 10); // Użycie przeskalowanej wartości
char buf[10];
sprintf(buf, "%.1f C", intakeTemp);
display3.drawStr(50, 50, buf);
} while (display3.nextPage());
}
void displayVWLogo(U8G2_SH1106_128X64_NONAME_F_HW_I2C &display) {
// Wyświetlanie napisu VOLKSWAGEN i PASSAT B7
display.firstPage();
do {
display.setFont(u8g2_font_ncenB08_tr); // Większa czcionka
display.drawStr(20, 20, "VOLKSWAGEN"); // Napis "VOLKSWAGEN"
display.setFont(u8g2_font_ncenB08_tr); // Mniejsza czcionka
display.drawStr(35, 40, "PASSAT B7"); // Napis "PASSAT B7"
} while (display.nextPage());
delay(3000); // Wyświetl tekst przez 3 sekundy
}