Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: ENCODER
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Схемотехника
XILINX
Всем добрый!

Есть такая штука -
у нее 2 выхода A и B.
В начальный момент оба в состоянии "0".
Задача : если первым импуьс появится на выходе A ,то счетчик должен считать эти импульсы UP,
а если первым импуьс появится на выходе B ,то счетчик должен считать эти импульсы DOWN.

Как это можно реализовать на VHDL ?
VladKot
Цитата(XILINX @ Jul 21 2009, 09:52) *
Есть такая штука -
у нее 2 выхода A и B.
В начальный момент оба в состоянии "0".

Вы уверены?
В зависимости от положения оси значения А и В могут принимать любые значения
XILINX
Цитата(VladKot @ Jul 21 2009, 10:01) *
Вы уверены?
В зависимости от положения оси значения А и В могут принимать любые значения

В моем случае это так.
Механически реализовано, что в момент прекращения вращения ось фиксируется в таком положении.
А на будущее очень интересен вариант, соответствующий вашему вопросу!
Как определить в какую сторону вращается?
MrYuran
Цитата(VladKot @ Jul 21 2009, 11:01) *
Вы уверены?
В зависимости от положения оси значения А и В могут принимать любые значения

Это вы наверно путаете с квадратурным энкодером.
А в данном случае - типа как в старинных мышах.

В ВХДЛ не силён, но с т.з. схемотехники - решение очевидное.
XOR-им оба сигнала, получаем клок.
Этим клоком защелкиваем один из сигналов в D-триггере.
На выходе получаем направление. 0 - одно направление, 1 - противоположное.
Его подаём на вход направления реверсивного счётчика.
А по заднему фронту нашего клока можно считать.

Нет, отставить...
Тут на фронтах будут фокусы...
По фронту 1-го сигнала защёлкиваем 2-й.
Получаем однозначное направление.
dimoon
А и Б - последовательность импульсов, Б сдвинут на 180 градусов относительно А. Я на контролере делал след. образом- родсчет импульсов по каждому фронту, не важно положит. или отрицат. Направление счета- если А и В "0", приходит фронт полож. по А направление счета на увеличение, если полож. фронт по В то уменьшение счета. Пример кода на С для MC68HC908GP32:
CODE
signed int num;
char KbierTemp, trt;

//************** Инициализация для работы энкодера ************************
DIR_PORT_ENC &=~LINE_ENC; //определяем линии управления энкодера на ввод
PUL_PORT_ENC |= LINE_ENC; //включаем подтягивающие резисторы на входах энкодера
INTSCR_MODE1=OFF; //Инициализация прерываний по модулю KBIER. Динамический режим
INTSCR_IMASK1=ON; //Инициализация прерываний по модулю KBIER. Запрет прерываний по модулю KBIR
delay_10mks(10);
KBIER=(PORT_ENC & LINE_ENC); //Разрешить прерывания только для линий, установленных в "1"
INTSCR_ACK1=ON; //Инициализация прерываний по модулю KBIER. Сброс тригера TKBI
INTSCR_IMASK1=OFF; //Инициализация прерываний по модулю KBIER. Разрешение прерываний по модулю KBIR
//************** end ****************************************************************
void interrupt 15 Isr_KBIER(void)
{
if (!INA0_ENC && (KBIER & 0x02))
{
if (INB0_ENC) ++num;
if (!INB0_ENC) --num;
}
if (!INA1_ENC && (KBIER & 0x04))
{
if (!INB0_ENC) ++num;
if (INB0_ENC) --num;
}
if (!INB0_ENC && (KBIER & 0x01))
{
if (!INA0_ENC) ++num;
if (INA0_ENC) --num;
}
if (!INB1_ENC && (KBIER & 0x08))
{
if (INA0_ENC) ++num;
if (!INA0_ENC) --num;
}
KBIER=(PORT_ENC & LINE_ENC);
INTSCR_ACK1=ON; //Сброс тригера TKBI
}

//*** Cекция для определения входов енкодера ***************************************
//*** ENCR
#define PORT_ENC PTA //Порт входов енкодера
#define DIR_PORT_ENC DDRA //Направление линий входов енкодера
#define PUL_PORT_ENC PTAPUE //Направление линий входов енкодера
#define INA0_ENC PTA_PTA1 //Вход линии А енкодера
#define INA1_ENC PTA_PTA2 //Вход линии ~А енкодера
#define INB0_ENC PTA_PTA0 //Вход линии B енкодера
#define INB1_ENC PTA_PTA3 //Вход линии ~B енкодера
//#define LINE_ENC 0x09 //Используемые линии для работы энкодера в "1" не изпользуемые в "0"
#define LINE_ENC 0x0F //Используемые линии для работы энкодера в "1" не изпользуемые в "0"
DpInRock
Цитата
По фронту 1-го сигнала защёлкиваем 2-й.
Получаем однозначное направление.

Абсолютно правильно.
D-триггером.
XILINX
Цитата(DpInRock @ Jul 21 2009, 12:19) *
Абсолютно правильно.
D-триггером.


Попробовал реализовать на VHDL в железе, все ОК.!!! Но очень много дребезга от этого механического устр-ва, а микросхема очень быстродействующая FPGA (250 MHz), по входу фильтрануть не получается, да и триггер Шмидта поставить не удастся, т.к. работаю на готовом продукте.
Всем спасибо!
izerg
Как говорять, самостоятельно писали наверное только древне греки - не укого было списать smile.gif
Нам же остается только пользоваться поиском и списывать smile.gif
http://www.fpga4fun.com/QuadratureDecoder.html
Там есть фильтр от дребезга.
DpInRock
Цитата(XILINX @ Jul 21 2009, 16:07) *
Попробовал реализовать на VHDL в железе, все ОК.!!! Но очень много дребезга от этого механического устр-ва, а микросхема очень быстродействующая FPGA (250 MHz), по входу фильтрануть не получается, да и триггер Шмидта поставить не удастся, т.к. работаю на готовом продукте.
Всем спасибо!

Дребезг при определении направления не должен иметь никакого значения.

При определении скорости вращения - будет. Самый простой путь - RС цепочка.
vik0
DpInRock, читаем внимательно:
Цитата
работаю на готовом продукте.

О какой RC-цепочке идет речь?

XILINX, иногда еще полезно заглядывать на сайт прародителя вашего ника wink.gif:
http://www.xilinx.com/products/boards/s3es...r_interface.pdf
http://www.xilinx.com/products/boards/s3es...r_interface.zip
DpInRock
О простой RC цепочке. Если у вас энкодер механический (фиговина такая с ручкой - иначе откуда дребезг), то просто припаять на сам энкодер. Либо по входу вашего триггера. Классическая защита от дребезга.

Но в любом случае - телепат из меня плохой. А вот энкодеры у меня работают замечательно.
XILINX
Цитата(vik0 @ Jul 21 2009, 21:00) *
DpInRock, читаем внимательно:

О какой RC-цепочке идет речь?

XILINX, иногда еще полезно заглядывать на сайт прародителя вашего ника wink.gif:
http://www.xilinx.com/products/boards/s3es...r_interface.pdf
http://www.xilinx.com/products/boards/s3es...r_interface.zip

Ну ни фига себе! И плата почти моя (у меня для 3AN) и rotary encoder такой же! И для теста результат выводил на те же светодиоды!
Огромное спасибо! Бегу читать!
haker_fox
Цитата(DpInRock @ Jul 22 2009, 04:22) *
О простой RC цепочке. Если у вас энкодер механический (фиговина такая с ручкой - иначе откуда дребезг), то просто припаять на сам энкодер. Либо по входу вашего триггера. Классическая защита от дребезга.

Но в любом случае - телепат из меня плохой. А вот энкодеры у меня работают замечательно.

Гм! Замечал дребезг и на оптическом энкодере. Для подтверждения сего факта, считал импульсы с двух фаз энкодера при его вращении. На одном из каналов появлялось +[1..6] импульсов на 2000000 общих. Обработка шла по прерываниям. Решил не заморачиваться с RC-цепочками, т.к. небыло времени на дополнительные исследования, а решил проблему поллингом. Причем решение о наличие логического уровня на входе решал не одной проверкой за полпериода сигнала, а, допустим, за 3. Если все три выборки содержат одинаковый уровень, то он и принимается действующим. После этого в течение длительного испытания количество импульсов на двух фазах энкодера стало одинаковым.
P.S. Подобным способом (но аппаратно) поллится USART в AVRках...
rv3dll(lex)
мой фильтр



CODE
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

library UNISIM;
use UNISIM.VComponents.all;

entity filtr_16t_v_01 is

port (
f_clk : in std_logic;
f_en_low_fr_strob : in std_logic;
input_nf : in std_logic;
output_f : out std_logic
);
end entity filtr_16t_v_01;
------------------------------------------------------------------------------
-- Architecture section
------------------------------------------------------------------------------

