Вращающийся энкодер, использующий прерывание
Я впервые работаю с поворотным энкодером и прерываниями. Я использую 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
Обсуждение1 ответ
▲ 2
Обнаружил свою ошибку... на ProMicro контакты не расположены 0, 1, 2, 3, 4, 5 и т. д., вместо этого они расположены 1, 0, 2, 3, 4, 5 и т. д.... На Я неправильно понял TXO и RXI как TX0 и RX1 и просто не заметил этого на листе выводов… поэтому я поменял местами D0 и D1. Теперь все работает хорошо. Учиться больше каждый день! Я ценю ваше время...
,
@
Смотрите также:
- Использование поворотных энкодеров с прерываниями смены контактов
- Выводы прерываний Arduino Mega 2560 и отображение портов с помощью поворотного энкодера
- Чтение квадратурного энкодера в реальном времени с полным разрешением только с одним прерыванием на ATmega328
- Проблема ISR: Arduino Pro Micro
- спам-выход поворотного энкодера
- Можно ли получить, какой вывод сгенерировал прерывание?
- От Uno до Mega, и где ошибка необъявленного прерывания?
- Отсутствуют импульсы ATTiny88 - возможно
подумайте о том, как код работает сейчас, всего с одним прерыванием... затем подумайте о том, что произошло бы, если бы у вас было прерывание на обоих выводах данных кодировщика... нужно отметить, что у вас было бы в два раза больше прерываний за один раз. оборот энкодера, но они не будут симметричными, если вы прерываете только на одном фронте ... я предполагаю, что вы используете квадратурный энкодер, @jsotola
attachInterrupt(digitalPinToInterrupt(PinA), isr, LOW);
Я думаю, вы имеете в видуFALLING
, иначе ISR будет постоянно вызываться, когда на выводе LOW, практически не оставляя циклов ЦП для вашего основного кода., @GerbenЯ не понимаю, почему это не сработает. В контактах 1 и 9 нет ничего особенного. 1 действительно является контактом прерывания, но вы не используете его здесь. Довольно странно., @Gerben
Как бы я использовал это как подпрограмму вместо основного цикла? Например, установив максимальное значение, затем запустив другой саб до тех пор, пока не будет достигнуто максимальное значение. Я бы предположил, что мы будем использовать другой вход для триггера прерывания., @Matt