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

Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Ср сен 25, 2013 09:39:16
AaNnDdRrEeYy
Добрый день.
Подскажите как можно подключить 4 энкодера, но так что бы не тратить 8 ног?
Например что то вреде подключения 4 кнопок к одной ноге АЦП (знаю только эту фишку), но у энкодера надо с двух ног значения считывать а АЦП может только к одному выводу в один момент времени подключаться, выходит этот фокус тут бесполезен.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Ср сен 25, 2013 09:47:23
s_black
А зачем четыре энкодера? Если для изменения четырёх параметров - то воспользуйтесь одним энкодером с дополнительной кнопкой, которая будет "листать" поочередно каждый из изменяемых четырёх (да хоть десяти) параметров. Понадобится всего три входа контроллера.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Ср сен 25, 2013 09:52:05
AaNnDdRrEeYy
О, спасибо. Энкодера с кнопкой нету, но я ее отдельно привинчу. Правда не очень удобно - надо сперва по кнопке потыкать потом крутить, но ног и так уже не хватает.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Ср сен 25, 2013 17:51:47
Eugene.Negrobov
Ну блин, энкодер сам по себе штука очень сложная в плане опроса, а ты еще и 4 штуки хочешь.
Если прямо очень-очень-очень хочется 4 энкодера и мало ножек, то можно воспользоватся любым PISO регистром с защелкой, который будет считывать состояния 8-ми ног, подключенных к энкодерам, затем пересылать полученный байт на SPI... В итоге тратится только 2 ноги, но делать это придется очень-очень быстро(т.е. высокая тактовая нужна), да и жопу порвать придется, чтобы это запрограммировать.
Лучше не морочить голову и банально поцепить 3 кнопки, одна переключает режимы, две других инкрементят или декрементят переменную. Для удобства можно добавить плавный разгон инкрементирования/декрементирования, выйдет не хуже энкодеров, а главное никакой мороки.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Ср сен 25, 2013 18:22:23
Engineer_Keen
Eugene.Negrobov писал(а):Ну блин, энкодер сам по себе штука очень сложная в плане опроса
В каком месте она сложная? Проверка состояния одной ноги при перепаде на другой делается за одну команду, далее уже переход на обработку "+" или "-", дальше программа для энкодера не отличается от программы для 2х кнопок.

Если нужно действительно 4 ручки, можно задействовать 5 ног. На 4 ноги заводим первые каналы энкодеров, это должны быть ноги с внешними прерываниями (обычно PCINT), вторые каналы соединяем через резисторную цепочку и на АЦП, как это делают во всяких пультах дистанционного управления. Приходит прерывание PCINT - определяем какой энкодер крутили, читаем АЦП - определяем, в какую сторону.

Но я все таки сделал бы (и делаю) один энкодер с кнопкой, как сказали выше, такой штукой можно регулировать ВООБЩЕ все что угодно...

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт сен 26, 2013 15:26:30
vitalik_1984
Чет я не догнал каким образом можно через Ацп вообще энкодер читать.там же две "кнопки" а через Ацп как известно хорошо получается читать одновременно только одну кнопку.
Даже если придумать какую извращенную резисторную матрицу голова кругом пойдет все предусмотреть.
Как вообще будет PCINT срабатывать?
Если только делать круговой опрос Ацп с четырех каналов и оценивать четыре напряжения которые могут быть с двумя кнопками.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт сен 26, 2013 15:44:50
Engineer_Keen
vitalik_1984 писал(а):Даже если придумать какую извращенную резисторную матрицу голова кругом пойдет все предусмотреть.
Да именно так, я и не говорил что это будет легко))
vitalik_1984 писал(а): Как вообще будет PCINT срабатывать?
А куда он денется?

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт сен 26, 2013 17:54:04
vitalik_1984
да сам то он никуда не денется, только вот как это работать будет я себе представить не могу. получается, чтобы отследить изменение одного контакта используем прерывание, а как при этом определить в каком положении второй контакт находится? по пятой ножке? Ума не приложу как можно отследить вместе с прерыванием.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт сен 26, 2013 18:25:56
Engineer_Keen
Да легко. Включить АПЦ в режиме постоянного преобразования и в его прерывании определать какая из "вторых ног" в каком состоянии, эту инфу писать в какой-нибудь регистр и в прерывании по перепаду ("первых ног энкодеров") проверять его. Да мудрено, но задача-то решаема... Ну это при условии, что энкодеры будут крутить с "человеческой" скоростью, а то АЦП перед прерыванием по перепаду будет давать неактуальную информацию.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт сен 26, 2013 18:38:56
ploop
Но я все таки сделал бы (и делаю) один энкодер с кнопкой, как сказали выше, такой штукой можно регулировать ВООБЩЕ все что угодно...
Да всё можно, любой интерфейс организуется просто одной кнопкой. Даже полноценный CLI - ввод команд по кнопке, вывод светодиодом. Команды морзянкой :)

