Aqui estan algunos còdigos de los que hemos desarrollado en clase
Este por ejemplo hace un barrido, eta compuesto por 3 módulos:
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;-- PARA TRABAJAR KN COMPUERTAS IF OR...ETC
entity cronometro is
Port ( clk : in STD_LOGIC;
go,clr : in STD_LOGIC;
d2,d1,d0 : out STD_LOGIC_VECTOR (3 downto 0));
end cronometro;
architecture Behavioral of cronometro is
constant DVSR: integer:=5000000;
signal ms_reg, ms_next: unsigned(22 downto 0);
signal d2_reg, d1_reg, d0_reg : unsigned (3 downto 0);
signal d2_next, d1_next, d0_next: unsigned (3 downto 0);
signal ms_tick: STD_LOGIC;
begin
-- REGISTRO
process (clk)
begin
if(clk'event and clk='1') then
ms_reg <= ms_next;
d2_reg <= d2_next;
d1_reg <= d1_next;
d0_reg <= d0_next;
end if;
end process;
--hacemos el siguiente estado logico para producir la señal de 0.1 segundos
ms_next<=(others=> '0') when clr='1' or (ms_reg= DVSR and go='1') else
ms_reg+1 when go='1' else
ms_reg;
ms_tick<= '1' when ms_reg = DVSR else '0';
--incrementar de 3 digitos
process (d0_reg, d1_reg, d2_reg, ms_tick, clr)
begin
--valores x defecto
d0_next<=d0_reg;
d1_next<=d1_reg;
d2_next<=d2_reg;
if clr='1' then
d0_next<= "0000";
d1_next<="0000";
d2_next<="0000";
elsif ms_tick='1' then
if(d0_reg /= 9) then -- /= diferente
d0_next<=d0_reg+ 1;
else --ya alcanzo XX9
d0_next<="0000";
if(d1_reg /= 9) then -- /= diferente
d1_next<=d1_reg+ 1;
else --ya alcanzo el estado X99
d1_next<="0000";
if(d2_reg /= 9) then -- /= diferente
d2_next<=d2_reg+ 1;
else --ya alcanzo el estado 999
d2_next<="0000";
end if;
end if;
end if;
end if;
end process;
-- LA SALIDA LOGICA
d0<=STD_LOGIC_VECTOR (d0_reg);
d1<=STD_LOGIC_VECTOR (d1_reg);
d2<=STD_LOGIC_VECTOR (d2_reg);
end Behavioral;
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;
entity disp_mux is
Port ( clk, reset : in STD_LOGIC;
bcd0, bcd1, bcd2, bcd3 : in STD_LOGIC_VECTOR (3 downto 0);
dp_in : in STD_LOGIC_VECTOR (3 downto 0);
sseg : out STD_LOGIC_VECTOR (7 downto 0);
comun : out STD_LOGIC_VECTOR (3 downto 0));
end disp_mux;
architecture Behavioral of disp_mux is
constant N: integer:=18;--tamaño de bits para bajar de frecuencia
signal q_reg, q_next: unsigned ((N-1) downto 0);
signal sel:STD_LOGIC_VECTOR (1 downto 0);
signal bcd:STD_LOGIC_VECTOR (3 downto 0);
signal dp:STD_LOGIC;
begin
-- REGISTRO:
process (clk, reset)
begin
if reset = '1' then
q_reg<=(others =>'0');
elsif (clk'event and clk='1') then
q_reg<=q_next;
end if;
end process;
-- PROXIMO ESTADO LOGICO DEL CONTADOR
q_next<= q_reg + 1;
--utilizamos los 2 bits mas signidficativos de las señales
--del registro para hacer el control de la multiplexaion
sel<=std_LOGIC_VECTOR (q_reg(N-1 downto N-2));
process(sel, bcd0,bcd1,bcd2, bcd3)
begin
case sel is
when "00"=>
comun <="1110";
bcd<=bcd0;
dp<=dp_in(0);
when "01"=>
comun <="1101";
bcd<=bcd1;
dp<=dp_in(1);
when "10"=>
comun <="1011";
bcd<=bcd2;
dp<=dp_in(2);
when others =>
comun <="0111";
bcd<=bcd3;
dp<=dp_in(3);
end case;
end process;
-- DECODIFICADOR DE BCD A 7 SEGMENTOS
with bcd select
sseg(6 downto 0) <=
--para catodo comun --gfdecba
"0111111"when "0000",--0
"0000110"when "0001",--1
"1011011"when "0010",
"1001111"when "0011",
"1100110"when "0100",
"1101101"when "0101",
"1111101"when "0110",
"0000111"when "0111",
"1111111"when "1000",
"1101111"when "1001",
"0000000"when others ;
sseg(7)<=dp;
end Behavioral;
Este es el módulo principal:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity cronostop is
Port ( clk : in STD_LOGIC;
b : in STD_LOGIC_VECTOR (3 downto 0);
comun : out STD_LOGIC_VECTOR (3 downto 0);
sseg : out STD_LOGIC_VECTOR (7 downto 0));
end cronostop;
architecture Behavioral of cronostop is
signal d2, d1 , d0: STD_LOGIC_VECTOR (3 downto 0);
begin
disp_uit: entity work.disp_mux
port map(
clk=>clk, reset=>'1',
bcd3=>"0000",bcd2=>d2, --- para catodo creo 1111
bcd1=>d1,bcd0=>d0,
dp_in => "0010", comun=>comun,sseg=>sseg ); -- anodo 1101
crono_unit: entity work.cronometro
port map (
clk => clk, go=>b(1), clr=> b(0),
d2=>d2, d1=>d1, d0=>d0 );
end Behavioral;
DIGI_MUNDO
lunes, 31 de enero de 2011
sábado, 29 de enero de 2011
Diseño, construcción y descripción en VHDL de un carro seguidor de líneas y evasor de obstáculos con una FPGA SPARTAN 3E
El proyecto está basado en dos funciones básicas del carro, seguir líneas y evadir obstáculos, dichas funciones se describen mediante dos módulos en VHDL para la implementación en hardware dispusimos de 6 sensores, tres infrarrojos, y tres de fin de carrera. Además de un puente H para el control de los servos.
Para conectar el puente H, hacemos lo siguiente: conectamos los pines 1, 8, 9, 16 a alimentación. Los pines 4, 5, 12, 13 van conectados a tierra. Los pines 2, 7, 10, 15 son las entradas uno, dos, tres, y cuatro respectivamente. Los pines 3, 6, 11, 14 son las salidas uno, dos, tres, y cuatro respectivamente.
En nuestro caso debíamos controlar solo dos servomotores por lo que un puente H era suficiente y su conexión seria así:
Las salidas de los sensores de fin de carrera van conectados como si fuesen switchs y van a la SPARTAN, en esta se procesan y sus salidas van conectadas a las entradas del puente H para mover los servos. En esto básicamente se basaría el hardware del evasor de obstáculos.
Una vez controlado la parte del evasor de obstáculos, seguimos con el seguidor de líneas, lo más idóneo fue subdividirlo en secciones, diseñadas dependiendo de las posibles combinaciones realizables de encendido de los tres led’s (mostrando un cero apagado, cuando cualquier sensor está sobre la línea negra, o un uno –encendido, cuando se desvía), al ser tres sensores se crearon las ocho combinaciones siguientes:
Una vez controlado la parte del evasor de obstáculos, seguimos con el seguidor de líneas, lo más idóneo fue subdividirlo en secciones, diseñadas dependiendo de las posibles combinaciones realizables de encendido de los tres led’s (mostrando un cero apagado, cuando cualquier sensor está sobre la línea negra, o un uno –encendido, cuando se desvía), al ser tres sensores se crearon las ocho combinaciones siguientes:
Sensores Infrarrojos | Descripción | ||
Izquierdo | Central | Derecho | |
0 | 0 | 0 | En medio de un cruce de líneas |
0 | 0 | 1 | En medio de un cruce de líneas |
0 | 1 | 0 | En medio de un cruce de líneas |
0 | 1 | 1 | A la derecha de las líneas |
1 | 0 | 0 | En medio de un cruce de líneas |
1 | 0 | 1 | Sobre la línea |
1 | 1 | 0 | A la izquierda de la línea |
1 | 1 | 1 | Totalmente fuera de las líneas |
Cuando el carro se encuentre sobre la línea, se mantiene el curso hacia el frente. Cuando el carro se encuentre a la derecha de la línea, se direccionaba hacia la izquierda. Cuando el robot se encontraba a la izquierda de la línea, se direccionaba hacia la derecha. Para el resto de las combinaciones se continuaba con la orden de control anterior.
DISEÑO O--O
Se comenzó a desarrollar por funciones:
- Seguir líneas
- Evadir obstáculos.
La placa que se incorporo al carro se puede visualizar en la siguiente imagen:
CÓDIGO:
--------------------------------------------
-- Carrito Seguidor de Lìneas----
----------Evasor de obstáculos-------------
--------------------------------------------
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;
entity compl is
Port ( s_fcc, s_fcd, s_fci, reset, ss, c, i, d : in STD_LOGIC;
clk: inout STD_LOGIC;
e1, e2, e3, e4 : out STD_LOGIC);
end compl;
architecture Behavioral of compl is
constant N : integer := 28; -- tamaño de bits para bajar de frecuencia
signal a: std_logic;
signal q_reg, q_reg1, q_reg2, q_next, q_next1, q_next2 : unsigned (N-1 downto 0);
signal sel : std_logic_vector (1 downto 0);
begin
process (s_fcc, s_fcd, s_fci,c,d,i,clk,ss,reset)
begin
if (reset = '0') then
---- GIRA ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
if (ss= '1') then
if (s_fcc = '1' ) then
a<= '1';
if(clk'event and clk = '1' ) then
q_reg <= q_next;
end if;
q_next <= q_reg + 1;
sel <= std_logic_vector(q_reg(N-1 downto N-2));
case sel is
when "00"=>
---- retrocede
e1<= '1';
e2<= '0';
e3<= '1';
e4<= '0';
when "01" =>
--- gira derecha
e1<= '0';
e2<= '1';
e3<= '1';
e4<= '0';
when others =>
---- GIRA ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
end case;
end if;
if (s_fcd = '1') then
a<= '1';
if(clk'event and clk = '1' ) then
q_reg1 <= q_next1;
end if;
q_next1 <= q_reg1 + 1;
sel <= std_logic_vector(q_reg1(N-1 downto N-2));
case sel is
when "00"=>
---- retrocede
e1<= '1';
e2<= '0';
e3<= '1';
e4<= '0';
when "01" =>
--- gira izquierda
e1<= '0';
e2<= '1';
e3<= '1';
e4<= '0';
when "10" =>
---- GIRA ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
q_next1 <= q_reg1;
when others =>
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
sel <="00";
a <='0';
end case;
end if;
if (s_fci = '1') then
a<= '1';
if(clk'event and clk = '1' and a = '1') then
q_reg2 <= q_next2;
end if;
q_next2 <= q_reg2 + 1;
sel <= std_logic_vector(q_reg2(N-1 downto N-2));
case sel is
when "00"=>
---- retrocede
e1<= '1';
e2<= '0';
e3<= '1';
e4<= '0';
when "01" =>
--- gira izquierda
e1<= '1';
e2<= '0';
e3<= '0';
e4<= '1';
when "10" =>
---- GIRA ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
q_next2 <= q_reg2;
when others =>
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
sel <="00";
a <='0';
end case;
end if;
else
if (c = '1' and d = '0' and i= '0') then
---- Seguir ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
end if;
if (c = '1' and d = '1' and i= '0') then
--- GIRAR DERECHA
e1<= '1';
e2<= '0';
e3<= '0';
e4<= '1';
end if;
if (c = '0' and d = '1' and i= '0') then
--- GIRAR DERECHA
e1<= '1';
e2<= '0';
e3<= '0';
e4<= '1';
end if;
if (c = '0' and d = '0' and i= '1') then
--- gira izquierda
e1<= '0';
e2<= '1';
e3<= '1';
e4<= '0';
end if;
if (c = '1' and d = '0' and i= '1') then
--- gira izquierda
e1<= '0';
e2<= '1';
e3<= '1';
e4<= '0';
end if;
end if;
elsif (reset = '1') then
e1<= '1';
e2<= '1';
e3<= '1';
e4<= '1';
end if;
end process;
end Behavioral;
--------------------------------------------
-- Carrito Seguidor de Lìneas----
----------Evasor de obstáculos-------------
--------------------------------------------
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;
entity compl is
Port ( s_fcc, s_fcd, s_fci, reset, ss, c, i, d : in STD_LOGIC;
clk: inout STD_LOGIC;
e1, e2, e3, e4 : out STD_LOGIC);
end compl;
architecture Behavioral of compl is
constant N : integer := 28; -- tamaño de bits para bajar de frecuencia
signal a: std_logic;
signal q_reg, q_reg1, q_reg2, q_next, q_next1, q_next2 : unsigned (N-1 downto 0);
signal sel : std_logic_vector (1 downto 0);
begin
process (s_fcc, s_fcd, s_fci,c,d,i,clk,ss,reset)
begin
if (reset = '0') then
---- GIRA ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
if (ss= '1') then
if (s_fcc = '1' ) then
a<= '1';
if(clk'event and clk = '1' ) then
q_reg <= q_next;
end if;
q_next <= q_reg + 1;
sel <= std_logic_vector(q_reg(N-1 downto N-2));
case sel is
when "00"=>
---- retrocede
e1<= '1';
e2<= '0';
e3<= '1';
e4<= '0';
when "01" =>
--- gira derecha
e1<= '0';
e2<= '1';
e3<= '1';
e4<= '0';
when others =>
---- GIRA ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
end case;
end if;
if (s_fcd = '1') then
a<= '1';
if(clk'event and clk = '1' ) then
q_reg1 <= q_next1;
end if;
q_next1 <= q_reg1 + 1;
sel <= std_logic_vector(q_reg1(N-1 downto N-2));
case sel is
when "00"=>
---- retrocede
e1<= '1';
e2<= '0';
e3<= '1';
e4<= '0';
when "01" =>
--- gira izquierda
e1<= '0';
e2<= '1';
e3<= '1';
e4<= '0';
when "10" =>
---- GIRA ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
q_next1 <= q_reg1;
when others =>
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
sel <="00";
a <='0';
end case;
end if;
if (s_fci = '1') then
a<= '1';
if(clk'event and clk = '1' and a = '1') then
q_reg2 <= q_next2;
end if;
q_next2 <= q_reg2 + 1;
sel <= std_logic_vector(q_reg2(N-1 downto N-2));
case sel is
when "00"=>
---- retrocede
e1<= '1';
e2<= '0';
e3<= '1';
e4<= '0';
when "01" =>
--- gira izquierda
e1<= '1';
e2<= '0';
e3<= '0';
e4<= '1';
when "10" =>
---- GIRA ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
q_next2 <= q_reg2;
when others =>
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
sel <="00";
a <='0';
end case;
end if;
else
if (c = '1' and d = '0' and i= '0') then
---- Seguir ADELANTE
e1<= '0';
e2<= '1';
e3<= '0';
e4<= '1';
end if;
if (c = '1' and d = '1' and i= '0') then
--- GIRAR DERECHA
e1<= '1';
e2<= '0';
e3<= '0';
e4<= '1';
end if;
if (c = '0' and d = '1' and i= '0') then
--- GIRAR DERECHA
e1<= '1';
e2<= '0';
e3<= '0';
e4<= '1';
end if;
if (c = '0' and d = '0' and i= '1') then
--- gira izquierda
e1<= '0';
e2<= '1';
e3<= '1';
e4<= '0';
end if;
if (c = '1' and d = '0' and i= '1') then
--- gira izquierda
e1<= '0';
e2<= '1';
e3<= '1';
e4<= '0';
end if;
end if;
elsif (reset = '1') then
e1<= '1';
e2<= '1';
e3<= '1';
e4<= '1';
end if;
end process;
end Behavioral;
· VHDL es un lenguaje muy poderoso que nos permite describir de manera muy sencilla funciones básicas para el manejo del carro.
· A los sensores de fin de carrera se los puede ver como switchs para recibir la señal desde la FPGA y luego enviarla a los servomotores.
· Para la implementación de los circuitos, se debe alimentar con una fuente externa ya que la SPARTAN no proporciona mucha corriente para el movimiento de los servomotores.
· Es necesario probar cada función por separado y luego unir todo en una sola unidad para poder depurar el programa en caso de errores.
Suscribirse a:
Entradas (Atom)