Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Тема закрыта

помогите опросить энкодер

Пн мар 08, 2010 21:50:49

здравствуйте,вот у меня возникла небольшая проблемка с опросом энкодера,подскажите пожалуйста как это осуществить.
пишу на СИ для пик
За раннее благодарен за оказанную помощ
Последний раз редактировалось vovik15 Сб янв 22, 2011 09:57:42, всего редактировалось 3 раз(а).

Пн мар 08, 2010 22:02:14

Про энкодер.
Подцепить лучше его к входам с прерываниями на внешнее событие и ждать когда сработает оно. Там формируется 2 импульса, один относительно другого сдвинут на "пол периода".
Остальное - стандартный счетчик - их тут море описано уже

Пн мар 08, 2010 22:13:38

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

1. я сделал прерывание, 1000 раз в сек.
2. В прерывании опрашиваю состояние двух линий энкодера, т.е. 2 бита
3. Беру из буферных переменных, предыдущие состояние энкодера, т.е. 2 бита которые были в предыдущий момент прерывания.
4. Т.е. получается 4 бита, т.е. 16 значений, они служат адресом в таблице, соответствено попросту по полученному адресу беру код события, + или - или пусто, если например состояние энкодера не изменилось.

Всё, результат готов, по факту получился формальный анализ и последующий синтез алгоритма преобразователя состояния энкодера в код события + или - или пусто.

В случае автора можно доработать как нибудь, пусть сам решает я честно не понял как доложно увеличиваться и как тогда отличать - от +.

Пн мар 08, 2010 23:37:59

а в виде програмного крда это можно изобразить?

Вт мар 09, 2010 00:11:46

Smirnov писал(а):1. я сделал прерывание, 1000 раз в сек.

Как-то уж больно часто показалось. Не вызывает ли так часто возникающее прерывание тормоза в основной программе и глюки различных интерфейсов со строго ограниченными таймингами (тот же 1-wire)?

Вт мар 09, 2010 07:57:06

Он вынужден делать высокую частоту опроса потому что опрашивает и запоминает состояние входов. Если к примеру энкодер имеет 20 импульсов на 1 оборот и скорость вращения 1 сек. То длительность импульса не превышает 25 мс. А если прикошачить энкодер к внешним прерываниям можно просто ждать на каком из этих двух входах появится первый импульс и соответсвенно либо инкрементировать либо декрементировать некую переменную. Не тратя системное время на бесполезный опрос. Другая схемная реализация вынудит искать другие решения и возможно запись окажется оптимальным из них

Вт мар 09, 2010 08:55:33

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

А во вторых ясно что энкодер имеет всего 16 состояний с учётом предыдущих, я их попросту вывел на дисплейчик и посмотрел какие коды за что отвечают, ну и вбил. В итоге на отработку энкодера в прерывании тратилось не более 2 мкс.

Хотя насчёт прерываний согласен, тоже будет просто. Может быть даже проще моего случая. Дерзайте :))

По просьбе трудящихся пример, предположим состояние энкодера у тебя находится в PORT в младших 2х битах тогда:
выполнять с большой частотой, минимум 100 раз в секунду.

Код:
temp1=PORT&0x03; // Читаем энкодер, берём 2 бита
temp2=temp1;  //запоминаем новое состояние енкодера
temp1=temp1 | old_encoder; // формируем из старого и нового состояние 4 бита
old_encoder=temp2<<2;       // запоминаем старое состояние энкодра
temp1=enc_table[temp1];    // адресуемся по таблице, извлекаем из неё код события если есть
if (temp1!=0) event=temp1; //если извлекли не нулевой код события то записываем его в переменную нового события, сюда можно поставить добавление события в очередь событий.

Вт мар 09, 2010 09:24:28

Smirnov писал(а):Во первых задача была не сложная, это управление кучей лазеров, измерение их параметров, регулирование мощности по этим параметрам, применение цифровых фильтров и как результат адаптивной подстройки мощности по множеству параметров. А так же отработка менюшек на графическом дисплейчике 640х200.
а можно посмотреть на этот проект? он уже реализовал аппаратно? если да, то видео может?

Вт мар 09, 2010 09:59:11

ibiza11 писал(а):а можно посмотреть на этот проект? он уже реализовал аппаратно? если да, то видео может?


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

нашел только простейший вариант, самый первый который я делал, без энкодера, но управление а полная автоподстройка уже была:
http://www.srz-holding.ru/katalog/index02.php?id=6
http://medprom.ru/medprom/mpp_0004849

Вт мар 09, 2010 11:01:02

Meteor писал(а):Про энкодер.
.. Там формируется 2 импульса, один относительно другого сдвинут на "пол периода"...

