#include <Wire.h> //Используется для связи Arduino Uno с OLED-дисплеем
#include <Adafruit_GFX.h> //Используется для вывода текста и графики на OLED-дисплей.
#include <Adafruit_SSD1306.h> //Позволяет Arduino Uno работать с OLED-дисплеем
// Параметры OLED-дисплея
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
// Создаем объект дисплея
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Пины подключения энкодера
#define ENC_A 2
#define ENC_B 3
#define ENC_SW 4
// Пины подключения первого джойстика
#define JS1_VRX A0
#define JS1_VRY A1
#define JS1_SW 5
// Пины подключения второго джойстика
#define JS2_VRX A2
#define JS2_VRY A3
#define JS2_SW 6
// Пин подключения зуммера
#define BUZZER_PIN 7
// Переменные для отслеживания состояния энкодера
volatile int encoderPos = 0;
volatile bool p0, p1;
// Функция обработки изменений на пинах энкодера
void pollEnc(bool e0, bool e1) {
// Проверяем изменение состояния энкодера
if (p0 ^ p1 ^ e0 ^ e1) {
// Определяем направление вращения
if (p1 ^ e0) encoderPos++; // Вращение по часовой стрелке
else encoderPos--; // Вращение против часовой стрелки
// Обновляем предыдущее состояние пинов
p0 = e0;
p1 = e1;
}
}
// Обработчик прерывания для пина ENC_A (CLK)
void isrA() {
pollEnc(!p0, p1);
}
// Обработчик прерывания для пина ENC_B (DT)
void isrB() {
pollEnc(p0, !p1);
}
void setup() {
Serial.begin(115200); // Инициализация последовательного порта для отладки
// Настройка пинов энкодера как входов
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
pinMode(ENC_SW, INPUT_PULLUP);
// Считываем начальное состояние пинов энкодера
p0 = digitalRead(ENC_A);
p1 = digitalRead(ENC_B);
// Подключаем прерывания к пинам энкодера
attachInterrupt(digitalPinToInterrupt(ENC_A), isrA, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENC_B), isrB, CHANGE);
// Настройка кнопок джойстиков
pinMode(JS1_SW, INPUT_PULLUP);
pinMode(JS2_SW, INPUT_PULLUP);
// Настройка пина зуммера как выход
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
// Инициализация OLED-дисплея
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Адрес 0x3C — стандартный для большинства OLED
Serial.println(F("SSD1306 allocation failed"));
for(;;);
}
// Очистка дисплея и вывод приветственного сообщения
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println("Pult Control Init");
display.display();
delay(1000);
}
void loop() {
// Считываем значения осей первого джойстика
int js1_x = analogRead(JS1_VRX);
int js1_y = analogRead(JS1_VRY);
// Считываем состояние кнопки первого джойстика (LOW — нажата)
bool js1_btn = digitalRead(JS1_SW) == LOW;
// Считываем значения осей второго джойстика
int js2_x = analogRead(JS2_VRX);
int js2_y = analogRead(JS2_VRY);
// Считываем состояние кнопки второго джойстика
bool js2_btn = digitalRead(JS2_SW) == LOW;
// Считываем состояние кнопки энкодера
bool enc_btn = digitalRead(ENC_SW) == LOW;
// Статические переменные для отслеживания предыдущего состояния кнопок
static bool last_js1_btn = false, last_js2_btn = false, last_enc_btn = false;
// Если кнопка джойстика 1 была нажата (переход с отпущено на нажато)
if (js1_btn && !last_js1_btn) {
tone(BUZZER_PIN, 2000, 100); // Звуковой сигнал 2000 Гц длительностью 100 мс
}
// Если кнопка джойстика 2 была нажата
if (js2_btn && !last_js2_btn) {
tone(BUZZER_PIN, 1500, 100); // Звуковой сигнал 1500 Гц
}
// Если кнопка энкодера была нажата
if (enc_btn && !last_enc_btn) {
tone(BUZZER_PIN, 1000, 100); // Звуковой сигнал 1000 Гц
}
// Обновляем предыдущие состояния кнопок
last_js1_btn = js1_btn;
last_js2_btn = js2_btn;
last_enc_btn = enc_btn;
// Выводим данные на OLED-дисплей
display.clearDisplay();
// Позиция энкодера
display.setCursor(0,0);
display.print("Enc Pos: ");
display.println(encoderPos);
// Состояние кнопки энкодера
display.print("Enc Btn: ");
display.println(enc_btn ? "Pressed" : "Released");
// Джойстик 1 и кнопка
display.setCursor(0, 20);
display.print("JS1 X:");
display.print(js1_x);
display.print(" Y:");
display.println(js1_y);
display.print("Btn:");
display.println(js1_btn ? "Pressed" : "Released");
// Джойстик 2 и кнопка
display.setCursor(0, 40);
display.print("JS2 X:");
display.print(js2_x);
display.print(" Y:");
display.println(js2_y);
display.print("Btn:");
display.println(js2_btn ? "Pressed" : "Released");
display.display(); // Обновляем экран
delay(100); // Задержка для обновления 10 раз в секунду
}