Автор: WildCat
Работа с энкодерами
Энкодеры (от слов angle decoder - преобразователь угол-код) - особый тип вращаемых переключателей. Такие, например, стоят в колесиках на мышках, цифровых регуляторах громкости на усилителях и в куче других устройств с регулируемыми параметрами. Это очень удобный тип переключателей, в которых шаг изменения параметра не зависит от диапазона, как в случае с переменными резисторами и АЦП. К тому же энкодеры вращаются "бесконечно".
У большинства энкодеров есть два выхода - A и B, которые переключаются при повороте ручки:
Энкодеры бывают двух типов - контактные (механические) и оптические. В механическом энкодере стоят обычные контактные пластины, которые размыкаются и замыкаются при повороте. У них есть проблема дребезга, которую мы уже рассматривали, когда изучали клавиатуры. Еще у них есть характерная особенность - ощутимый щелчок при каждом повороте на один шаг.
В оптических энкодерах установлен диск с прорезями и оптопара. Фототранзисторы расположены таким образом, что при вращении диска на их выходе получаются сигналы такого же вида, что и у механического энкодера. Распотрошите старую и новую компьютерные мышки с колесиками, и вы поймете, как оно работает. Подробнее про типы энкодеров можно почитать на википедии.
У механических энкодеров три вывода - земля и выводы A, B, замыкаемые на землю. Так что для работы с ними их можно напрямую подключать к выводам микроконтроллера. Я бы порекомендовал использовать дополнительно подтягивающие резисторы 10 кОм.
В оптических энкодерах подтягивающие резисторы, как правило, уже встроены. (сверьтесь с даташитом!) В них также стоят выходные транзисторы, так что вам не нужно беспокоиться о дребезге. Некоторые энкодеры имеют выход Index, на котором импульсы возникают независимо от направления вращения.
Оба типа энкодеров иногда имеют дополнительный переключатель, который срабатывает при нажатии на вал. Это приятное дополнение можно использовать в качестве клавиши Enter при навигации по меню.
Давайте посмотрим, как подключить энкодер к микроконтроллеру:
Накатаем простую программку, которая бесконечно проверяет состояние контактов:
test-encoder.bas
$regfile = "2313def.dat" $crystal = 4000000 Config Pind.6 = Output Config Pind.2 = Input Config Pind.3 = Input Const Debouncetime = 25 Dim Wtime As Byte Dim Encounter As Integer Cls Wtime = 100 Encounter = 0 Set Portd.2 Set Portd.3 Do Cls Lcd Pind.2 ; " " ; Pind.3 Waitms Wtime Loop EndНу тут понятно, что в цикле Do Loop происходит отображение состояния лапок Pind.2 и Pind.3 на ЖКИ.
Использование контактного энкодера
Я использовал энкодер ECW1J-B24-AC0024 фирмы Bourns. И у этого энкодера есть дребезг:

Не очень то и страшный. Даташит заявляет о максимальном дребезге в 5 мс при вращении вала со скоростью 15 об/мин.
В следующей программе использовано время антидребезга 1 мс: encoder-bourns-ecw1j.bas
$regfile = "2313def.dat" $crystal = 4000000 Cha Alias Pind.2 Chb Alias Pind.3 Config Cha = Input Config Chb = Input Config Pind.6 = Output Config Int0 = Falling Const Debouncetime = 1 Dim Wtime As Byte Dim Encounter As Integer Set Chb On Int0 Getencoder Cls Wtime = 100 Encounter = 0 Enable Interrupts Enable Int0 Do Set Portd.6 Waitms Wtime Upperline Lcd "encounter: " ; Encounter ; " " Reset Portd.6 Waitms Wtime Loop Getencoder: Waitms Debouncetime If Cha = 0 Then If Chb = 0 Then Incr Encounter Else Decr Encounter End If Gifr = 64 Return EndPin Portd.2 назван Cha, Portd.3 назван Chb. Оба настроены на вход.
Int0 настроено на спад сигнала на Cha.
В цикле Do Loop моргаем светодиодом и выводим значение счетчика на ЖКИ.
В подпрограмме обработки прерывания Getencoder выжидаем время антидребезна и проверяем Cha (там должен быть низкий уровень). Если на Chb низкий уровень, увеличим значение счетчика, иначе уменьшим.
Формально, проверка Cha = 0 в подпрограмме прерывания не очень то и нужна, ведь мы попали в подпрограмму именно из-за того, что сигнал на Cha сменил уровень с высокого на низкий! Однако она все равно не будет лишней из-за нестабильных состояний в момент переключения между положениями A/B.
Использование оптического энкодера
В качестве подопытного был выбран HEDS-550 фирмы Agilent. Даташита на сайте уже нет.
У оптических энкодеров нету дребезга:

(обратите внимание на время одного деления! 100 нс!)
Теперь пишем программу:
encoder-hp-heds-5700.bas
$regfile = "2313def.dat" $crystal = 4000000 Cha Alias Pind.2 Chb Alias Pind.3 Config Chb = Input Config Pind.6 = Output Config Int0 = Falling Dim Wtime As Byte Dim Encounter As Integer Set Chb On Int0 Getencoder Cls Wtime = 100 Encounter = 0 Enable Interrupts Enable Int0 Do Set Portd.6 Waitms Wtime Upperline Lcd "encounter: " ; Encounter ; " " Reset Portd.6 Waitms Wtime Loop Getencoder: If Chb = 0 Then Incr Encounter Else Decr Encounter Gifr = 64 Return EndПод впечатлением осциллограммы переключения, в подпрограмме обработки прерывания все проверки дребезга выкинуты нафиг за ненадобностью.
"Особый" энкодер
Был обнаружен экземпляр энкодера фирмы ALPS с немного другим поведением контактов. У него был не стандартный выход на A/B, выводы работали независимо. При повороте против часовой стрелки на выводе A возникают импульсы низкого уровня (вывод B все время разомкнут). При повороте по часовой стрелке - наоборот, импульсы возникают на выводе B, вывод A все время разомкнут.
Такой вид энкодера гораздо проще в управлении, в этом случае можно обе лапки просто повесить на прерывания:
encoder-alps-special.bas
$regfile = "2313def.dat" $crystal = 4000000 Config Pind.6 = Output Config Int0 = Falling Config Int1 = Falling Dim Wtime As Byte Dim Encounter As Integer Const Debouncetime = 5 On Int0 Encodera On Int1 Encoderb Cls Wtime = 100 Encounter = 0 Enable Interrupts Enable Int0 Enable Int1 Do Set Portd.6 Waitms Wtime Upperline Lcd "encounter: " ; Encounter ; " " Reset Portd.6 Waitms Wtime Loop Encodera: Waitms Debouncetime Incr Encounter Gifr = 64 Return Encoderb: Waitms Debouncetime Decr Encounter Gifr = 128 Return EndИспользуются оба прерывания, Int0 и Int1.
Время антидребезга установлено в 5 мс.
В подпрограмме прерывания всего лишь происходит инкремент или декремент счетчика, никаких других проверок состояния выводов.
Обратите внимание на Gifr = 64/128. Почитайте об этом подробнее в 10 главе про прерывания.