Может, и такие есть, но если имеется в виду инкрементирующий энкодер контактного типа как в регуляторах музыкальных центров/микроволновок, то мне попадались только такие у которых "импульс" короче чем "полпериода", а в равновесном положении оба контакта разомкнуты. Такой энкодер опрашивается так же, как если бы было просто две кнопки (плюс и минус) по принципу - кто первый тот и прав, т.е. какая первая кнопка нажата, та и обрабатывается, затем запрещается обработка до тех пор, пока обе кнопки не будут отпущены. На асме я сделал так:
Код:
_mainloop:
   .
   .
   .

   in   r16,pinc   ;разрешать ли прерывания по пинам?
   andi   r16,0x03
   cpi   r16,0x03
   brne   _mainloop
   ldi   r16,0
   out   pcifr,r16   ;очистка флагов
   ldi   r16,2
   sts   pcicr,r16   ;разрешить прерывания от энкодера
   rjmp   _mainloop

_pci1_int:
   push   r16
   in   r16,sreg
   push   r16

   ldi   r16,0
   sts   pcicr,r16   ;запрет pci1_int до особого распоряжения

   in   r16,pinc
   andi   r16,0x03   ;маска для PC0,PC1
   cpi   r16,0x01
   breq   _minus
   cpi   r16,0x02
   breq   _plus
   rjmp   _eoi2
_plus:
   lds   r16,T
   cpi   r16,250   ;правый упор
   brsh   _eoi2
   inc   r16
   sts   T,r16
   rjmp   _eoi2
_minus:

   lds   r16,T
   cpi   r16,30   ;левый упор
   brlo   _eoi2
   dec   r16
   sts   T,r16
   rjmp   _eoi2

_eoi2:
   pop   r16
   out   sreg,r16
   pop   r16
   reti

Немного кривовато написано, но работает. Энкодер у меня подключен к PC0, PC1; дребезг давится аппаратно - кондеры по 10нФ на землю.

Вт мар 09, 2010 11:22:46

вот тут делал с энкодером, есть комментария и проект протеуса, поидее должно работать с любыми энкодерами http://radiokot.ru/forum/viewtopic.php?p=386004#386004 без использования прерываний и таймеров.

Вт мар 09, 2010 11:23:42

PS Если основной цикл "тяжелый", то проверку того, что энкодер в "нейтральном" положении лучше перенести из основного цикла в другое прерывание, - например, в таймерное.

Вт мар 09, 2010 13:33:23

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

Вт мар 09, 2010 16:52:31

Пример на прерывании:


Код:

interrupt [EXT_INT0] encoder(void)
{
if(PIN*.*){delay_ms(2); temp=1;}
else {delay_ms(2);temp=0;};
}


цепляешь на внешнее прерывание, другую ногу на любой другой пин (PIN*.*). В основном цикле программы смотришь на temp, он и определяет направление вращения.

Вт мар 09, 2010 17:03:27

спосибо,а как быть со счетчиком нажатий на кнопку?

Вт мар 09, 2010 17:50:44

ZUB а зачем делать пауза 2 мс ? впринципе можно и вприрывание необходимый код запихнуть.
а как быть со счетчиком нажатий на кнопку?
что конкретно нужно?

Вт мар 09, 2010 18:19:43

ooogo писал(а):ZUB а зачем делать пауза 2 мс ? впринципе можно и вприрывание необходимый код запихнуть.
а как быть со счетчиком нажатий на кнопку?
что конкретно нужно?


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

Если код запихнуть в прерывание то будет работать криво, лучше использовать "флаги".

Вт мар 09, 2010 18:33:01

Я тут думал все уже знают как правильно работать с энкодерами. Не надо никаких подавителей дребезга. Все решается несложной машиной состояний. Движение вправо: два последовательных перехода 00 -> 01 -> 11. Т.е. если он дребезднет 00-01-00-01-00-01-11-01 - все равно отработает только стабильный кусок (выделен). При этом можно использовать табличную технологию которую описал Smirnov. Конечно, разрешающая способность при этом падает в два раза, по сравнению с отсчетом по каждому переходу, но зато появляется надежность. При этом необязательно делать чтения показаний через равные интервалы времени. Главное делать достаточно часто чтобы не произошел пропуск события. Естественно, два подряд одинаковых состояния энкодера не учитываются.

Вт мар 09, 2010 18:44:31

2 uldemir

Хороший метод, надежный. Если не важна разрешающая способность и есть возможность разместить все это дело в основном цикле, то им стоит воспользоваться.

Вт мар 09, 2010 19:49:28

я сколько не мучался, пока кондюки по 0,1 мкФ не припоял к контактам энкодера, дребезг никак побороть не мог, но конечно при быстром вращении пропускает. Наверное самый хороший вариант - это валкодер из шаговика! :)
Тема закрыта