Как подключить энкодер к компьютеру

Обновлено: 04.07.2024

Поворотный энкодер представляет собой электромеханическое устройство, которое преобразует вращательное движение в цифровую или аналоговую информацию. Он очень похож на потенциометр, но может вращаться бесконечно как по часовой стрелке, так и против часовой стрелки. Существует несколько типов поворотных энкодеров. Двумя основными типами являются абсолютные и относительные (инкрементальные) энкодеры. В то время как абсолютный энкодер выдает значение, пропорциональное текущему углу вала, инкрементальный энкодер выдает шаг движения вала и его направление. Поворотные энкодеры становятся всё более и более популярными в потребительской электронике, особенно в качестве ручек управления, в дополнение к приложениям во многих других областях. Они заменяют собой потенциометры и кнопки навигации, где требуются быстрая навигация, настройка, ввод данных и выбор пункта меню. Некоторые энкодеры также включают в себя встроенную кнопку, которая создает дополнительный вход для процессора, который может использоваться в качестве другой пользовательской команды в интерфейсе управления. На рисунке ниже вы можете увидеть типовой инкрементальный поворотный энкодер с кнопкой включения.

Инкрементальный поворотный энкодер

Инкрементальный поворотный энкодер

В данной статье мы покажем вам, как использовать инкрементальный поворотный энкодер в проекте на Arduino. Мы объясним, как бороться с дребезгом контактов и интерпретировать сигналы энкодера в программе микроконтроллера, используя прерывания.

Сигнал квадратурного выхода инкрементального энкодера

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

Сигналы на выходах инкрементального поворотного энкодера при вращении вала по часовой стрелке и против

Сигналы на выходах инкрементального поворотного энкодера при вращении вала по часовой стрелке и против

Как видно из рисунка, оба выхода в изначально находятся в состоянии логической единицы. Когда вал энкодера начинает вращаться в направлении по часовой стрелке, первым падает до логического нуля состояние на выходе A, а затем с отставанием за ним следует и выход B. При вращении против часовой стрелки всё происходит наоборот. Временные интервалы на диаграмме сигнала зависят от скорости вращения, но отставание сигналов гарантируется в любом случае. На основе этой характеристики инкрементального поворотного энкодера мы напишем программу для Arduino.

Фильтрация дребезга контактов механического энкодера

Механические энкодеры имеют встроенные переключатели, которые формируют сигнал на квадратурном выходе во время вращения.

Дребезг контактов на выходе механического энкодера

Дребезг контактов на выходе механического энкодера

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

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

Фильтрация шума с помощью дополнительных аппаратных средств проще, и она останавливает шум еще в его источнике. Вам понадобится RC фильтр первого порядка. На рисунке ниже вы можете увидеть, как выглядит сигнал после использования RC фильтра.

RC фильтр и форма сигнала на его выходе

RC фильтр и форма сигнала на его выходе

RC-фильтр замедляет время спада и время нарастания и обеспечивает аппаратное удаление дребезга контактов. При выборе пары резистор-конденсатор вы должны учитывать максимальную частоту вращения. Иначе будет отфильтрован и ожидаемый отклик энкодера.

Простое приложение

Мы создадим приложение, демонстрирующее, как использовать поворотный энкодер в проекте на Arduino. Мы будем использовать энкодер для навигации, ввода данных и выбора. Ниже приведена принципиальная схема приложения.

Принципиальная схема примера приложения с использованием поворотного энкодера на Arduino

Принципиальная схема примера приложения с использованием поворотного энкодера на Arduino

Схема построена на базе платы Arduino Uno. Для графического интерфейса используется LCD дисплей Nokia 5110. В качестве средств управления добален механический поворотный энкодер с кнопкой и RC-фильтрами.

Собранная схема примера использования поворотного энкодера на Arduino

Собранная схема примера использования поворотного энкодера на Arduino

Мы разработаем простое программное меню, в котором и продемонстрируем работу поворотного энкодера.

