Энкодер ky-040 приручаем сноровистую лошадку.

  • Цена: 37 руб

Мне очень нравятся энкодеры. Гениальная штука для управления. Везде хорош, хоть в крошечном самодельном устройстве, хоть в BMW. В большинстве случаев ничего больше для управления не нужно. И при этом мы имеем дело не с холодными цифровыми кнопками, а с теплой ламповой крутилкой. Хочу рассказать о том, как я дрессировал одного из представителей славного семейства энкодеров. У ky-040 есть несомненное преимущество- он очень дешевый и мелкий недостаток- он очень капризный. Работает кое-как, лажает и глючит. Попробуем приручить и обуздать его скверный характер.

Кто-то подумает, что это схема зачатия робота. Но на самом деле это приблизительная схема работы энкодера.
Представим, что голубой диск электро проводящий, белые окна — изолятор, а синий, красный и зеленый кружки — контакты.
Когда крутишь ручку энкодера, явно ощущаются щелчки. Энкодер фиксируется в определенных положениях. На нашей схеме этот механизм обозначен выемками и, типа, шариком на пружинке, который в этих выемках фиксируется. А вы что подумали?
Диск привязан к ручке и крутится вместе с ней. Что же происходит в момент вращения? Если диск крутится по часовой стрелке, то сперва красный контакт подключенный к выводу А замыкается на диск и, соответственно, на зеленый контакт С, потом синий контакт В также замыкается на диск. Диск фиксируется в следующем положении, когда оба контакта, красный и синий оказываются замкнуты на диск. В следующий шаг сперва красный контакт разомкнется с диском, вслед за ним синий. И так в цикле будет продолжаться до тех пор, пока вы крутите ручку энкодера по часовой стрелке, если вы крутите ручку против часовой стрелки, все происходит точно также, но с точностью до наоборот. В данном случае контакты замыкаются и размыкаются в обратной последовательности.
Что нам надо? Понять в какую сторону крутиться ручка и подсчитать количество шагов. Подключаем наш энкодер к контролеру.
Контакт С подключаем к массе, или минусовому проводу. Контакт А будет у нас ведущим, подключаем его к GPIO которое можно настроить на прерывание по изменению уровня сигнала. Контакт В к любому GPIO на котором можно проверить цифровой уровень сигнала.

Я буду иллюстрировать работу с энкодером на примере конторлера esp8266, на основе прошивки NODEMCU LUA. Но это в принципе не имеет особого значения, если понять суть, то не так важно каким языком и каким контролером вы пользуетесь. А суть в том, что наша функция обработки будет вызвана в тот момент когда изменится потенциал на контакте А, и в этот момент, мы измерим потенциал на контакте В. Если диск крутится по часовой стрелке. То в тот момент когда контакт А замкнется на диск, контакт В не будет замкнут, или на следующем шаге, когда контакт А разомкнется с диском, контакт В еше будет замкнут на диск. То-есть потенциал на контактах А и В будет разным. Еслиже диск крутиться против часовой стрелки. То сперва на диск будет замкнут контакт В и когда замкнется контакт А и мы будем обрабатывать и проверять, оба контакта уже будут замкнуты на диск. На следующем шаге, в тот момент когда придет прерывание на контакт А, контакт В уже будет разомкнут. Значит оба контакта будут в одинаковом состоянии.
Это значит в момент прерывания на контакте А, проверяем потенциал контакта В и если они не совпадают, значит ручка крутится по часовой стрелке, иначе против часовой.
gpio.mode(4,gpio.INT,gpio.PULLUP) -- Устанавливает 4 вывод в режим прерывания. Если на этом выводе изменится потенциал прерывании вызовет нашу функцию и мы обработаем ситуацию.
gpio.trig(4, "both",function(level) -- Собственно сама функция которая будет вызвана
if gpio.read(3)==level -- level - состояние контакта А. Проверяем равно ли оно контакту В?
then print('left') -- если потенциалы равны, значит крутиться против часовой 
else print('rigth') -- иначе крутится по часовой
end
end) 


Но так происходит в идеальном мире. В реальности с энкодером ky-040 это работать не будет. Точнее будет глючить дергаться и дрыгаться в разные стороны. Первая проблема дребезг контактов. Это такая неприятность, когда вместо одного четкого сигнала, на контакты приходит серия беспорядочных всплесков. Она решается использованием таймера.

TM=tmr.now() -- запоминаем текущее время
gpio.mode(4,gpio.INT,gpio.PULLUP)
gpio.trig(4, "both",function(level)
if tmr.now()-TM<50000 then return end -- если прошло меньше чем 50000 микросекунд ничего не обрабатываем
TM=tmr.now() -- запоминаем новую метку времени 
if gpio.read(3)==level
then print('left') 
else print('rigth') 
end
end) 


Если функция будет вызвана повторно через слишком маленький промежуток времени, ничего не случится, функция не отработает. Это самая легкая проблема. Есть более серьезная. Данный энкодер периодически выдает ошибки. Например, когда ручка крутиться против часовой стрелки, при срабатывании прерывания на контакте А ожидается точно такой же потенциал на контакте В. Но этого не происходит. Происходит ошибочное срабатывание алгоритма программы. К счастью такие ошибки обычно выглядят как одиночная аномалия, и можно попытаться их предупредить.

Я сделал это примерно так
VL=1 Эта переменная будет хранить направление движения на предыдущем шаге.

TM=tmr.now() 
gpio.mode(4,gpio.INT,gpio.PULLUP)
gpio.trig(4, "both",function(level)
if tmr.now()-TM<50000 then return end 
TM=tmr.now()
if VL==1 then -- Если предыдущий шаг был вращением против часовой 
if gpio.read(3)==level -- Если Сигнал на контакте В соответствует движению против часовой 
then print('left') -- Тогда фиксируем поворот против часовой 
else VL=0 return -- Иначе устанавливаем поворот по часовой, но при этом пока ничего не фиксируем, это может быть ошибка 
end
else -- Иначе, если предыдущий шаг был вращением по часовой происходит аналогичная обработка поворота по часовой стрелки.
if gpio.read(3)~=level 
then print('Right') 
else VL=1 return 
end
end
end) 


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

Я использовал энкодер пока для управлением ШИМ регулировкой яркости TFT дисплея.
Планирую купить +47 Добавить в избранное +39 +64
+
avatar
  • civil
  • 15 мая 2016, 16:40
+3
Можно воспользоваться встроенной в ModeMCU функцией rotary.
+
avatar
+2
(N)odeMCU?
+
avatar
  • civil
  • 15 мая 2016, 21:08
0
Без всякого сомнения. Жаль, не могу уже исправить.
+
avatar
+2
Читал, читал, нифига не понял.
Обзор вообще о чем? Вроде умно написано, но ничего не понятно.
+
avatar
  • delong
  • 15 мая 2016, 20:17
0
Из серии «Как ничего не понять и не подать виду». Вместо обычного переменника эта хрень с контроллером и кучей глюков… Не вижу логики.
+
avatar
0
Ну эта колбаса, в отличие от переменника, не имеет ограничителей поворота. Потому и непонятно, нафига ей яркость регулировать?
+
avatar
  • barkon
  • 15 мая 2016, 21:27
+4
Этот обзор имел целью рассказать как можно использовать энкодер в своих устройствах. Я описал как это работает. Конечно лучше использовать его для выбора в меню. Но мне пока это не нужно.
+
avatar
  • sergk
  • 15 мая 2016, 23:51
+2
Ну в таком случае было бы неплохо указать на каком языке и в какой среде писалась программа…
В общем чуть больше данных для возможного повторения.
Если же просто теория применения, тогда было бы неплохо вообще уйти от кода и нарисовать алгоритм работы, разъясняющий суть вашего метода обхода проблем энкодера
+
avatar
  • sls
  • 15 мая 2016, 21:21
+2
обычные переменники иногда начинают шуршать, скрипеть и всяко разно плохо себя вести
энкодеры местами лучше себя ведут
+
avatar
0
между прочим, в старых «мышках» тоже есть энкодеры на колесиках прокрутки. Куда бы его использовать?
+
avatar
  • VGA
  • 15 мая 2016, 21:35
+2
У меня на газовой плите встроенный цифровой таймер с «теплой ламповой крутилкой». Очень удачное решение вместо кнопок.
Если скорость вращения высокая, то цифры меняются очень быстро, при торможении резко замедляются. Очень удобно выставить любое время меньше чем за оборот, интуитивно простой интерфейс. Кнопкой обязательно проскочишь нужное, а крутилкой, даже если чуть перекрутишь, легко вернуть, не надо искать кнопку назад.
+
avatar
0
а энкодер в виде фейдера — скользящего потенциометра бывает?
+
avatar
  • Motto
  • 16 мая 2016, 07:32
0
Я вот отсюда инфу брал, когда ваял скетч под Ардуино.
forum.hobbycomponents.com/viewtopic.php?f=73&t=1669
+
avatar
0
Никаких прерываний! Опрос портов 1-2 тысяч раз в секунду и все. Программа пару десятков команд на асме. Работает идеально уже очень давно.
+
avatar
  • barkon
  • 16 мая 2016, 09:51
0
Почему так? Я предпочитаю, для контролеров программирование по событиям.
+
avatar
0
Для результата.
Если такой энкодер подключить к прерыванию по изменению уровня, то будет куча помех плюс дребезг, надо фильтры ставить на ножки плюс код усложнится на порядок для учета дребезга.
Это не настолько быстрое устройство, чтобы вешать его на прерывание. Ну или если у вас в программе есть какие-то мощные расчеты по 10 тысяч тактов.
+
avatar
0
Вот мой кусок кода для обработки такого точно энкодера:
//опрос энкодера R18 (+ — 0), PC3,PC4 — энкодер, вариант 2
CLR R18
IN R16,PINC ANDI R16,0b00011000
LDS R17,Enc_old STS Enc_old,R16
CP R16,R17 BREQ M_e99
LDS R20,enc_count
LSL R16 SWAP R16
LSL R20 LSL R20
OR R20,R16
STS enc_count,R20
CPI R20,0b01001011
BREQ M_e1
CPI R20,0b10000111
BREQ M_e2
BRNE M_e99

M_e1: INC R18 //+
RJMP M_e4
M_e2: DEC R18 //-

M_e4: //был поворот
//…
M_e99:
+
avatar
0
Это на асме?
+
avatar
  • DVANru
  • 11 июня 2016, 13:44
0
приручаем сноровистую лошадку
… возможно, норовистую?
+
avatar
0
Отличная идея — с несколькими значениями для устранения ошибок! Можно и 3 значения помнить — для надежности. А с прерываниями или без — ну, тут уж как кому нужно — мне например их жалко — на атмеге 328 их всего 2… А вот на меге — да легко… Еще можно дребезг давить конденсаторами небольшими керамикой — хорошо работает.