// 1. Объявление пинов и переменных
const int pinA = 2; // Выход А (CLK) энкодера подключен к D2[cite: 22]
const int pinB = 3; // Выход В (DT) энкодера подключен к D3[cite: 22]
const int pinSW = 4; // Кнопка SW энкодера подключена к D4[cite: 22]
const int pinLED = 9; // Светодиод LED подключен к D9[cite: 21, 22]
volatile int val = 0; // Текущее значение счётчика импульсов (volatile для прерываний)[cite: 22]
int prev_val = 0; // Предыдущее значение счётчика для расчёта скорости[cite: 22]
int enc_speed = 0; // Вычисленная скорость вращения (об/мин)[cite: 22]
unsigned long previousMillis = 0; // Время предыдущего расчёта скорости[cite: 22]
// 2. Функция-обработчик прерывания для канала А
void chan_A() {
// Состояние канала В читаем с помощью digitalRead(3)[cite: 23]
if (digitalRead(pinB) == HIGH) {
val++; // При высоком уровне на B увеличиваем счетчик[cite: 23]
} else {
val--; // Иначе уменьшаем[cite: 23]
}
}
void setup() {
// 3. Настройка пинов и прерываний
pinMode(pinA, INPUT_PULLUP); // Настраиваем вывод A как вход с внутренней подтяжкой[cite: 23]
pinMode(pinB, INPUT_PULLUP); // Настраиваем вывод B как вход с внутренней подтяжкой[cite: 23]
pinMode(pinSW, INPUT_PULLUP); // Настраиваем кнопку как вход с внутренней подтяжкой[cite: 23]
pinMode(pinLED, OUTPUT); // Настраиваем светодиод как выход[cite: 23]
// Привязываем прерывание к пину D2 (функция chan_A, срабатывание по спадающему фронту FALLING)[cite: 23]
attachInterrupt(digitalPinToInterrupt(pinA), chan_A, FALLING);
// Запуск последовательного порта на скорости 9600 бод[cite: 21, 23]
Serial.begin(9600);
}
void loop() {
// 4. и 5. Управление яркостью светодиода через ШИМ
int led_brightness;
// Ограничиваем значение val диапазоном 0...255 для аналогового выхода[cite: 23]
led_brightness = constrain(val, 0, 255);
analogWrite(pinLED, led_brightness); // Подаем сигнал на светодиод[cite: 23]
// 6. Сброс счётчика по кнопке (если кнопка нажата, уровень LOW)[cite: 24]
if (digitalRead(pinSW) == LOW) {
val = 0;
prev_val = 0;
}
// 7. Вычисление скорости вращения каждые 500 мс
unsigned long currentMillis = millis(); // Получаем текущее время в миллисекундах[cite: 23]
if (currentMillis - previousMillis >= 500) {
previousMillis = currentMillis; // Обновляем метку времени[cite: 23, 24]
// Вычисляем разницу импульсов за последние 500 мс[cite: 24]
int diff = val - prev_val;
if (diff < 0) {
diff = -diff; // Берем модуль значения, если оно отрицательное[cite: 24]
}
// Перевод в обороты в минуту (об/мин) для энкодера с 24 импульсами на оборот:
// diff * 2 (перевод в сек) * 60 (перевод в мин) / 24 (импульсов на оборот) = diff * 5[cite: 24]
enc_speed = diff * 5;
prev_val = val; // Запоминаем текущее значение как предыдущее[cite: 24]
// 8. Вывод результата в монитор порта[cite: 24]
Serial.print("Счетчик импульсов: ");
Serial.print(val);
Serial.print("\tСостояние кнопки: ");
Serial.print(digitalRead(pinSW));
Serial.print("\tСкорость: ");
Serial.print(enc_speed);
Serial.println(" об/мин");
}
}