martes, 10 de abril de 2018



Ultrasonic sensor HC-RS04 for robotics applications using VHDL





In this sample, I show how to design the architecture of the ultrasonic sensor for robotics applications. A number represented in the seven segment display correspond to some distance defined in the distant calculation entity.

Finally, it is a part of my complete FPGA course. If you interested in my course or you need help in your projects as freelancer contact me at:
postgraduatecahg@gmail.com 


Figure 1. Working principle.


Solution:



Figure 2. TOP Design.




Figure 3. RTL schematic. 



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity HCRS04 is
    Port ( clk : in  STD_LOGIC;
           echo : in  STD_LOGIC;
           Trigger : out  STD_LOGIC;
  an0 : out std_logic;
           display_out : out  STD_LOGIC_VECTOR (6 downto 0));
end HCRS04;

architecture Behavioral of HCRS04 is

COMPONENT TriggerGen
PORT(
clk : IN std_logic;          
trigger : OUT std_logic
);
END COMPONENT;

COMPONENT counter
PORT(
clk : IN std_logic;
reset : IN std_logic;
enable : IN std_logic;          
q : OUT std_logic_vector(19 downto 0)
);
END COMPONENT;
COMPONENT distance_calculation
PORT(
echo_count : IN std_logic_vector(19 downto 0);          
distance : OUT std_logic_vector(3 downto 0)
);
END COMPONENT;

COMPONENT display_decoder
PORT(
distance_in : IN std_logic_vector(3 downto 0);          
display_out : OUT std_logic_vector(6 downto 0)
);
END COMPONENT;

signal Trigger_out: std_logic;
signal echo_counter1 : STD_LOGIC_VECTOR (19 downto 0);
signal echo_count : STD_LOGIC_VECTOR (19 downto 0);
signal distance_bits : std_logic_vector(3 downto 0);

begin

Inst_TriggerGen: TriggerGen PORT MAP(
clk,
Trigger_out 
);
Inst_counter: counter PORT MAP(
clk,
Trigger_out,
echo,
echo_counter1 
);
process(echo) begin
if falling_edge(echo) then
echo_count <= echo_counter1;
end if;
end process;
Inst_distance_calculation: distance_calculation PORT MAP(
echo_count,
distance_bits 
);
Inst_display_decoder: display_decoder PORT MAP(
distance_bits,
display_out 
);

Trigger <= Trigger_out;
an0 <= '1';


end Behavioral;

---------------------- TriggerGen ----------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity TriggerGen is
generic (n: integer :=20);
    Port ( clk : in  STD_LOGIC;
           trigger : out  STD_LOGIC);
end TriggerGen;

architecture Behavioral of TriggerGen is

signal tick: std_logic_vector(n-1 downto 0) := (others =>'1');
constant nclks: integer := 750000; --1000000; --it corresponds to 20ms
begin
  process (clk) begin
   if clk'event and clk = '1' then
    if tick < nclks-1 then
     tick <= tick + 1;
    else
     tick <= (others => '0');
     end if;
   end if;
  end process;
 trigger <= '1' when (tick < 500) else '0'; 
end behavioral;

----------------------------- counter  -----------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;

entity counter is
generic (N: integer := 20);
    Port ( clk : in  STD_LOGIC;
           reset : in  STD_LOGIC;
           enable : in  STD_LOGIC;
           q : out  STD_LOGIC_VECTOR (N-1 downto 0));
end counter;

architecture Behavioral of counter is

signal tick: std_logic_vector(N-1 downto 0);

begin

process (reset, clk, enable) begin

if reset = '1' then
tick <= (others => '0');
elsif clk'event and clk = '1' then
if enable = '1' then
tick <= tick + 1;
end if;
end if;
end process;

q <= tick;

end Behavioral;

------------------------------------ distance_calculation  -------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;


entity distance_calculation is
port(
echo_count : in STD_LOGIC_VECTOR (19 downto 0);
distance : out  STD_LOGIC_VECTOR (3 downto 0)
);
end distance_calculation;

architecture Behavioral of distance_calculation is

begin

