Отслеживание всех состояний энкодера
Методист по олимпиадной робототехнике Университета Иннополис Алексей Овсянников продолжает серию уроков. Читайте, как легко и просто отслеживать все возможные состояния (фазы) энкодера.
Продолжаю публиковать материалы для слушателей курсов повышения квалификации по робототехнике. В одной из прошлых статей я рассказал про обработку сигналов энкодера в Arduino. Сегодня я хотел бы продолжить эту тему и рассказать, как легко и просто можно отследить все возможные состояния (фазы).
В прошлой статье я привел код для Arduino, позволяющий с помощью прерываний отслеживать только один выход энкодера, а сигнал на втором проверялся уже внутри обработчика и указывал на направление вращения. В результате мы улавливали 11-12 тиков на один оборот диска энкодера. Сегодня разовьем программу и научимся «отлавливать» все возможные состояния, что позволит в 4 раза увеличить точность (улавливать 44-48 состояний на один оборот диска).
Вспомним сигналы, возникающие на двух выходах энкодера:
С каждого энкодера приходит два сигнала. Для полного отслеживания сигналов потребуется их подключать к пинам, поддерживающим прерывания. У общеизвестной «народно любимой» платы Arduino UNO всего лишь два таких пина (2 и 3), то есть к ней получится подключить всего один мотор для полного отслеживания или два мотора, как было описано в прошлой статье. Узнать подробнее о прерываниях можно на официальном сайте. Для экспериментов хватит и UNO, но я сразу переключился на Arduino MKR Zero, которая имеет 9 пинов с прерываниями (до 4 моторов). Код итоговой программы от выбранной платы почти не меняется, только указываются другие пины.
Про подключение подробно не буду рассказывать, для мотора Pololu 75:1 MP 12V выглядит как на фото:
Зеленый провод — «земля» энкодера — соединяем с GND платы
Синий провод — питание энкодера — соединяем с Vcc платы (работает и от 3.3В, и от 5В)
Желтый провод — выход А энкодера — на пин платы с прерыванием
Белый провод — выход B энкодера — на другой пин платы с прерыванием
На красный и черный провода подается питание мотора, я же оставлю их пустыми и буду крутить мотор рукой.
Итак, я подключил выходы А и В энкодера к пинам 6 и 7 Arduino MKR Zero (у Arduino UNO это будут пины 2 и 3). В программе я могу настроить прерывание на переход сигнала из 0 в 1 (передний фронт, RISING), из 1 в 0 (задний фронт, FALLING) или на любое подобное изменение (CHANGE). Для полноты картины придется ловить оба фронта.
В процедурах intAsub и intBsub будет происходить обработка прерываний. Первым делом, в каждой из них считываю и запоминаю текущий сигнал:
и
Внимательно изучим сигналы, приходящие по линиям А и В. При вращении мотора вперед:
При вращении мотора назад:
Зелеными стрелками я обозначил передний фронты, красными — задние. На любой из линий передний фронт возникает при изменении сигнала с 0 на 1, при этом на другой линии еще с прошлого шага стабильно держится какой-то сигнал. Задний фронт возникает при изменении сигнала с 1 на 0, на другой линии опять же с прошлого шага держится какой-то сигнал.
Если следить за прерываниями линии А, то получаем:
Передний фронт А при вращении вперед — на линии В сигнала нет,
Задний фронт А при вращении вперед — на линии В есть сигнал,
Передний фронт А при вращении назад — на линии В есть сигнал,
Задний фронт А при вращении назад — на линии В нет сигнала.
Внимательно смотрим на эти четыре варианта и замечаем, что при движении вперед сигналы sigA (считанный в самом начале прерывания) и sigB (считанный ранее в другом прерывании) отличаются, а при движении назад совпадают. Если не уловили, то остановитесь на этом моменте и еще раз внимательно изучите сигналы. Например, мотор крутится вперед и возникло прерывание на заднем фронте; мы считываем этот сигнал командой digitalRead и видим 0. А на линии В с последнего прерывания той линии хранится значение 1.
Таким образом обработчик прерывания для линии А принимает вид:
Переменная sigB обновляется и актуализируется в другом прерывании.
Если следить за прерываниями линии В, то получаем:
Передний фронт B при вращении вперед — на линии А сигнал есть,
Задний фронт В при вращении вперед — на линии А сигнала нет,
Передний фронт В при вращении назад — на линии А сигнала нет,
Задний фронт В при вращении назад — на линии А сигнал есть.
Внимательно смотрим на эти четыре варианта и замечаем, что при движении вперед сигналы sigA (считанный в самом начале прерывания) и sigB (считанный ранее в другом прерывании) совпадают, а при движении назад отличаются. Обработчик прерываний для линии В:
Вот и все! Не надо никаких сложных алгоритмов, запоминания текущей фазы и сравнивания с предыдущими, не надо хранить сигналы в 8 переменных и выстраивать трехэтажную логику.
Если к контроллеру надо подключить несколько моторов, то придется создавать такие процедуры для каждого пина. На три мотора получится 6 процедур, на 4 мотора 8 процедур и т.д.
Реализовать подобный алгоритм можно на любом контроллере, имеющем достаточно внешних прерываний. Некоторые контроллеры, например STM32, имеют даже аппаратную поддержку подобных энкодеров. Но об этом можно поговорить позже, пока что остановимся на доступной и понятной линейке Arduino, которую просто надо научиться эффективно использовать.
Кстати, итоговый код программы:
Надеюсь, что рассмотренный материал пригодится кому-нибудь при подготовке к олимпиаде Innopolis Open in Robotics. Более подробно о подготовке к олимпиаде мы будем рассказывать на тематических КПК, да и подробнее познакомиться с подобными приемами можно на курсах Arduino.
Дмитрий
10.03.2020
Друзья, а есть ли где-нибудь на просторах интернета модели энкодера для протеуса? Чего-то я весь гугль перерыл, нашел только какую-то старую модель от 2006 года, которая, сцуко, даже прилепленная средней ногой к земле, не может даже пересилить внутреннюю подтяжку меги. Не говоря уж о том, что сигнал она выдает совсем не как в даташитах. Импульс на ноге A в два раза длинне, чем на ноге B получается. Я уж думаю, может подцепить к меге еще и тиньку 13 с двумя кнопками, которя будет сигнал энкодера эмулировать?! :)))
Овсянников Алексей
10.03.2020
Дмитрий, модель какого энкодера Вам нужна? Который на моторе или который руками крутят в реальном мире?
Мотор с энкодером точно есть, в протеусе принцип его работы нам и показывали в далеком студенчестве. Беглый поиск в гугле дал это: ttps://radiokot.ru/forum/viewtopic.php?f=2&t=117513
Вращаемые руками энкодеры не встречал. Протеуса под рукой нет, поискать не могу.
Что касается разной длительности импульсов на разных ногах, то это наводит на мысль об энкодере не инкрементном (который выдает импульсы и их надо считать), а абсолютном (который выдает двоичный код, не повторяющийся за весь оборот). Подробнее о таких энкодреах: https://megasensor.com/products/princip-raboty-absolyutnogo-enkodera/