Главная » Статьи » Как подключить

Энкодер и Bascom-AVR. Счетчик импульсов
  В проектах на микроконтроллерах для ввода какой-нибудь пользовательской информации чаще всего используются тактовые кнопки. Для оперативного изменения параметров, когда нужно быстро изменить значение например с 0 до 50, такое решение не самый лучший вариант. Давить на кнопку 50 раз или вводить в программу распознавание долгого нажатия кнопки не наш метод, поэтому обратим внимание на инкрементальный энкодер.
  Разговор пойдет о механическом энкодере, как самом распространенном типе. Оптоэлектрические энкодеры отличаются лишь тем что требуют дополнительного питания светодиода, в остальном принцип работы схож с механическими собратьями.
  Механический энкодер внешне очень похож на переменый резистор, такой же трехногий и с крутилкой. Но в отличии от переменника, энкодер не имеет фиксаторов угла поворота, тоесть его можно крутить сколько угодно.
  К примеру вот механический энкодер выдернутый со старой мышки:
 
 
   Внутри у него находятся контактные площадки и контакты, которые при повороте замыкают эти площадки по хитрому алгоритму:
 
 
 
  При повороте ручки на двух выводах энкодера появляются импульсы, смещенные относительно друг друга на 90 градусов. Именно это позволяет микроконтроллеру определить направление вращения. Для определения направления требуется завести один импульс (М1) на любую ногу прерывания (например INT0), а второй импульс (М2) на любую свободную ногу микроконтроллера. Общий вывод энкодера обычно сажается на землю. 
Затем в программе заводим и разрешаем прерывание (у нас это INT0). Прерывание настраивается по нисходящему импульсу (когда уровень меняется с логической 1 на логический 0). В обработчике прерывания проверяем состояние на ноге куда завели импульс с М2. Если там 0 (тоесть импульс пришел) выполняем одно действие, если там осталась единица (импульс не пришел) - другое действие. 
 
 
  Также прерывание можно настраивать и на положительный фронт импульса (когда логический уровень меняется с - на +), разницы большой нет. 
  Можно заметить, что аналогией энкодера могут служить две кнопки, замыкающие два выхода на общий вывод.
   Для примера решил собрать очень простой счетчик импульсов на attiny2313, позволяющий считать до 65535 как в прямом так и в обратном направлении. Схема приведена ниже. В качестве индикатора использованы семисегментные индикаторы с общим анодом (5 разрядов, на схеме один разряд не используется).
 
  Можно также подтянуть выходы энкодера к шине питания, на случай сильных наводок (резисторами по 10к будет достаточно). Я обошелся внутренними подтягивающими резисторами, стоящими в самом мк.
 
  А вот собственно код в Bascom-AVR:

$regfile = Attiny2313.dat
$crystal = 8000000

Dim W As Word

Dim N1 As Byte
Dim N2 As Byte
Dim N3 As Byte
Dim N4 As Byte
Dim N5 As Byte
Dim N6 As Byte

Dim M1 As Long
Dim M2 As Long
Dim M3 As Long
Dim M4 As Long
Dim M5 As Long
Dim M6 As Long

Ddrd = &B11011011         ' аноды
Ddrb = &B11111111         ' сегменты

Config Int0 = Falling     ' прерывание INT0 по нисходящему фронту (c + на -)
On Int0 Encod

Enable Interrupts
Enable Int0

Do        ' в главном цикле отображаем количество импульсов

Portd = &B11111110

Select Case N1
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 5

Portd = &B11111101

Select Case N2
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 5

Portd = &B11110111

Select Case N3
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 5

Portd = &B11101111

Select Case N4
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 5


Portd = &B10111111

Select Case N5
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 5

Loop

End