Distance <="0000" when (echo_count < 2900) else --0cm
  "0001" when (echo_count > 2900 and echo_count < 8700) else --3cm
  "0010" when (echo_count > 8700 and echo_count < 14500) else --3-5cm
  "0011" when (echo_count > 14500 and echo_count < 21750) else --5-7.5cm
  "0100" when (echo_count > 21750  and echo_count < 27550) else --7.5-9.5cm
  "0101" when (echo_count > 27550  and echo_count < 30450) else --9.5-10.5cm
  "0110" when (echo_count > 30450 and echo_count < 33350) else --10.5-11.5cm
  "0111" when (echo_count > 33350 and echo_count < 37700) else --11.5-13cm
  "1000" when (echo_count > 37700 and echo_count < 40600) else --13-14cm
  "1001" when (echo_count > 40600 and echo_count < 46400) else --14-16cm
  "1010" when (echo_count > 46400 and echo_count < 49300) else --16-17cm
  "1011" when (echo_count > 49300 and echo_count < 52200) else --17-18cm; 
  "1100" when (echo_count > 52200 and echo_count < 55100) else --18-19cm; 
  "1101" when (echo_count > 55100 and echo_count <58000) else --19-20cm; 
  "1110" when (echo_count > 58000 and echo_count < 63800) else --20-22cm; 
  "1111";--more than 22cm
end Behavioral;


-----------------------------  display_decoder   ------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity display_decoder is
    Port ( distance_in : in  STD_LOGIC_VECTOR (3 downto 0);
           display_out : out  STD_LOGIC_VECTOR (6 downto 0));
end display_decoder;

architecture Behavioral of display_decoder is

begin

display_out <="1000000" when distance_in = "0000" else 
  "1111001" when distance_in = "0001" else
  "0100100" when distance_in = "0010" else
  "0110000" when distance_in = "0011" else
  "0011001" when distance_in = "0100" else
  "0010010" when distance_in = "0101" else
  "0000010" when distance_in = "0110" else
  "0111000" when distance_in = "0111" else
  "0000000" when distance_in = "1000" else
  "0011000" when distance_in = "1001" else
  "0000110";

end Behavioral;


--------------------------------  Test Bench of All----------------
USE ieee.std_logic_1164.ALL;

ENTITY hcrs04_top IS
END hcrs04_top;
ARCHITECTURE behavior OF hcrs04_top IS 
    -- Component Declaration for the Unit Under Test (UUT)
    COMPONENT HCRS04
    PORT(
         clk : IN  std_logic;
         echo : IN  std_logic;
         Trigger : OUT  std_logic;
         an0 : OUT  std_logic;
         display_out : OUT  std_logic_vector(6 downto 0)
        );
    END COMPONENT;
    

   --Inputs
   signal clk : std_logic := '0';
   signal echo : std_logic := '0';

  --Outputs
   signal Trigger : std_logic;
   signal an0 : std_logic;
   signal display_out : std_logic_vector(6 downto 0);

   -- Clock period definitions
   constant clk_period : time := 20 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
   uut: HCRS04 PORT MAP (
          clk => clk,
          echo => echo,
          Trigger => Trigger,
          an0 => an0,
          display_out => display_out
        );

   -- Clock process definitions
   clk_process :process
   begin
clk <= '1';
wait for clk_period/2;
clk <= '0';
wait for clk_period/2;
   end process;

   echo_process :process
   begin
echo <= '0';
wait for (clk_period/2)*100000;
echo <= '1';
wait for (clk_period/2)*10000;
echo <= '0';
wait for (clk_period/2)*1600000;
end process;

END;






Figure 4.  Test bench simulation.



-------------- UCF file using Nexys II board -----------------------
#clk
NET 'clk' LOC = 'B8';

# HCRS04
  NET 'echo' LOC = 'M15' |  CLOCK_DEDICATED_ROUTE = FALSE;
NET 'Trigger' LOC = 'L17';



#Display
NET 'display_out(0)' LOC = 'L18';
NET 'display_out(1)' LOC = 'F18';
NET 'display_out(2)' LOC = 'D17'; 
NET 'display_out(3)' LOC = 'D16';
NET 'display_out(4)' LOC = 'G14';
NET 'display_out(5)' LOC = 'J17';
NET 'display_out(6)' LOC = 'H14'; 

# Anodo.
NET 'an0' LOC = 'F17'; 

No hay comentarios.:

Publicar un comentario

BTFSS INSTRUCTION  IN ASSEMBLER FOR PIC18F In this sample, we show that how to use a switch input to make an action. Remember that I...