Обработка сигналов энкодера с помощью прерываний

Сигналы энкодера должны быть обнаружены и интерпретированы в программе как можно быстрее, чтобы не блокировать основной поток программы. Мы можем детектировать сигналы путем опроса в основном цикле, или используя прерывания. Опрос не эффективен, так как вам необходимо зарезервировать время и ресурсы в основном цикле, что приводит к дополнительным задержкам. Использование прерываний – это более быстрое и экономичное решение. Мы покажем вам, как использовать прерывания для обработки сигналов энкодера.

В Atmega328 есть два типа прерываний, которые можно использовать для этих целей; внешнее прерывание и прерывание по изменению состояния вывода. Выводы INT0 и INT1 назначены на внешнее прерывание, а PCINT0 - PCIN15 назначены на прерывание по изменению состояния вывода. Внешнее прерывание может определить, произошел ли спад или нарастание входного сигнала, и может быть запущено при одном из следующих состояний: нарастание, спад или переключение. Для прерывания по изменению состояния выводов существует гораздо больше аппаратных ресурсов, но оно не может обнаруживать нарастающий и спадающий фронты, и оно вызывается, когда происходит любое изменение логического состояния (переключение) на выводе.

Чтобы использовать прерывание по изменению состояния выводов, подключите выходы поворота энкодера A и B к выводам A1 и A2 , а выход кнопки – к выводу A0 платы Arduino, как показано на принципиальной схеме. Установите выводы A0 , A1 и A2 в режим входа и включите их внутренние подтягивающие резисторы. Включите прерывание по изменению состояния выводов в регистре PCICR и включите прерывания для выводов A0 , A1 и A2 в регистре PCMS1 . При обнаружении любого изменения логического состояния на одном из этих входов будет вызовано ISR(PCINT1_vect) (прерывание по изменению состояния выводов).

Поскольку прерывание по изменению состояния выводов вызывается для любого логического изменения, нам необходимо отслеживать оба сигнала (и A, и B) и обнаруживать вращение при получение ожидаемой последовательности. Как видно из диаграммы сигналов, движение по часовой стрелке генерирует A = …0011… и B = …1001… . Когда мы записываем оба сигналы в байты seqA и seqB , сдвигая последнее чтение вправо, мы можем сравнить эти значения и определить новый шаг вращения.

Вы можете увидеть часть кода, включающую инициализацию и функцию обработки прерывания по изменению состояния выводов.

Использование внешнего прерывания делает процесс более простым, но поскольку для этого прерывания назначено только два вывода, то вы не сможете использовать его для других целей, если займете его энкодером. Чтобы использовать внешнее прерывание, вы должны установить выводы 2 ( INT0 ) и 3 ( INT1 ) в режим входа и включить их внутренние подтягивающие резисторы. Затем выберите вариант спадающего фронта для вызова обоих прерываний в регистре EICRA . Включите внешние прерывания в регистре EIMSK . Когда начнется вращение вала энкодера, сначала ведущий сигнал падает до логического нуля, а второй сигнал некоторое время остается на уровне логической единицы. Поэтому нам нужно определить, какой из сигналов во время прерывания находится в состоянии логической единицы. После того, как ведущий сигнал упал до логического нуля, через некоторое время второй сигнал также упадет до логического нуля, что вызовет другое прерывание. Но этот раз и другой (ведущий) сигнал будет на низком логическом уровне, что означает, что это не начало вращения, поэтому мы игнорируем его.

Ниже вы можете увидеть часть кода, включающую в себя инициализацию и функцию обработки внешнего прерывания.

Макет для проверки кода работы с инкрементальным поворотным энкодером на Arduino

Макет для проверки кода работы с инкрементальным поворотным энкодером на Arduino

Блог посвящен радиоэлектронике, микроконтроллерам, платформе Arduino, а также частично программированию.

воскресенье, 20 февраля 2011 г.

