Подключение энкодера KY-040 к Arduino

Энкодер с кнопкой

KY-040 к Arduino Uno и Nano: CLK и DT на D2 и D3 — выводы с аппаратными внешними прерываниями, SW — на любой цифровой, питание 5 В.

Схема подключения энкодера KY-040 к Arduino

KY-040Arduino Uno
CLKD2
DTD3
SWD4
VCC5V
GNDGND

Схема из примера «Arduino Uno: энкодер — яркость ручкой».

Arduino Uno: энкодер — яркость ручкой

Открыть пример целиком

Выводы KY-040

ВыводНазначение
CLKвыход A
DTвыход B — по нему определяют направление
SWкнопка на валу, замыкает на GND
VCCпитание (для подтягивающих резисторов модуля)
GNDобщий провод

Код для Arduino

// Энкодер KY-040: яркость светодиода ручкой.
//
// Внутри энкодера два контакта, замыкающихся со сдвигом на четверть
// оборота щелчка. По часовой стрелке первым опускается CLK, потом DT;
// против — наоборот. Поэтому достаточно поймать спад CLK и посмотреть
// на DT: единица — ручку крутят по часовой, ноль — против.
//
// Спад ловит прерывание: у Uno их два, на выводах 2 и 3, и CLK сидит на
// втором. Опрос в loop() тоже работает, но пропускает щелчки, пока
// скетч занят чем-то долгим (печатью в порт, например).
//
// На схеме: возьмите ручку мышью и тяните по кругу — по часовой или
// против; кнопки ↺ ↻ под ручкой — по щелчку (держите — повторяются);
// колесо мыши над ручкой — тоже поворот; середина ручки — кнопка.

const int CLK = 2, DT = 3, SW = 4;
const int LED = 9;                 // вывод с ШИМ

volatile int clicks = 0;           // меняется в прерывании

void onClk() {
  if (digitalRead(DT)) clicks++; else clicks--;
}

void setup() {
  Serial.begin(9600);
  pinMode(CLK, INPUT);             // подтяжка на CLK и DT есть на модуле
  pinMode(DT, INPUT);
  pinMode(SW, INPUT_PULLUP);       // а на кнопке — нет
  pinMode(LED, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(CLK), onClk, FALLING);
  Serial.println("крутите ручку, нажмите — погасить");
}

int level = 0;                     // 0…16 ступеней по 16

void loop() {
  // Щелчки забираются под запретом прерываний: int у AVR — два байта,
  // и прерывание посреди чтения дало бы половину старого значения.
  noInterrupts();
  int n = clicks;
  clicks = 0;
  interrupts();

  if (n) {
    level = constrain(level + n, 0, 16);
    Serial.print("яркость: ");
    Serial.println(level * 16);
  }
  if (digitalRead(SW) == LOW && level) {
    level = 0;
    Serial.println("погашено");
  }
  analogWrite(LED, min(level * 16, 255));
  delay(10);
}

Скетч можно править и запускать в симуляторе без платы и установки среды.

Что учесть на Arduino

В железе

На модуле стоят подтягивающие резисторы 10 кОм на CLK и DT, а на SW — не у всех: для кнопки включайте INPUT_PULLUP.

Частые ошибки при подключении к Arduino

Другие детали для Arduino