Decada
Автор: WildCat
2010-05-07

Работа с энкодерами

Энкодеры (от слов 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

End
Pin 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 главе про прерывания.

WildCat
2010-05-07

Желаете купить табак для кальяна?
CMS версия 3.0.0 by Demson