Using FPGA to implement Encoder velocity Calculation

Principle

We usually use a general mathematical equation to calculate the velocity:

Velocity = \frac{\Delta Position}{\Delta T}

If we want to calculate the velocity of the rotary encoder, the changed position \Delta Position should be changed radian.

Implementation

The BISS communication protocol is usually used for reading position information from the encoder. At present We don't need to consider the details of BISS, we only need to know there is a sample frequency to fetch the encoding information. In our application, the sample frequency is:

F_{s} = \frac{125,000,000}{9300}

The general solution uses an array in VHDL to store consecutive position information, then let the latest position minus the oldest position, and finally divide the period elapsed.

Confirm the number of elements of the array

Actually, we can choose the number of elements arbitrarily, but in our application, we need to simulate the scenario that 26 elements are collected at the frequency of 2000 HZ because our algorithm engineer thought the velocity calculated under this case is good, and our system control frequency is 2000HZ. Therefore the velocity calculation equation is below:

\begin{align*} & F_{System} = 2000 HZ \\ & Velocity = \frac{P(25) - p(0)}{\frac{1}{F_{System}}*25} = (P(25) - p(0))*80 \\ \end{align*}

If we want to completely mimic the computation above, we have to know how many times the system control frequency over the encoder sample frequency. This number is calculated below:

n = \frac{\frac{1}{F_{System}}}{\frac{1}{F_{s}}} = \frac{F_{s}}{F_{System}} = \frac{\frac{125,000,000}{9300}}{2000} = 6.72

Then we use this number n to multiply 25, the result is our array's size. It equals 168.

The VHDL implementation

Firstly I define a constant to indicate the number of elements in an array:

  constant Buffer_Size : integer := 169;

Then we build the array type and then instantiate it.

type encoder_buffer is array (0 to Buffer_Size) of std_logic_vector(31 downto 0);
signal buffer_position : encoder_buffer := (others => (others => '0'));

The main part of calculating velocity is below:

VELOCITY_CALCULATE : process (CLK)
        constant full_range : integer := 2**Encoder_BitWidth;
        constant one_quater_full_range    : integer :=  2**(Encoder_BitWidth - 2);
        constant three_quater_full_range  : integer :=  3*(2**(Encoder_BitWidth - 2));
        variable velocity_integer : integer := 0;
        variable current_p : integer := 0;
        variable previous_p : integer := 0;
    begin
        if (CLK'event and CLK = '1') then
            if sig_biss_latching_falling = '1' then
                l_encoder: for i in 0 to (Buffer_Size - 1) loop
                    buffer_position(i + 1) <= buffer_position(i);
                end loop;
                buffer_position(0) <= sig_position;

                current_p  := to_integer(unsigned(buffer_position(0)));
                previous_p := to_integer(unsigned(buffer_position(Buffer_Size)));

                if current_p < one_quater_full_range and previous_p > three_quater_full_range then
                  velocity_integer := current_p - previous_p + full_range;
                elsif current_p > three_quater_full_range and previous_p < one_quater_full_range then
                  velocity_integer := current_p - previous_p - full_range;
                else
                  velocity_integer := current_p - previous_p;
                end if;

                sig_veloctiy  <= std_logic_vector(to_signed(velocity_integer*80, 32));
            end if;
        end if;
    end process;
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容