KY-040 Interrupts ESP32 — ESP32 simulation

Обработка энкодера KY-040 с использованием прерываний на ESP32

An interactive ESP32 circuit simulation you can run free in your browser on Velxio, by o-droshnev.

Components

Sketch code

#include <Wire.h>
#include <GyverOLED.h>
#include "GyverOLEDMenu.h"
#include <GyverEncoder.h>

// Пины
#define CLK 32
#define DT 33
#define SW 34  // Пин 34 (подтянут внешним резистором 10к к 3V3)

// Инициализация энкодера GyverEncoder (CLK, DT, Кнопка)
Encoder enc(CLK, DT, SW);

GyverOLED<SSD1306_128x64, OLED_BUFFER> oled;
OledMenu<8, GyverOLED<SSD1306_128x64, OLED_BUFFER>> menu(&oled);

int magnetic_declination = 0;

// --- Обработчик аппаратного прерывания для энкодера ---
void IRAM_ATTR encoderISR() {
  enc.tick(); // Обязательный опрос внутри прерывания исключает пропуск шагов
}

void setup() {
  Serial.begin(115200);
  delay(500);
  Serial.println("System initialized successfully.");

  // Настройка пина 34 как чистого входа (без внутренней подтяжки)
  pinMode(SW, INPUT);

  // Инициализация OLED
  oled.init();
  Wire.setClock(400000L);
  oled.clear();
  oled.setScale(1);
  oled.home();
  oled.print("OLED Ready");
  oled.update();

  // Настройка пунктов меню
  menu.onChange(onItemChange, true);
  menu.addItem(PSTR("STOP"));                  // 0
  menu.addItem(PSTR("Magnetic Declination"), GM_N_INT(1), &magnetic_declination, GM_N_INT(1), GM_N_INT(108000)); // 1
  menu.addItem(PSTR("N direction"));           // 2
  menu.addItem(PSTR("PN direction"));          // 3
  menu.addItem(PSTR("Position"));              // 4
  menu.addItem(PSTR("Manual"));                // 5
  menu.addItem(PSTR("Start"));                 // 6
  menu.addItem(PSTR("Get GPS"));               // 7

  menu.showMenu(true);
  oled.update();
  
  // Подключаем прерывание по изменению состояния пина CLK
  attachInterrupt(digitalPinToInterrupt(CLK), encoderISR, CHANGE);
  
  Serial.println("Setup complete. Interrupts attached.");
}

void onItemChange(const int index, const void* val, const byte valType) {
  if (valType == VAL_ACTION) {
    if (index == 0) {
      Serial.println("Menu action: STOP selected");
    }
  }
}

void loop() {
  // На всякий случай дублируем tick() для надежной обработки кнопки
  enc.tick();

  // Обработка поворота энкодера
  if (enc.isRight()) {
    menu.selectNext(enc.fast());
    Serial.println("Поворот ВПРАВО -> Следующий пункт меню");
  } 
  if (enc.isLeft()) {
    menu.selectPrev(enc.fast());
    Serial.println("Поворот ВЛЕВО -> Предыдущий пункт меню");
  }

  // Обработка нажатия кнопки
  if (enc.isClick()) {
    menu.toggleChangeSelected();
    Serial.println("Кнопка нажата (Клик)");
  }

  // Обновление дисплея
  oled.update();
}