Encod:              ' тут узнаем в каком направлении вращают ручку энкодера
 Waitms 2                  ' ждем пока утихнет дребезг контактов
 If Pind.5 = 1 Then        ' если на ноге единица (импульс не пришел) тогда
 Incr W                    ' инкременируем переменную (увеличиваем на 1)
 Else                      ' в обратном случае
 Decr W                    ' декрементируем переменную (уменьшаем на 1)
 End If
           
 Gifr = 64                ' сбрасываем регистр хранения прерывания INT0

' а тут готовим переменную к выводу на дисплей

M1 = W
M2 = M1
M3 = M1
M4 = M1
M5 = M1

M1 = M1 / 10000        ' обработка первого разряда
N1 = Abs(M1)

M2 = M2 Mod 10000      ' обработка второго разряда
M2 = M2 / 1000
N2 = Abs(M2)

M3 = M3 Mod 1000        ' обработка третьего разряда
M3 = M3 / 100
N3 = Abs(M3)

M4 = M4 Mod 100         ' обработка четвертого разряда
M4 = M4 / 10
N4 = Abs(m4)

M5 = M5 Mod 10           ' обработка пятого разряда
N5 = Abs(m5)

Return

Плату с контроллером собирал отдельно от индикатора, затем обе платы соединил стойками. Получается удобная и компактная двухэтажная конструкция.
Вот что получилось:
 
 
  А это в сборе, в энкодер воткнул родное колесо от мышки, так удобней крутить:
 

 
  
 

Скачать архив с готовой прошивкой для МК
Категория: Как подключить | Добавлено: 08.03.2011
Просмотров: 61559 | Комментарии: 52 | Теги: индикатор, исходники, bascom-avr, энкодер, ATtiny2313 | Рейтинг: 4.7/9
Всего комментариев: 521 2 »
52 valeriy2650   (27.04.2018 09:03) [Материал]
Здравствуйте exersizze! Понравились Ваша схема, но кое что хотелось бы изменить в прошивке(конечно если это возможно).Предполагается использовать такой девайс в качестве измерителя длины ленты (2 младших разряда сантиметры, 3 старших - метры).
Какие нужны изменения в прошивке:
1.Нужен счет до 99999 а потом сброс до 0.
2.Нужна постоянно горящая точка перед 2 младшим разрядом (отделить метры от сантиметров).
3.Информация всех разрядов записывается в EEPROM. После исчезновения питания и его подачи, высвечивается последняя запомненная информация.

Сам в программировании не силен, поэтому прошу Вас поправить прошивку (если позволят ресурсы микроконтроллера).Такой девайс будет для многих актуален! Надеюсь на Вашу помощь!

0  
51 exersizze   (19.03.2016 12:27) [Материал]
Собирать в железе, в симуляторе транзисторы не работают как положено.

50 Azerhud   (19.03.2016 09:28) [Материал]
собрал схему в proteus но почему то она не заработала. На индикаторе горят все сигменты (5 блоков) и всё больше ничего не происходит :( посоветуйте что делать?

0  
49 exersizze   (07.01.2016 13:19) [Материал]
Модели энкодера в протеусе и нет. Но можно собрать аналог ему из двух тактовых кнопок.

48 Doctor-X144   (26.12.2015 14:12) [Материал]
Здравствуйте. Выложите пожалуйста архивчик проекта для Proteus. Не получается найти в нём модель энкодера. Буду очень благодарен :)

0  
47 exersizze   (09.08.2015 18:40) [Материал]
Да, когда микроконтроллер стартует все переменные обнулены (равны нулю), есть такая  возможность доставать значения переменных из энергонезависимой памяти, но это другая тема.
Советую научиться работать с симулятором Proteus ну и не мешало бы разобраться  с симулятором встроенным в баском. Многие кочки в программах можно  обходить с помощью них. Закомментируй строки разрешающие прерывания и посмотри что получится.

Цитата
После вкл. питания идет инициализация портов прерываний и т.д.
Далее если нет движухи со входов он крутится в основном цикле DO...LOOP, правильно я понял?
Как только случилось прерывание он летит на метку ENCOD: и обрабатывает входы Правильно?
да правильно.


Код
Вот только не могу дотумкать какой командой нужно проверить 10 имп. и если условие не выполнелось(нет 10 имп) куда деваться?
подсказка: можно же завести вспомогательную переменную и вертеть ею как угодно.

46 leshui   (07.08.2015 19:13) [Материал]
exersizze Спасибо, заработало! Я только учусь программированию и еще не совсем понимаю логику команд.
Когда мы вкл. питание в переменной W какое число?
w=1000 это потому что три разряда?
Теперь я хочу разобраться с импульсами чтобы при 10 имп. менялась переменная W
куда бы я не втыкал переменную w=0 все равно не сбрасывает и при подаче питания горит 001.
После вкл. питания идет инициализация портов прерываний и т.д.
Далее если нет движухи со входов он крутится в основном цикле DO...LOOP, правильно я понял?
Как только случилось прерывание он летит на метку ENCOD: и обрабатывает входы Правильно?
Вот только не могу дотумкать какой командой нужно проверить 10 имп. и если условие не выполнелось(нет 10 имп) куда деваться?

0  
45 exersizze   (07.08.2015 08:05) [Материал]
Как и говорил ошибка в куске кода вывода информации, смотри внимательно. Сначала выводим сотни, потом десятки а потом единицы (Case N3, Case N2, Case N1). Должно быть так
Код
Select Case N3
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 3

Portd = &B11111101

Select Case N2
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 3

Portd = &B11111011

Select Case N1
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 3

Это первое. Вторая ошибка в подсчете переменной. Когды мы добавили условие что переменная при обратном отсчете будет считаться от 1000, переменная после поворота энкодера в положительную сторону, при переходе значения 999 начинает прибавлять единицу не к нулю а к 1000, поэтому нужно добавить еще одно условие

Код
Encod:
Waitms 4
If Pind.5 = 1 Then
Incr W
  If W >= 1000 Then                    'добавляем условие сброса переменной
   W = 0                    'сбрасываем переменную
  End If
Else
Decr W
If W > 1000 Then
W = 999
End If
End If

Gifr = 64


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

44 leshui   (06.08.2015 16:03) [Материал]
вот мой варриант:

$regfile = "2313def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32

Config Portb = Output
Config Portd.3 = Input
Set Portd.3
Config Portd.4 = Input
Set Portd.4
Config Portd.5 = Input
Set Portd.5
Config Portd.0 = Output
Config Portd.1 = Output
Config Portd.2 = Output

Dim W As Word

Dim N1 As Byte
Dim N2 As Byte
Dim N3 As Byte
Dim N4 As Byte
Dim M1 As Integer
Dim M2 As Integer
Dim M3 As Integer
Dim M4 As Long

Config Int1 = Falling
On Int1 Encod

Enable Interrupts
Enable Int1

Do

Portd = &B11111110

Select Case N2
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 3

Portd = &B11111101

Select Case N3
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 3

Portd = &B11111011

Select Case N1
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select

Waitms 3

Loop

End

Encod:
Waitms 4
If Pind.5 = 1 Then
Incr W
Else
Decr W
If W > 1000 Then
W = 999
End If
End If

Gifr = 64

M1 = W
M2 = M1
M3 = M1
'M4 = M1
'M5 = M1

M1 = M1 / 100
N1 = Abs(m1)

M2 = M2 Mod 100
M2 = M2 / 10
N2 = Abs(m2)

M3 = M3 Mod 10
'M3 = M3 / 10
N3 = Abs(m3)
'M4 = M4 Mod 10
'N4 = Abs(m4)

Return

Вот где здесь ошибка, все перепробовал все равно дублирует первый и третий разряд
после перехода через ноль. Коментарии к исходнику копируются из BASCOM-a в кракозябрах поэтому убрал.
Подскажите пожалуйста где может быть ошибка?

0  
43 exersizze   (05.08.2015 22:42) [Материал]
>>> после 0 первый и третий разряд дублируются
действительно чудеса, проверь кусок кода отвечающий за подготовку данных к выводу на индикатор.


Цитата
При вкл. там нули, далее по мере вращения энкодера туда пишутся кол-во имп. и макс. там может быть 65535, а кто(что) сбрасывает эту переменную
при переполнении?
странный вопрос) Переменная сама обнуляется при переполнении, попробую объяснить .  Word это двухбайтная переменная, когда все биты в этой переменной заполняются единичками, выглядит это следующим образом 11111111 11111111 (что в десятичном представлении будет 65535). Если к получившемуся значению добавить еще одну единичку, то первые 16 бит сбрасываются в 0,  в бинарном представлении это будет выглядеть так 1 00000000 00000000, но (!) как уже было написано word это двухбайтная переменная и что находится за за пределами 16 бит ей фиолетово, больше все равно не влезет. Так и получается что при достижении максимального значения переменная "переполняется" и снова принимает нулевое значение.


Цитата
почему переменную W нужно брать 999?
ну так сам же хотел чтобы счет начинался с 999 (см. свой предыдущий комент)


Цитата
Как мне сделать чтобы при вкл. пит. были 000 какая функция за это отвечает?
После подачи питания на микроконтроллер переменные равны нулю. Скорей всего при подаче питания уровни на ножках меняются и срабатывает прерывание. Переменную можно всегда сбросить принудительно: W=0

42 leshui   (05.08.2015 18:05) [Материал]
Какие-то чудеса происходят. Вот этот код немного не правильно работает:
Encod:
Waitms 2
If Pind.5 = 1 Then
Incr W
Else
Decr W
If W > 1000 Then
W = 999
End If
End If

Когда я кручу в обратку, да он считает имп. на уменьшение, но как только я кручю в плюс он считает имп. до 0 нормально, но после 0 первый и третий разряд дублируются.
например:
101, 202,303 и т.д

Мне вот непонятно: Мы задаем переменную W WORD
При вкл. там нули, далее по мере вращения энкодера туда пишутся кол-во имп. и макс. там может быть 65535, а кто(что) сбрасывает эту переменную при переполнении?

почему переменную W нужно брать 999?
при подаче питания там появляется 001 (у меня трех разрядный индикатор и считает имп. справа налево)
Как мне сделать чтобы при вкл. пит. были 000 какая функция за это отвечает?

0  
41 exersizze   (05.08.2015 09:34) [Материал]
Все делается через условие. Для того чтобы отсчитывалось от 999, просто задаем условие что если переменная w больше 1000 (переменная W при отсчитывании "назад" принимает значение 65535) приравниваем W=999

Код
Encod:
  Waitms 2
  If Pind.5 = 1 Then
  Incr W
  Else
  Decr W
    If W > 1000 Then
     W = 999
    End If
  End If


По второму вопросу, заводи вторую переменную в которой считаешь количество импульсов. Когда в переменной окажется нужное значение, меняй значение переменной W.

40 leshui   (04.08.2015 21:35) [Материал]
на третий день мне удалось исходник запустить в протеусе. Подскажите пожалуйста как сделать чтобы после нуля отсчитывал 999-998-997 и т.д. если в обратку крутим?
И еще как мне задать переменную чтобы через столько-то импульсов менялся результат
например 30имп=1 еще 30имп=2 еще 30имп=3 и т.д.?

0  
39 exersizze   (04.08.2015 00:16) [Материал]
С битами конечно я лишканул)) старший бит конечно же не нужен, он все равно программой не учитывается.
Переменная м6 не нужна, и от м5 можно отказаться, код писался в момент когда осваивал энкодер и баском. Поэтому строго не судите)

38 leshui   (02.08.2015 20:48) [Материал]
Пытаюсь разобраться в исходнике и не понятно:
Зачем переменная М5,М6?
в порту D всего 7 бит, а у вас в исходнике 8 это как?

37 exersizze   (28.10.2013 11:18) [Материал]
Насколько помню у меги2560 и прочих новых камней нет регистра GIFR (general interrupt flag register), надо работать с регистром EIFR (external interrupt flag register).

36 Scorpushka   (28.10.2013 10:50) [Материал]
почему у меня при компиляции ругается на строчку Gifr = 64?
версия 2.0.5.0
мк мега2560
спасибо

35 UNSCRIPTED   (12.02.2013 10:52) [Материал]
exersizze:"раза собирал на макетке на отладочной безпаечной плате-результат нулевой ,не работает даже в протеусе постояно светятся нули и при вращении энкодера в протеусе мигают просто все сегменты и разряды.И я не один так делал-может отправить схему протеуса с данной прошивкой для подтверждения?

34 exersizze   (11.02.2013 22:18) [Материал]
Проверяйте внимательно соединения, по большому счету там просто нечему не работать)) Все стандартно, программа/подключения.
В чем выражается "неработоспособность" схемы?

33 UNSCRIPTED   (11.02.2013 20:10) [Материал]
exersizze:Подскажи вы собирали счётчик импульсов на энкодере,все пишут ,что отлично работает!Не работает схема и прошивка даже в железе-отзовитесь плиз если собирали конструкцию данную .

32 kvadra   (27.01.2013 21:31) [Материал]
Доброго Вам здравия. Подскажите пожайлуста возможно ли сделать прошивку чтобы младший разряд менялся (прибавлялось и отнималось) по 0,05(т.е. 0,05-0,10-0,15-0,2 и т.д.) и горела третья запятая с права. После запятой счёт как обычно по 1 и сделать схему с кнопкой обнуления , не значашиеся нули желательно чтобы не светились .Индикатор с общ. анодом. В написании программ не селён потому и прошу Вас. Мне необходим реверсивный счётчик с такими функциями и с пятью разрядами. Спасибо !!! Буду Вам признателен!

31 exersizze   (15.07.2012 23:14) [Материал]
Нет, энкодер и переменный резистор - вещи разные. Для второго нужно использовать АЦП

30 trim   (15.07.2012 02:44) [Материал]
А интересно можно ли так же вместо энкодера впаять резюк переменный на ацп какнить

29 Aleks8383   (18.06.2012 15:39) [Материал]
Какой ещё расчёт,тут всёго 3 детали.Если ты про резисторы то (для индикатора) обычные светодиоды (не повышенной яркости), потребляют где-то 10…20 мА. Возьмем число 15. Напряжение на выходе контроллера - 5В, Падение напряжения на любом светодиоде - около 1,5 В.(Вообще - в зависимости от цвета свечения, от 1,3 до 1,7). Значит, на резистор остается 5 - 1,5 = 3,5 В.Считаем по закону Ома сопротивление резистора: 3,5 / 0,015 = 233ом.
На базах транзисторов вообще можно от 1 до 10к ставить тотому что 5 вольт для открытия ему много вот и ими и гасят напряжение.

28 exersizze   (15.06.2012 00:17) [Материал]
ааа, еще разок внимательно 22 коментарий ))
написано про форум, в комментариях к статьям вложения не предусмотрены.

27 amv2000   (14.06.2012 23:07) [Материал]
нет нету, пробовал другой браузер тоже самое ... сам в шоке.
http://zalil.ru/33445628

26 exersizze   (14.06.2012 21:42) [Материал]
ну как, нету этого?
http://avrproject.ru/files/filsint.png

25 amv2000   (14.06.2012 19:38) [Материал]
Сейчас вышел уже с IE, думал может глюк с оперой, нет у меня ни какой кнопки кроме как добавить комментарий

24 exersizze   (14.06.2012 09:52) [Материал]
при написании топика есть кнопочка прикрепить файл.

23 amv2000   (14.06.2012 08:06) [Материал]
И как добавлять никаких доп. кнопок не видно кроме редактирования?

1-30 31-52
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]






авторизация
Логин:
Пароль: