Вы не вошли.
Вообще, для парафазного эгкодера самым простым способом является определение уровня на одном из выходов в время (допустим) ТОЛЬКО СПАДА на втором выходе (или ТОЛЬКО ФРОНТА). Но, когда я сделат тупо именно так, то жить мешало дрожание фронтов импльсов. Уже потом, когда написал по шпоргалке ЛИВ-а, и переделывать что-то было лень, подумалось - нужно было просто использовать задержку, рекомендованную в даташите на подавление дребезга (мерять только после нее)... Но, еще один нюанс, для такой обработки нужен один вход с прерыванием...
Почему когда мы нарушаем, нас штрафуют, а когда всё делаем правильно, с нас берут налоги?....
Вне форума
Вообще энкодер похож на парафазный. Смотрел осцилом на каждой из ног за один щелчек проскакивает 1 отрицательный ипульс. Вообще надо подумать о прерывании да смотеть просто, какой сигнал изменился первее. Ипользовать прерывание по спаду линии А, как только упала в ноль, смотреть что сейчас на В. подождать немного, и как только А снова стала в 1 выходить из обработчика. При вращении вправо сперва упадет в ноль А, затем В, при вращении влево - наоборот. Вообще довольно удобно что он защелкивается в состоянии 11. Всегда есть точка отсчета.
......There is someone in my head, but it's not me.......
Вне форума
насколько я понимаю вопрос, то самое "предыдущее" состояние у меня должно уже быть на момент начала выполнения этого алгоритма. Так?
Да. Перед тем, как попасть в основной цикл, программа производит инициализацию своих переменных. Это надо сделать и для глобальной переменной, хранящей предыдущее состояние энкодера. Нужно просто выполнить одно сканирование энкодера и записать результат в эту переменную. А затем уже в цикле выполнять указанный алгоритм.
У меня есть энкодер, производителя не знаю, написано XLEE EC12P24L15F. по поиску ничего не нашел.
Возможно, это клон энкодера PEC12: www.bourns.com/pdfs/pec12.pdf
У него 24 щелчка, причем во всех "устойчивых" состояниях вала линии А и В всегда в 1 (не замкнуты на 3-й вывод). Т.е. если его не крутить, то с него всегда считаются единицы по по обоим линиям.
Всё правильно. У PEC-16 то же самое.
Получается, что если "предыдущим" у нас считется состояние когда вал не крутили (т. е. А и В = 1 ) в пункте 7 никогда А не будет равно 0, следовательно и инкремента величины не получиться (если это первый после покоя щелчёк).
Предыдущее состояние нужно обновлять в каждом цикле выполнения алгоритма, если обнаруживается новое состояние энкодера (после подавления дребезга, т.е. после пункта 6). Я обновляю глобальную переменную предыдущего состояния между пунктами 6 и 7, а в алгоритм декодера (пункты 7 - 15) в локальных переменных передаю старое предыдущее состояние и текущее состояние энкодера. При вращении энкодера от щелчка до щелчка он проходит все состояния, и предыдущее состояние несколько раз успевает обновиться. Так что на первый щелчок реакция тоже будет.
Вне форума
А мне вчера пришло в голову следующее:
Подпрограмма проверяет состояние сигнала А. Если А=1, ничего не происходит. Если А стало равно 0, дается задержка на подавление дребезга, затем проверяется в каком состоянии находиться сигнал В. При повороте вправо в момент спада А В=1, влево - наоборот. Затем ожидается изменения сигнала В (если вертели вправо ожидаем ожидаем В=1, влево В=0). Затем даем задержку (вдруг дребезг В) и ждем когда А станет равно 1. Все. (все последние действия делаются для проверки коректности кода)
Собсно алгоритм:
>1. Проверяем А
Если А=1 - выход
Если А=0 - Задержка 300 мкс
>2 Снова проверяем А
Если А=1 - выход
Если А=0 - проверяем В
>3. Если В=1 - инкремент величины
Переход на 6
>4 Если В=0 - декремент величины
>5. Снова проверяем В
Если В=0 - возврат на 5 (цикл)
Если В=1 - то переход на 8 (ожидание А=1)
>6. Проверяем В
Если В=1 - возврат на 6 (цикл)
Если В=0 - то
>7. Проверяем А
Если А=0 - возврат на 7 (цикл)
Если А=1 - выход
Конечно получается что проц как бы подвисает на время щелчка и ничего больше не может делать, но для юзера это не должно быть заметно
>8. Выход.
Отредактировано Матроскин (18.05.2007 13:58:14)
......There is someone in my head, but it's not me.......
Вне форума
Работает на ура та Лив-овская программа.
Но если так охота, то немного подправьте Ваш алгоритм. Я думаю так:
(до того как - один из входов висит на прерывании и прерывание настроено на (допустим) только по спаду )насколько помню то, что смотрел про АВР, они такое позволяют, равно как и ПИК-и).
1. Сработало прерывание (внешнее).
2. Запрещаем прерывание (внешнее).
3. Запускаем таймер, на выдержку равную подавлению дребезга и разрешаем его прерывание.
4. Сработало прерывание таймера.
5. Проверяем второй вход и видим направление (1- в плюс, 0 - в минус, или наоборот)
6. Останавливаем таймер и запрещаем его прерывание.
7. Ставим флаг "случился энкодер" (ну и "флаг направления" тоже).
8. Разрешаем внешнее прерывание.
...в принципе, можно перед п.8 тоже запустить задержку (типа, защитную)...
Ну и не "...висим в тупом простое ожидания"...
Почему когда мы нарушаем, нас штрафуют, а когда всё делаем правильно, с нас берут налоги?....
Вне форума
Да у мнея что-то с той прогой не получилось вот и начал гадать. Эта тоже. В эмуляторе все красиво, на железе - труп
Я хотел для пробы заставить мк под управлением энкодера зажигать линеку из 8 светодиодов.
Как все таки вписать тот алгоритм в программу??
Вот может так:
сегмент данных, переменные
EncMode_Loc ;Локальная переменная для запоминания состояния энкодера в теле подпрограммы
EncMode_Glob ;Глобальная переменная для запоминания состояния энкодера в теле основной программы
Enc_Rezult ;управляемуя энкодером переменная
Start: Здесь опрашиваем энкодер и запоминаем в EncMode_Glob (скорее всего будет 11, ну да ладно )
Обнуляем Enc_Rezult
Scan: rcall EncScan (Вызываем подпрограмму обрабоки энкодера)
вернулись из подпрограммы
Берем Enc_Rezult и сравниваем с нулем
Равно - выводим в порт 0b00000000
Не равно - сравниваем с 1
равно - выводим в порт 0b00000001
не равно - сравниваем с 2
равно - выводим в порт 0b00000011
и тд. до "равно 8"
rjmp Scan (цикл)
EncScan:
>1. Сканируем энкодер (сигналы А и Б).
>2. Сравниваем состояние с EncMode_Glob, если не
>изменилось - выход.
>3. Изменилось. Запоминаем промежуточное состояние в EncMode_Loc.
>4. Задержка 200 мкс.
>5. Сканирование.
>6. Сравниваем состояние с EncMode_Loc, если не
>совпадает - выход
>7. Дальше идет 1х-декодер: Если в EncMode_Glob
>А=0, то переход на 10.
>8. Если в EncMode_Loc А=0, то переход на 14.
>9. Выход.
>10. Если в EncMode_Loc А=1, то переход на 12
>11. Выход.
>12. Если в EncMode_Loc Б=0, то сравниваем
Enc_Rezult с 8 (т.е выясняем, надо ли еще инкрементировать или уже максимум)
Если Enc_Rezult < 8 то инкрементируем его, переписываем EncMode_Loc в EncMode_Glob и выход.
Если Enc_Rezult = 8 то просто переписываем EncMode_Loc в EncMode_Glob и выход.
>13. Выход.
>14. Если в EncMode_Loc Б=0, то сравниваем Enc_Rezult с 0
Если Enc_Rezult > 0 то декрементируем его, переписываем EncMode_Loc в EncMode_Glob и выход
Если Enc_Rezult = 0 то просто переписываем EncMode_Loc в EncMode_Glob и выход
>15. Выход. (ret)
так чи не так??
Отредактировано Матроскин (18.05.2007 16:15:02)
......There is someone in my head, but it's not me.......
Вне форума
Если интересно, вот демо-проект, читаем энкодер и выводим на индикатор: upload.caxapa.ru/Encoder.zip
Вне форума
Вот на асм-е для пик-а по алгоритму Лива:
;=============================================================================
; Блок ОЗУ
;=============================================================================
CBLOCK
ENC_CURENT ; Текущее значение состояния входов энкодера
ENC_PREV ; Предыдущее значение состояния входов энкодера
ENC_TEMP ; временное значение состояния входов энкодера
ENC_DLY_CNT ; Регистр счетчика задержки
ENDC
;=============================================================================
; Флаги, по которым внешние програмы определяют, что произошло.
;=============================================================================
#define ENCODER_F ENC_CURENT,7 ; Флаг события - энкодер крутили
#define ENCODER_UP ENC_CURENT,6 ; Направление врашения - в плюс
;=============================================================================
; Определение выводов, к которым подключены выходы энкодера.
;=============================================================================
#define ENC_IN_A PORTA,1 ;
#define ENC_A_TRIS TRISA,1 ;
#define ENC_IN_B PORTA,0 ;
#define ENC_B_TRIS TRISA,0 ;
;=============================================================================
; Инициализация подпрограмы - переключение используемых контактов на вход, а
; также сброс регистров используемых в работе подпрограммы.
;=============================================================================
ENC_INIT
BSF ENC_A_TRIS ;
BSF ENC_B_TRIS ;
CLRF ENC_CURENT ;
CLRF ENC_PREV ;
CLRF ENC_TEMP ;
RETURN
;=============================================================================
;
;=============================================================================
ENC_WORK
BTFSC ENCODER_EN ; Проверяем - разрешел ли энкодер. Если "нет" -
RETURN ; возвращаемся. Если "да - продолжаем...
CALL ENC_SCAN ; Вызываем процедуру сканирования состояния входов
MOVF ENC_CURENT,W ; Берем текущее значение переменной ENC_CURENT
ANDLW B'00000011' ; и отбрасываем все, кроме двух младших разрядов.
XORWF ENC_PREV,W ; Полученное значение сравниваем с ENC_PREV.
BZ ENC_OUT ; Если равны - обработка завершена.
MOVF ENC_CURENT,W ; Берем текущее значение переменной ENC_CURENT
ANDLW B'00000011' ; и отбрасываем все, кроме двух младших разрядов.
MOVWF ENC_TEMP ; Полученное значение записываем в ENC_TEMP
CALL ENC_DELAY ; Вызываем задержку.
CALL ENC_SCAN ; Вызываем процедуру сканирования состояния входов
MOVF ENC_CURENT,W ; Берем текущее значение переменной ENC_CURENT
ANDLW B'00000011' ; и отбрасываем все, кроме двух младших разрядов.
XORWF ENC_TEMP,W ; Полученное значение сравниваем с ENC_TEMP.
BNZ ENC_OUT ; Если НЕ равны (дребезг) - обработка завершена.
BTFSS ENC_PREV,0 ; если предыдущее состояние входа А было "0"
GOTO CHECK_10 ; переходим на метку
BTFSS ENC_CURENT,0 ; если текущее состояние входа А равно "0"
GOTO CHECK_14 ; переходим на метку
GOTO ENC_OUT ; В противном случае - обработка завершена.
CHECK_10
BTFSC ENC_CURENT,0 ; если текущее состояние входа А равно "1"
GOTO CHECK_12 ; переходим по метке
GOTO ENC_OUT ; В противном случае - обработка завершена.
CHECK_12
BTFSS ENC_CURENT,1 ; если текущее состояние входа В равно "0"
GOTO ENC_PLUS ; переходим по метке
GOTO ENC_OUT ; В противном случае - обработка завершена.
CHECK_14
BTFSS ENC_CURENT,1 ; если текущее состояние входа В равно "0"
GOTO ENC_MINUS ; переходим по метке
GOTO ENC_OUT ; В противном случае - обработка завершена.
ENC_PLUS
BSF ENCODER_F ; Ставим флаг - "энкодер крутили"
BSF ENCODER_UP ; Ставим флаг - "крутили в плюс"
GOTO ENC_OUT ; ВСЁ - обработка завершена.
ENC_MINUS
BSF ENCODER_F ; Ставим флаг - "энкодер крутили"
BCF ENCODER_UP ; Снимаем флаг "крутили в плюс" (крутили в минус)
; GOTO ENC_OUT ;
ENC_OUT
MOVF ENC_CURENT,W ; Берем текущее значение переменной ENC_CURENT
ANDLW B'00000011' ; и отбрасываем все, кроме двух младших разрядов.
MOVWF ENC_PREV ; Результат записываем как значение ENC_PREV
RETURN
;=============================================================================
; Сканирование (побитное) входов энкодера с записью результатов в регистр
; ENC_CURENT
;=============================================================================
ENC_SCAN
BTFSS ENC_IN_A ; Если на входе А "ноль", то
BCF ENC_CURENT,0 ; пишем "ноль" в разряд (0) рнгистра ENC_CURENT
BTFSC ENC_IN_A ; Если на входе А "единица", то
BSF ENC_CURENT,0 ; пишем "единицу" в разряд (0) рнгистра ENC_CURENT
BTFSS ENC_IN_B ; Если на входе В "ноль", то
BCF ENC_CURENT,1 ; пишем "ноль" в разряд (1) рнгистра ENC_CURENT
BTFSC ENC_IN_B ; Если на входе В "единица", то
BSF ENC_CURENT,1 ; пишем "единицу" в разряд (1) рнгистра ENC_CURENT
RETURN
;=============================================================================
; Процедура задержки, используется в подавлении дребезга
;=============================================================================
ENC_DELAY
MOVLW D'198' ; Берем длительность задержки
MOVWF ENC_DLY_CNT ; Пишем в регистр счетчика задержки
ENC_DELAY_LOOP
DECFSZ ENC_DLY_CNT, F ; Уменьшаем счетчик, пока тот не достигнет "0"
GOTO ENC_DELAY_LOOP ; иначе - возврат на метку (цикл)...
RETURN
... с тех пор только подключаю к проекту, ничего не выдумывая...
Отредактировано Dmitry (19.05.2007 12:14:20)
Почему когда мы нарушаем, нас штрафуют, а когда всё делаем правильно, с нас берут налоги?....
Вне форума
2 Dmitry, Liv Спасибо за ответы, понятно только то, что ничего не понятно. Ладно, буду долбиться сам. Как сделаю, напишу. (если сделаю).
......There is someone in my head, but it's not me.......
Вне форума
Может надо выгнать того "кого-то" из головы? (без обид, шучу эт я)...
А серьезно - зачастую оч-ч-ч-чень помогает на время отвлечься от той "засады", что не получается... Вон, как Лив, например, пробку вынуть, на девок поглазеть, можно на природе шашлык съесть. У меня семья периодически вытаскивает меня на Хортицу погулять (пешком). Эт конечно не как главред - на велике , да в Крым, да еще и в грязюку залезть, но тожне ничего...
Почему когда мы нарушаем, нас штрафуют, а когда всё делаем правильно, с нас берут налоги?....
Вне форума
[ Сгенерировано за 0.048 сек, 7 запросов выполнено - Использовано памяти: 649.98 Кбайт (Пик: 700.35 Кбайт) ]