Страница 1 из 3

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

Добавлено: Пн мар 08, 2010 21:50:49
vovik15
здравствуйте,вот у меня возникла небольшая проблемка с опросом энкодера,подскажите пожалуйста как это осуществить.
пишу на СИ для пик
За раннее благодарен за оказанную помощ

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

Добавлено: Пн мар 08, 2010 22:13:38
Smirnov
а я делал энкодер проще, т.к. мне нужно было сделать энкодер который вращать будет человек, т.е. не быстро:

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

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

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

Добавлено: Пн мар 08, 2010 23:37:59
vovik15
а в виде програмного крда это можно изобразить?

Добавлено: Вт мар 09, 2010 00:11:46
AI_Disable
Smirnov писал(а):1. я сделал прерывание, 1000 раз в сек.
Как-то уж больно часто показалось. Не вызывает ли так часто возникающее прерывание тормоза в основной программе и глюки различных интерфейсов со строго ограниченными таймингами (тот же 1-wire)?

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

Добавлено: Вт мар 09, 2010 08:55:33
Smirnov
сделал по таймеру потому что так было проще. Во первых задача была не сложная, это управление кучей лазеров, измерение их параметров, регулирование мощности по этим параметрам, применение цифровых фильтров и как результат адаптивной подстройки мощности по множеству параметров. А так же отработка менюшек на графическом дисплейчике 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
ibiza11
Smirnov писал(а):Во первых задача была не сложная, это управление кучей лазеров, измерение их параметров, регулирование мощности по этим параметрам, применение цифровых фильтров и как результат адаптивной подстройки мощности по множеству параметров. А так же отработка менюшек на графическом дисплейчике 640х200.
а можно посмотреть на этот проект? он уже реализовал аппаратно? если да, то видео может?

Добавлено: Вт мар 09, 2010 09:59:11
Smirnov
ibiza11 писал(а):а можно посмотреть на этот проект? он уже реализовал аппаратно? если да, то видео может?
Видео нет, ибо часть приборов шло воякам с соответствующими предостарожностями, это было 5 лет назад и я кое как выпросил видео для защиты диплома, до сегодняшнего дня оно не дожило и противоречит правилам форума ибо видео операции зрелище такое что даже если человек заверяет что ему безразлично то всё равно в лучшем случае отворачивается.

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

Добавлено: Вт мар 09, 2010 11:01:02
stas00n
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
ooogo
вот тут делал с энкодером, есть комментария и проект протеуса, поидее должно работать с любыми энкодерами http://radiokot.ru/forum/viewtopic.php?p=386004#386004 без использования прерываний и таймеров.

Добавлено: Вт мар 09, 2010 11:23:42
stas00n
PS Если основной цикл "тяжелый", то проверку того, что энкодер в "нейтральном" положении лучше перенести из основного цикла в другое прерывание, - например, в таймерное.

Добавлено: Вт мар 09, 2010 13:33:23
ooogo
лучше всего повесить одну пару контактов энкодера на внешнее прервывание, но у меня все будет занято, поэтому намутил такой код.

Добавлено: Вт мар 09, 2010 16:52:31
ZUB
Пример на прерывании:

Код: Выделить всё


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
vovik15
спосибо,а как быть со счетчиком нажатий на кнопку?

Добавлено: Вт мар 09, 2010 17:50:44
ooogo
ZUB а зачем делать пауза 2 мс ? впринципе можно и вприрывание необходимый код запихнуть.
а как быть со счетчиком нажатий на кнопку?
что конкретно нужно?

Добавлено: Вт мар 09, 2010 18:19:43
ZUB
ooogo писал(а):ZUB а зачем делать пауза 2 мс ? впринципе можно и вприрывание необходимый код запихнуть.
а как быть со счетчиком нажатий на кнопку?
что конкретно нужно?
задержка для защиты от дребезга (может у меня такой энкодер разболтаный, что сильный дребезг, но без задержки часто были ложные срабатывания).

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

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

Добавлено: Вт мар 09, 2010 18:44:31
ZUB
2 uldemir

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

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