Arduino: как подключить энкодер к PC

Здесь находится описание и видео процесса подключения к компьютеру датчика угла поворота через Arduino и USB-порт. Получившийся прототип по принципу своего действия похож на устройство Powermate от компании Griffin

Сегодня рассказываю о том, как сделать из простого механического энкодера устройство ввода для компьютера.

Разрешение это количество шагов (сигнальных изменений) которое обеспечивает энкодер за один свой полный оборот. Разрешение сильно зависит от типа энкодера и большая часть устройств находится в диапазоне от 8 до 1000 шагов. Однако, если верить фильтрам магазина DigiKey и чуть-чуть Википедии, то существуют какие-то промышленные монстры с разрешением 6000 шагов и более. Доставшийся вариант имел разрешение в 24 шага. Забегая вперёд скажу, что этого мало.




Для того чтобы подружить получившуюся железку с компьютером было нужно чтобы прошивка Ардуино, получив сигнал от энкодера, писала данные об изменениях в виртуальный COM-порт через USB.

Естественно, я не первый, кто подключил энкодер к Ардуино, поэтому писать прошивку-сэмпл мне не пришлось и я взял готовую (кстати, в заметке по ссылке много полезного). Поигравшись с delay, скоростью COM, отключив счётчики и включив обработку кнопки я добился приемлемого для прототипа качества опроса. Без реализации акселерации, обработки ложных срабатываний, непредсказуемого флуда в порт и других тысяч важных мелочей.

Итоговый результат вы можете оценить по видеоролику. Я надеюсь, что кому-то этот рассказ поможет решить давно заброшенную задачу, или, наоборот, вдохновит взяться за паяльник, или, на крайний случай, поведает о существовании такого класса устройств, как энкодеры.


Однажды ко мне попал линейный энкодер ПЛФ-3 и мне захотелось подключить его к микроконтроллеру. Однако, как оказалось, дело это не самое простое. Какие именно проблемы возникли при этом, и как они были решены — читайте далее.

ПЛФ-3 — линейный инкрементальный энкодер. Его назначение — измерять относительные перемещения частей приборов. Обеспечиваемая точность может быть очень высокой — до долей мкм. Принцип работы такого энкодера довольно прост — есть стеклянная «линейка» (1) с нанесенными на нее штрихами, относительно которой перемещается каретка, на которой закреплены источник света (3), оптическая система (2,4) и набор фотодиодов. Оптическая система и фотодиоды сгруппированы в пары, так чтобы на их выходе формировались квадратурные сигналы (со сдвигом в 90 градусов). За счет этого можно определять направление движения энкодера.

Так как шаг штрихов очень маленький (десятки микрон), то для того, чтобы на более крупных фотодиодах возник сигнал, используется дополнительный растр (2).
Более подробно про принцип работы таких энкодеров написано здесь.
Линейный энкодер обычно можно найти практически в любом струйном принтере. Линейка в данном случае представлена тонкой лентой со штрихами, и натянута рядом с кареткой, на которой находятся остальные части энкодера.

Судьба энкодера, попавшего ко мне, была нелегкой. Изначально он входил в состав микроскопа ИМЦЛ150х50Б, который стоял в нашем институте. Микроскоп был никому не нужен, и в его списали вместе с кучей других приборов. Тащить их на задний двор никому не хотелось, и все приборы просто выкинули в окно (высота там около 10 метров). Уже после этого я заметил разбитый микроскоп, и снял с него два энкодера. Как ни странно, в обоих энкодерах стеклянные линейки остались целыми, но каретки были довольно сильно повреждены, хотя позже удалось привести их в более приличное состояние.
Внешний вид каретки:

Стоит заметить, что риски на линейках в данном типе энкодеров, да и, скорее всего, в других, очень нежные — прикасаться к ним нельзя. Даже мягкой кисточкой протирать нельзя — иначе они могут стереться. Это касается и различных дифракционных решеток, которые можно встретить в некоторых оптических приборах.
В энкодере ПЛФ-3 каретка никак не закреплена, она содержит только направляющие подшипники и прижимную пружину, используемые для того, чтобы положение оптической части каретки относительно линейки оставалось неизменным. Поэтому для экспериментов пришлось соорудить специальное крепление из мебельной направляющей, чтобы можно было двигать линейку относительно каретки.

Электроники в этом энкодере практически нет. В качестве источника света используется микролампочка (похоже, что в момент разработки энкодера достаточно мощных светодиодов еще не было). К сожалению, при падении она разбилась, так что пришлось покупать новую, и вклеивать ее туда (родная тоже была приклеена). Очевидно, что это тоже не лучшим образом повлияло на работу точной оптики энкодера.

Сигнал с фотодиодов в этом энкодере просто выводится на довольно длинный провод (как минимум 1.5 метра). Сейчас в современные энкодеры встраивают усилители, и иногда компараторы, чтобы выход энкодера был цифровым.
Таким образом, мне пришлось сделать усилитель сигнала с фотодиодов и компаратор.
Схема усилителя простейшая (взята отсюда):

Фото конструкции:

В качестве ОУ используется LM358. На еще одной LM358 собрал простейший компаратор на два канала. Таким образом, я получил два цифровых квадратурных сигнала. Для эксперимента я подал их на Arduino, с подключенной библиотекой, предназначенной для работы с быстрыми энкодерами. Тут-то и вылезли проблемы.
Как оказалось, по каким-то причинам средний уровень сигнала в каждом из каналов сильно «плавает» — на величину, чуть ли не большую амплитуды сигнала. Понятно, что при таких условиях компаратор нормально работать не будет. Положение среднего уровня зависело от абсолютного положения каретки энкодера, так что проблема была явно связана с ним самим. Была еще одна проблема — насколько я понял, разность фаз сигналов в каналах была не 90 градусов. В некоторых случаях она доходила до 120 градусов, из-за чего фронты сигналов оказывались слишком близко друг от друга. В результате при попытке двигать энкодер в счетчике Arduino постоянно накапливалась ошибка, и довольно большая.
Поэтому я решил пойти по более необычному пути — обрабатывать аналоговые сигналы на STM32F4-DISCOVERY. Для проверки работы алгоритмов я записал сигналы с энкодера при помощи USB-осциллографа, а потом обрабатывал их в самописной программе на ПК.
Пример проблемного участка сигнала:

Толстая синяя линия — средний уровень сигнала. Алгоритм в данном случае выполняет роль компаратора с определенным уровнем гистерезиса — его выходные сигналы тоже выведены на график. Выборки в каналах ведутся одновременно — они отмечены черными точками. На графике красным отмечен участок, показывающий пересечение фронтов компаратора. Очевидно, что в нормальных квадратурных сигналах фронты пересекаться не должны. При сдвиге фаз аналоговые сигналы должны пересекаться на уровне 0.7 от амплитуды сигнала. Здесь, как видно, они могут пересекаются при меньших значениях.

Для того, чтобы скомпенсировать вышеупомянутые эффекты, пришлось написать специальный алгоритм, который с минимальной задержкой вычисляет текущую величину среднего уровня в каждом из каналов, которая потом используется для работы программного компаратора. По данным от компараторов определяется наличие движения и его направление. В случае обнаружения вышеупомянутых «пересечений фронтов» счетчик энкодера уменьшается или увеличивается на 2, в зависимости от предыдущего направления движения.
Контроллер захватывает аналоговые сигналы при помощи сразу двух АЦП, работающих одновременно, причем скорость выборок приходится делать очень высокой — более 300 ksps. Один АЦП генерирует прерывания, из обработчика которых вызывается вышеупомянутый алгоритм. Из-за высокой частоты прерываний и достаточно длинного алгоритма загрузка контроллера получается довольно высокой.
Результат измерений переводится в микроны и выводится на ЖКИ от кассового аппарата Штрих-М.

У энкодера ПЛФ-3 шаг штрихов линейки составляет 20 мкм. С учетом того, что энкодер формирует квадратурные сигналы, дискретность измеряемого расстояния после «компаратора» составляет 5 мкм. Так как сигнал на выходе датчика аналоговый, то можно повысить точность измерений, вычисляя арктангенс отношения сигнала в каналах (с учетом величины среднего уровня в каждом из каналов). Так как вычислять atan с частотой 300кгц на контроллере проблематично, а результат измерений просто отображается на экране, то я вычисляю atan для перед выводом на индикатор. Для более высокой точности нужно было бы дополнительно нормировать сигналы в каналах, но я не стал это реализовывать. В своей программе я ограничил дискретность 1 мкм — с использованным энкодером получить даже такую точность кажется не совсем реально.
Видео работы:



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


Этот угловой энкодер также известен как квадратурный энкодер или относительный угловой энкодер. Сигнал с его выход представляет собой серию прямоугольных импульсов.

Как работает поворотный энкодер

Давайте подробнее рассмотрим энкодер и разберемся, как он работает. Вот как генерируются прямоугольные импульсы: энкодер имеет диск с равномерно расположенными контактными зонами, которые подключены к общему контакту C и двум другим отдельным контактам A и B, как показано ниже:

Работа энкодера

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

Любой из двух выходов может использоваться для определения повернутого положения, если мы просто подсчитываем количество импульсов сигнала. Однако, если мы хотим также определить направление вращения, нам нужно рассматривать оба сигнала одновременно.


Обновленная версия, мощность: 600 Вт, расход воздуха: 240 л/час.

Мы можем заметить, что оба выходных сигнала смещены по фазе на 90 градусов друг относительно друга. Если энкодер вращается по часовой стрелке, сигнал с выход A будет опережать сигнал с выхода B:


Поэтому, если мы будем считать шаги каждый раз, когда сигнал изменяется (с высокого на низкий или с низкого на высокий), мы можем заметить, что в это время два выходных сигнала имеют противоположные значения.

Учитывая это, мы можем легко запрограммировать Ардуино на считывание положения энкодера и направления вращения.

Подключение энкодера к Ардуино без библиотек

Давайте проверим это на практическом примере, используя Ардуино. Конкретный модуль энкодера, который мы будем использовать в этом примере, поставляется на коммутационной плате и имеет пять контактов.

Рассмотрим распиновку данного энкодера:

Фото распиновки

Мы можем подключить выходные контакты к любому цифровому выводу платы Ардуино.

Скетч для проверки работы энкодера:

Разбор кода: Итак, сначала нам нужно определить контакты, к которым подключен наш поворотный энкодер, и определить некоторые переменные, необходимые для программы.

В разделе setup() нам нужно определить два контакта в качестве входов, запустить последовательную связь для печати результатов в монитор последовательного порта, а также прочитать начальное значение выхода «A» и поместить значение в переменную aLastState.

Затем в разделе цикла мы снова читаем состояние вывода «A», но теперь мы помещаем значение в переменную aState. Таким образом, если мы повернем энкодер и будет сгенерирован импульс, эти два значения будут отличаться, и первое утверждение «if» станет истинным.

Сразу после этого с помощью второго оператора «if» мы определяем направление вращения. Если состояние выхода «B» отличается от состояния выхода «A», счетчик будет увеличен на единицу, иначе он будет уменьшен.

В конце, после печати результатов в монитор последовательного порта, нам нужно обновить переменную aLastState с помощью переменной aState.

Это все, что нам нужно для этого примера. Если мы загрузим скетч в Ардуино, запустим Serial Monitor и начните вращать энкодер, то мы начнем получать значения в последовательном мониторе. Конкретный модуль, который у нас есть в наличии, делает 30 отсчетов за каждый полный цикл.

Читайте также: