0% encontró este documento útil (0 votos)
174 vistas44 páginas

Circuitos Combinacionales y Secuenciales

Este documento describe varios circuitos secuenciales y combinacionales desarrollados en una práctica. Se incluye un sistema de detección de personas que activa una alarma, un foco y un vibrador. También se describen sistemas de detección de llenado de un tanque y un contador de objetos. Se explican conceptos como servomotores, módulos Bluetooth y motores paso a paso.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
174 vistas44 páginas

Circuitos Combinacionales y Secuenciales

Este documento describe varios circuitos secuenciales y combinacionales desarrollados en una práctica. Se incluye un sistema de detección de personas que activa una alarma, un foco y un vibrador. También se describen sistemas de detección de llenado de un tanque y un contador de objetos. Se explican conceptos como servomotores, módulos Bluetooth y motores paso a paso.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

UPIITA – IPN Materia: (i.e. Disp. Log. Prog.

Práctica 02: Circuitos combinacionales y secuenciales


• Bernal Casas Héctor Obed
• Martínez Ríos Jesús Alejandro
• Santos López Luis Enrique
• Secundino Vázquez Noé Alejandro
Grupo: 2MV10
Mesa: 6
➢ Resumen:
En esta segunda práctica se realizaron circuitos secuenciales y combinacionales para controlar elementos como
motor a pasos, focos, decodificadores, motores bipolares, así como los circuitos necesarios para una
alimentación externa de estos dispositivos. Se emplearon los lenguajes VHDL y Verilog y la FPGA AMIBA2.
Se reporta el funcionamiento de los dispositivos a través de fotos, simulaciones y enlaces a videos de youtube,
además de haberlos presentado en clase.
➢ Abstract:
In this second practice, sequential and combinational circuits were made to control elements such as stepper
motors, spotlights, decoders, bipolar motors, as well as the necessary circuits for an external power supply of
these devices. The VHDL and Verilog languages and the AMIBA2 FPGA were used. The operation of the
devices is reported through photos, simulations and links to YouTube videos, in addition to having presented
them in class.

➢ Résumé:
Dans cette deuxième pratique, des circuits séquentiels et combinatoires ont été réalisés pour contrôler des
éléments tels que des moteurs pas à pas, des projecteurs, des décodeurs, des moteurs bipolaires, ainsi que les
circuits nécessaires à une alimentation externe de ces appareils. Les langages VHDL et Verilog ainsi que le
FPGA AMIBA2 ont été utilisés. Le fonctionnement des appareils est rapporté à travers des photos, des
simulations et des liens vers des vidéos YouTube, en plus de les avoir présentés en classe
➢ Introducción:

• Servomotor
Un servomotor es un dispositivo similar a un motor de corriente continua que tiene la capacidad de ubicarse
en cualquier posición dentro de su rango de operación, y mantenerse estable en dicha posición.
El servomotor lleva incorporado un sistema se regulación que puede ser controlado tanto en velocidad como
en posición.
Es posible modificar un servo para obtener un motor de corriente continua que, si bien ya no tiene la capacidad
de control del servo, conserva su fuerza, velocidad y baja inercia que caracteriza a estos dispositivos.
Para posicionar el servomotor es necesario aplicarle un pulso eléctrico cuya duración determinará el ángulo
de giro del motor.

En la figura muestra que para un tiempo de 1ms el eje del motor estará en la posición izquierda, para un pulso
de 1.5ms se colocará en medio y para pulsos de 2ms se moverá hasta el extremo derecho.

• Módulo Bluetooth HC-06


Módulo Bluetooth HC-06 es un dispositivo que soporta conexiones inalámbricas a través del protocolo
“bluethooth”. Se puede comportar como esclavo o maestro, los cuales sirven para escuchar peticiones de
conexión y otros para generar peticiones de conexión. So algún dispositivo se conecta, el módulo transmite a
este todos los datos que recibe desde nuestro microcontrolador y viceversa.
El módulo HC-06 cumple con las especificaciones del estándar Bluetooth 2.0 a2.4 Ghz que es perfectamente
compatible con celulares o smartphones Android, más no con los Iphone. Además, es compatible con Arduino
y PIC.

Las características de un circuito UART para comunicación com el módulo BT HC-06 o similar, usando el
protocolo RS232, que inicie con un bit de start y termine con un bit de stop, son: bus de datos de 8 bits, un
bit de stop y un bit de paridad, como se muestra en la figura 1, aunque otra alternativa con bit de paridad se
muestra en la figura 2.

Figura1 : Protocolo RS323 de 8bits sin bit de paridad.

Figura2: Protocolo RS232 de 8 bits con bit de paridad.


Posteriormente se elige la velocidad de transmisión, que para este caso es de 9600, y a partir de esta se obtiene
el periodo de la señal (T=1/9600=104.16us, por bit transmitido), con el que se diseña un contador para
alcanzar la mitad del periodo (T/2=52.08us) a partir del reloj de la tarjeta Nexys 2 que trabaja a 50MHz
(Tnexys = 1/50MHz= 20ns). Realizando el cálculo de 52.08us/20ns da un resultado de 2604.16 veces que
cabe T/2 en el periodo de la tarjeta Tnexys, por lo que se necesita un contador de 2604 pulsos para establecer
el alto y 2604 veces para el pulso bajo. Si se deseara cambiar de velocidad, la tabla 1 muestra los cálculos a
otras velocidades de transmisión y el tamaño del contador.
Tabla1: Datos importantes obtenidos de la velocidad en baudios.

Para la recepción de datos del módulo BT se implementa una máquina de estados finitos tipo Mealy de solo
dos estados, mostrada en la figura 3, la cual funciona con las señales Rx (terminal D0 del HC-06) que detecta
el primer nivel bajo para dar inicio a la recepción, y la señal done que indica cuando terminó de recibir los 8
bits del dato de Rx.

Figura3: Maquina de Mealy de dos estados

El primer estado EDO_1 espera a que el receptor tenga el primer bit con cero que es el bit de start del protocolo
RS232 para pasar al segundo estado EDO_2. En el EDO_2 se realizan varios procesos de la recepción, el
primero y más importante es la generación de la señal de captura (capture) a partir del contador “c2” que tiene
3 veces la velocidad de transmisión. Con la señal de captura se guardan los datos de Rx con un registro de
corrimiento, se activa un contador i que cuenta de 0 a 8 (el bit de start y los 8 bits de datos), y por último la
actualización de la máquina de estados, como se muestra en la figura 4.
Figura4: Actualización de la máquina de estados

• Motor a pasos
El motor paso a paso es un motor de corriente continua sin escobillas en el que la rotación se divide en un cierto
número de pasos resultantes de la estructura del motor. Normalmente, una revolución completa del eje de 360°
se divide en 200 pasos, lo que significa que se realiza una sola carrera del eje cada 1,8°. También hay motores
donde la carrera del eje se realiza cada 2; 2,5; 5, 15 o 30°.La funcionalidad descrita es posible gracias a la
construcción especial del motor paso a paso. Debido al hecho de que la rotación completa del eje se divide en
ciertas secciones discretas, el motor paso a paso no gira suavemente, sino que realiza saltos y cruza estados
intermedios, por lo que el funcionamiento del motor paso a paso se acompaña de un sonido y vibración
característicos.
El principio de funcionamiento del motor paso a paso en el modo de paso completo se ilustra en el dibujo. En
este modo, el motor gira en un ángulo resultante de su construcción, que puede ser, por ejemplo, 1,8°. Como es
fácil de calcular, en tal caso es necesario dar 200 pasos para un giro completo (200×1.8° = 360°).
El recorrido del eje se realiza después de energizar una o dos bobinas. El funcionamiento de una sola bobina
requiere una potencia mínima del controlador. En funcionamiento bifásico, con suministro de bobinas opuestas,
se requiere el doble de potencia, pero también aumentan la velocidad y el par.
El principio de funcionamiento del motor en el modo de medio paso se muestra en el dibujo 2. Como su nombre
lo indica, en este modo la carrera discreta del rotor se divide por 2 y, haciendo una sola carrera, gira la mitad del
ángulo nominal. Con referencia al ejemplo anterior, una sola carrera será de 0,9°, mientras que el número de
pasos por revolución completa aumentará a 400.
En el trabajo en modo de medio paso, se requiere energía alterna para las dos fases (bobinas). Esto da como
resultado un aumento del par en comparación con el funcionamiento con un suministro monofásico, un
funcionamiento "más suave" del motor y la duplicación de la resolución angular mencionada anteriormente.
➢ Desarrollo:

Para el circuito combinacional se optó por realizar el sistema de detección de personas en un torniquete del
inciso a), y los sistemas correspondientes a los incisos c) y d) como circuitos secuenciales.
a) Sistema de detección de paso de personas:
c) Sistema de detección de llenado de un tinaco con sensores:
d) Contador de objetos:
a) Sistema de detección de paso de personas por un torniquete que accione una alarma tipo “beep”, que
encienda un foco de 120V y que prenda un vibrador, además de indicar en el display la letra “A”.
Para este problema realizamos un código que enciende un motor vibrador, activa un buzzer que genera una alarma
de un solo beep, enciende un display de 7 segmentos para mostrar la letra A y enciende un foco de 120V. Todos
estos componentes se activan cuando, mediante uno de los pines tipo hembra que funciona como entrada, la
tarjeta detectaba energía.

Pines de
voltaje
de 3.3V

Pines de
Tierra
(GND)

Mediante el voltaje de 3.3V proporcionado por la tarjeta enviamos una señal la cual pasaba por un sensor de
Resistencia como el que se muestra en la siguiente imagen.

Cuando presionamos el sensor, este permite el paso del voltaje de 3.3V y la señal entra por el pin de entrada
asignado en la FPGA. Una vez que el pin detecta la señal, entonces la misma tarjeta envía un ‘1’ lógico a los
pines de salida que asignamos para poder encender el vibrador, el buzzer y el foco, además de mostrar una letra
“A” con los display de 7seg de la tarjeta.

Para encender el buzzer y el motor vibrador, mediante uno de los pines hembra, enviamos un ‘1’ lógico con ayuda
de un jumper para que este llegue a la terminal positiva de ambos componentes y estos se activen, la terminal
negativa de estos los podemos conectar a uno de los pines GND de la tarjeta.
Para el display de 7seg solo necesitamos realizar el código para poder encender únicamente uno de los 8 displays
y que se enciendan solo los segmentos necesarios. Ya que los displays son de tipo ánodo debemos asignar un ‘0’
lógico al display y a los segmentos que queremos activar. En nuestro caso activamos el ultimo display inferior
(mostrado en la sig. imagen) y solo dejamos inactivo el segmento D para simular la letra A.

Finalmente, para poder encender el foco se necesitó armar un circuito con un optoacoplador, un relevador y una
fuente como se muestra a continuación.

Este circuito nos permite tanto proteger la tarjeta como permitir que la tarjeta funciones como un “switch” para
encender el foco. El foco de 120V lo conectamos a una fuente de CA (Un enchufe) para que tenga suficiente
voltaje y encienda. Entonces cuando presionamos el sensor, tanto el buzzer, vibrador, display y el foco se activan.
El código fue escrito en VHDL y es el que se muestra a continuación.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity Torniquete is port(


an : out STD_LOGIC_vector(7 downto 0);
sal : out STD_LOGIC_vector(0 to 7);
foco: out STD_LOGIC;
vib : out STD_LOGIC;
sen : in STD_LOGIC);
end Torniquete;

architecture Behavioral of Torniquete is


signal dis : STD_LOGIC_vector(0 to 7);
begin

an <= "11111110";
process (sen)
begin

case sen is
when '1' => dis <= "10001000"; vib <= '1'; foco <= '1';
when others => dis <= "11111111"; vib <= '0'; foco <= '0';
end case;

end process;

sal <= dis;

end Behavioral;

El archivo UCF para la Amiba2 es:


net sen loc = "C4";
net vib loc = "E4";
net foco loc = "D6";

net sal<7> loc = "K13";


net sal<6> loc = "L15";
net sal<5> loc = "M15";
net sal<4> loc = "P15";
net sal<3> loc = "P14";
net sal<2> loc = "K15";
net sal<1> loc = "L14";
net sal<0> loc = "N15";

net an<7> loc = "G12";


net an<6> loc = "F13";
net an<5> loc = "H12";
net an<4> loc = "G13";
net an<3> loc = "H13";
net an<2> loc = "K11";
net an<1> loc = "J13";
net an<0> loc = "K12";

A continuación, se muestra la simulación del código.

c) Sistema de llenado de un tinaco con 3 sensores en cisterna y tres sensores en tinaco y visualización en
vummer.
Para esta parte se generó un código para activar y desactivar una bomba para el llenado de un tinaco. Debido a
que no fue posible la adquisición de los sensores de nivel de agua, se optó por simularlos con los switches de la
FPGA.
La bomba se simulo con un ventilador de 12v y una fuente de alimentación externa, como se muestra en la figura:

El cógigo VHDL para que se empleo fue el siguiente:


----------------------------------------------------------------------------------
-- Company:
-- Create Date: 20:48:07 03/28/2022
-- Module Name: TINACO - Behavioral
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity Ejercicio1C is --Inicio de la entidad
port (
S : in STD_LOGIC_VECTOR(5 DOWNTO 0); --Entrada de sensores
dp: out std_LOGIC_VECTOR(7 DOWNTO 0); --salida a display
dp_sg: out STD_LOGIC_VECTOR(7 DOWNTO 0); --anodos del display
motor : out STD_LOGIC; --señal de salida para activar/desactivar la
bomba
B: OUT STD_LOGIC; -- LED indica cuando la bobma prende
OV : out STD_LOGIC_VECTOR(5 DOWNTO 0)); --Salida a LEDs (vummer)
end Ejercicio1C; --Fin de la entidad

architecture Behavioral of Ejercicio1C is --Inicia la arquitectura


begin
dp<="01111111"; --Anodos de display
OV<=S; --La lectura de sensores se refleja en los
leds
process (S) --Inicia
proceso
begin
if S="001111" or S="000111" or S="001011" or S="000011" or S="011111" or
S="011011" or S="011011" then
motor <= '1'; --bomba enciende
dp_sg <= "10011111"; -- de despliega un "uno" en el display
B<='1'; --Enciende led indicando que la bomba
encendio
elsif S(5)='1' and S(4)='0' and S(3)='1' then --Posible error de sensado
motor <= '0'; --Bomba se apaga
dp_sg <= "01110001"; --Se mustra una "F" en el display
B<='0'; --Led indicador se apaga
elsif S(2)='1' and S(1)='0' and S(0)='1' then
motor <= '0';
dp_sg <= "01110001";
B<='0';
elsif S(5)='1' and S(4)='1' and S(3)='0' then
motor <= '0';
dp_sg <= "01110001";
B<='0';
elsif S(2)='1' and S(1)='1' and S(0)='0' then
motor <= '0';
dp_sg <= "01110001";
B<='0';
elsif S(5)='1' and S(4)='0' and S(3)='0' then
motor <= '0';
dp_sg <= "01110001";
B<='0';
elsif S(2)='1' and S(1)='0' and S(0)='0' then
motor <= '0';
dp_sg <= "01110001";
B<='0';
elsif S(5)='0' and S(4)='0' and S(3)='0' then
motor <= '0';
dp_sg <= "01110001";
B<='0';
elsif S(2)='0' and S(1)='0' and S(0)='0' then
motor <= '0';
dp_sg <= "01110001";
B<='0';
elsif S(3)='0' and S(4)='1' and S(5)='0' then
motor <= '0';
dp_sg <= "01110001";
B<='0';

else
motor <= '0';
dp_sg <= "00000011";
B<='0';
end if;
end process; --Fin del proceso
end Behavioral; --Fin de la arquitectura

La UCF para la amiba2 es:


//AMIBA2
NET "S(5)" LOC = "M1";
NET "S(4)" LOC = "P2";
NET "S(3)" LOC = "N5";
NET "S(2)" LOC = "T7";
NET "S(1)" LOC = "R9";
NET "S(0)" LOC = "P4";
NET "OV(5)" LOC = "M4";
NET "OV(4)" LOC = "R1";
NET "OV(3)" LOC = "T5";
NET "OV(2)" LOC = "T9";
NET "OV(1)" LOC = "M12";
NET "OV(0)" LOC = "N6";
NET "motor"LOC = "B15";
NET "dp_sg(7)" LOC = "P16";#a
NET "dp_sg(6)" LOC = "P15";#b
NET "dp_sg(5)" LOC = "T15";#c
NET "dp_sg(4)" LOC = "T14";#d
NET "dp_sg(3)" LOC = "T13";#e
NET "dp_sg(2)" LOC = "R16";#f
NET "dp_sg(1)" LOC = "R15";#g
NET "dp_sg(0)" LOC = "R14";#dp
NET "dp(7)"LOC = "E11";
NET "dp(6)"LOC = "D11";
NET "dp(5)"LOC = "C15";
NET "dp(4)"LOC = "E15";
NET "dp(3)"LOC = "D16";
NET "dp(2)"LOC = "E16";
NET "dp(1)"LOC = "F16";
NET "dp(0)"LOC = "G16";
NET B LOC=P12;
A continuación, se muestran las simulaciones efectuadas
El circuito queda como se muestra a continuación:
En el siguiente enlace se puede ver un pequeño video del funcionamiento: https://youtu.be/HS3r94bs7Qg
b) Controlador de motor a pasos bipolar
Para este sistema, se utilizó el driver L293D con tal de proteger la tarjeta ante una sobre exigencia de corriente
por parte del motor a pasos. El diagrama utilizado se muestra a continuación:
L293D

FPGA

El código en VHDL usado es el siguiente:


--------------------------------------------------------------------
-- Company: PiQ2 - UPIITA
-- Create Date: 03/27/2022
--------------------------------------------------------------------

--vel = 0 => lento


--vel = 1 => rápido
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity FSM_Motor is
port(
clk,reset,vel,stop,sentido : in std_logic; --Botones de control
Bobina : out std_logic_vector(3 downto 0); --Bobinas del motor
AN : out STD_LOGIC_VECTOR (7 downto 0) := "11111111"; --Ánodos del Display
DISPLAY : out STD_LOGIC_VECTOR (7 downto 0) := "00000000" --Segmentos del
Display
);
end entity FSM_Motor;
architecture arq of FSM_Motor is
type estados_type is (E0,E1,E2,E3,E4,E5,E6,E7); --Estados posibles de la FSM
signal E_actual : estados_type := E0;
signal cont1 : std_logic_vector(21 downto 0); --para dividir la frecuencia del reloj
signal clko : std_logic; --
señal de reloj de menor frecuencia
signal conta_1250us: integer range 1 to 62_500:=1; -- pulso1 de 1250us@400Hz (0.25ms)
signal SAL_400Hz : std_logic; --señal de
reloj de 400Hz
signal SEL: std_logic_vector (1 downto 0):="00";--para recorrerse entre los displays
--signal E_sig : estados_type;
begin

--divisor de frecuencias para señal de control del giro del motor


divisor_motor : process(clk)
begin
if rising_edge (clk) then
cont1 <= cont1 + 1;
clko <= cont1(20);
end if;
end process divisor_motor;

--FSM que describe la sucesión de energización de las bobinas del motor


estados_machine : process(clko)
begin
if clko'event and clko='1' then
if reset = '1' then E_actual <= E0;
else
case E_actual is
when E0 =>
Bobina <= "0001";
if stop <= '0' then
if (vel = '0' and sentido = '0') then E_actual <= E1;
elsif (vel = '1' and sentido = '0') then E_actual <= E2;
elsif (vel = '0' and sentido = '1') then E_actual <= E7;
elsif (vel = '1' and sentido = '1') then E_actual <= E6;
end if;
else E_actual <= E0;
end if;
when E1 =>
Bobina <= "0011";
if stop <= '0' then
if (vel = '0' and sentido = '0') then E_actual <= E2;
elsif (vel = '1' and sentido = '0') then E_actual <= E3;
elsif (vel = '0' and sentido = '1') then E_actual <= E0;
elsif (vel = '1' and sentido = '1') then E_actual <= E7;
end if;
else E_actual <= E1;
end if;
when E2 =>
Bobina <= "0010";
if stop <= '0' then
if (vel = '0' and sentido = '0') then E_actual <= E3;
elsif (vel = '1' and sentido = '0') then E_actual <= E4;
elsif (vel = '0' and sentido = '1') then E_actual <= E1;
elsif (vel = '1' and sentido = '1') then E_actual <= E0;
end if;
else E_actual <= E2;
end if;
when E3 =>
Bobina <= "0110";
if stop <= '0' then
if (vel = '0' and sentido = '0') then E_actual <= E4;
elsif (vel = '1' and sentido = '0') then E_actual <= E5;
elsif (vel = '0' and sentido = '1') then E_actual <= E2;
elsif (vel = '1' and sentido = '1') then E_actual <= E1;
end if;
else E_actual <= E3;
end if;
when E4 =>
Bobina <= "0100";
if stop <= '0' then
if (vel = '0' and sentido = '0') then E_actual <= E5;
elsif (vel = '1' and sentido = '0') then E_actual <= E6;
elsif (vel = '0' and sentido = '1') then E_actual <= E3;
elsif (vel = '1' and sentido = '1') then E_actual <= E2;
end if;
else E_actual <= E4;
end if;
when E5 =>
Bobina <= "1100";
if stop <= '0' then
if (vel = '0' and sentido = '0') then E_actual <= E6;
elsif (vel = '1' and sentido = '0') then E_actual <= E7;
elsif (vel = '0' and sentido = '1') then E_actual <= E4;
elsif (vel = '1' and sentido = '1') then E_actual <= E3;
end if;
else E_actual <= E5;
end if;
when E6 =>
Bobina <= "1000";
if stop <= '0' then
if (vel = '0' and sentido = '0') then E_actual <= E7;
elsif (vel = '1' and sentido = '0') then E_actual <= E0;
elsif (vel = '0' and sentido = '1') then E_actual <= E5;
elsif (vel = '1' and sentido = '1') then E_actual <= E4;
end if;
else E_actual <= E6;
end if;
when E7 =>
Bobina <= "1001";
if stop <= '0' then
if (vel = '0' and sentido = '0') then E_actual <= E0;
elsif (vel = '1' and sentido = '0') then E_actual <= E1;
elsif (vel = '0' and sentido = '1') then E_actual <= E6;
elsif (vel = '1' and sentido = '1') then E_actual <= E5;
end if;
else E_actual <= E7;
end if;
end case;
end if;
end if;
end process;

--Divisor de frecuencia para el display


process (CLK)
begin
if rising_edge(CLK) then
if (conta_1250us = 62_500) then
SAL_400Hz <= NOT(SAL_400Hz); --genera un barrido de 2.5ms
conta_1250us <= 1;
else
conta_1250us <= conta_1250us + 1;
end if;
end if;
end process;

--Mostrar velocidad en displays


process(SAL_400Hz,vel,SEL)
begin
if SAL_400Hz'event and SAL_400Hz = '1' then SEL <= SEL+'1';
if vel = '1' then
case(SEL) is
when "00" =>
AN <="11110111";
DISPLAY <= "01110001";--F
when "01" =>
AN <="11111011";
DISPLAY <= "00010001";--A
when "10" =>
AN <="11111101";
DISPLAY <= "01001001";--S
when "11" =>
AN <="11111110";
DISPLAY <= "11100001";--t
when OTHERS=>
AN <="11111111";
DISPLAY <= "00000000";
end case;
elsif vel = '0' then
case(SEL) is
when "00" =>
AN <="11110111";
DISPLAY <= "01001001";--S
when "01" =>
AN <="11111011";
DISPLAY <= "11100011";--L
when "10" =>
AN <="11111101";
DISPLAY <= "00000011";--O
when "11" =>
AN <="11111110";
DISPLAY <= "10111001";--W
when OTHERS=>
AN <="11111111";
DISPLAY <= "11111111";
end case;
end if;
end if;
end process;
end arq;
El archivo de restricciones es el siguiente:
NET "clk" LOC = "E7";
NET "reset" LOC = "M2";
NET "vel" LOC = "M1";
NET "stop" LOC = "P2";
NET "sentido" LOC = "N5";
NET "Bobina(0)" LOC = "E3";
NET "Bobina(1)" LOC = "E4";
NET "Bobina(2)" LOC = "F5";
NET "Bobina(3)" LOC = "D8";
NET "AN(7)" LOC = "E11";
NET "AN(6)" LOC = "D11";
NET "AN(5)" LOC = "C15";
NET "AN(4)" LOC = "E15";
NET "AN(3)" LOC = "D16";
NET "AN(2)" LOC = "E16";
NET "AN(1)" LOC = "F16";
NET "AN(0)" LOC = "G16";
NET "DISPLAY(7)" LOC = "P16";
NET "DISPLAY(6)" LOC = "P15";
NET "DISPLAY(5)" LOC = "T15";
NET "DISPLAY(4)" LOC = "T14";
NET "DISPLAY(3)" LOC = "T13";
NET "DISPLAY(2)" LOC = "R16";
NET "DISPLAY(1)" LOC = "R15";
NET "DISPLAY(0)" LOC = "R14";

Veamos que cuando la señal “sentido” pasa de 1 a 0, los estados comienzan a cambiar de manera ascendente, por
lo que el motor gira en el otro sentido también.

Ahora bien, cuando stop está activo, los estados no cambian, por lo que el motor no se mueve, y cuando la
velocidad cambia, los estados cambian de dos en dos, por lo que el motor dará pasos completos, y no medios
pasos.
c) Detector de 4 unos seguidos
Este código genera una señal mediante la lectura de los valores de un DIP switch, y en otra etapa se encuentra
la máquina de estado finito que va leyendo dicha señal, y si esta se encuentra en estado alto durante 4 ciclos
seguidos, activará una alarma. El programa se realizó en un Top Level Design, y los códigos de las entidades
se muestran a continuación:
TLD.vhd (Top Level Design):
--------------------------------------------------------------------
-- Company: PiQ2 - UPIITA
-- Create Date: 03/25/2022
--------------------------------------------------------------------
Library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;

entity TLD is
port(
clk:in std_logic;
reset:in std_logic;
DIP:in std_logic_vector(3 downto 0);--Entradas del DIPswitch
alarma, speaker:out std_logic;
AN : out STD_LOGIC_VECTOR (7 downto 0)--Ánodos del Display
);
end TLD;

architecture Behavioural of TLD is


signal dato:std_logic;

begin
FSM_Detector: entity work.FSM_Detector_unos port map(
clk => clk,
reset => reset,
dato => dato,
alarma => alarma,
speaker => speaker,
AN => AN
);

Generador_seq: entity work.Generador_seq port map(


clk => clk,
reset => reset,
dato => dato,
DIP => DIP
);
end Behavioural;

FSM_Detector_unos.vhd:
--------------------------------------------------------------------
-- Company: PiQ2 - UPIITA
-- Create Date: 03/25/2022
--------------------------------------------------------------------
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 FSM_Detector_unos is
port(
clk,reset,dato : in std_logic;
alarma,speaker : out std_logic;
AN : out STD_LOGIC_VECTOR (7 downto 0) := "11111111"
);
end entity FSM_Detector_unos;

architecture arq of FSM_Detector_unos is


type estados_type is (E0,E1,E2,E3);--Estados posibles de FSM
signal estados : estados_type := E0;--Estado inicial E0
signal counter : std_logic_vector(16 downto 0) := "00000000000000000";
signal a : std_logic;--Detonador de la alarma
begin

--Determina el valor de a, segun lo que reciba de la señal dato


estados_machine : process(clk)
begin

if clk'event and clk='1' then


if reset='1' then estados <= E0;
alarma <= '0';
else
case estados is
when E0=>
alarma <= '0';
a <= '0';
if dato = '0' then estados <= E0;
elsif dato = '1' then estados <= E1;
end if;

when E1=>
alarma <= '0';
a <= '0';
if dato='0' then estados <= E0;
elsif dato='1' then estados <= E2;
end if;

when E2=>
alarma <= '0';
a <= '0';
if dato='0' then estados <= E0;
elsif dato='1' then estados <= E3;
end if;

when E3=>
if dato='0' then estados <= E0;
elsif dato='1' then
estados <= E0;
alarma <= '1';
a <= '1';
end if;
end case;
end if;
end if;
end process;

--Detector de cambio de a, si esta pasa a 1


--activa speaker
process(clk,a)
begin
if clk'event and clk='1' then
if counter = "00011011101111100100"then
counter <= "00000000000000000";
else
counter <= counter+1;
end if;
if a = '1' then
speaker <= counter(16);
else
speaker <= '0';
end if;
end if;
end process;

end architecture arq;

Generador_seq.vhd
--------------------------------------------------------------------
-- Company: PiQ2 - UPIITA
-- Create Date: 03/26/2022
--------------------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;

entity Generador_seq is
port(
clk,reset : in std_logic;
DIP : in std_logic_vector(3 downto 0);--Entradas del DIPswitch
dato : out std_logic--Salida hacia entidad "FSM_Detector"
);
end entity Generador_seq;

architecture behaviour of Generador_seq is


signal contador : integer := 1;
begin

process(clk)--Lee los valores de los DIPswitch y genera la señal dato


begin

