Загрузка данных


// 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(" об/мин");
  }
}