Вращающийся энкодер, использующий прерывание

Я впервые работаю с поворотным энкодером и прерываниями. Я использую Pro Micro, у которого есть контакты прерывания на контактах 0 и 1. Приведенный ниже код работает должным образом.

Мой вопрос: нужно ли мне использовать контакт прерывания для PinB, или я могу использовать любой цифровой контакт?

Похоже, это не работает, например, когда я выбираю PinB = 9.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // установить адрес ЖК-дисплея на 0x27 для 16-символьного и 2-строчного дисплея


// Используется для генерации прерываний по сигналу CLK
const int PinA = 0;

// Используется для чтения сигнала DT
const int PinB = 1;

// Используется для кнопочного переключателя
const int PinSW = 8;

// Следим за последним вращающимся значением
int lastCount = 50;

// Обновляется ISR (процедура обслуживания прерываний)
volatile int virtualPosition = 50;



// ------------------------------------------------ ------------------
// ПРЕРЫВАНИЕ ПРЕРЫВАНИЕ ПРЕРЫВАНИЕ ПРЕРЫВАНИЕ ПРЕРЫВАНИЕ
// ------------------------------------------------ ------------------


void isr ()  {
  static unsigned long lastInterruptTime = 0;
  unsigned long interruptTime = millis();

  // Если прерывания приходят быстрее, чем 5 мс, считайте, что это отказ, и игнорируйте
  if (interruptTime - lastInterruptTime > 5) {
    if (digitalRead(PinB) == LOW)
    {
      virtualPosition-- ; // Может быть -5 или -10
    }
    else {
      virtualPosition++ ; // Может быть +5 или +10
    }

    // Ограничение значения от 0 до +100
    // виртуальная позиция = мин (100, макс (0, виртуальная позиция));


  }
  // Отслеживаем, когда мы были здесь в последний раз (не чаще, чем каждые 5 мс)
  lastInterruptTime = interruptTime;
}

// ------------------------------------------------ ------------------
// НАСТРОЙКА НАСТРОЙКА НАСТРОЙКА НАСТРОЙКА НАСТРОЙКА НАСТРОЙКА НАСТРОЙКА
// ------------------------------------------------ ------------------
void setup() {
  // Пока мы отлаживаем, смотрим вывод на последовательном мониторе
  // Serial.begin(9600);

  lcd.init();                      // инициализируем ЖК-дисплей

  lcd.backlight();

  // Вращающиеся импульсы являются ВХОДАМИ
  pinMode(PinA, INPUT);
  pinMode(PinB, INPUT);

  // Переключатель плавающий, поэтому используйте встроенный PULLUP, поэтому нам не нужен резистор
  pinMode(PinSW, INPUT_PULLUP);

  // Подключаем подпрограмму для обслуживания прерываний
  attachInterrupt(digitalPinToInterrupt(PinA), isr, LOW);


}

// ------------------------------------------------ ------------------
// ГЛАВНЫЙ КОНТУР ГЛАВНЫЙ КОНТУР ГЛАВНЫЙ КОНТУР ГЛАВНЫЙ КОНТУР ГЛАВНЫЙ КОНТУР
// ------------------------------------------------ ------------------
void loop() {

  // Кто-то нажимает поворотный переключатель?
  if ((!digitalRead(PinSW))) {
    virtualPosition = 50;
    while (!digitalRead(PinSW))
      delay(10);
    // Serial.println("Сброс");
  }

  // Если текущая позиция поворотного переключателя изменилась, то обновить все
  if (virtualPosition != lastCount) {



    lcd.clear();
    lcd.print(virtualPosition);

    // Следим за этим новым значением
    lastCount = virtualPosition ;
  }

  // задержка (100);
}

, 👍1

Обсуждение

подумайте о том, как код работает сейчас, всего с одним прерыванием... затем подумайте о том, что произошло бы, если бы у вас было прерывание на обоих выводах данных кодировщика... нужно отметить, что у вас было бы в два раза больше прерываний за один раз. оборот энкодера, но они не будут симметричными, если вы прерываете только на одном фронте ... я предполагаю, что вы используете квадратурный энкодер, @jsotola

attachInterrupt(digitalPinToInterrupt(PinA), isr, LOW); Я думаю, вы имеете в виду FALLING, иначе ISR будет постоянно вызываться, когда на выводе LOW, практически не оставляя циклов ЦП для вашего основного кода., @Gerben

Я не понимаю, почему это не сработает. В контактах 1 и 9 нет ничего особенного. 1 действительно является контактом прерывания, но вы не используете его здесь. Довольно странно., @Gerben

Как бы я использовал это как подпрограмму вместо основного цикла? Например, установив максимальное значение, затем запустив другой саб до тех пор, пока не будет достигнуто максимальное значение. Я бы предположил, что мы будем использовать другой вход для триггера прерывания., @Matt


1 ответ


2

Обнаружил свою ошибку... на ProMicro контакты не расположены 0, 1, 2, 3, 4, 5 и т. д., вместо этого они расположены 1, 0, 2, 3, 4, 5 и т. д.... На Я неправильно понял TXO и RXI как TX0 и RX1 и просто не заметил этого на листе выводов… поэтому я поменял местами D0 и D1. Теперь все работает хорошо. Учиться больше каждый день! Я ценю ваше время...

,