Radiohobby Forum

Интернет конференция журнала "Радиохобби"

Вы не вошли.

Объявление

Подписка на новые материалы от Николая Сухова - ролики, схемы, модели, онлайн конференции, консультации, чат.

Внимание! Почта в доменах Яндекс и Mail.ru не будет работать в профилях форумчан, из-за введённых правительством Украины санкций против этих компаний. Всем, кто ранее использовал подобную почту, для сохранения прежней функциональности форума, рекомендуется её поменять.

Огромная просьба, заливать тематические картинки и файлы в личные файловые каталоги на форуме, чтобы они не потерялись, со временем!

Ссылка "Загрузки" находится справа внизу формы набора сообщения.

Подписка на журнал "Радиохобби" прекращена. Подробности. Форум же - продолжает свою работу.

#391 17.05.2007 17:01:20

Dmitry
Забанен
Откуда: Запорожье
Здесь с 03.02.2004
Сообщений: 3,105
Сайт

Re: AVR для "чайников"

Вообще, для парафазного эгкодера самым простым способом является определение уровня на одном из выходов в время (допустим) ТОЛЬКО СПАДА на втором выходе (или ТОЛЬКО ФРОНТА). Но, когда я сделат тупо именно так, то жить мешало дрожание фронтов импльсов. Уже потом, когда написал по шпоргалке ЛИВ-а, и переделывать что-то было лень, подумалось - нужно было просто использовать задержку, рекомендованную в даташите на подавление дребезга (мерять только после нее)... Но, еще один нюанс, для такой обработки нужен один вход с прерыванием...


Почему когда мы нарушаем, нас штрафуют, а когда всё делаем правильно, с нас берут налоги?....

Вне форума

#392 17.05.2007 21:18:12

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

Вообще энкодер похож на парафазный. Смотрел осцилом на каждой из ног за один щелчек проскакивает 1 отрицательный ипульс. Вообще надо подумать о прерывании да смотеть просто, какой сигнал изменился первее. Ипользовать прерывание по спаду линии А, как только упала в ноль, смотреть что сейчас на В. подождать немного, и  как только А снова стала в 1 выходить из обработчика. При вращении вправо сперва упадет в ноль А, затем В, при вращении влево - наоборот. Вообще довольно удобно что он защелкивается в состоянии 11. Всегда есть точка отсчета.


......There is someone in my head, but it's not me.......

Вне форума

#393 18.05.2007 11:05:18

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Матроскин пишет:

насколько я понимаю вопрос, то самое "предыдущее" состояние у меня должно уже быть на момент начала выполнения этого алгоритма. Так?

Да. Перед тем, как попасть в основной цикл, программа производит инициализацию своих переменных. Это надо сделать и для глобальной переменной, хранящей предыдущее состояние энкодера. Нужно просто выполнить одно сканирование энкодера и записать результат в эту переменную. А затем уже в цикле выполнять указанный алгоритм.

Матроскин пишет:

У меня есть энкодер, производителя не знаю, написано XLEE  EC12P24L15F. по поиску ничего не нашел.

Возможно, это клон энкодера PEC12: www.bourns.com/pdfs/pec12.pdf

Матроскин пишет:

У него 24 щелчка, причем во всех "устойчивых" состояниях вала линии А и В всегда в 1 (не замкнуты на 3-й вывод). Т.е. если его не крутить, то с него всегда считаются единицы по по обоим линиям.

Всё правильно. У PEC-16 то же самое.

Матроскин пишет:

Получается, что если "предыдущим" у нас считется состояние когда вал не крутили (т. е. А и В = 1 ) в пункте 7 никогда А не будет равно 0, следовательно и инкремента величины не получиться (если это первый после покоя щелчёк).

Предыдущее состояние нужно обновлять в каждом цикле выполнения алгоритма, если обнаруживается новое состояние энкодера (после подавления дребезга, т.е. после пункта 6). Я обновляю глобальную переменную предыдущего состояния между пунктами 6 и 7, а в алгоритм декодера (пункты 7 - 15) в локальных переменных передаю старое предыдущее состояние и текущее состояние энкодера. При вращении энкодера от щелчка до щелчка он проходит все состояния, и предыдущее состояние несколько раз успевает обновиться. Так что на первый щелчок реакция тоже будет.

Вне форума

#394 18.05.2007 13:49:43

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

А мне вчера пришло в голову следующее:

Подпрограмма проверяет состояние сигнала А. Если А=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.......

Вне форума

#395 18.05.2007 14:39:20

Dmitry
Забанен
Откуда: Запорожье
Здесь с 03.02.2004
Сообщений: 3,105
Сайт

Re: AVR для "чайников"

Работает на ура та Лив-овская программа.

Но если так охота, то немного подправьте Ваш алгоритм. Я думаю так:
(до того как - один из входов висит на прерывании и прерывание настроено на (допустим) только по спаду )насколько помню то, что смотрел про АВР, они такое позволяют, равно как и ПИК-и).

1. Сработало прерывание (внешнее).
2. Запрещаем прерывание (внешнее).
3. Запускаем таймер, на выдержку равную подавлению дребезга и разрешаем его прерывание.
4. Сработало прерывание таймера.
5. Проверяем второй вход и видим направление (1- в плюс, 0 - в минус, или наоборот)
6. Останавливаем таймер и запрещаем его прерывание.
7. Ставим флаг "случился энкодер" (ну и "флаг направления" тоже).
8. Разрешаем внешнее прерывание.

...в принципе, можно перед п.8 тоже запустить задержку (типа, защитную)...
Ну и не "...висим в тупом простое ожидания"...


Почему когда мы нарушаем, нас штрафуют, а когда всё делаем правильно, с нас берут налоги?....

Вне форума

#396 18.05.2007 16:13:51

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

Да у мнея что-то с той прогой не получилось вот и начал гадать. Эта тоже. В эмуляторе все красиво, на железе - труп smile
Я хотел для пробы заставить мк под управлением энкодера зажигать линеку из 8 светодиодов.

Как все таки вписать тот алгоритм в программу??

Вот может так:

сегмент данных, переменные

EncMode_Loc     ;Локальная переменная для запоминания состояния энкодера в теле подпрограммы
EncMode_Glob   ;Глобальная переменная для запоминания состояния энкодера в теле основной программы
Enc_Rezult         ;управляемуя энкодером переменная

Start:  Здесь опрашиваем энкодер и запоминаем в EncMode_Glob (скорее всего будет 11, ну да ладно smile )

          Обнуляем 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.......

Вне форума

#397 19.05.2007 11:40:29

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Если интересно, вот демо-проект, читаем энкодер и выводим на индикатор: upload.caxapa.ru/Encoder.zip

Вне форума

#398 19.05.2007 12:12:47

Dmitry
Забанен
Откуда: Запорожье
Здесь с 03.02.2004
Сообщений: 3,105
Сайт

Re: AVR для "чайников"

Вот на асм-е для пик-а по алгоритму Лива:

;=============================================================================
; Блок ОЗУ
;=============================================================================
	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)


Почему когда мы нарушаем, нас штрафуют, а когда всё делаем правильно, с нас берут налоги?....

Вне форума

#399 19.05.2007 15:39:40

Матроскин
Ветеран
Откуда: Краснодар
Здесь с 06.02.2006
Сообщений: 2,022

Re: AVR для "чайников"

2 Dmitry, Liv Спасибо за ответы, понятно только то, что ничего не понятно.  Ладно, буду долбиться сам. Как сделаю, напишу. (если сделаю).


......There is someone in my head, but it's not me.......

Вне форума

#400 19.05.2007 16:00:18

Dmitry
Забанен
Откуда: Запорожье
Здесь с 03.02.2004
Сообщений: 3,105
Сайт

Re: AVR для "чайников"

Может надо выгнать того "кого-то" из головы? (без обид, шучу эт я)...

А серьезно - зачастую оч-ч-ч-чень помогает на время отвлечься от той "засады", что не получается... Вон, как Лив, например, пробку вынуть, на девок поглазеть, можно на природе шашлык съесть. У меня семья периодически вытаскивает меня на Хортицу погулять (пешком). Эт конечно не как главред - на велике , да в Крым, да еще и в грязюку залезть, но тожне ничего...


Почему когда мы нарушаем, нас штрафуют, а когда всё делаем правильно, с нас берут налоги?....

Вне форума

Сейчас в этой теме пользователей: 0, гостей: 1
[Bot] ClaudeBot

Подвал форума

Под управлением FluxBB
Модифицировал Visman

[ Сгенерировано за 0.048 сек, 7 запросов выполнено - Использовано памяти: 649.98 Кбайт (Пик: 700.35 Кбайт) ]