lunes, 9 de diciembre de 2013

Hercules Launchpad #1 - LED Parpadeante (Project 0)

Pues a penas me compré un Hercules Launchpad en Newark y les voy a enseñar lo que he aprendido. Este tutorial se consistirá en hacer parpadear uno de los LEDs que trae la tarjeta utilizando los timers que tiene el procesador.

Nota 1: para comenzar a desarrollar en esta tarjeta hay que instalar el compilador/debugger de Texas Instruments llamado Code Composer Studio. A mi me costó un chin*** instalarlo, pero (por si les interesa) lo logré instalar estando en el modo seguro de Windows. Este programa es gratis para desarrollar en esta tarjeta sin límites de ningún tipo.
También necesitarán de una herramienta llamada HALcoGen (HAL Code Generator). Este también es un programa de Texas Instruments (gratuito) y lo que hace es que genera todos los archivos de configuración por nosotros.

Paso 1:
Debemos abrir el mítico HALcoGen y nos va a aparecer lo siguiente


Después le damos en File -> New -> New Project y seleccionamos la familia y el procesador correspondiente. Le damos un nombre y la ubicación y dado que vamos a usar Code Composer Studio, en Tools seleccionamos "Texas Instruments Tools" y le damos "Ok".


Paso 2:
Nos va a aparecer una ventana medio friki con un montón de pestañas. Para este tutorial debemos ir a la pestaña de "Driver Enable" y desmarcamos todas las cajitas y marcamos solo la que dice HET. Les debe quedar así



Nota 2: HET significa High End Timer y es una especie de subsistema que controla todo lo que tenga que ver con timers. Este módulo posee 30 poderosas instrucciones para ser controlado.

Continuemos....

Paso 3:
Ahora nos vamos a la pestaña que dice HET. Como podrán ver, aquí es donde se configura todo lo del timer. Vamos a configurar un PWM para poder prender un LED con un periodo de 1 segundo. Para esto nos vamos a la pestaña que dice "Pwm 0-7" y ponemos el periodo del primer PWM de 1'000,000us con un ciclo de trabajo del 50% para que podamos ver que si funciona. Luego le damos clic en el cuadrito de enable con salida al pin 8, que es el pin al cual está asignado uno de los LEDs.


Paso 4:
Ahora lo que hay que hacer es habilitar el pin 8 para que funcione como salida. Para eso nos vamos a la pestaña que dice "Pin 8-15" y marcamos la cajita que se encuentra junto a "DIR:". Esto habilita el pin como salida.



Paso 5:
Ya con esto hemos configurado todo. Ahora hay que generar el código en File -> Generate code o tecleando F5. Ya que generamos el código, abrimos Code Composer Studio. Cuando nos pregunte por el Workspace, le decimos que sea en la dirección exacta donde se generó nuestro código. Luego nos vamos a Project -> New CCS Project. En el nombre del proyecto hay que escribir el nombre que usamos en HALcoGen. En la variante seleccionamos "Cortex R" y "RM42L432" y en la conexión seleccionamos "Texas Instruments XDS100v2 USB Emulator". Por último, seleccionamos la opción de "Empty Project".


Paso 6:
Ya que creamos nuestro proyecto, hay que configurarlo para que funcione con el código que generamos en HALcoGen. Para esto, nos vamos a "Project Explorer" y le damos clic derecho a la carpeta con el nombre de nuestro proyecto y luego a propiedades. En la ventana que aparece nos vamos a Build -> ARM Compiler -> Include Options y en el cuadro que dice "Add dir to #include search path" le damos clic en "Add". En la ventana que aparece le damos clic en Workspace y seleccionamos la carpeta "Nombre_del_proyecto" -> include.


Le damos a OK a las dos ventanas y en las propiedades nos vamos a "General" y verificamos que donde diga "Runtime support library" esté la opción de "automatic".

Paso 7:
Ahora si nos vamos a programar. Abrimos el archivo "sys_main.c" que se encuentra en la carpeta "source" y vemos que nos aparece un poco de código ya escrito.

Nota 3: Todos los archivos que genera HALcoGen tienen secciones de comentario que dicen 
/* USER CODE BEGIN (0) */
/* USER CODE END */
Nuestro código debe ir en estas secciones. Esto es porque es posible que tengamos que regresar a HALcoGen varias veces para cambiar algo y volver a generar el código. HALcoGen va a reescribir todo el código que no se encuentre dentro de estas secciones. Por eso es importante escribir nuestro código dentro de estos espacios.

Sigamos...

En el USER CODE BEGIN (0) hay que incluir la librería del HET. para esto escribimos

/* USER CODE BEGIN (0) */
#include "het.h";
/* USER CODE END */

Luego, en el USER CODE BEGIN (3), que es el código principal, hay que inicializar el HET. Esto se hace con la instrucción hetInit(). Por último, hacemos que nuestro código no termine con un while(1). Al final se debe ver algo así

void main(void)
{
/* USER CODE BEGIN (3) */
hetInit();
while(1);
/* USER CODE END */
}

Paso 8:
Ya que escribimos nuestro código, podemos cargarlo al microcontrolador y "debuggearlo". Esto se hace en Run -> Debug o picándole en el bichito verde. Una vez que ya se cargó el programa podemos comenzar a correrlo dándole clic en Resume (F8) y verán la magia de los sistemas embebidos hacer lo suyo.


Y pues esto ha sido todo. Eventualmente iré subiendo tutoriales de cosas más cool, ya que esta tarjeta da para mucho (deja al Arduino y todos esos micros muy muy atrás).

Por si les interesa, aquí les dejo el link de Newark

Y les dejo el link para descargar los archivos de este tutorial
http://www.mediafire.com/download/ujg9jqjc04nrjdh/Tutorial%201.zip

My Github
https://github.com/DiegoRosales

sábado, 2 de noviembre de 2013

Tutorial: cómo crear sub circuitos en OrCAD en 12 simples pasos

Ok, esto va a ser largo, así que al punto. Quieres crear una librería con sub circuitos para usarlos en tus otros circuitos y nomás no hallas cómo. Pues ahí te va.

Paso 1
Crea un nuevo proyecto en OrCAD y llámalo como gustes




Paso 2
Arma el circuito que quieras configurar como sub circuito




Paso 3
Añade los puertos de entrada y de salida en Place -> Hierarchical Port y renómbralos.
Estas serán los puertos de tu sub circuito





Paso 4 (opcional)
Renombra tu proyecto




Paso 5
Crea un netlist en Tools -> Create Netlist...





Dale clic en Aceptar y espera a que se cree. Puede que te aparezca un Warning como este



Esto quiere decir que no pusiste ninguna tierra en tu circuito, pero no pasa nada.


Paso 6
Crea la parte en Tools -> Generate Part y al final cambia lo que gustes y dale clic en Save (que onda con el spanglish de esta cosa, ¿verdad?)






Paso 7
Una vez que ya hayas creado tu sub circuito, vamos a modificar su apariencia.
En Outputs va a aparecer tu circuito con extensión .OLB. Expándelo y en el archivo que aparece dale clic derecho y pícale en Edit Part.



Te va a aparecer algo así



Ahora dale vuelo a tus dotes artísticos y dibuja tu cajita como se te antoje y al final guarda todo.


Paso 8
Ahora que ya tienes tu sub circuito bien chulo, vamos a probarlo.
Crea un nuevo proyecto con otro nombre





Paso 9
Ahora, del lado derecho aparece un cuadrito para añadir una librería. Dale clic en ese cuadrito y busca lo que se generó del archivo anterior. Es un archivo con extención .OLB




Ahora vamos a añadirle una fuente de prueba y una resistencia al final



Paso 10
Crea un nuevo perfil de simulación y añádele los parámetros que quieras.




Paso 11
Ahora vete a la pestaña que dice Options y en la categoría que dice Library, dale clic en Browse. Ahora busca el archivo .LIB que también se generó hace rato y dale clic en Add to Design. Esto lo vas a tener que hacer cada vez que quieras usar una nueva librería. Supongo que si le das clic en Add as Global, sólo lo tendrás que hacer una vez, pero no lo he probado.






Paso 12
Una vez añadido el diseño, podemos correr la simulación


¡Pero que chulo ha quedado! Ahora puedes hacer todo lo que se te antoje con tu sub circuito.

Por cierto, estoy usando la versión 16.3 de OrCAD.

Aquí les dejo los archivos de la simulación y del sub circuito

http://www.mediafire.com/?job5ommy94e74xl

domingo, 27 de octubre de 2013

Bloques lógicos útiles en VHDL #4 RAM basada en LUTs (asíncrona)

Como ustedes sabrán (o no), hace como 10 minutos aprendí que practicamente todos los FPGAs tienen unos módulos especiales para almacenar datos y leerlos. A estos módulos en inglés se les llama "Look Up Table" o LUT. Esto en cristiano significa algo así como "Ve a ver si ya puso la marrana", pero pues a pesar de que esto lo decimos con el fin de que se vayan a dejar de "molestar", ya que muy probablemente la marrana no ha puesto nada, en el mundo de los FPGAs, la marrana muy probablemente ya puso algo que necesitamos. El caso es que estos módulos almacenan datos y los podemos usar y ordenar como queramos. Un dato importante es que a este tipo de memoria, también se le llama RAM distribuida (Distributed RAM). Para el caso del Spartan 3E, que es el que usa el Basys2, esta memoria varía entre 15 y 38Kbytes, dependiendo cuánto quieras pagar.

Usar esta RAM es algo realmente fácil, y lo hacemos todo el tiempo cuando almacenamos constantes y cosas así, pero ahora la vamos a usar como se debe (más o menos). En estos ejemplos vamos a construir un bloquecito de RAM de 8x8 (8 registros de 8 bits). Este ejemplo es cuando queremos leer la RAM de manera asíncrona. Más adelánte postearé un tutorial de RAM con lectura síncrona

RAM Asíncrona

Primero comenzamos con la declaración de librerías y de puertos.
























Necesitamos declarar ciertas constantes para que nuestro código se pueda adaptar fácilmente. Los puertos que necesitamos son la dirección de la memoria, el dato a enviar, una señal que nos indique cuándo podemos escribir y por último la lectura de la memoria en la dirección deseada.

Ahora nos vamos a la parte de la arquitectura. El truco aquí es crear una matriz de datos (8x8), por lo que necesitamos declarar un nuevo tipo. Llamémosle "tipo_ram". También hay que declarar una señal con este tipo









Por último hay que declarar la manera en la que se va escribir y accesar la memoria.














Nótese que la escritura es síncrona y está controlada por la entrada "escribir". Si esta entrada esta en '0', no escribe y nada más lee. Hay que realizar cambios de tipos, ya que la entrada "dir" esta en "std_logic_vector", pero el índice de la variable "ram" que es "tipo_ram" debe ser "integer".


Como pordán ver la simulación funciona de maravilla. El dato se escribe cuando tenemos un flanco positivo en el reloj y cuando "escribir" es '1'.

Este ejemplo lo saqué de un libro titulado "FPGA Prototyping by VHDL Examples - Xilinx Spartan 3 Version", aunque le modifiqué algunas cosas, como el tamaño de el bloque de la RAM.

Ahora les dejo el código .vhd y los archivos de la simulación

Código .vhd


Simulación usando ActiveHDL


My Github
https://github.com/DiegoRosales

sábado, 26 de octubre de 2013

Bloques lógicos útiles en VHDL #3 Control de sincronización para VGA

Ok, ahora les voy a enseñar como hacer un controlador VGA usando un FPGA para que con base en eso puedan mandarle cualquier imagen a un monitor. Lo primero es entender las señales. Los monitores VGA trabajan con 5 señales básicas: la señal de sincronía vertical, la señal de sincronía horizontal, la señal del color rojo, la señal del color verde y la señal del color azul (RGB). 

Las señales de los colores son analógicas y varían entre 0 y 0.7V. Entre más voltaje, más brillante es el color. Haciendo combinaciones con los tres colores, se puede representar cualquier imagen.

Por otro lado, las señales de sincronía funcionan de la siguiente manera. El monitor va "imprimiendo" cada pixel de izquierda a derecha y de arriba hacia abajo, como se ve en la siguiente imagen



Por lo tanto, tiene que haber alguien que le diga cuándo empieza y cuándo termina. Este alguien son las señales de sincronización vertical y horizontal, y funcionan así.


Tanto la señal horizontal como la señal vertical tienen este formato. La señal comienza con un pulso de sincronización (Sync Pulse). Luego pasa a un "tiempo de espera" llamado Back Porch. Durante el Sync Pulse y el Front Porch, no se despliega ninguna imagen, y es recomendable no mandar a desplegar nada en ese momento. Después de que el pasó el Sync Pulse y el Back Porch, comienza el área visible. Aquí es el momento de comenzar a mandar la imagen. Una vez que termina de mandarse la imagen, se llega a un segundo tiempo de espera llamado Front Porch. Terminando este tiempo, la señal vuelve a comenzar.

Si tenemos un monitor de X pixeles de ancho por Y pixeles de alto, la señal de sincronización horizontal se debe mandar Y veces por cada vez que se refresca la pantalla (una por cada línea). Es decir, si tenemos un monitor de 640x480 pixeles, la señal de sincronización vertical se debe mandar 480 veces por cada señal de sincronización horizontal.

Ahora se estarán preguntando ¿cuánto deben durar estas señales?
Pues la respuesta varía según dos factores: la resolución que deseamos lograr y la frecuencia de actualización de nuestro monitor. La mayoría de los monitores utilizan una frecuencia de 50 o 60Hz, pero las resoluciones pueden variar mucho.

El motivo de estas señales que pueden llegar a ser hasta cierto punto ambiguas, es debido a la tecnología que usaban los monitores CRT. Ahora ya casi nadie usa estos monitores, pero el protocolo VGA sigue siendo bastante popular y prácticamente no ha cambiado.

Aquí es va el ejemplo. Vamos a utilizar una resolución de 640x480 pixeles a una frecuencia de 60Hz. Si se meten a este link (http://tinyvga.com/vga-timing/640x480@60Hz) encontrarán una tabla muy útil que es esta


Se darán cuenta que el Sync Pulse, el Front Porch y todas las partes de la señal se miden en pixeles. Esto facilitará impresionantemente nuestro código. Cabe destacar que aunque dice que necesitamos una frecuencia de pixeles de 25.175MHz, no es necesario generar esa frecuencia exacta, ya que los monitores modernos se pueden acoplar a tan sólo 25MHz. Sin embargo, si se va a usar un monitor viejo, pues sí hay que generar esa frecuencia exacta.

Pues bien, comencemos con el código. Este código está planeado para una tarjeta de desarrollo Basys2 con un FPGA de Xilinx modelo Spartan 3E y un reloj de 50MHz. Esta tarjeta cuenta con un puerto VGA, que internamente tiene un convertidor digital a analógico de 3 bits para el color rojo y el color verde y de 2 bits para el color azul, teniendo un total de 256 posibles colores.

Primero los puertos y las librerías

La única entrada es la señal de reloj de 50MHz.
Las salidas son las señales de sincronización horizontal y vertical, una señal que nos indique en qué momento comienza el área visible, una cuenta de pixeles en X y en Y, y el reloj de 25MHz para que esté todo bien sincronizado.

Ahora siguen las constantes que vamos a usar

Estas constantes son los datos de la tabla de hace un momento

Ahora siguen las señales internas


Ahora comenzamos con el divisor de frecuencia (de 50 a 25 MHz)

Luego, con esta nueva frecuencia, pasamos a hacer un contador horizontal y un contador vertical. Cada vez que el contador horizontal llegue a su límite, el contador vertical aumenta 1

Ahora viene la parte que manda el pulso de sincronización y la parte donde detecta cuándo comienza la parte visible de la señal

Finalmente viene la parte donde la cuenta horizontal y vertical del área visible comienza (aquí es donde se cuenta en qué pixel del área visible nos encontramos), y las asignaciones de las señales.

Como podrán ver, si lo implementamos en el FPGA, obtenemos estas señales (arriba es la horizontal y abajo es la vertical)


Señal horizontal completa


Pulso de sincronización vertical


Pulso de sincronización horizontal

Y pues si hacemos un código de prueba que despliegue 3 colores verticales, obtenemos el siguiente resultado



Y pues bueno, aquí les dejo los códigos de la simulación en Active HDL y del proyecto completo del Xilinx ISE Design Suite. Incluyen la imagen de prueba.

Simulación


Proyecto


Puro código de sincronización


My Github
https://github.com/DiegoRosales

jueves, 24 de octubre de 2013

Dimmer controlado con aplausos (clap controlled dimmer)

Este es un proyecto que hice con unos compañeros para la materia de electrónica industrial. Consiste en realizar el control de la intensidad de la luz de un foco incandecente de 100W únicamente aplaudiendo. Les voy a compartir el reporte que le entregamos al profesor, pero como la materia es impartida en inglés, el reporte también está en inglés y me da mucha flojera traducirlo. Sólo les pondré lo básico. Lo que utilizamos fue un SCR (era requisito del proyecto) para controlar la cantidad de energía que es transferida al foco. El diagrama a bloques básico es este.


El chiste es sincronizar la señal de activación del SCR con el voltaje de la linea eléctrica. Esto es necesario ya que si no se hace, la señal que se le manda al SCR no coincidirá siempre con el semiciclo positivo de la línea, y si llegase a coincidir, ésta no siempre se mandaría en la misma parte del semiciclo positivo de la señal. Es decir, el foco estaría parpadeando todo el tiempo. Es por esto que fue necesario el detector de cruce por cero.

Hay un montón de circuitos en internet para realizar la detección del cruce por cero, ya que para muchas aplicaciones es muy importante (como ésta jaja), pero la mayoría de ellas requieren ya sea transistores (que a mi me cuesta mucho trabajo usarlos) o amplificadores operacionales con entrada bipolar (que no quería usar, ya que queríamos utilizar únicamente los 5V que tiene el Arduino) o cosas medio bizarras. Es por esto que nosotros "inventamos" nuestro propio sistema de detección utilizando las bondades del Arduino Duemilanove. Nuestra solución fue bajar el voltaje de la línea a algo razonable (3V aprox), rectificarlo con un rectificador de media onda (para no causar problemas con los voltajes negativos) y meterlo al ADC del Arduino con una resistencia limitadora de corriente. Entonces el Arduino analiza la señal y determina cuándo está en la parte positiva de la señal y cuándo en la parte negativa. Ojo que para esto, necesitamos muestrear la señal de la línea lo más rápido posible que es 5kHz (en realidad lo más rápido son 10kHz, pero ahorita les cuento qué pasa). A pesar de que el teorema de Nyquist nos dice que necesitamos una frecuencia de muestreo del doble de la frecuencia más grande de nuestra señal para evitar el aliasing (que en este caso sería 2x60=120Hz), necesitamos sobremuestrear la señal para saber con precisión y en todo momento en qué parte de la señal nos encontramos, para poder mandar una señal precisa al SCR que no ande variando. Esto implica que para depurar y optimizar el programa, necesitamos una velocidad de comunicación serial muy grande con la computadora (de 115200 baud/seg, en vez de los típicos 9600).

Para la detección del aplauso, íbamos a usar uno de esos micrófonos electret de condensador, pero resultaron ser basura para lo que queríamos. Por eso usamos un micrófono de computadora que nos sirvió de maravilla. Curiosamente estos micrófonos requieren un circuito de polarización y acoplamiento, mismo que obtuvimos de esta página http://www.hobby-hour.com/electronics/computer_microphone.php y pues nos sirvió a la primera. Por supuesto que de la salida del circuito lo mandamos a un buffer (que quién sabe si era necesario) y a un amplificador de ganancia como de 3, y de ahí a otro ADC del Arduino para que éste determine cuando hubo aplauso o no.

Finalmente, con la detección de los aplausos y la detección del cruce por cero de la línea, el Arduino genera un pulso cuya duración que va a depender del número de aplausos detectados hasta el momento y de la detección del cruce por cero (los detalles están en el reporte ;D). El caso es que este pulso va a un optoacoplador con salida SCR, que va a permitir que el segundo SCR (de potencia) se active con la misma señal de la línea, como es común para este tipo de circuitos.

El resultado final fue este


En la parte de arriba está el voltaje en el SCR y en la parte de abajo está la corriente en el foco. Nuestro circuito (que se ve un poco desastroso fue este)


Aquí les dejo el link del reporte y del código para el Arduino

Reporte


Código del Arduino


My Github
https://github.com/DiegoRosales

jueves, 10 de octubre de 2013

Bloques lógicos útiles en VHDL #2 - Contador de 1 bit (divisor de frecuencia)

Bueno, ahora les mostraré cómo se puede hacer un contador de 1 bit por si quieren dividir su señal de reloj entre 2 o cualquier cosa que necesiten. Este es un contador utilizando los muy útiles FlipFlops tipo D con Clear y Chip Enable (FDCE). Les enseño el circuito


El código para implementar este circuito es muy sencillo. Se los muestro

library IEEE;
use IEEE.std_logic_1164.all;

library UNISIM;
use UNISIM.vcomponents.all;

entity contador_1bit is
port(
CK1: in std_logic; -- Reloj de entrada(50MHz)
CK2: out std_logic -- Reloj de salida (25MHz)
);
end contador_1bit;

architecture contador_1bit of contador_1bit is

signal notQ, temp_Q: std_logic; -- Crea las señales a utilizar
begin
bit0: FDCE generic map ('0') -- Comienza en 0
port map (C=>CK1, D=>notQ, Q=>temp_Q, CE=>'1', CLR=>'0');         -- Asigna los pines  
notQ<=not temp_Q; 
      -- Niega la salida del FDCE y la regresa a la entrada
CK2<=temp_Q; -- Asigna la salida
end architecture;

Como podrán ver, hice uso del FDCE que vimos la vez anterior. Con esto ya no tenemos que construir nuestros Flip Flops, pues ya vienen hechos. Para que vean que sí funciona, les enseño la simulación.


Les dejo los archivos que utilicé en mi cuenta de MediaFire.

domingo, 6 de octubre de 2013

Bloques lógicos útiles en VHDL #1 - Flip Flop tipo D con Clear y Chip Enable (FDCE)

Como ahora ando metido en esto de los FPGAs, he decidido comprartirles unos cuantos códigos útiles que pueden utilizar en sus diseños a bloques. Este primer código es un Flip Flop tipo D con habilitador (Chip Enable), Reset (Clear) asíncrono y entrada de reloj.
Si se dan cuenta (y con mucha imaginación), el nombre de este Flip Flop se puede simplificar como FDCE. Recuerden esto, pues les será muy útil después. El circuito es este:



Como podrán ver, tiene una entrada "D", una salida "Q", un habilitador "CE", un reset asíncrono "CLR" y una entrada de reloj (el triangulito). Es bastante básico, pero muy útil.

Este es el código.



library IEEE;
use IEEE.STD_LOGIC_1164.all;  

entity FDCE is
generic (INIT :std_logic:='0'); -- El Flip Flop inicia en 0
port(CE, CLR, C, D: in std_logic;
Q: out std_logic);
end FDCE;

architecture FDCE of FDCE is
signal temp: std_logic :=INIT;
begin
process (CLR, C)
begin
if(CLR='1') then -- Clear asíncrono
temp <='0';
elsif(CE='1' and C' event and C='1') then -- Si hay una señal de reloj con flanco positivo, Q obtiene el valor de D
temp <=D;
end if;
end process;
Q<= temp;
end FDCE;


Aquí les dejo una captura de la simulación en Active-HDL para que vean que sí funciona


Ahora lo padre de este Flip Flop es que en prácticamente todos los FPGAs viene ya construido y es muy fácil hacerlo funcionar sin necesidad de escribir este código. Lo único que tienen que hacer es instanciarlo y ya. Ni siquiera lo tienen que declarar como componente. Aquí les va un ejemplo usando las librerías de Xilinx para un Spartan 3E.

library IEEE;
use IEEE.STD_LOGIC_1164.all; 

library UNISIM;
use UNISIM.vcomponents.all;

entity FDCE_Xilinx is
port(
CK, D, CE, CLR: in std_logic;
Q: out std_logic
);
end FDCE_Xilinx;


architecture FDCE_Xilinx of FDCE_Xilinx is
begin

FlipFlop: FDCE generic map('0') -- Comienza en 0
port map (C=>CK, D=>D, CE=>CE, CLR=>CLR, Q=>Q);

end FDCE_Xilinx;

Como podrán ver, estoy utilizando una librería adicional que es la UNISIM. Esta librería es de Xilinx y está hecha para instanciar un montón de cosas en sus FPGAs, entre ellas este FlipFlop llamado FDCE (como el nombre que convenientemente le puse al otro código!!). Existe una muy buena documentación sobre todo lo que trae esta librería. Les dejo el link de la info para el Spartan 3.

Los archivos del Active-HDL también los pueden bajar de mi cuenta de MediaFire. Les dejo el link.

My Github
https://github.com/DiegoRosales

Saludos!!