Выводы прерываний Arduino Mega 2560 и отображение портов с помощью поворотного энкодера
Я пытаюсь использовать манипуляции с портами в прерываниях для чтения поворотного энкодера. Я нашел код для Uno, поэтому вызов порта для контактов 2 и 3 различен. Я думаю, что на Меге это PORTH3 и PORTH4 соответственно. Мой код не работает. У меня неправильные порты? Я пробовал читать об этом, но не до конца понимаю часть Bxxxxxxxx. Я думаю, что это может быть неправильно. Вот часть моего кода с одним из прерываний.
static int pinA = 2;
// Наш первый вывод аппаратного прерывания — цифровой вывод 2
static int pinB = 3;
// Наш второй вывод аппаратного прерывания — цифровой вывод 3
volatile byte aFlag = 0;
// сообщаем нам, когда мы ожидаем, что нарастающий фронт на выводе pinA будет сигнализировать о том, что энкодер достиг фиксации
volatile byte bFlag = 0;
// сообщаем нам, когда мы ожидаем, что нарастающий фронт на выводе B будет сигнализировать о том, что энкодер достиг фиксации (направление, противоположное тому, когда установлен aFlag)
volatile byte encoderPos = 0;
//эта переменная хранит наше текущее значение позиции энкодера. Измените значение на int или uin16_t вместо byte, если вы хотите записать больший диапазон, чем 0–255.
volatile byte oldEncPos = 0;
//сохраняет последнее значение позиции энкодера, чтобы мы могли сравнить его с текущим показанием и посмотреть, изменилось ли оно (чтобы мы знали, когда печатать на последовательный монитор)
volatile byte reading = 0;
void setup () {
pinMode(pinA, INPUT);
// устанавливаем контакт A в качестве входа, вытягиваем ВЫСОКИЙ уровень логического напряжения (5 В или 3,3 В в большинстве случаев)
pinMode(pinB, INPUT);
attachInterrupt(0, PinA, RISING);
// устанавливаем прерывание на PinA,
// ищем нарастающий фронт сигнала и выполняем процедуру обслуживания прерываний «PinA» (ниже)
attachInterrupt(1, PinB, RISING);
// устанавливаем прерывание на PinB,
// ищем нарастающий фронт сигнала и выполняем процедуру обслуживания прерываний «PinB» (ниже)
}
void PinA() {
//CCW
cli();
//прекращаем прерывания до того, как мы прочитаем значения контактов
reading = PORTH & 0xC;
// считываем значения всех восьми контактов, затем удаляем все значения, кроме значений pinA и pinB
if (reading == B00001100 && aFlag) {
//проверяем, что оба контакта зафиксированы (ВЫСОКИЙ) и что мы ожидаем фиксации на нарастающем фронте этого контакта
encoderPos --; //уменьшаем счетчик позиций кодировщика
bFlag = 0; //сбрасываем флаги для следующего хода
aFlag = 0; //сбрасываем флаги для следующего хода
} else if (reading == B00000100) bFlag = 1;
//сигнал того, что мы ожидаем, что вывод pinB сигнализирует о переходе в фиксацию из свободного вращения
sei(); //перезапускаем прерывания
}
@kumquat, 👍2
Обсуждение2 ответа
Что касается контактов 2 и 3, они разные. Я думаю, что на Mega это PORTH3 и PORTH4 соответственно», это правда, что цифровые контакты Arduino 2 и 3 относятся к разным портам на платах Uno и Mega2560.
У Mega2560 шесть контактов INTx, а у Uno их два. В Mega INT0...INT3 — это PD0…PD3, а INT4,INT5 — это PE4,PE5. В Uno INT0,INT1 — это PD2,PD3. Обратите внимание: в ответе на Могут ли внешние прерывания объединяться по ИЛИ на '328 (Uno)? я показываю пару подпрограмм, которые будут отображать соответствующие маски. для контактов на разных ардуино. См. разделы «Использование других контактов для PCI» и «Скетч, генерирующий ISR-фреймворк».
Вот несколько проблем с кодом, показанным в вопросе:
aFlag
инициализируется нулевым значением и никогда не устанавливается ненулевым в показанном коде. Таким образом, первое условиеif
вPinA()
никогда не выполняется.PinA()
— это обработчик прерываний, подключенный к прерываниям с помощью вызововattachInterrupt()
. Поскольку аппаратное обеспечение отключает прерывания до того, как они попадут в обработчик прерываний, обработчику прерываний нет необходимости отключать прерывания. То есть удалитеcli()
вPinA()
. Аналогичным образом удалитеsei()
в концеPinA()
, поскольку аппаратное обеспечение восстанавливает статус прерывания при выполнении инструкции RETI.Программная среда Arduino определяет константы типа
B00001100
с двоичными значениями, соответствующими имени. То есть в программной среде Arduino константаB00001100
имеет значение0B00001100
. На мой взгляд, это глупая и ненужная функция; Я предлагаю использовать в вашем коде стандартную нотацию C, например0B00001100
, если вы хотите использовать значения двоичных констант.Я считаю извращением написание
encoderPos --
вместоencoderPos--
и предлагаю удалить это ненужное пространство.Поскольку вы не показали обработчик прерываний
PinB()
, я не знаю, как вы собираетесь обрабатывать случайencoderPos++
. Судя по показанному коду, вы используете метод, который неправильно обрабатывает отказы и периодические ошибки. Я предлагаю использовать прерывания по смене контактов и метод конечного автомата, как показано в ответах на:
• Чтение с поворотного энкодера KY-040 с помощью Digispark
• Как считать RPS для быстрого вращения с помощью метода изменения статуса в Arduino?
• Чтение каналов приемника RC с использованием прерывания вместо PulseIn
• Могут ли внешние прерывания объединяться по логическому ИЛИ в '328 (Uno)?
На мега-памяти можно было читать с помощью PINE.
Итак, ваш код в PinA изменится на:
reading = PINE & 0b00110000;
if(reading == 0b00110000 && aFlag)
{ encoderPos --;
bFlag = 0;
aFlag = 0;
}
else if (reading == 0b00010000) bFlag = 1;
Здесь я нашел отличное обсуждение необходимой маскировки: https://forum.arduino.cc/index .php?topic=561741.0
- От Uno до Mega, и где ошибка необъявленного прерывания?
- Считывание нескольких поворотных энкодеров
- Использование поворотных энкодеров с прерываниями смены контактов
- Эквивалент PORTB в Arduino Mega 2560
- Измерение скорости двигателя постоянного тока с помощью поворотного энкодера
- Взаимодействие с датчиком SSI?
- Возникла проблема с переобъявлением символа другого типа
- Кодировщик + Библиотека Bounce2
У вас когда-нибудь это работало? Я тоже хотел использовать Arduino Mega для отслеживания углового положения энкодера Omron с тремя прерываниями. Одно из прерываний для сброса индекса в 0 каждый раз, когда он совершает один оборот. Я хочу использовать его для отслеживания вращающейся мачты для определения направления. Есть куски кода, но ничего полного. Ваш полный? [email protected], @Bkukuk62