Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

distance measuring by encoder

I bought an encoder which generate square pulses sig.

i have to stop the engine if arrived to a required distance.

i know that the wheel diameter is 7cm. and the distance is pi*diameter and it equals to 8 pulses counting (1 wheel cycle = 8 pulses counting).

so i thought i have to definfe a cm counter by this way : counter = required_distance/2.75

how can i do that by synthesis way ???

thank you for help...

6 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Is yours a single or dual phase encoder?

    Usually encoders have two phases, namely two square pulses signals 90 degrees out of phase. This allows you to know direction, besides distance.

    If this is your case, you may use a standard encoder counter: try browsing opencores.org, search for quadrature encoder/decoder.

    Instead, if you have a single phase encoder, you simply need to count raw pulses.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    i have one phase encoder ...

    i wrote this program but got an errore about the multiplication, how can i alternate that by synthessisable way ??

    library IEEE;

    use IEEE.std_logic_1164.all;

    use ieee.std_logic_arith.all;

    use ieee.std_logic_unsigned.all;

    entity encoder is

    port(

    CLK : in std_logic;

    sig : in std_logic ;

    reset : in std_logic;

    req_dist: buffer std_logic_vector(8 downto 0) -- till 5 meter.

    );

    end entity encoder;

    architecture arc_encoder of encoder is

    signal tmp_sig : std_logic;

    signal counter : std_logic_vector(8 downto 0);

    signal distance : std_logic_vector(8 downto 0);

    begin

    process(CLK)

    begin

    if (reset='1') then

    counter <= (others => '0');

    else

    distance <= req_dist*24 and "111000000"; ------------------------------------------------------ HERE IS THE ERRORE

    end if;

    if rising_edge(sig) then

    if (counter < distance) then

    counter <= counter+1;

    else counter <= counter;

    end if;

    end if;

    end process;

    end architecture arc_encoder;
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    the * function in the std_logic_unsigned library does not allow std_logic_vector to be multiplied by an integer, only another std_logic_vector.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Another point - the process is NOT synchronous to the clock because you have not added the "if rising_edge(clk) then" condition to the process.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Rather than using

    if rising_edge(sig)

    I'd follow Tricky's advice and make everything synchronous to clk.

    Then, sample sig at regular intervals, store in a register and wait for a low to high transition in order to increment counter.

    This would also allow you some filtering to avoid fake counts, which is a common problem with single phase encoders, especially if the rotating wheel is supposed to start and stop.