#include <Wire.h> // Бібліотека для роботи з I2C
#include <Adafruit_SSD1306.h> // Бібліотека для OLED-дисплея
#include <Adafruit_GFX.h> // Бібліотека для графіки
// === Налаштування дисплея ===
#define SCREEN_WIDTH 128 // Ширина OLED-дисплея
#define SCREEN_HEIGHT 64 // Висота OLED-дисплея
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1); // Створюємо об'єкт дисплея
// === Налаштування кнопок ===
#define BUTTON_UP 33 // GPIO-пін для кнопки "Вгору"
#define BUTTON_DOWN 27 // GPIO-пін для кнопки "Вниз"
#define BUTTON_SELECT 13 // GPIO-пін для кнопки "OK" (вибір)
#define SWITCH_PIN 15 // GPIO-пін для перемикача, який вмикає меню
// === Глобальні змінні ===
int menuLevel = 0; // Поточний рівень меню (0 - головне меню, 1 - Kalibrovka тощо)
int menuIndex = 0; // Поточний вибраний пункт меню
float temperaturaValue = 0.0; // Поточне значення параметра
float savedValue = 0.0; // Збережене значення
bool inEditMode = false; // Чи активний режим редагування (true - редагування активне)
// === Прототипи функцій ===
void drawMenu(); // Функція для малювання меню
void handleButtons(); // Функція для обробки кнопок
void setup() {
pinMode(BUTTON_UP, INPUT_PULLUP);
pinMode(BUTTON_DOWN, INPUT_PULLUP);
pinMode(BUTTON_SELECT, INPUT_PULLUP);
pinMode(SWITCH_PIN, INPUT_PULLUP);
Serial.begin(115200);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
for (;;); // Зупиняємо програму, якщо дисплей не вдалося запустити
}
display.clearDisplay();
display.display();
}
void loop() {
// Перевіряємо, чи активовано меню (перемикач увімкнений, сигнал LOW)
if (digitalRead(SWITCH_PIN) == LOW) {
handleButtons(); // Обробка кнопок
drawMenu(); // Малювання меню
} else {
// Якщо меню вимкнене, показуємо значення 5.3
display.clearDisplay();
display.setTextSize(2); // Великий розмір тексту
display.setTextColor(SSD1306_WHITE); // Білий колір тексту
display.setCursor(40, 26); // Позиція тексту на дисплеї
display.println("5.3"); // Виводимо значення 5.3
display.display(); // Оновлюємо дисплей
}
}
// === Функція для обробки кнопок ===
void handleButtons() {
static unsigned long lastDebounceTime = 0; // Таймер для антидребезку кнопок
unsigned long debounceDelay = 200; // Час затримки для уникнення подвійного спрацювання
if (millis() - lastDebounceTime > debounceDelay) {
if (digitalRead(BUTTON_UP) == LOW) { // Якщо натиснута кнопка "Вгору"
if (menuLevel == 11 && inEditMode && menuIndex == 0) {
temperaturaValue += 0.1; // Збільшуємо значення на 0.1
if (temperaturaValue > 100.0) temperaturaValue = 100.0; // Обмеження значення
} else {
menuIndex--;
if (menuIndex < 0) menuIndex = 2; // Зациклення пунктів меню
}
lastDebounceTime = millis(); // Оновлюємо таймер антидребезку
} else if (digitalRead(BUTTON_DOWN) == LOW) { // Якщо натиснута кнопка "Вниз"
if (menuLevel == 11 && inEditMode && menuIndex == 0) {
temperaturaValue -= 0.1; // Зменшуємо значення на 0.1
if (temperaturaValue < -100.0) temperaturaValue = -100.0; // Обмеження значення
} else {
menuIndex++;
if (menuIndex > 2) menuIndex = 0; // Зациклення пунктів меню
}
lastDebounceTime = millis(); // Оновлюємо таймер антидребезку
} else if (digitalRead(BUTTON_SELECT) == LOW) { // Якщо натиснута кнопка "OK"
if (menuLevel == 0) {
if (menuIndex == 0) menuLevel = 1; // Перехід до "Kalibrovka"
if (menuIndex == 1) menuLevel = 2; // Перехід до "Ethernet"
} else if (menuLevel == 1) {
if (menuIndex == 0) menuLevel = 11; // Перехід до "Temperatura"
if (menuIndex == 1) menuLevel = 12; // Перехід до "Volog"
} else if (menuLevel == 11) {
if (menuIndex == 0) {
inEditMode = !inEditMode; // Перемикаємо стан редагування
if (!inEditMode) {
savedValue = temperaturaValue; // Зберігаємо значення при виході з редагування
}
} else if (menuIndex == 1) {
Serial.print("Sent value: ");
Serial.println(savedValue); // Відправка збереженого значення
}
}
if (menuIndex == 2) { // Пункт "Back"
if (menuLevel == 1) menuLevel = 0; // Повернення з "Kalibrovka"
else if (menuLevel == 11) menuLevel = 1; // Повернення з "Temperatura"
}
lastDebounceTime = millis(); // Оновлюємо таймер антидребезку
}
}
}
// === Функція для відображення меню ===
void drawMenu() {
display.clearDisplay(); // Очищуємо дисплей перед малюванням нового меню
display.setTextSize(1); // Розмір тексту
display.setTextColor(SSD1306_WHITE); // Колір тексту
if (menuLevel == 0) {
display.fillRect(0, menuIndex * 10, 128, 10, SSD1306_WHITE);
display.setTextColor(menuIndex == 0 ? SSD1306_BLACK : SSD1306_WHITE);
display.setCursor(2, 0); display.println("1. Kalibrovka");
display.setTextColor(menuIndex == 1 ? SSD1306_BLACK : SSD1306_WHITE);
display.setCursor(2, 10); display.println("2. Ethernet");
display.setTextColor(menuIndex == 2 ? SSD1306_BLACK : SSD1306_WHITE);
display.setCursor(2, 20); display.println("Back");
} else if (menuLevel == 1) {
display.fillRect(0, menuIndex * 10, 128, 10, SSD1306_WHITE);
display.setTextColor(menuIndex == 0 ? SSD1306_BLACK : SSD1306_WHITE);
display.setCursor(2, 0); display.println("1.1 Temperatura");
display.setTextColor(menuIndex == 1 ? SSD1306_BLACK : SSD1306_WHITE);
display.setCursor(2, 10); display.println("1.2 Volog");
display.setTextColor(menuIndex == 2 ? SSD1306_BLACK : SSD1306_WHITE);
display.setCursor(2, 20); display.println("Back");
} else if (menuLevel == 11) {
display.fillRect(0, menuIndex * 10, 128, 10, SSD1306_WHITE);
display.setTextColor(menuIndex == 0 ? SSD1306_BLACK : SSD1306_WHITE);
display.setCursor(2, 0);
if (inEditMode) {
display.print("1.1.1 Zmina*: ");
} else {
display.print("1.1.1 Zmina: ");
}
display.print(temperaturaValue, 1);
display.setTextColor(menuIndex == 1 ? SSD1306_BLACK : SSD1306_WHITE);
display.setCursor(2, 10); display.println("1.1.2 Pidtverd");
display.setTextColor(menuIndex == 2 ? SSD1306_BLACK : SSD1306_WHITE);
display.setCursor(2, 20); display.println("Back");
}
display.display();
}