Добрый день.
Подскажите как можно подключить 4 энкодера, но так что бы не тратить 8 ног?
Например что то вреде подключения 4 кнопок к одной ноге АЦП (знаю только эту фишку), но у энкодера надо с двух ног значения считывать а АЦП может только к одному выводу в один момент времени подключаться, выходит этот фокус тут бесполезен.
А зачем четыре энкодера? Если для изменения четырёх параметров - то воспользуйтесь одним энкодером с дополнительной кнопкой, которая будет "листать" поочередно каждый из изменяемых четырёх (да хоть десяти) параметров. Понадобится всего три входа контроллера.
О, спасибо. Энкодера с кнопкой нету, но я ее отдельно привинчу. Правда не очень удобно - надо сперва по кнопке потыкать потом крутить, но ног и так уже не хватает.
Ну блин, энкодер сам по себе штука очень сложная в плане опроса, а ты еще и 4 штуки хочешь.
Если прямо очень-очень-очень хочется 4 энкодера и мало ножек, то можно воспользоватся любым PISO регистром с защелкой, который будет считывать состояния 8-ми ног, подключенных к энкодерам, затем пересылать полученный байт на SPI... В итоге тратится только 2 ноги, но делать это придется очень-очень быстро(т.е. высокая тактовая нужна), да и жопу порвать придется, чтобы это запрограммировать.
Лучше не морочить голову и банально поцепить 3 кнопки, одна переключает режимы, две других инкрементят или декрементят переменную. Для удобства можно добавить плавный разгон инкрементирования/декрементирования, выйдет не хуже энкодеров, а главное никакой мороки.
Eugene.Negrobov писал(а):Ну блин, энкодер сам по себе штука очень сложная в плане опроса
В каком месте она сложная? Проверка состояния одной ноги при перепаде на другой делается за одну команду, далее уже переход на обработку "+" или "-", дальше программа для энкодера не отличается от программы для 2х кнопок.
Если нужно действительно 4 ручки, можно задействовать 5 ног. На 4 ноги заводим первые каналы энкодеров, это должны быть ноги с внешними прерываниями (обычно PCINT), вторые каналы соединяем через резисторную цепочку и на АЦП, как это делают во всяких пультах дистанционного управления. Приходит прерывание PCINT - определяем какой энкодер крутили, читаем АЦП - определяем, в какую сторону.
Но я все таки сделал бы (и делаю) один энкодер с кнопкой, как сказали выше, такой штукой можно регулировать ВООБЩЕ все что угодно...
Чет я не догнал каким образом можно через Ацп вообще энкодер читать.там же две "кнопки" а через Ацп как известно хорошо получается читать одновременно только одну кнопку.
Даже если придумать какую извращенную резисторную матрицу голова кругом пойдет все предусмотреть.
Как вообще будет PCINT срабатывать?
Если только делать круговой опрос Ацп с четырех каналов и оценивать четыре напряжения которые могут быть с двумя кнопками.
да сам то он никуда не денется, только вот как это работать будет я себе представить не могу. получается, чтобы отследить изменение одного контакта используем прерывание, а как при этом определить в каком положении второй контакт находится? по пятой ножке? Ума не приложу как можно отследить вместе с прерыванием.
Да легко. Включить АПЦ в режиме постоянного преобразования и в его прерывании определать какая из "вторых ног" в каком состоянии, эту инфу писать в какой-нибудь регистр и в прерывании по перепаду ("первых ног энкодеров") проверять его. Да мудрено, но задача-то решаема... Ну это при условии, что энкодеры будут крутить с "человеческой" скоростью, а то АЦП перед прерыванием по перепаду будет давать неактуальную информацию.
Но я все таки сделал бы (и делаю) один энкодер с кнопкой, как сказали выше, такой штукой можно регулировать ВООБЩЕ все что угодно...
Да всё можно, любой интерфейс организуется просто одной кнопкой. Даже полноценный CLI - ввод команд по кнопке, вывод светодиодом. Команды морзянкой
Но кроме того, что можно, есть то, что удобнее. И 4 раздельных энкодера гораздо удобнее одного с кнопкой. Если позволяет корпус, детали, дизайн - я бы оставил 4 отдельных. Ну а сложности с опросом придётся решать, благо там не такие уж и сложности.
Мультиплексом можно потратить 6 это понятно. Не сильно большая экономия.
Вот доперло как можно пять ног
Вес у каждой кнопки будет разный, поэтому трудно ошибиться.
Один раз откалибровать и реф взять от того же источника, что и питание для кнопок, чтобы скачки напряжения не влияли на показания.
Можно еще поставить на опрос энкодеров отдельный простенький МК. И соединить через UART. Нужна всего одна нога и никакого головняка в основном МК. Хоть к компу подключай.
Добрый день.
Я хотел для одного устройства использовать схему энкодер - кнопка, но решил что это будет в моем случае не так удобно как два энкодера.
Подключил их (пока только на схеме) к четырем ногам ATTiny24, которые с PCINT и вроде все - доволен, можно код писать.
Но подождите, в даташите написано, что прерывания PCINT обрабатываются одним обработчиком, одним и тем же для любого прерывания с любого пина PCINT, нам что, в обработчике все ноги проверять, к которым энкодеры подключены?
В общем даташит меня смутил.
Кто знает, подскажите, пожалуйста, как лучше сделать?
PeterHirt писал(а):Но подождите, в даташите написано, что прерывания PCINT обрабатываются одним обработчиком, одним и тем же для любого прерывания с любого пина PCINT, нам что, в обработчике все ноги проверять, к которым энкодеры подключены?
Да именно так, или в одном векторе проверять все задействованные ноги или раскидать их между PCINT0, PCINT1 и INT0.
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
сохраняем состояние соответствующих пар битов, сравниваем с предыдущими состояниями и, при несовпадении, работаем через код грея.
Понятия не имею как это, если не затруднит - можете подсказать (как получить направление через код Грея )?
Added:
Посмотрел хедер Encoder.h из библитек тинзи, они решили проблему просто перебором чисел из таблички через switch-case =)
;Пример обработки нескольких энкодеров через прерывание 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
Неправильно собранная из неисправных деталей схема нуждается в отладке и сразу не работает... (С)
Очень сложно понять как использовать этот код в своем приложении без знания асма.
На C у меня обработчик прерывания PCINT выполняется 78 циклов. Это нормально? Или не очень?