Search code examples
vhdlsensorsfpga

Can't run HC - SR04 Sensor (VHDL)


I'm a student working on a project, on a custom designed board that has a Spartan-6 FPGA on board. My project is to make a game that outputs its interface through HDMI, and recieves input via a sensor. My sensor is the HC - SR04 (http://www.micropik.com/PDF/HCSR04.pdf). All modules are wokring, except for the sensor module. I'm not getting any warning or errors. The following shows my code for the module, in which I created a finite state machine to run through the stages required to send/receive data from the sensor. Note that I have an additional state than what is required in the datasheet, but that shouldn't be a problem since it doesn't trigger the sensor.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Sensor is
    Port (  clk  :  in      STD_LOGIC; --24 MHz
                Echo     :  in      STD_LOGIC;
        Trig     :  out STD_LOGIC;
        Echo_Time:  out integer
    );
end Sensor;

architecture Behavioral of Sensor is

type state_type is (    Init_state, Trigger_state, Echo_state);


signal  state       :   state_type  := Init_state;
signal  echoing     :   std_logic   := '0';             -- determines if we are echoing or not
signal  echoReceived    :   std_logic   := '0';             -- determines if we are echoing or not
signal  d       :   integer;                                -- the first and highest possible delay, this is 20 ms
signal  en_timer    :   std_logic;                          --active high
signal  rst_timer   :   std_logic;                          --active high


signal cnt_timer    : integer := 0;--was 19,
signal final_timer  : integer := 0;--was 19,

begin

state_machine: process (clk, cnt_timer, echoReceived)
    begin
        if rising_edge(clk) then
            if state = Init_state then
                if cnt_timer = d then
                    state <= Trigger_state;
                    rst_timer <= '1';
                else
                    rst_timer <= '0';
                end if;
            elsif state = Trigger_state then
                if cnt_timer = d then
                    state <= Echo_state;
                    rst_timer <= '1';
                else
                    rst_timer <= '0';
                end if;
            elsif state = Echo_state then
                if echoReceived = '1' then--change this one
                    state <= Init_state;
                    rst_timer <= '1';
                else
                    rst_timer <= '0';
                end if;
            end if;
      end if;
    end process;


timer: process(clk, en_timer,rst_timer)
    begin
        if rising_edge(clk) then
            if en_timer = '1' and rst_timer = '0' then
                cnt_timer <= cnt_timer + 1;
            elsif rst_timer = '1' then
                cnt_timer <= 0;
            end if;
        end if;             
    end process;


state_machine_output: process(state, Echo, echoing,cnt_timer)
    begin

            --internal signals
            en_timer        <= '0';

            --state machine signals
            d               <= 0;
            echoing         <= '0';
            echoReceived            <= '0';
            final_timer     <= 0;
            --external signals
            Trig            <= '0';
        if state = Init_state then

            en_timer        <= '1';
            Trig            <= '0';
            d           <= 48; -- this will delay the system by 2 us
            echoing         <= '0';
            echoReceived            <= '0';
        elsif state = Trigger_state then    

            en_timer        <= '1';
            Trig            <= '1';
            d           <= 240; -- this will delay the system by 10 us
            echoing         <= '0';
            echoReceived    <= '0';
        elsif state = Echo_state then   --think about it later

            if Echo = '1' then
                en_timer    <= '1';
                echoing     <= '1';
            elsif Echo = '0' and echoing = '1' then
                final_timer     <= cnt_timer;
                en_timer        <= '0';
                echoing     <= '0';
                echoReceived    <= '1'; 
            end if;

        else

            --internal signals
            en_timer        <= '0';

            --state machine signals
            d           <= 0;
            echoing         <= '0';
            echoReceived            <= '0';
            final_timer     <= 0;
            --external signals
            Trig            <= '0';

        end if;
    end process;

Echo_Time   <= final_timer;--output data here

end Behavioral;

So, my question is whether my logic here is correct or not, because I'm only getting 0 from Echo_time.

Also, note that the sensor is working fine with arduino.


Solution

  • Echo_time is always 0 because of these code lines:

    if Echo = '1' then
      en_timer    <= '1';
      echoing     <= '1';
    elsif Echo = '0' and echoing = '1' then
      final_timer     <= cnt_timer;
      en_timer        <= '0';
      echoing     <= '0';
      echoReceived    <= '1';
    end if;
    

    Trace the signal from the output:

    1. Echo_time is equal to final_timer.
    2. final_timer is always 0 except if Echo = '0' and echoing = '1'
    3. echoing is always 0 except if Echo = '1'
    4. because Echo is either 0 or 1, final timer can not be positive.