Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Энкодер и как с ним работать.
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
TamTam
Поделитесь грамотным кодом для обработки энкодера.
_Sam_
описание
исходники

Исходники правда на VHDL, но думаю идея будет ясна, тем более что алгоритмы работы описаны.

Обратите внимание на цифровой фильтр, который используется в указанных примерах! Частота его работы должна быть выше максимальной частоты импульсов энкодера минимум в два раза! Энкодер может выдать максимальную частоту например, если его вал неподвижен, стоит на границе дискреты, и начинает движение! Если рабочая частота вашего цифрового фильтра будет меньше заявленной максимальной частоты импульсов энкодера, то вы будете либо пропускать импульсы, либо насчитывать лишние.
kanzler
Цитата(TamTam @ Jun 8 2006, 09:59) *
Поделитесь грамотным кодом для обработки энкодера.


Всё зависит от модели энкодера. Есть энкодеры у которы два вывода синхроимпульсов, если нужно определять направление движения то обрабатывать нужно два выхода. Если не нужно определять направление движения то достаточно одного вывода который подключён на счётный вход любого таймера микроконтроллера. Есть модели у которых один вывод синхроимпульсов и вывод направления движения. Тут нужно только следить за состоянием вывода направления движения, а вывод синхроимпульсов подать так жена счётный вывод таймера микроконтроллера.
TamTam
Цитата(kanzler @ Jun 8 2006, 11:48) *
Цитата(TamTam @ Jun 8 2006, 09:59) *

Поделитесь грамотным кодом для обработки энкодера.


Всё зависит от модели энкодера. Есть энкодеры у которы два вывода синхроимпульсов, если нужно определять направление движения то обрабатывать нужно два выхода. Если не нужно определять направление движения то достаточно одного вывода который подключён на счётный вход любого таймера микроконтроллера. Есть модели у которых один вывод синхроимпульсов и вывод направления движения. Тут нужно только следить за состоянием вывода направления движения, а вывод синхроимпульсов подать так жена счётный вывод таймера микроконтроллера.


Энкодер с 2 выводами синхроимпульсов

Код
// решение дернуто из аврлиб
// тока дернул, пока не проверял но думаю работать должен
if( (((PIND.2) & (1<<PIND.2)) == 0) ^
   (((PIND.3) & (1<<PIND.3)) == 0) )
      {
          PORTB=0xff;
      }
      else
      {
         PORTB=0x00;
      }



вот тока вопрос с дребезгом и залипанием как решить ?
TamTam
Да вроде в протеусе работает без глюков, в верхнем коде есть ошибка.
[code]
// процедуру вызываем из прерывания.
void SIGNAL(void);
void SIGNAL(void)
{
if( (((PIND.2) & (1<<PIND.3)) == 0) ^
(((PIND.3) & (1<<PIND.3)) == 0) )
{

PORTB = (PORTB >> 1) | ( (PORTB == 0) <<7);
}
else
{
PORTB = (PORTB << 1) | ( (PORTB == 0));
}
}
[code]
psw
у меня вот так все работает PD0,PD1 входа тодтянутые к плюсу через 4к7
возвращает +1 при повороте по часовой и -1 против


#define PIN_Coder PIND// PD0,PD1
#define Port_Coder PORTD
#define Ddr_Coder DDRD
char status,encoder = 0;
signed char EN = 0;
...
...
//-----------------------------------------------------------------------------------
signed char ReadEncoder(void)
{
register signed char temp = 0;
encoder = (~PIN_Coder & 0x03);//проверяем PD0,PD1
if(status != encoder)
{
switch(encoder)
{
case 0:
if(status == 1) temp = 1;
else if(status == 2) temp = -1;
break;
case 1:
if(status == 3) temp = 1;
else if(status == 0) temp = -1;
break;
case 2:
if(status == 0) temp = 1;
else if(status == 3) temp = -1;
break;
case 3:
if(status == 2)temp = 1;
else if(status == 1) temp = -1;
break;
}
status = encoder;
}
return temp;
}
//-----------------------------------------------------------------------------------
OlegIvanov
делаю приблизительно так (подразумевается сигнал чистый, два канала)
_Sam_
Цитата
если нужно определять направление движения то обрабатывать нужно два выхода. Если не нужно определять направление движения то достаточно одного вывода


Выкидывая второй сигнал вы уменьшете разрешающую способность энкодера в 2 раза!


Код
prev_pind2 = pind2;
prev_pind3 = pind3;

pind2 = ( ((PIND.2) & (1<<PIND.2)) == 0 );
pind3 = ( ((PIND.3) & (1<<PIND.3)) == 0 );

any_edge_d3 = ( prev_pind3 ^ pind3 )

any_edge_d3 выделяет все фронты одного из сигналов.

Код

if(!pind2 & any_edge_d3)
              count = (pind3) ? count + 1 : count - 1;

Это мы получили половину разрядности

Теперь остальное
Код
full_code = count << 1 | ( (pind2 ^ pind3) == 0);


В принципе у psw таже задача решена табличным способом.

Ещё хотелось бы знать какова разрешающая способность вашего датчика.
_Diman_
Вот там тоже про это
http://stas633.narod.ru/ProVse/Valcoder/Valcod.html
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.