if clk'event and clk='1' then


if reset ='1' then dato<='0';
else
case contador is
when 1 =>
contador<=2;
if DIP(0) = '1' then dato <= '1';
else dato <= '0';
end if;
when 2 =>
contador<=3;
if DIP(1) = '1' then dato <= '1';
else dato <= '0';
end if;
when 3=>
contador<=4;
if DIP(2) = '1' then dato <= '1';
else dato <= '0';
end if;
when 4=>
contador<=1;
if DIP(3) = '1' then dato <= '1';
else dato <= '0';
end if;
when others =>
contador <=1;
end case;
end if;
end if;
end process;
end architecture behaviour;

El esquemático RTL del Top Level Design es el siguiente:

Además, el archivo de restricciones es el siguiente:


NET "clk" LOC = "E7";
NET "reset" LOC = "M2";
NET "DIP(0)" LOC = "M1";
NET "DIP(1)" LOC = "P2";
NET "DIP(2)" LOC = "N5";
NET "DIP(3)" LOC = "T7";
NET "alarma" LOC = "N1";
NET "speaker" LOC = "E3";
NET "AN(7)" LOC = "E11";
NET "AN(6)" LOC = "D11";
NET "AN(5)" LOC = "C15";
NET "AN(4)" LOC = "E15";
NET "AN(3)" LOC = "D16";
NET "AN(2)" LOC = "E16";
NET "AN(1)" LOC = "F16";
NET "AN(0)" LOC = "G16";

El siguiente video muestra el circuito funcionando: https://youtube.com/shorts/XG86Y5mDxEY?feature=share


(a) Se implemento el código en VHDL para controlar 5 posiciones fijas de un servomotor FUTABA
S3003. El código es el siguiente:
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
-- Create Date: 22:06:14 03/22/2022
-- Design Name:
-- Module Name: PWM - Behavioral
----------------------------------------------------------------------------------
--Código para controlar 5 posiciones para un servomotor Futaba S3003

--implementado en la amiba2.

--Se considera una frec. de 100Hz (periodo de 10ms) del PWM.

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

ENTITY PWM is

generic( Max: natural := 500000);

Port ( clk : in STD_LOGIC; --reloj de 50MHz de la FPGA

selector : in STD_LOGIC_VECTOR (2 downto 0); --selecciona las 5 posiciones


pos: out STD_LOGIC_VECTOR(7 downto 0):="11111111"; --salida a display
(posicion 1,2,3,4,5)
an: out STD_LOGIC_VECTOR(7 downto 0):="11110111";-- anodos del display
PWM : out STD_LOGIC); --salida de señal PWM

end PWM;
ARCHITECTURE PWM of PWM is

signal PWM_Count: integer range 1 to Max; --500000;

begin

generacion_PWM:

process( clk, selector,PWM_Count)

constant pos1: integer := 12000; --0°

constant pos2: integer := 40000; --45°

constant pos3: integer := 60000; --90°

constant pos4: integer := 80000; --135°

constant pos5: integer := 105000; -- 180°

begin

if rising_edge(clk)then PWM_Count <= PWM_Count + 1;

end if;

case (selector) is

when "000" => -- 0°


pos<="10011111"; --1

if PWM_Count <= pos1 then PWM <= '1';

else PWM <= '0';

end if;

when "001" => -- 45°


pos<="00100101"; --2

if PWM_Count <= pos2 then PWM <= '1';

else PWM <= '0';

end if;
when "011" => -- 90°
pos<="00001101"; --3

if PWM_Count <= pos3 then PWM <= '1';

else PWM <= '0';

end if;

when "010" => -- 135°


pos<="10011001"; --4

if PWM_Count <= pos4 then PWM <= '1';

else PWM <= '0';

end if;

when "110" => -- 180°


pos<="01001001"; --5

if PWM_Count <= pos5 then PWM <= '1';

else PWM <= '0';

end if;

when others => null; pos<="11101111"; -- _

end case;

end process generacion_PWM;

end PWM; Implementado para la AMIBA2 el UCF es:


NET "clk" LOC="E7";
NET "PWM" LOC="E3";
NET "selector(2)" LOC="M1";
NET "selector(1)" LOC="P2";
NET "selector(0)" LOC="N5";
NET "pos(7)" LOC= P16;
NET "pos(6)" LOC= P15;
NET "pos(5)" LOC= T15;
NET "pos(4)" LOC= T14;
NET "pos(3)" LOC= T13;
NET "pos(2)" LOC= R16;
NET "pos(1)" LOC= R15;
NET "pos(0)" LOC= R14;

NET "an(7)" LOC= E11;


NET "an(6)" LOC= D11;
NET "an(5)" LOC= C15;
NET "an(4)" LOC= E15;
NET "an(3)" LOC= D16;
NET "an(2)" LOC= E16;
NET "an(1)" LOC= F16;
NET "an(0)" LOC= G16;

Se empleo una lampara de mano como carga y se uso la misma como referencia para las cinco posiciones del
servomotor, este se alimentó con los 5v de la FPGA.
A continuación, se muestran las imágenes de las cinco posiciones.

Foto 3.1: posición 1, cero grados


Foto 3.2: posición 2, 45 grados

Foto 3.3: posición 3, 90 grados


Foto 3.4: posición 4 135°

Foto 3.5: posición 5 180°.

En el siguiente enlace puede verse un video del funcionamiento con las cinco posiciones:
https://youtu.be/H0gS4dLEDns
b) Se implemento el código verilog para programar una secuencia de dos posiciones de un servomotor
FUTABA, empleando una lampara como carga. El código quedo como sigue:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 23:03:47 03/23/2022
// Design Name:
// Module Name: Servo_Controler
//////////////////////////////////////////////////////////////////////////////////
module top(
input mclk, //Reloj de la FPGA
output [0:0] Led, //Salida a led
output servo //Señal de salida PWM al servo
);

reg [19:0] counter; //Contador


reg servo_reg;

