Проблема с прерываниями и энкодерами 4х на Nano 33 BLE

rotary-encoder arduino-nano-ble

У меня есть кодировщик Pololu 4x, и я пытаюсь написать код, чтобы заставить его работать на моем Nano 33 BLE. (Интересно, что проблема, которая не позволяет мне работать с некоторыми уже существующими библиотеками, — это та же проблема, которую я собираюсь здесь описать...)

Когда я поворачиваю вал двигателя по часовой стрелке, я получаю следующие сигналы (первый бит в каждой паре — это канал A, второй бит — канал B):

11 –> 10 -> 11 -> 10 -> 11 -> 10

Обратите внимание, что значение канала А никогда не меняется, а значение канала Б переключается туда и обратно.

Аналогично для направления против часовой стрелки:

01 –> 11 -> 01 -> 11 -> 01 -> 11

Конечно, это неправильно, так как каналы ' значения должны быть примерно такими: 00 -> 10 -> 11 -> 01 -> 00 при вращении вала. Собственно говоря, это именно то, что я получаю, когда запускаю тот же самый код на обычном Arduino Nano.

Кто-нибудь знает, что происходит? Вот мой код. Насколько я знаю, я не использую прерывания неправильно или что-то в этом роде, по крайней мере, для обычного Nano.

#define PIN_A 2
#define PIN_B 3

volatile int val = 0;
volatile bool newVal = true;

void encoder() {
  int a = digitalRead(PIN_A);
  int b = digitalRead(PIN_B);
  val = ((a << 1) | b);
  newVal = true;
}

void setup() {
  Serial.begin(57600);

  pinMode(PIN_A, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_A), encoder, CHANGE);

  pinMode(PIN_B, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_B), encoder, CHANGE);
}

void loop() {
  if (newVal) {
    Serial.print(bool(val & 0b10));
    Serial.print(bool(val & 0b01));
    Serial.println();
    newVal = false;
  }
}

ОТРЕДАКТИРОВАНО: Взглянув на следующую диаграмму, мы видим, что ошибочные шаблоны кодировщика соответствуют шаблонам, в которых обнаруживаются только нарастающие фронты. Поэтому по какой-то причине attachInterrupt() действует так, как если бы аргумент CHANGE был RISING вместо Nano BLE.

, 👍0

Обсуждение

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


2 ответа


Лучший ответ:

0

Получается, что причина проблемы заключалась в том, что реализация attachInterrupt() в ядре nRF528x Mbed не поддерживает должным образом обнаружение нарастающего/спадающего фронта, как это требуется для режима CHANGE. Я открыл запрос на вытягивание, внедрив необходимые изменения, и протестировал их с помощью моего кодировщика, и я могу подтвердить, что теперь все работает правильно.

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

,

0

Наилучшей практикой будет использование одного прерывания для кодера. BLE имеет более быстрый процессор, и ваш код не основан на кадрах, так что это также может повлиять на него. Этот код не делает точно то, что делал ваш код, но он будет использовать val для отслеживания позиции в виде числа. Это также можно сделать немного лучше, используя CHANGE вместо RISING, но для отладки «голых костей» меньше вероятность того, что что-то пойдет не так.

#define PIN_A 2
#define PIN_B 3

volatile int val = 0;
int oldVal;
// volatile bool newVal = true;

void encoder() {
  if(digitalRead(PIN_B)) ++val;
  else --val;
}

void setup() {
  Serial.begin(57600);

  pinMode(PIN_A, INPUT_PULLUP);
  pinMode(PIN_B, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_A), encoder, RISING);
}

void loop() {
  if (val != oldVal) {
    oldVal = val;
    Serial.println(oldVal);
  }
  delay(500);
}
,

Добро пожаловать в Ардуино:SE. Пожалуйста, не публикуйте несколько ответов на один и тот же вопрос. Просто отредактируйте информацию в исходном ответе., @sempaiscuba

Пожалуйста, оценивайте ответы как ответы без предвзятости для тех, кто их опубликовал., @Abel

Меня не беспокоит, кто публикует ответы, но SE — это сайт вопросов и ответов, а не форумы, к которым вы, возможно, привыкли. Редко кому нужно публиковать более одного ответа на заданный вопрос. Возможно, вам будет полезно ознакомиться с сайтом [tour](https://arduino.stackexchange.com/tour) и [Справочным центром](https://arduino.stackexchange.com/help) и, в частности, [Как мне написать хороший ответ?](https://arduino.stackexchange.com/help/how-to-answer)., @sempaiscuba