ARDUINO Странности с энкодером

PankTech

✩✩✩✩✩✩✩
16 Авг 2020
5
0
Здравствуйте. Пытаюсь получить данные с китайского энкодера.
2022-02-07 16-53-25.JPG
Заявлено 1000 линий на оборот и рассчитан на 5000 об/мин.
Подключил выходы А и В энкодера к пинам 20,21 Arduino Mega 2560, запитал от 12в.
2022-02-07 16-53-33.JPG
Это я загрузил в Ардуино:
Енкодер:
volatile int counter = 0;   // счётчик
volatile byte reset = 0, last = 0;
volatile bool encFlag = 0;  // флаг поворота
int old_counter;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(21, INPUT_PULLUP);
  pinMode(20, INPUT_PULLUP);
  attachInterrupt(3, test, CHANGE);
  attachInterrupt(2, test, CHANGE);
}

void loop() {
  if (counter != old_counter)
  {
    Serial.println(counter);
  }
  old_counter = counter;
}
void test(void)
{
  byte state = (PIND & 0b11);
  if (reset && state == 0b11) {
    int prevCount = counter;
    if (last == 0b10) counter++;
    else if (last == 0b01) counter--;
    if (prevCount != counter) encFlag = 1;
    reset = 0;
  }
  if (!state) reset = 1;
  last = state;
if(counter >= 1000 || counter <= -1000) counter=0; //Один оборот
}
При небольшой скорости вращения всё работает отлично. На один оборот ровно 1000 тиков энкодера.
Но при увеличении скорости всё ломается. Как будто дуня не успевает обработать прерывания.

Скриншот 07-02-2022 18_10_42.jpg

Тест показал, что обработка прерывания происходит за 28 тактов процессора.
Видео прилагается.
Кто знает в чём дело? Подскажите, что я не так делаю?

Этот энкодер должен считывать положение шпинделя на токарном станке. Максимальная скорость шпинделя 2000 об/мин.
 
Изменено:

Геннадий П

★★★★★★✩
14 Апр 2021
1,975
634
45
Нужно смотреть как подключено, а еще лучше осциллографом посмотреть что творится на входах контроллера.
Т.к. для отработки на 2000 об/мин этого энкодера нужно чтобы контроллер нормально отрабатывал примерно 4000 прерываний в секунду.
Ну или может банально прерывание не успевает отрабатывать.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,975
634
45
@Старик Похабыч, Не знаю как на атмегах аппаратный UART устроен, но по идее он не должен влиять на срабатывание прерываний.
Но впрочем, для проверки лучше не выводить данные каждый цикл без задержки, лучше например раз в пол-секунды.

Если кто не понял в чем проблема:
  • Ставится энкодер в "нулевое положение"
  • Вращаем медленно - все работает нормально, "нулевое положение" сохраняется
  • Вращяем быстро - получаем пропуски отсчетов, "нулевое положение" сбивается
И еще. Чтобы задавать точное "нулевое положение" есть специальные энкодеры с абсолютным позициаонированием, например на коде Грея.
 
  • Лойс +1
Реакции: PankTech

Старик Похабыч

★★★★★★★
14 Авг 2019
4,277
1,303
Москва
В UART есть буфер, пока он не заполнен , то в него моджно что то положить, и далее аппартно из него идет послы. Но как только буфер заполняется, то Serial.println() будет ждать освобождения . В общем замедляется работа. Останавливает ли оно прерывания , которые аттач, я сказать не могу
 

bort707

★★★★★★✩
21 Сен 2020
3,073
915
А с какой частотой Mega 2560 обрабатывает прерывания? Кто нибудь знает?
насколько успевает. Зависит от числа действий в прерывании и от времени входа в процедуру. В любом случае пока не закончится одно прерывание, другое не начнется.
У вас доаольно много действий в прерывании, думаю оно занимает сотни тактов
 

PankTech

✩✩✩✩✩✩✩
16 Авг 2020
5
0
Максимально сократил обработку прерывания. Не помогло, пляски с бубном продолжаются.
C++:
volatile int counter = 0;   // счётчик

void setup() {

  Serial.begin(115200);
  pinMode(21, INPUT_PULLUP);
  pinMode(20, INPUT_PULLUP);
  attachInterrupt(2, test, RISING);
}

void loop() {

    Serial.println(counter);

}
void test(void)
{
  counter +=((PIND & 0b10)==0b0) ? -1:1;

}
На выполнение требуется 17 тактов
 

bort707

★★★★★★✩
21 Сен 2020
3,073
915
@PankTech, в этой строчке вы читаете только один пин
C++:
counter +=((PIND & 0b10)==0b0) ? -1:1;
это явно недостаточно для энкодера
 

poty

★★★★★★✩
19 Фев 2020
3,264
949
@bort707, достаточно. Событие перехода второго пина в 1 вызывает само прерывание.
Надо пробовать без Serial.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,975
634
45
@PankTech, Понял, у него внутри своя схема усилителей. Если уверены в коде, то тогда нужно пробовать смотреть осциллографом что у него на выходе творится, т.к. китайцы часто завышают значения, и он может легко не дотягивать до 5000 об/мин.