////////////////////////////////////////////////////////////
//Registros de control ///////////////////////////////////
////////////////////////////////////////////////////////////
reg [15:0] control = 0;
reg toggle = 1;

always @(posedge mclk) //En cada flanco de subida del reloj


begin
//secuencia
counter <= counter + 1;
if(counter == 'd999999)
counter <= 0;

if(counter < ('d50000 + control))


servo_reg <= 1;
else
servo_reg <= 0;

////////////////////////////////////////////////////////////
//Control de la secuencia///////////////////////////////////
////////////////////////////////////////////////////////////

if(control == 'd50000)
toggle <= 0;
if(control == 0)
toggle <= 1;

if(counter == 0)
begin
if(toggle == 0)
control <= control - 1000;
if(toggle == 1)
control <= control + 1000;
end
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////

end

assign Led[0] = toggle;


assign servo = servo_reg;

endmodule

Se implemento para la AMIBA2 por lo que el UCF queda como sigue:


NET mclk LOC=E7;

NET servo LOC=E3;

NET led(0) LOC=M4;

Las siguientes fotos mustran el funcionamiento

Foto 3.6: posición 1 de la secuencia


Foto 3.7: posición 2 de la secuencia

El siguiente enlace muestra el funcionamiento del dispositivo: https://youtu.be/kCkkJSwaqEU

(C) Se programo el código para generar un control de velocidad gradual para un servo sin tope, quedando el mismo
de la siguiente forma:
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
-- Create Date: 22:06:14 03/22/2022
-- Design Name:
-- Module Name: PWM - Behavioral
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity PWM_vel is
Generic(
min:integer:=100000; --mínimo
max:integer:=1000000; --Máximo
inc:integer:=1;
width:integer:=1000000;
N:integer:=11);
port(
clk: in std_logic; --reloj de la FPGA
servo: out std_logic; --Salida al servo
switch1: in std_logic); --Switch de inicio

end PWM_vel;

architecture Behavioral of PWM_vel is --inicio de la arquitectura


--Señales--
signal clkdiv: std_logic_vector(N downto 0);
signal cnt1: integer range 0 to 25000000:= 0;
signal cntPWM1: integer range 0 to width:= 0;
signal high1: integer range min to max := min;
signal PWMservo: std_logic;

begin
servo<=PWMservo;
divisor:process(clk)
begin
if rising_edge(clk) then --por cada flanco de subida de reloj
clkdiv<=clkdiv + 1;
end if;
end process divisor;

tiempocnt:process(clkdiv(N))
begin
if rising_edge(clkdiv(N)) then
if switch1='1' then
cnt1<=cnt1+1;
if cnt1=250000000 then cnt1<=cnt1;
end if;
else cnt1<=1;
end if;

end if;
end process tiempocnt;

pulso:process(clk)
begin
if rising_edge(clk) then
cntPWM1<=cntPWM1+1;
high1<=min+((cnt1)*(inc));
if cntPWM1<=high1 then
PWMservo<='1';
else
PWMservo<='0';
end if;
else null;
end if;
end process pulso;
end Behavioral
Implementado para la amiba2 el UCF queda:

NET "clk" LOC="E7";


NET "servo" LOC="F4";
NET "switch1" LOC="M1"

El el siguiente enlace puede verse un video del funcionamiento del dispositivo: https://youtu.be/hSnO-P1bCDc

Se implemento el un control on-off Con un receptor BT HC-06 conectado a la FPGA como se muestra en la
figura 2.13. A la salida (LOAD) se conectó un ventilador de 12v con fuente externa (baterías 18650) mediante
un transistor 2n222 como switch electrónico, como se muestra en el diagrama 4.1.

Diagrama 4.1: Conexión de salida de PFGA a ventilador 12v.


El circuito queda de la siguiente forma:

El código Verilog empleado para este apartado es el que se muestra a continuación:


`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Create Date: 17:16:39 03/17/2022
// Module Name: HC-05

//////////////////////////////////////////////////////////////////////////////////
module HC_05(

input clk, //50MHz


input reset, //reset
input tx, //entrada de datos del modulo bluetooth
output reg salida=0, //señal de salida
output reg[7:0] leds=8'b00000000, //salida a leds
output reg[7:0] dsply=8'b11111110, //salida a display 7seg
output reg[7:0] anode=8'b11101111 //salida a ánodos
); //fin del módulo receptor

//fsm states
reg [1:0] presentstate, nextstate;
parameter EDO_1 = 2'b00;
parameter EDO_2 = 2'b10;

//señales

reg control=0; //indica cuando ocurre el bit de start


reg done=0; // bandera que indica que termino de recibir los
datos
reg[8:0]tmp=9'b000000000; //registro que recibe los datos enviados

//contadores para los retardos


reg[3:0]i=4'b0000; //contador de los bits recibidos
reg[9:0]c=10'b1111111111; //contador de retardos
reg delay=0; //algoritmo para los retardos
reg[1:0]c2=2'b11;
reg capture=0;

always@(posedge clk)
begin
if(c<868)
c=c+1;
else
begin
c=0;
delay=~delay;
end

end

//proceso para el contador C2 para la captura


always@(posedge delay)
begin
if (c2>1)
c2=0;
else
c2=c2+1;
end

//proceso para capturar en el bit de en medio (capture)


always@(c2)
begin
if (c2==1)
capture=1;
else
capture=0;

end

//FSM actualiza
always@(posedge capture, posedge reset)
if (reset) presentstate <= EDO_1;

else presentstate <= nextstate;


//FSM
always@(*)
begin
case(presentstate)
EDO_1:
if(tx==1 && done==0)
begin
control=0;
nextstate= EDO_1;
end
else if(tx==0 && done==0)
begin
control=1;
nextstate= EDO_2;
end
else
begin
control=0;
nextstate= EDO_1;
end
EDO_2:
begin
if(done==0)
begin
control=1;
nextstate= EDO_2;
end
else
begin
control=0;
nextstate= EDO_1;
end
end
default

nextstate= EDO_1;

endcase
end

//proceso de recepción de datos


always@(posedge capture)
begin
if (control==1 && done==0)
begin
tmp <= {tx,tmp[8:1]};
end
end

//proceso que cuenta los bits que llegan (9 bits)


always@(posedge capture)
begin
if (reset)
begin
// abcdefgP
leds<=8'b00000000;
anode<=8'b11101111;
end
else if (control)

if(i>=9)
begin
i=0;
done=1;
leds<=tmp[8:1];

case (tmp[8:1]) // abcdefgp


8'h31 : dsply <= 8'b00010001; // A apagado
8'h32 : dsply <= 8'b01100001; // E encendido
default : dsply <= 8'b11101111;// _
endcase

case (tmp[8:1])
8'h31 : salida <= 0; // Apagado
8'h32 : salida <= 1; // Encendido
default : salida <= 0;// _
endcase
end
else
begin
i=i+1;
done=0;
end

else

done=0;

end

endmodule

Con un UCF para la amiba2:


Net "clk" LOC = "E7";
Net "tx" LOC = "F4";
Net "reset" LOC = "L1";
Net "salida" LOC ="D6";
NET "leds(7)" LOC = "P1";
NET "leds(6)" LOC = "T4";
NET "leds(5)" LOC = "T6";
NET "leds(4)" LOC = "T9";
NET "leds(3)" LOC = "M12";
NET "leds(2)" LOC = "N6";
NET "leds(1)" LOC = "P9";
NET "leds(0)" LOC = "N12";

NET "dsply(7)" LOC = "P16";


NET "dsply(6)" LOC = "P15";
NET "dsply(5)" LOC = "T15";
NET "dsply(4)" LOC = "T14";
NET "dsply(3)" LOC = "T13";
NET "dsply(2)" LOC = "R16";
NET "dsply(1)" LOC = "R15";
NET "dsply(0)" LOC = "R14";

NET "anode(3)"LOC = "E11";


NET "anode(2)"LOC = "D11";
NET "anode(1)"LOC = "C15";
NET "anode(0)"LOC = "E15";
En el siguiente enlace puede verse un pequeño video del funcionamiento: https://youtu.be/d3dsRB_lxzQ

Conclusiones:
• Santos López Luis Enrique
Esta práctica fue complicada debido a la necesidad de la implementación de circuitos para poder alimentar de
forma externa los dispositivos empleados, ventilador, motor a pasos etc. Así también fue necesario la adquisición
de algunos dispositivos como servos con y sin tope, motor a pasos y sensores, algunos de los cuales, como los
sensores de nivel de agua, no fue posible conseguirlos. El dispositivo HC-06 dio particulares problemas ya que
no todas las apps lo reconocían por lo que fue necesario probar con varias hasta encontrar la más adecuada.
Gracias a esta práctica aprendimos sobre circuitos combinacionales, secuenciales, así como la máquina de
estados, para esto empleamos los códigos tanto VHDL como Verilog implementados para la FPGA AMIBA2.

• Martínez Ríos Jesús Alejandro


En esta práctica se realizaron circuitos combinacionales, secuenciales y máquinas de estado finito, además de
que se implementaron diversos tipos de sensores, que se tuvieron que acoplar para funcionar adecuadamente en
conjunto con la tarjeta de desarrollo FPGA.
Gracias a esta práctica, aprendimos a definir correctamente las máquinas de estado finito en VHDL, y a
distinguir en qué casos resulta conveniente su implementación, o de un circuito secuencial o combinacional.
• Bernal Casas Héctor Obed
Gracias a esta práctica aprendimos a implementar circuitos externos con la FPGA para poder controlar diferentes
dispositivos como motores, bocinas, focos, etc. Era necesario tener conocimiento de electrónica para poder
implementar dichos circuitos externos de manera correcta y evitar dañar la tarjeta. Desafortunadamente durante
la realización del ejercicio del torniquete (1a) la tarjeta de uno de los integrantes del equipo de descompuso, pero
finalmente se logró la implementación del programa y los componentes externos de manera funcional.
• Secundino Vázquez Noé Alejandro
En esta práctica observamos la implementación de circuitos analógicos para poder acondicionar un sensor y otros
componentes como motores, bocinas, focos y módulos bluetooth que serían controlados desde la FPGA con lo
que observamos un espectro más amplio de las funciones que puede tener la tarjeta con el adecuado conocimiento
de electrónica. Gracias a esta práctica aprendimos como se pueden implementar muchos más componentes a
través de el correcto diseño de circuitos analógicos y en cuanto a la programación de la tarjeta para los ejercicios
fue algo sencillo por los conocimientos previos que tenemos, pero ahora adecuando a las entradas que nos ofrecían
los componentes externos implementados en secuencias, entradas serie y paralelas, máquinas de estados y
circuitos combinacionales.

Referencias:
[1] NAYLAMP MECHATRONICS << MÒDULO BLUETOOTH HV06>> [En línea]. Available:
https://naylampmechatronics.com/inalambrico/24-modulo-bluetooth-hc06.html
[Último acceso: 17/03/2022].
[2] Hackeando Tec <<FPGA comunicación RS-323 con el módulo Bluethooth HC05 usando Verilog>> [En línea].
Available: https://www.youtube.com/watch?v=tpajglbrd-
A&list=PLIyIZGa1sAZqeQJ6Y02b7O8HV0gK25zc2&index=27 [Último acceso: 17/03/2022].
[3] Boletín UPIITA <<Control de posición de un servo utilizando Nexys2 y VHDL>> [En línea]. Available:
https://www.boletin.upiita.ipn.mx/index.php/ciencia/211-cyt-numero-29/214-control-de-posicion-de-un-
servomotor-utilizando-la-tarjeta-de-desarrollo-nexys-2-y-vhdl [Último acceso: 23/03/2022].
[4] Boletin UPIITA <<Control de servomotor con encorder mecánico rotatorio >> [En línea]. Available
https://www.areatecnologia.com/electricidad/servomotor.html [Último acceso: 23/03/2022].

También podría gustarte