Но кроме того, что можно, есть то, что удобнее. И 4 раздельных энкодера гораздо удобнее одного с кнопкой. Если позволяет корпус, детали, дизайн - я бы оставил 4 отдельных. Ну а сложности с опросом придётся решать, благо там не такие уж и сложности.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт сен 26, 2013 19:14:37
vitalik_1984
Мультиплексом можно потратить 6 это понятно. Не сильно большая экономия.
Вот доперло как можно :) пять ног
Изображение
Вес у каждой кнопки будет разный, поэтому трудно ошибиться.
Один раз откалибровать и реф взять от того же источника, что и питание для кнопок, чтобы скачки напряжения не влияли на показания.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт сен 26, 2013 19:44:28
Engineer_Keen
Ну во, именно это я и имел ввиду!

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт сен 26, 2013 20:33:06
AVSel
Можно еще поставить на опрос энкодеров отдельный простенький МК. И соединить через UART. Нужна всего одна нога и никакого головняка в основном МК. Хоть к компу подключай.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт сен 26, 2013 20:38:39
vitalik_1984
Это некошерно контроллерами разбрасываться :))
Вот повесть прикольная

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт авг 28, 2014 19:10:49
PeterHirt
Добрый день. :))
Я хотел для одного устройства использовать схему энкодер - кнопка, но решил что это будет в моем случае не так удобно как два энкодера.
Подключил их (пока только на схеме) к четырем ногам ATTiny24, которые с PCINT и вроде все - доволен, можно код писать.
Но подождите, в даташите написано, что прерывания PCINT обрабатываются одним обработчиком, одним и тем же для любого прерывания с любого пина PCINT, нам что, в обработчике все ноги проверять, к которым энкодеры подключены?
В общем даташит меня смутил. :?
Кто знает, подскажите, пожалуйста, как лучше сделать?

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт авг 28, 2014 20:52:29
НАПАЛМ
offtopic:
Спойлер
vitalik_1984 писал(а): Вот повесть прикольная
Впечатлило.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт авг 28, 2014 21:53:13
Engineer_Keen
PeterHirt писал(а):Но подождите, в даташите написано, что прерывания PCINT обрабатываются одним обработчиком, одним и тем же для любого прерывания с любого пина PCINT, нам что, в обработчике все ноги проверять, к которым энкодеры подключены?
Да именно так, или в одном векторе проверять все задействованные ноги или раскидать их между PCINT0, PCINT1 и INT0.

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Чт авг 28, 2014 22:52:12
PeterHirt
НАПАЛМ писал(а):в одном векторе проверять все задействованные ноги
НУ в принципе оказалось не проблема в векторе отследить с какого энкодера пришло изменение.

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

    uint8_t E1_thisState= (PINA & 0x03);
    uint8_t E2_thisState= ((PINA & 0x0C) >> 2);
    if (E1_thisState != E1_prevState)
    {
        //........//
        E1_prevState= E1_thisState;
    } 
сохраняем состояние соответствующих пар битов, сравниваем с предыдущими состояниями и, при несовпадении, работаем через код грея.
Понятия не имею как это, если не затруднит - можете подсказать (как получить направление через код Грея )?

Added:
Посмотрел хедер Encoder.h из библитек тинзи, они решили проблему просто перебором чисел из таблички через switch-case =)

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Пт авг 29, 2014 09:01:52
Engineer_Keen
Если кому надо, пример для 2х энкодеров без экономии ног (задействованы 4 ноги, из них 2 обязательно на PCINT).
Ровно сотня байт кода:
Спойлер

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

;Пример обработки нескольких энкодеров через прерывание Pin Change
;!!!антидребезг не использован в целях упрощения кода, использовать в таком виде!!!
;!!!можно только в симуляторах или со схемотехническим подавлением дребезга	!!!
;это вариант средней грубости - прерывания только по 1 каналу энкодера, анализ обоих фронтов
;другие возможные варианты:
;самый грубый - анализ только одного фронта, одного канала (в 2 раза меньше тактов на оборот, простейший обработчик)
;самый точный - анализ фронтов обоих каналов (в 2 раза больше тактов, но сложнее обработчик)
;(C) Engineer_Keen

	.include	"tn2313def.inc"
	.include	"macroavr.asm"

	.def	STR=R1				;для сохранения SREG в прерываниях
	.def	OLD=R21

	.equ	ENC1_A=PB0			;канал А первого энкодера
	.equ	ENC1_B=PB1			;канал В первого энкодера
	.equ	ENC2_A=PB2			;тоже самое для второго
	.equ	ENC2_B=PB3
	.equ	LCW1=PB4			;индикаторы направления
	.equ	LCCW1=PB5			;вращения энкодеров
	.equ	LCW2=PB6
	.equ	LCCW2=PB7
;-----------------------------------------------------------------------------
	.cseg
	.org	0
	RJMP	RESET
	.org	PCIaddr
	RJMP	ENCODERS			;обработка вращения в прерывании по PinChange
	.org	INT_VECTORS_SIZE
RESET:	OUTI	SPL,Low(RAMEND)			;инициализация стека
	OUTI	PORTB,(1<<ENC1_A)|(1<<ENC1_B)|(1<<ENC2_A)|(1<<ENC2_B)	;настройка портов
	OUTI	DDRB,(1<<LCW1)|(1<<LCCW1)|(1<<LCW2)|(1<<LCCW2)		
	OUTI	PCMSK,(1<<ENC1_A)|(1<<ENC2_A)	;настройка прерываний
	OUTI	GIMSK,(1<<PCIE)			
	SEI					
LOOP:	RJMP	LOOP				;вечное безделье
;-----------------------------------------------------------------------------
ENCODERS:
	IN	STR,SREG			;обработка прерываний от энкодеров
	PUSH	R16
	PUSH	R17
	IN	R16,PINB			;читаем порт
	ANDI	R16,(1<<ENC1_A)|(1<<ENC2_A)	;накладываем маску
	MOV	R17,R16				;чтобы читать только по 1 каналу
	EOR	R16,OLD				;проверяем какой из энкодеров крутили
	MOV	OLD,R17				;сохраняем новое значение
;-----------------------------------------------------------------------------
	SBRS	R16,ENC1_A			;если крутили не первый
	RJMP	ENC2				;пропускаем его проверки
	SBIC	PINB,ENC1_A			;проверяем первый энкодер
	RJMP	RISEA1				
FALLA1:	SBIC	PINB,ENC1_B			;задний фронт, если второй канал=1
	RJMP	CCW1				;то переход на метку "против часовой стрелки"
	RJMP	CW1				;иначе "по часовой"
RISEA1:	SBIC	PINB,ENC1_B			;передний фронт, наоборот
	RJMP	CW1				;если второй канал=1, то "по часовой"
						;если 0, по "против часовой" (переход на следующую строку)
CCW1:	;тут действия при вращении против часовой
	SBI	PINB,LCCW1			;например мигаем диодом	
	RJMP	ENC2				
CW1:	;тут при вращении по часовой
	SBI	PINB,LCW1			;например мигаем другим диодом	
;-----------------------------------------------------------------------------
ENC2:	SBRS	R16,ENC2_A			;теперь аналогичным образом проверяем 
	RJMP	ENC3				;второй энкодер
	SBIC	PINB,ENC2_A
	RJMP	RISEA2
FALLA2:	SBIC	PINB,ENC2_B
	RJMP	CCW2
	RJMP	CW2
RISEA2:	SBIC	PINB,ENC2_B
	RJMP	CW2
CCW2:	
	SBI	PINB,LCCW2
	RJMP	ENC3
CW2:	
	SBI	PINB,LCW2
;-----------------------------------------------------------------------------
ENC3:						;следующие энкодеры, если надо
	POP	R17
	POP	R16
	OUT	SREG,STR
	RETI
Вариант с макросом:
Спойлер

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

;Пример обработки нескольких энкодеров через прерывание Pin Change
;!!!антидребезг не использован в целях упрощения кода, использовать в таком виде!!!
;!!!можно только в симуляторах или со схемотехническим подавлением дребезга	!!!
;это вариант средней грубости - прерывания только по 1 каналу энкодера, анализ обоих фронтов
;другие возможные варианты:
;самый грубый - анализ только одного фронта, одного канала (в 2 раза меньше тактов на оборот, простейший обработчик)
;самый точный - анализ фронтов обоих каналов (в 2 раза больше тактов, но сложнее обработчик)
;(C) Engineer_Keen

	.include	"tn2313def.inc"
	.include	"macroavr.asm"

	.def	STR=R1				;для сохранения SREG в прерываниях
	.def	OLD=R21

	.equ	ENC1_A=PB0			;канал А первого энкодера
	.equ	ENC1_B=PB1			;канал В первого энкодера
	.equ	ENC2_A=PB2			;тоже самое для второго
	.equ	ENC2_B=PB3
	.equ	LCW1=PB4			;индикаторы направления
	.equ	LCCW1=PB5			;вращения энкодеров
	.equ	LCW2=PB6
	.equ	LCCW2=PB7
;-----------------------------------------------------------------------------
;макрос проверки энкодера, использование:
;DefineDirection канал_А,канал_В, метка по часовой, метка против часовой, метка для следющего энкодера
	.macro	DefineDirection
	SBRS	R16,@0				;если крутили не его
	RJMP	@4				;пропускаем его проверки
	SBIC	PINB,@0				;проверяем этот энкодер
	RJMP	PC+4				
	SBIC	PINB,@1				;задний фронт, если второй канал=1
	RJMP	@3				;то переход на метку "против часовой стрелки"
	RJMP	@2				;иначе "по часовой"
	SBIC	PINB,@1				;передний фронт, наоборот
	RJMP	@2				;если второй канал=1, то "по часовой"
	.endm
;-----------------------------------------------------------------------------
	.cseg
	.org	0
	RJMP	RESET
	.org	PCIaddr
	RJMP	ENCODERS			;обработка вращения в прерывании по PinChange
	.org	INT_VECTORS_SIZE
RESET:	OUTI	SPL,Low(RAMEND)			;инициализация стека
	OUTI	PORTB,(1<<ENC1_A)|(1<<ENC1_B)|(1<<ENC2_A)|(1<<ENC2_B)	;настройка портов
	OUTI	DDRB,(1<<LCW1)|(1<<LCCW1)|(1<<LCW2)|(1<<LCCW2)		
	OUTI	PCMSK,(1<<ENC1_A)|(1<<ENC2_A)	;настройка прерываний
	OUTI	GIMSK,(1<<PCIE)			
	SEI					
LOOP:	RJMP	LOOP				;вечное безделье
;-----------------------------------------------------------------------------
ENCODERS:
	IN	STR,SREG			;обработка прерываний от энкодеров
	PUSH	R16
	PUSH	R17
	IN	R16,PINB			;читаем порт
	ANDI	R16,(1<<ENC1_A)|(1<<ENC2_A)	;накладываем маску
	MOV	R17,R16				;чтобы читать только по 1 каналу
	EOR	R16,OLD				;проверяем какой из энкодеров крутили
	MOV	OLD,R17				;сохраняем новое значение
;-----------------------------------------------------------------------------
ENC1:	DefineDirection ENC1_A,ENC1_B,CW1,CCW1,ENC2 ;проверка первого энкодера
CCW1:	;тут действия при вращении против часовой
	SBI	PINB,LCCW1			;например мигаем диодом	
	RJMP	ENC2				
CW1:	;тут при вращении по часовой
	SBI	PINB,LCW1			;например мигаем другим диодом	
;-----------------------------------------------------------------------------
ENC2:	DefineDirection ENC2_A,ENC2_B,CW2,CCW2,ENC3 ;второго
CCW2:	
	SBI	PINB,LCCW2
	RJMP	ENC3
CW2:	
	SBI	PINB,LCW2
;-----------------------------------------------------------------------------
ENC3:						;следующие энкодеры, если надо
	POP	R17
	POP	R16
	OUT	SREG,STR
	RETI

Re: Как подключить 4 энкодера но не тратить 8 ног?

Добавлено: Вс авг 31, 2014 22:38:30
PeterHirt
Engineer_Keen писал(а):Ровно сотня байт кода:
Очень сложно понять как использовать этот код в своем приложении без знания асма.
На C у меня обработчик прерывания PCINT выполняется 78 циклов. Это нормально? Или не очень?