Подключение энкодера к микроконтроллеру



Подключение энкодера к микроконтроллеру
Инкрементальный энкодер представляет собой механическое устройство (датчик) преобразующее угол поворота вала (ручки) в электрические сигналы. Энкодер имеет три вывода, или пять в зависимости от наличия встроенной кнопки. Здесь я рассматриваю наиболее распространенные энкодеры, которые встраивают в бытовую аппаратуру, например, для регулировки громкости, навигации в меню и т.д. В отличие от переменного резистора, положение ручки энкодера меняется дискретно, “щелчками”, при этом происходит несколько коммутаций, последовательность которых зависит от направления вращения. На один полный оборот ручки может приходиться различное количество дискретных положений (12, 20, 24), в зависимости от модели энкодера.

На рисунке ниже представлена функциональная схема поясняющие принцип действия энкодера.
Временные диаграммы для энкодера
Как видно из временных диаграмм, при повороте на одно дискретное положение (на один “щелчок”), на выводах A и B формируются отрицательные импульсы (полярность импульсов зависит от схемы подключения), сдвинутые по фазе между собой. Сдвиг фаз зависит от направления вращения. Из временной диаграммы можно выделить четыре состояния, которые составляют период одного дискретного изменения (“щелчка”), длительность периода варьируется примерно от 2 мс до 4 мс.

На следующем рисунке представлена схема подключения энкодера к микроконтроллеру:
Схема подключения энкодера к МК
Выводы A и B энкодера необходимо подтянуть к линии питания +5В с помощью резисторов, также необходимо установить конденсаторы C1 и C2 которые уменьшают влияние дребезга контактов.

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

Ниже представлен код программы, в которой реализован периодический опрос состояния выводов энкодера. Опрос состояний выводов А и B энкодера выполняется в подпрограмме обработки прерываний, которая периодически вызывается по переполнению таймера TMR0 (см. Таймеры. Организация временной задержки). В моем варианте таймер переполняется примерно через 1 мс, то есть энкодер опрашивается каждую миллисекунду.

Внутри обработчика прерываний сначала сохраняется текущее состояние выводов энкодера, для этого используется дополнительный регистр flag, содержимое которого всегда перед выходом из обработчика сдвигается влево на два бита, таким образом сохраняется предыдущее состояние выводов энкодера. После сохранения текущего состояния в 0-й и 1-й бит регистра flag, осуществляется проверка предыдущего состояния, то есть анализируются 2-й и 3-й биты. Алгоритм следующий: если предыдущее состояние обоих выводов соответствовало логической единице, проверяем текущее сохраненное значение (биты 0,1 регистра flag), если значение битов равно 0 и 1, произошел поворот в одну сторону, если значение равно 1 и 0, произошел поворот в противоположную сторону. После определения факта поворота происходит инкремент или декремент регистра shet, содержимое которого (число от 0 до 255) в основной программе выводится на семисегментные индикаторы. Инкремент производится до числа 255 и ограничивается на этом значении, даже при дальнейшем повороте ручки энкодера, то же самое и при декременте до 0.

Если предыдущее состояние обоих выводов не соответствует 1, просто выходим из обработчика, также смещая содержимое регистра flag влево. Это необходимо чтобы пропустить все остальные возможные состояния выводов энкодера, то есть для определения направления вращения используется половина периода одного дискретного изменения (два состояния из четырех возможных).

При использовании такого алгоритма выявились некоторые недостатки, сам факт поворота ручки определялся стабильно, но из-за наличия дребезга контактов в конце периода одного дискретного изменения (после “щелчка”), происходило повторное определение факта поворота, причем в обратную сторону. То есть после инкремента регистра shet происходил декремент и наоборот. Чтобы избежать этого, после инкремента/декремента регистра shet, я дополнительно добавил условие для многократной проверки состояния выводов энкодера на соответствие высокому логическому уровню. После инкремента/декремента shet, перед выходом из обработчика прерывания устанавливается флаг (0-й бит) в дополнительном регистре flag1. При последующих входах в обработчик, после проверки предыдущего состояния и соответствия выводов энкодера высокому логическому уровню, по установленному флагу в регистре flag1 происходит инкремент регистра shet1. Если его содержимое не равно числу 3 происходит выход из обработчика. Таким образом, после факта поворота, следующее определение состояния энкодера будет выполняться, при условии трехкратной фиксации высоких логических уровней на выводах энкодера, после чего регистр shet1 обнуляется и сбрасывается флаг регистра flag1.

