Выводы прерываний 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?
- Возникла проблема с переобъявлением символа другого типа
У вас когда-нибудь это работало? Я тоже хотел использовать Arduino Mega для отслеживания углового положения энкодера Omron с тремя прерываниями. Одно из прерываний для сброса индекса в 0 каждый раз, когда он совершает один оборот. Я хочу использовать его для отслеживания вращающейся мачты для определения направления. Есть куски кода, но ничего полного. Ваш полный? bkukuk@cox.net, @Bkukuk62