architecture IMP of filtr_16t_v_01 is

signal flag : STD_LOGIC;
signal cnt : STD_LOGIC_VECTOR (0 to 5);

begin

filtr: process( f_clk) is
begin
if (f_clk = '1' and f_clk'event) and f_en_low_fr_strob = '1' then
if input_nf = flag then
if cnt(0) = '1'
then
output_f <= flag;
else
cnt <= cnt + 1;
end if;
else
cnt <= (others => '0');
flag <= input_nf;
end if;
end if;
end process filtr;

end IMP;
muravei
Цитата(DpInRock @ Jul 21 2009, 17:50) *
Самый простой путь - RС цепочка.

А какие у вас номиналы, ну или пост. времени.
Я попробовал, что-то у меня дребезг не давит, а импульсы , при быстрм вращении валятся в половину.

Начал все с алгоритма мистера Чана (первая функция), но чего-то она тоже дребезжит. sad.gif
haker_fox
Цитата(muravei @ Aug 1 2009, 15:31) *
А какие у вас номиналы, ну или пост. времени.
Я попробовал, что-то у меня дребезг не давит, а импульсы , при быстрм вращении валятся в половину.

При быстром вращении длина импульса становится настолько мала, что RC-цепочка "давит" амплитуду импульсов. Вот и получается пропуск. RC-цепочка хороша для механических энкодеров, предназначенных для управления приборами. Там частота вращения ротора низка, а длительность импульсов при вращении много больше длительности импульсов дребезга. И при расчете постоянной времени не возникает проблем. Тогда RC-цепь эффективна. В остальных случаях спасает поллинг. По-крайней мере я пришел к такому выводу.
rx3apf
Цитата(muravei @ Aug 1 2009, 10:31) *
А какие у вас номиналы, ну или пост. времени.
Я попробовал, что-то у меня дребезг не давит, а импульсы , при быстрм вращении валятся в половину.

Ничего удивительного - бороться с дребезгом механических энкодеров RC-цепочками это идиотизм. С бубном вокруг поплясать - и то больше толку. Надо сделать автомат состояний, забирая выборки либо по прерываниям (от обоих каналов энкодера), либо поллингом с достаточно высокой частотой. Дальше все просто, имеем два значения в текущий момент и два те же самые, но на предыдущей выборке. Всего 16 комбинаций. Их декодируем в три варианта - счетчик в "+", в "-" либо ничего не делать. Для большинства энкодеров один щелчок - сдвиг счетчика на 4 либо на 2 (реже). Выборку обработали, сдвинули "историю" и так дальше. Я использовал выборку 4 kHz, энкодер PEC16. Ошибка на шаг при резких рывках вперед-назад - событие редчайшее, при вращении в одну сторону вообще никаких проблем.
muravei
Цитата(rx3apf @ Aug 2 2009, 00:33) *
Дальше все просто, имеем два значения в текущий момент и два те же самые, но на предыдущей выборке. Всего 16 комбинаций. Их декодируем в три варианта - счетчик в "+", в "-" либо ничего не делать. Для большинства энкодеров один щелчок - сдвиг счетчика на 4 либо на 2 (реже). Выборку обработали, сдвинули "историю" и так дальше. Я использовал выборку 4 kHz, энкодер PEC16. Ошибка на шаг при резких рывках вперед-назад - событие редчайшее, при вращении в одну сторону вообще никаких проблем.

Энкодер такой .
У Чана тоже самое:
Код
volatile struct {
    long position;  
    int moved;      
} Encoder;


void sample_encoder(void)
{
    static const int dir[] = { 0,1,-1,0,-1,0,0,1,1,0,0,-1,0,-1,1,0 };
    static int i;                          
    int n;


    i = (i << 2) + (PA.PIN.BYTE & 3);  
    n = dir[i & 15];                  
    if (n) {                            
        Encoder.position += n;
        Encoder.moved = 1;
    }
}


Что-то написано про 1 кГц, я с такой частотой опрашивал его. Нифига не работает, скачет непредсказуемо.
Или надо эту функцию вызывать, получив стабильные данные?
x736C
rv3dll(lex), есть такой вариант, правда на verilog.
http://www.fpga4fun.com/SerialInterface4.html
После слов: «We filter the data, so that short spikes...»
Он интуитивно понятнее и существенно проще описан.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.