После изменения значения регистра shet в обработчике прерываний, дополнительно устанавливается флаг регистрации поворота энкодера flag1,1, который опрашивается в основной программе, если флаг установлен вызывается подпрограмма vivod, для вывода содержимого регистра shet на семисегментные индикаторы.

Теперь рассмотрим программу опроса энкодера основанную на прерываниях по изменению уровня на входах микроконтроллера:

Выводы энкодера подключены к линиям RB4, RB5, в микроконтроллере включены прерывания по изменению уровня на входах RB4-RB7. Линии RB6, RB7 настроены на выход, чтобы не вызывать ложных прерываний, так как в данном микроконтроллере нельзя разрешать прерывания по отдельности на каждую линию. В обработчике прерываний происходит сохранение текущих состояний выводов энкодера в 0-й и 1-й биты регистра flag, далее идет проверка сохраненных значений, если биты 0 и 1 равны нулю, происходит переход на метку i2, где проверяется предыдущее состояние выводов энкодера записанных в биты 2 и 3 регистра flag. Если значение битов равно 0 и 1 произошел поворот в одну сторону, если 1 и 0 в другую сторону, состояние 0-0 и 1-1 игнорируется, в этом случае происходит выход из обработчика прерываний. После определения факта поворота происходит изменение значения счетчика shet, а также установка флага регистрации поворота энкодера flag1,0. Этот флаг опрашивается в основной программе, и если равен единице вызывается подпрограмма vivod, для вывода содержимого регистра shet на семисегментные индикаторы.

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

Вышеприведенные программы тестировались на микроконтроллере PIC16F628A, тактовый генератор внутренний на 4 МГц, энкодер на 20 дискретных положений. Для отображения содержимого регистра shet, использовано цифровое табло из семисегментных индикаторов на драйвере MC14489AP. Результат представлен на видеоролике ниже.

Последние записи:

Комментариев 27 на “Подключение энкодера к микроконтроллеру

  1. Не могу написать подпрограмму вывода регистра на семисегментный индикатор, если есть у кого, выложите, пожалуйста.

  2. Может кто посоветовать схему управления асинхронным двигателем на микроконтроллере с энкодером?

    • А энкодер какую роль должен выполнять? Как именно должен управляться двигатель?

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

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

            • Ну в таком случае (с асинхронным двигателем) на выходе редуктора (на мембране) надо ставить датчик положения (потенциометр, переменный резистор) чтобы отслеживать угол поворота, у обычного переменного резистора диапазон поворота около 270 градусов, то есть мембрана будет поворачиваться только в этом диапазоне (не более 270 град.). Без датчика положения (обратной связи) нельзя будет узнать положение.

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

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

  4. Здраствуйте.
    Xотел спросить можна переделать немного програму штоб она не изменяла регистр shet, а изменяла логические уровни на двух выводах (имитацыя кнопок).
    Cпасибо.

    • Здравствуйте, поменять можно как угодно, вы не уточнили как именно, например в случае инкремента что должно происходить, если изменение уровня на выводе, то какой уровень выставлять, и что делать при следующем инкременте? Пишите конкретнее.

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

    • Кнопка может иметь 2 состояния, нажата и отжата, соответственно получаем два логических уровня низкий и высокий. Ладно если произошел инкремент, ставим низкий уровень на выводе, а что дальше, так и оставляем низкий уровень? То есть по вашему получаем имитацию нажатия кнопки, а имитация отжатия в каком случае должна происходить, при следующем инкременте?

  6. Да должна как обычная кнопка нажали отпустили еслы надо ещо нажали отпустили.

    • Вот поправил

  7. Огромное спасибо.
    Здравствуйте, а для чего в программе в 123 строке подпрограмма program?
    В Протеусе работает , хочу перенести на 12f675 чтоб вышло компактное устройство, которое можно подключить к уже готовому устройству на кнопках.

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

  8. Чет туго у меня с переводом на 675. Я думаю что проблема с конфигурацией битов.

    • Попробуйте этот код

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

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *