Skip to content

Vídeo 30: Puerto serie

Juan Gonzalez-Gomez edited this page Dec 9, 2018 · 534 revisions

Vídeos

Este tutorial es más largo, y se ha divido en varios vídeos

Parte I: Puesta en marcha

Click to see the youtube video

Parte II: Transmisor serie de 8 bits

Click to see the youtube video

Parte III: Transmisor serie de múltiples caracteres

Click to see the youtube video

Parte IV: Funcionamiento del transmisor múltiple

Click to see the youtube video

Parte V: Funcionamiento del transmisor de 8 bits

Click to see the youtube video

Parte VI: Receptor serie

Click to see the youtube video

Parte VII: Funcionamiento del receptor

Click to see the youtube video

Parte VIII: Transmisor y receptor

Click to see the youtube video

Parte IX: Aplicación 1. Comunicación Arduino-FPGA

Click to see the youtube video

Parte X: Aplicación 2. Comunicación de nuestros programas en el PC con la FPGA

Click to see the youtube video

Parte XI: Aplicación 3. Comunicación Bluetooth-serie con la FPGA

Click to see the youtube video

Parte XII: Ejercicios

Click to see the youtube video

Descripción

El puerto serie nos abre la posibilidad de comunicar el PC y el móvil con nuestros circuitos en la FPGA. Aprenderemos a usar el transmisor y receptor serie, sus fundamentos internos y veremos ejemplos de aplicación

Colección

Academia-Jedi-HW-30.zip: Colección para este tutorial. Descargar e instalar

Contenido

Introducción

Una forma sencilla de comunicar nuestros circuitos de la FPGA con el PC es usando el Puerto serie. Se trata de comunicaciones serie ASÍNCRONAS y se usan muchísimo en los dispositivos. Con ellas nos podemos comunicar también con otros dispositivos, como bluetooth-serie, Arduinos, microcontroladores, etc

Se utiliza un único cable de datos para cada sentido. El pin por el que sale la información se llama TX, y por el que entra RX. No hay un cable con la señal de reloj, como en las comunicaciones serie síncronas que vimos en el tutorial anterior. La velocidad se acuerda a priori

Este es el esquema típico de conexión de dos dispositivos. Las velocidades de comunicación están estandarizadas, y se deben acordan a priori entre los dispositivos. Tipicamente se usan 9600 ó 115200 baudios (pero hay más). En este contexto, un baudio equivale a una velocidad de 1 bit por segundo (bps)

Cuando hablamos de puerto serie en el PC, nos estamos refieriendo usualmente a la Norma RS-232, que además de las comunicaciones serie asíncronas, define más cosas, como por ejemplo 6 cables de control, que son opcionales: DTR, RTS, CTS, DSR, DCD y RI

Estos cables de control son muy útiles. La señales DTR o RTS, por ejemplo, se usan en las placas de Arduino para que el PC haga un reset de la placa, para activar el bootloader y cargar el programa. Nosotros los podemos usar en nuestros circuitos como pines de E/S genéricos, con el PC

Los ordenadores modernos no tienen los conectores del puerto serie. Pero como se sigue usando mucho, han aparecido unos chips que son USB-serie: se conectan al PC por el USB y nos ofrecen todas las señales del puerto serie. Los más extendidos son los del fabricante FTDI

En la Icezum Alhambra se usa el chip FT2232H que ofrece dos interfaces a través del USB. Uno de comunicaciones serie síncronas (bus spi) para realizar la carga de los circuitos y otro de puerto serie, realizando la conversión USB-serie y dando acceso a las señales de la norma RS-232 desde la FPGA

Desde los pines de la FPGA se tiene acceso a las señales TX y RX para la trasmisión/recepción de datos, así como a las señales de control DTR, RTS, CTS, DSR y DCD. De estas, dos son de entrada (PC->FPGA) y tres de salida (FPGA->PC)

En Icestudio accedemos a los pines del puerto serie seleccionando la etiqueta con el nombre de la señal: TX y RX para las señales de datos, y DTR, RTS, CTS, SDR y DCD para las de control

Puesta en marcha

Para empezar a trabajar con el puerto serie necesitamos instalarnos un terminal de comunicaciones, desde el que enviar datos a nuestros circuitos en la FPGA y en el que visualizar la información recibida de ellos. Haremos pruebas para comprobar que funciona correctamente, antes de diseñar nuestros circuitos

Terminal de comunicaciones

Se puede utilizar cualquier terminal de los que existen, en cada sistema operativo. En este tutorial usaremos dos: el Arduino-Ide (1.8.7) y el ScriptComunicator (5.09), que son libres y multiplataforma

Instalación de Arduino-IDE

Los pasos concretos de instalación dependen del sistema operativo usado. En general, los pasos son:

  • Acceder a la web del Arduino-IDE
  • Descargar el fichero de instalación del entorno para tu sistema operativo
  • Ejecutar el fichero de instalación
  • Lanzar el entorno

GNU/Linux Ubuntu 18.04

Si eres usuario de Linux habitual de linux, lo instalarás sin problemas siguiendo las instrucciones anteriores. Aquí voy a poner las instrucciones para hacerlo desde la interfaz gráfica, para usuarios que saben poco a nada de Linux

  • Paso 0: Configura el navegador de archivos (Nautilus) para poder ejecutar programas haciendo doble click desde la interfaz gráfica. Esta opción no está activada por defecto
    • Abrir el navegador de archivos
    • Abrir las preferencias desde el menú Archivos/preferencias (Files/preferences)
    • Seleccionar la pestaña comportamiento (Behavior)
    • Activar la opción "Preguntar qué hacer" (Ask what to do) en "Ficheros ejecutables de texto" (Executable Text Files)

  • Paso 1: Descarga el fichero arduino-1.8.7-linux64.tar.xz (o la última versión) desde la web de Arduino

  • Paso 2: Descomprimir el fichero arduino-1.8.7-linux64.tar.xz. Por defecto tendremos el fichero en la carpeta de Descargas (Downloads). Navegamos a esa carpeta y sobre el archivo arduino-1.8.7-linux64.tar.xz apretamos el botón derecho del ratón y seleccionamos la opción: extraer aquí (extract here)

Como el archivo es grande, esta acción tardará unos 15 segundos o más (dependiendo de nuestro ordenador). Al cabo de ese tiempo nos aparecerá la carpeta arduino-1.8.7-linux64

  • Paso 3: Arrancar el entorno de Arduino. Entramos en la carpeta arduino-1.8.7-linux64, damos permisos de ejecución al fichero arduino y hacemos docle click en él. En la ventana que aparece pinchamos en "Ejecutar" (Run)

Nos aparecerá la ventana principal del entorno de arduino:

  • Paso 4 (Opcional): Instalación del Entorno de arduino. Si lo vamos a usar mucho, es mejor tenerlo instalado en el sistema, y añadirlo en la barra de aplicaciones favoritas. Lo único que tenemos que hacer es ejecutar el archivo install.sh

¡Ya está instalado! :-) Para arrancarlo pinchamos en el icono para mostrar las aplicaciones (abajo a la izquierda)

y nos ahí nos aparecerá el Arduino Ide. Lo arrancamos pinchando en su icono. Opcionalmente, una vez arrancado, lo podemos añadir a favoritos para que se quede anclado en la barra de aplicaciones

Windows 10

  • Paso 2: Descargar el fichero arduino-1.8.7-windows.exe, que nos aparecerá al pinchar en la opción Just Download

  • Paso 3: Ir a la carpeta de Descargas y ejecutar el instalador (arduino-1.8.7-windows.exe)

Al ejecutarlo aparecerá la siguiente pantalla de aviso. Pinchamos en

Aparece la siguiente pantalla: Pinchamos en I Agree

Por defecto dejamos que se instale todo. Pinchamos en Next

El Entorno se instala en C:\Program Files(x86)\Arduino\. Dejamos esa ubicación por defecto y pinchamos en Install

Comienza la instalación de los ficheros. Este proceso puede tardar unos minutos. Al terminar pinchamos en Close

  • Paso 4: Abrir el entorno. En el escritorio aparecerá el icono de Arduino. Pinchamos y lo ejecutamos. Nos aparecerá la pantalla principal:

¡Ya lo tenemos instalado y listo para usar!

Instalación del ScriptCommunicator

Los pasos concretos de instalación dependen del sistema operativo usado. En general, los pasos son:

  • Acceder a la web del ScriptCommunicator
  • Descargar el fichero de instalación del entorno para tu sistema operativo
  • Ejecutar el fichero de instalación
  • Lanzar el entorno

ScriptCommunicator en Gnu/Linux Ubuntu 18.04

Si eres usuario de Linux habitual de linux, lo instalarás sin problemas siguiendo las instrucciones anteriores. Aquí voy a poner las instrucciones para hacerlo desde la interfaz gráfica, para usuarios que saben poco a nada de Linux

  • Paso 0: Configura el navegador de archivos (Nautilus) para poder ejecutar programas haciendo doble click desde la interfaz gráfica. Esta opción no está activada por defecto. Sigue las mismas instrucciones del paso 0 de la instalación del Arduino IDE, si no lo has hecho ya

  • Paso 1: Descarga el fichero ScriptCommunicator_05_09_linux_64_bit.zip (o la última versión) desde la web del ScriptCommunicator

  • Paso 2: Descomprimir el fichero ScriptCommunicator_05_09_linux_64_bit.zip. Por defecto tendremos el fichero en la carpeta de Descargas (Downloads). Navegamos a esa carpeta y sobre el archivo ScriptCommunicator_05_09_linux_64_bit.zip apretamos el botón derecho del ratón y seleccionamos la opción: extraer aquí (extract here). Nos metemos en la carpeta ScriptCommunicator_05_09_linux_64_bit

  • Paso 3: Arrancamos el script communicator. Entramos en la carpeta ScriptCommunicator_05_09_linux_64_bit, damos permisos de ejecución al fichero ScriptCommunicator.sh y hacemos docle click en él. En la ventana que aparece pinchamos en "Ejecutar" (Run)

Nos aparecerá la ventana principal del ScriptCommunicator:

¡Ya lo tenemos listo para usar!

ScriptCommunicator en Windows 10

La zona de descarga se encuentra en la parte final de la web:

Pincha en la primera opción: Windows. Aparecerá una web nueva y al cabo de unos segundos podremos comenzar la descarga

Paso 2: Descomprime el fichero y ejecuta el instalador

En la carpeta de Descargas tenemos el fichero ScriptCommunicatorSetup_05_09_windows.zip

Nos situamos encima del fichero, y apretamos el botón derecho del ratón. Pinchamos en la opción Extraer todo

Se crea la carpeta ScriptCommunicatorSetup_05_09_windows y dentro de ella está el instalador

Ejecutamos el instalador como administrador, situándonos encima y pinchando con el botón derecha. Elegimos la opción Ejecutar como Administrador

En algunos equipos nos puede aparece un mensaje de advertencia, en el que se impide la ejecución del instalador (Windows es muy pesado)

Pinchamos en más información y luego en Ejecutar de todas formas

...Y nos aparece un nuevo mensaje de advertencia (Windows es cansino, cansino...). Pinchamos en

Ya por fin arranca el instalador. El programa se instala por defecto en C:\Program Files (x86)\ScriptCommunicator_5.09. Pinchamos en Next

Volvemos a pinchar en Next

Y ahora en Install. Comienzan a instalarse los archivos

Al cabo de unos segundos el proceso habrá terminado, y aparece la última ventana. Pinchamos en Finish

Paso 3: Lanzar el ScriptCommunicator. Al terminar la instalacion se lanza automáticamente. También tendremos un acceso directo desde el Escritorio para lanzarlo. Nos aparecerá una pantalla como esta:

¡Ya lo tenemos listo para empezar!

Primera prueba

Haremos una primera prueba para comprobar que está todo funcionando. Esta prueba la haremos a nivel físico: no usaremos ningún circuito transmisor ni receptor todavía. Simplemente uniremos cables y mostraremos en los LEDs las señales de control

Ejemplo 1: Comprobación de señales a nivel físico

Cargamos este circuito en la FPGA. El cable RX, por donde llegan los datos, está unido directamente al de TX, por donde se envían. Así, todo lo que llega se devuelve, sin ningún tipo de procesado. Las señales de control DTR y RTS están conectadas a los LEDs 7 y 0 respectivamente. Y los pulsadores a las señales CTS, DCD y DSR, a través de un decodificador de 2 a 4

Lo cargamos en la placa

Primero probaremos su funcionamiento con el Arudino IDE. Lo lanzamos y seleccionamos el puerto serie desde Tools/Port. El nombre del dispositivo depende del sistema operativo que usemos:

  • Linux: Dispositivo /dev/ttyUSB1 (Aparecerá también el /dev/ttyUSB0, pero NO es el correcto)

  • Windows: Dispositivo COMx, donde la X es un número que varía de un ordenador a otro. En el ordenador donde se ha probado estaba en el COM4

  • MAC: TODO

Abrimos el terminal serie y hacemos una prueba de envío de varias cadenas. Veremos cómo recibimos las mismas (el eco). Es indiferente la velocidad a la que esté configurado el terminal

Vemos cómo los LEDs de TX y RX de la Icezum Alhambra se encienden unos instantes. Se corresponden con las señales TX y RX del PC, y nos indican que hay datos que se están intercambiando con el PC

Desde el entorno de Arduino NO tenemos acceso a las señales de control, por lo que para la siguiente prueba usaremos el ScriptCommunicator

Probando las señales de control con el ScriptCommunicator

Abrimos el ScriptCommunicator. Pinchamos en el botón de Settings para seleccionar el puerto serie. Si estamos en Linux seleccionamos el /dev/ttyUSB1. La velocidad es indiferente, de momento. Pinchamos en Close para volver

En windows es igual, pero seleccionamos el COM4, que es donde está el puerto serie de la Icezum Alhambra en este ordenador

Para comenzar las pruebas nos conectamos a la placa pinchando en Connect. Comprobamos que el eco funciona (igual que en el IDE de arduino). Vemos que las señales CTS, DSR y DCD están a 1. Al apretar los pulsadores, se pondrá a 0 la seleccionada (tienen la lógica invertica). Los LEDS 7 y 0 estarán encendidos. Pinchando en DTR y RTS se cambia su estado.

En este vídeo se muestra el ejemplo en acción:

Click to see the youtube video

Ahora que ya tenemos todo funcionando, es momento de aprender a hacer circuitos que se comuniquen mediante el puerto serie

Transmisor Serie

El envío de datos desde la FPGA al PC lo realizamos a través del transmisor serie. El bloque de Icestudio está disponible en el menú Varios/Serial/Serial-tx de la colección Academia-Jedi-HW-30

El dato a transmitir se introduce por la entrada de datos, de 8 bits. Al generar el tic de transmisión, se captura el dato y se envía por la línea serie (TX). Es un funcionamiento similar a la captura de los registros

Hasta que el dato no se haya transmitido completamente, NO se puede enviar el siguiente. El estado del transmisor lo sabemos por su salida Busy: que indica si está ocupado o no. Cuando se ha enviado el dato actual, emite el tic de dato transmitido

La velocidad de transmisión la fijamos mediante el parámetro. Tenemos que introducir alguna de las velocidades estándares (en baudios): 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600 ó 115200. Por defecto se usan 115200 baudios

Ejemplo 2: Envío de un carácter al apretar un botón

Empezaremos con el ejemplo más sencillo: Enviar un carácter constante al PC cada vez que apretamos el pulsador SW1 de la Icezum Alhambra. Cuando se haya enviado, encenderemos un LED durante 100ms. El circuito es el siguiente:

El dato a enviar es el carácter "A". Lo introducimos como una constante de 8 bits, y bien podemos indicar su código ascii, o bien el propio carácter usando las dobles comillas. El tic que aparece al apretar el pulsador lo usamos como tic de tranmsión, conectándolo a la entrada txmit. El tic de dato enviado se introduce en un temporizador para generar un pulso de 100ms que enciende el LED 0 durante ese tiempo

La velocidad se ha configurado a 115200 baudios, mediante el parámetro. La salida TX se conecta directamente al pin de TX, para que el dato serie llegue al PC

Cargamos el circuito y lo probamos. En el PC arrancamos el ScriptCommunicator, configurado a la velocidad de 115200 baudios. Comprobamos cómo llega una "A" con cada pulsación, y un parpadeo en el LED0

Click to see the youtube video

La configuración que estoy usando en el ScriptCommunicator en Linux es la siguiente:

y las opciones de la consola son estas (como referencia)

En esta animación se puede ver con más detalle el funcionamiento del ejemplo anterior. El tamaño de la letra de la consola se ha agrandado para que se vea mejor

Ejemplo 3: Enviando un número en binario

En este ejemplo enviaremos al PC los números introducidos en binario mediante 3 interruptores externos. Al apretar el botón de ENTER, el número se mostrará en el display de 7 segmentos y se enviará al PC. Cada vez que se envía un dato se enciende un LED durante 100ms:

Como el número es de 3 bits y el transmisor envía números de 8 bits, usamos un componente "acoplador" que pasa de 3 a 8 bits, rellenando con 0s los bits de mayor peso. En el montaje tenemos los 3 interruptores, el botón de enter, el LED de transmisión y el display de 7 segmentos:

Lo cargamos y lo probamos. Cada vez que se aprieta el pulsador de enter se envía el número actual

Click to see the youtube video

Lo que se está enviando son números crudos. El ScriptCommunicator tiene un par de pestañas activables que nos permiten visualizar el dato recibido en hexadecimal y en binario. Si lo visualizamos en ASCII, veremos "Basura", ya que lo que se envían no se corresponde con caracteres ASCII visibles

Se activan desde la ventana de Settings, pinchando en las casillas hex y binary

Ejemplo 4: Circuito BCD a ASCII

La mayoría de terminales serie, como el de Arduino IDE, sólo muestran la información en ASCII (y no números en crudo como el ScriptCommunicator). Para poder visualizar los dígitos 0-9 en estos terminales, hay que realizar una conversión de binario a ASCII

La tabla de conversión es la siguiente:

Número BCD Código ASCII (hex) Dígito
0000 30 0
0001 31 1
0010 32 2
0011 33 3
0100 34 4
0101 35 5
0110 36 6
0111 37 7
1000 38 8
1001 39 9

Esta conversión se implementa muy fácilmente mediante una tabla de 4 entradas y 8 salidas. Para los valores superiores a 9 se usan los caracteres hexadecimales. De esta forma nos sirve tanto para convertir dígitos decimales y hexadecimales

Utilizaremos el spiner conectado a un sensor IR para contar las pasadas que dan sus brazos, en un contador decimal de 4 bits. Su valor se muestra en decimal en un display de 7 segmentos y se envía el dígito ASCII para verlo en el terminal serie. El montaje es el siguiente:

Este es el circuito. Los tics del Spiner incrementan el contador de 4 bits, cuya salida se saca por el display de 7 segments y se convierte a dígito ASCII antes de enviarlo por el puerto serie. El primer tic recibido está retrasado un periodo para que se incremente primero el contador y empiece a contar desde 1

Se han añadido dos componentes auxiliares para hacer el ejemplo más compacto: un IR de tics con sonido, que emite un pitido cada vez que se recibe un tic del spiner, y el componente flash que enciende el LED durante 50ms para indicar que el dígito se ha enviado

En este vídeo se puede ver el ejemplo en funcionamiento. Se usa el terminal del Arduino IDE para mostrar los dígitos recibidos

Click to see the youtube video

Este es el aspecto del terminal del Arduino IDE tras girar el spiner un tiempo, después de inicializarlo. Se observan los dígitos ASCII recibidos, y cómo el primero es el 1, y no el 0, gracias a la acción del biestable D que retrasa el primer tic

Ejemplo 5-1: Transmisor de 16 bits

El puerto serie funciona con datos de 8 bits. Si queremos enviar un dato de 16 bits, debemos partirlo en dos de 8 bits, y enviarlos por separado. Este es un ejemplo de un circuito que nos permite hacer eso, y que veremos detalladamente a continuación

Primero veremos qué hace: al apretarse el pulsador se emite un pitido y se envían los caracteres J y A seguidos, uno a continuación de otro. El LED parpadea cuando se han enviado el dato. Esto es lo que aparecerá en el terminal al apretar varias veces el botón

El montaje es muy básico: sólo están el pulsador para enviar, el LED y el zumbador

Lo cargamos y lo probamos. Cada vez que se aprieta el pulsador aparece la palabra "JA" en el terminal. Primero se envía la "J" (byte alto) y luego la "A" (byte bajo)

Click to see the youtube video

Funcionamiento del Transmisor de 16 bits

El transmisor se encuentra en dos estados: transmitiendo y apagado. Esto lo determina el biestable RS de estado. Inicialmente está a 0 (apagado). Al recibirse el tic de enviar dato se activa, y pasa a 1. En su salida hay un detector de flanco de subida que emite un tic cuando arranca (paso de apagado a encendido)

Usamos un biestable de cambio para seleccionar qué byte enviar: 0 para el byte de menor peso y 1 para el de mayor. Inicialmente tiene el valor 1, porque primero enviamos el de mayor peso. La salida del multiplexor llega directamente a la entrada de datos del transmisor serie. Cuando llega el siguiente tic al Biestable de cambio, cambia a 0 y se selecciona el byte de menor peso

El transmisor seríe sólo recibe tics de transmisión cuando el transmisor de 16 bits está activado. Una vez apgado, no se permiten más transmisiones. Esto se controla mediante una puerta AND conectada al biestable de estado. Se reciben dos tics de transmisión en total, que provienen de diferentes lugar. El primero es el de inicio, que lo provoca el biestable al encenderse. El segundo llega cuando se ha terminado de enviar el primero. Ambos se combinan a través de una puerta OR

El final del envío lo determina el flanco de subida generado por el biestable de cambio. Cuando ocurre se apaga el transmisor poniendo a cero el biestable de estado, y ya no se pueden realizar más transmisiones hasta que se active

Ejemplo 5-2: Bloque transmisor de 16 bits

El transmisor de 16 bits anterior lo metemos dentro un bloque para que sea más fácil su reutilización. Es el bloque serial-tx16, y está dispoinible en el menú Varios/Serial/serial-tx16. Es igual que el transmisor de 8 bits, pero con entrada de datos de 16

Como segundo ejemplo de pruebas, enviaremos dos datos de 16 bits, según el estado de un interruptor externo. Usaremos valores que se corresponden con caracteres ASCII, para poderlos visualizar en cualquier terminal. El montaje es el siguiente:

En el circuito se usa un multiplexor 2:1 de 16 bits para seleccionar el dato. Cuando el interruptor está a 0, se envía el dato 0x2D3E (que se corresponde con los caracteres ->), y cuando está en 1 se envía una "A" y el carácter de línea nueva (\n)

Lo cargamos y lo probamos. En el terminal obtenemos algo como estos, según vamos enviando diferentes datos:

En este vídeo se puede ver el circuito en acción:

Click to see the youtube video

Ejemplo 6-1: Enviando una cadena

Generalizaremos el ejemplo anterior para enviar N caracteres por el puerto serie. Los dejamos almacenados en una memoria (tabla) y usamos un contador para recorrerla. En este ejemplo concreto enviamos la cadena "HOLA:)\n" de 7 caracteres

El tamaño de la cadena lo indicamos mediante el parámetro módulo del contador, de forma que cuando se active la señal de overflow (ov) será porque hemos llegado al final, y hay que apagar el transmisor. Usamos el mismo montaje que el ejemplo 5-1. En el terminal veremos lo siguiente

Cada vez que apretamos el pulsador aparece la cadena HOLA:) y el cursor salta a la línea siguiente. En este vídeo lo vemos en funcionamiento

Click to see the youtube video

Funcionamiento del transmisor de cadenas

El funcionamiento del circuito de envío de cadenas es muy parecido al que envía 2 bytes. Colocamos un biestable RS para describir su estado: funcionando o apagado. Al recibir el tic de envío se activa, y a través del detector de flancos de subida envía un tic inicial para transmitir el primer carácter

La cadena se encuentra almacenada en una memoria, que en este ejemplo es de 8 bytes, pero podría ser mayor. Usamos un contador de 3 bits para recorrer esta memoria. Inicialmente se accede al carácter de la posición 0. Al recibir un tic por cnt se incrementa y apunta al siguiente carácter

El tamaño de la cadena se introduce como parámetro módulo del contador, de forma que cuando se alcanza su valor se emite un tic por ov y se sabe que se ha llegado al final. El dato que sale de la memoria se introduce por la entrada de datos del tranmisor serie, y se envía al recibir un tic por txmit

Tanto el contador como el transmisor serie sólo funcionan cuando el biestable está a 1, permitiendo el paso de los tics. Al apagarse, se bloquen, y ni se transmiten caracteres ni se incrementa el contador. Los tics que les llegan son el inicial, y el de siguiente carácter, a través de la puerta OR

El final del envío lo determina la señal de overflow del contador, que está conectada a la entrada de reset del biestable, haciendo que vuelva a cero. Esto a su vez hace que todo quede deshabilitado hasta que se vuelva a recibir un nuevo tic de arranque

Ejemplo 6-2: Usando el bloque serial-tx-str

El circuito anterior lo convertimos en un bloque y así será más fácil su uso. La cadena máxima que se puede enviar con este bloque es de 32 bytes porque estamos usando un contador de 5 bits, y una memoria de 32 bytes. Este componente se encuentra en Varios/Serial/blocks/serial-tx-str32. Para enviar cadenas más largas sólo hay que crear el componente con un contador y memoria de mayor número de bits

Sin embargo, para que sea más fácil su uso, tenemos el componente serial-tx-str que es paramétrico (el bloque está implementado en verilog). Nos permite enviar cadenas de cualquier longitud (siempre que no desbordemos el tamaño máximo de memoria interna)

Este transmisor, a diferencia de los anteriores, NO tiene entrada de datos. Cuando recibe el tic de transmisión envía la cadena completa y emite un tic por done cuando ha terminado

En este circuito vemos un ejemplo de su uso. Se envía una cadena de 35 bytes al apretar el pulsador. No se ha introducido nada por el parámetro baudios. En ese caso, se usan 115200 por defecto.

Lo cargamos y lo probamos. En el terminal veremos el siguiente mensaje, cada vez que apretamos el pulsador

Y en este vídeo vemos la demo en acción:

Click to see the youtube video

Ejemplo 6-3: Leyendo la cadena de un fichero

Las cadenas las estamos introduciendo como parámetro en la memoria (tabla). Cada carácter (8 bits) ocupa una posición de la memoria, empezando por 0. Se codifica en ASCII hexadecimal. Así, para representar el carácter 'A' escribimos 41, y para representar el '1' usamos 31. La cadena "Hola" la almacenamos así:

Opcionalmente podemos colocar comentarios usando //. Así, el contenido de la memoria es más legible y sabemos qué carácter está en cada posición

También podemos escribir la información en horizontal, separando los caracteres por espacios. En esta disposición nos es más difícil saber la dirección en la que se almacena cada dato, sin embargo para representar cadenas no es necesario conocer estos detalles. Además podemos escribir un comentario inicial con la cadena

Estos mismos datos también pueden estar almacenados en un fichero de texto, que debe estar guardado en el mismo directorio donde se encuentra nuestro proyecto de icestudio. Cuando se realiza la síntesis del circuito, icestudio lee este fichero y rellena la memoria con esos datos

El fichero se introduce como parámetro, y debe estar entre comillas dobles "". Además, su extensión debe ser .list. En este ejemplo hemos usado el fichero cad.list. Con cualquier editor de texto lo creamos y editamos. Aquí lo tengo abierto con Atom, que es libre y multiplataforma

Este es el ejemplo completo de envío de una cadena leída de un fichero. Adicionalmente se han añadido bloques con otras posibles formas de almacenar la cadena en la memoria

Ejemplo 6-4: Generación de una cadena desde un programa en python

Los ficheros de datos para la memoria se pueden generar "a mano", escribiendo en el editor de texto, o mediante un programa externo, hecho en cualquier lenguaje de programación. Este programa genera los datos, que luego Icestudio lee, introduce en la memoria y sintetiza el circuito final

Estos datos pueden ser cadenas de caracteres, como en este ejemplo, instrucciones en código máquina si estamos haciendo un microprocesador, o cualquier otro dato (píxeles, notas...) según la aplicación

En este ejemplo estamos imprimiendo cadenas que tenemos que convertir a ASCII hexadecimal. Bien, pues hagamos un programa externo que haga el trabajo por nosotros. Una primer forma es introducir esta línea de python en el intérprete, y luego copiamos la salida en un fichero de datos o directamente en la memoria de icestudio:

print(" ".join(["{:02X}".format(ord(i)) for i in "Mi cadena de texto"]))

En estos pantallazos se pueden ver cómo se ejecuta esta línea en el intérprete de python lanzado desde un terminal, tanto en Linux como windows. Se obtiene como salida los datos ASCII hexadecimales correspondientes la cadena "Mi cadena de texto": 4D 69 20 63 61 64 65 6E 61 20 64 65 20 74 65 78 74 6F

La segunda forma es hacer un programa completo, pasándole como argumento la cadena, y que genere directamente el fichero cad.list con los datos ASCII hexadecimales. El programa lo puedes descargar de aquí: gen_str_data.py. Este es el código:

#!/usr/bin/python3
import sys
from pathlib import Path

# Nombre del fichero de datos a generar
FILEDATA = "cad.list"

# Cadena por defecto
CADENA_DEFECTO = "Mensaje de prueba\n"

# Especificar descriptor del fichero
fichero = Path("./{}".format(FILEDATA))

# La cadena a generar es o bien la que se pasa como argumento o bien
# el mensaje de prueba por defecto
cadena = ""
try:
  cadena = sys.argv[1]
except IndexError:
  cadena = CADENA_DEFECTO

# Imprimir la informacion en la consola
print("Cadena: {}".format(cadena))
print("Longitud cadena: {}".format(len(cadena)))
print("Fichero: {}".format(fichero))

# Crear la cadena de datos, con los caracteres en ASCII hexadecimal
data = " ".join(["{:02X}".format(ord(i)) for i in cadena])

# Anadir al comienzo la propia cadena en comentarios
data = "\n".join(["//-- {}".format(cadena), data])

# Imprimir los datos
print(data)

# Crear fichero con los datos
fichero.write_text(data)

Si no sabes python no te preocupes. Basta con que te descargues el fichero y lo ejecutes desde el terminal. Necesita el intérprete de python3. Al ejecutarlo se le pasa como parámetro la cadena que queremos:

python3 gen_str_data.py "Hola, probando mi cadena..."

En estos pantallazos se muestran las pruebas en Linux y windows:

Además de salir la información por pantalla, para hacer copy&paste, se genera automáticamente el fichero cad.list con la cadena. ¡Listo para que se cargue desde Icestudio!. En esta animación vemos el proceso, generando dos cadenas diferentes y probando su envío

¡Importante! No olvidar de introducir el tamaño de cada cadena generada en el parámetro size

Funcionamiento del transmisor

Ya sabemos usar el transmisor serie. Es muy fácil. Pero... ¿Cómo funciona? ¿Qué magia tiene en su interior que hace que se envíen los bits?. Desde el menú Varios/Serial/Blocks/serial-tx tenemos acceso a los bloques que forman el transmisor. Veremos su funcionamiento en detalle

Para enviar un dato de 8 bits, usamos una trama de 10 bits. El primer bit debe ser el bit de start, que es 0. A continuación los 8 bits de datos, empezando por el de menor peso (bit 0). Por último el bit de stop, que es 1. Cuando no hay transmisión, la línea está en reposo, y debe estar a 1.

La parte central del transmisor es el registro de desplazamiento, que pasa los datos de paralelo a serie. Su salida serie es la que se envía a la línea, pasando por un biestable del sistema para cumplir con las reglas de diseño síncrono. El registro es de 9 bits, para almacenar tanto el dato como el bit de start. El bit de stop se introduce por su entrada serie, de forma que tras 9 desplazamiento está listo en la salida serie

Al dato a transmitir (de 8 bits) se le agrega el bit de start en la parte de menor peso, y se introduce por la entrada de datos del registro. Cuando llegua el tic de arranque por load, este dato se captura

El estado del transmisor lo determina un biestable RS. Cuando vale 0, significa que está apagado. Cuando vale 1 está funcionando. Este estado se saca directamente por la salida busy. Cuando se activa la señal txmit para transmitir un dato, el biestable pasa de 0 a 1 y se genera el tic de arranque, se está conectado a la entrada load del registro, cargando el dato.

El biestable también activa el corazón de baudios, que genera tics a la velocidad necesaria para realizar la transmisión. Estos tics se introducen por la entrada shift del registro, y provocan su desplazamiento

Los tics del corazón de baudios también llegan al contador de bits, que se incrementa con cada bit enviado. Cuando llega a 10, se activa su señal de overflow. Significa que una trama completa se ha enviado. Como está conectada a la entrada reset del biestable, éste se apaga

Por último, la señal de overflow, retrasada un periodo, es la que se saca por la salida done para indicar que la transmisión ha terminado

Esta es toda la magia que hay en un transmisor serie 😀

Ejemplo 7: Midiendo las señales con el analizador Saleae

Durante el diseño de los circuitos digitales es muy útil medir las señales con un analizador lógico, para comprobar que se comportan como se espera, o para encontrar fallos y resolverlos. El analizador que uso es uno compatible con Saleae. Puedes encontrar más información en el VideoBlog 26

Mediremos 4 señales del transmisor serie, usando 4 canales del analizador: txmit, TX, busy y done. Hacemos un circuito que envíe el carácter A al apretar el pulsador. Las señales a medir las sacamos por los pines D1, D2, D3 y D4 de la FPGA, y ahí conectaremos el analizador

El montaje es el mostrado en esta imagen. El analizador es muy pequeño, y coloca en el mismo corcho donde están el resto de componentes

Lanzamos el PulseView, que es un programa libre y multiplataforma para realizar las mediciones con el analizador y obtenemos el comportamiento de las señales. Usamos la señal txmit como disparador: cuando llega un flanco de subida se empieza a medir

El PulseView se ha configurado para muestrear a una frecuencia de 24Mhz y tomar 5000 muestras. En TX veremos los bits que se envían. Esta señal está a 1 hasta que llega el tic de txmit y pasa a cero: transmisión del bit de start. Luego continúa con el resto de bits hasta que al final llega el bit de stop. En la señal inferior, llamada UART podemos ver mejor la trama serie: primero el bit de start, luego el dato y por último el bit de stop

También comprobamos cómo la señal busy está activa durante toda la transmisión, y se pone a 0 al terminar de enviar el bit de stop. Y podemos observar también, cómo al terminar se emite un tic por done. En este vídeo se muestra el proceso de captura:

Click to see the youtube video

Receptor serie

Para recibir datos en la FPGA desde el PC usamos el receptor serie. El bloque de Icestudio está disponible en el menú Varios/Serial/Serial-rx de la colección Academia-Jedi-HW-30

Los datos en serie llegan por el pin RX y salen por un bus de 8 bits en paralelo, listos para usarse. Cada vez que llega un dato nuevo, el receptor emite un tic de recibido, y la señal de busy se pone a 0. Por el parámetro velocidad fijamos los baudios. Deben ser los mismos que hemos puesto en el transmisor en el PC, o de lo contrario los datos recibidos serán "basura"

Ejemplo 8: Recibiendo datos del PC

Como primer ejemplo de recepción, leeremos todo lo que se envía desde el PC a la FPGA y lo mostraremos en binario en los LEDs. Los 4 bits menos significativos se ven en hexadecimal en el display de 7 segmentos. Adicionalmente, con cada llegada del dato se emite un pitido y un parpadeo en un LED

En el montaje tenemos el display de 7 segmentos, el LED de dato recibido y el zumbador

Lo cargamos y lo probamos. Usamos el ScriptComunicator para enviar los datos. Cada vez que se aprieta una tecla, se envia a la FPGA. En la ventana del ScriptComunicator no vemos nada porque se ha deshabilitado la visualización de lo enviado. En este vídeo lo vemos en acción

Click to see the youtube video

Para poder enviar datos pulsando teclas (y no tener que dar al Enter), hay que activar la opción send input del ScriptCommunicator

Y para no mostrar en el terminal las teclas que pulsamos, hay que deshabilitar la opción send en la pestaña de Console Options en la configuración del scriptCommunicator (Settings)

Ejemplo 9: Contador de datos recibidos

En el siguiente ejemplo contaremos los caracteres recibidos, usando un contador módulo 10. Sólo cuenta de 0 a 9 y vuelve a comenzar. Con cada carácter se emite un pitido y un flash en el led. Cuando se recibe el carácter 'r' (minúscula) se inicializa el contador a 0

El tic de dato recibido se envía al bloque que emite el pitido y el flash, y al contador. Mediante un comparador se comprueba si el carácter recibido es 'r'. En ese caso se activa la señal de reset del contador. El montaje es el mismo que el del ejemplo 8

En este vídeo se muestra el circuito en acción. Primero conectamos el scriptcommunicator. Cada tecla pulsada se envía por el puerto serie, y el contador se incremente. Al pulsar r se inicializa a 0

Click to see the youtube video

Ejemplo 10: Control de un servo con dos teclas

El puerto serie nos permite usar el teclado del PC para controlador nuestros circuitos. Esto es muy útil, sobre todo en la depuración. Este circuito mueve el servo a una posición al pulsar la tecla '1', y a otra al pulsar la tecla '2'. Se utiliza el servobit:

Un biestable RS almacena el bit de posición. Al recebirse la tecla 1, se emite un tic que pone este biestable a 1. Cuando se recibe la tecla 2 se emite otro tic que pone el biestable a 0. El montaje es el mismo que el ejemplo anterior, añadiendo el servo Futaba 3003

En este vídeo se muestra el ejemplo en funcionamiento. Sólo con las teclas 1 y 2 cambiamos la posición del servo. No hace falta que el servo llegue a la posición final. Se puede cambiar la posición al vuelo

Click to see the youtube video

¡Mola mucho! :-) Y lo más interesante, estamos controlando el servo... ¡sin software! ¡Todo por hardware!

Ejemplo 11: Control de un servo a cualquier posición

Desde el puerto serie podemos envir cualquier dato de 8 bits a nuestros circuitos. Eso nos ahorra el tener que conectar muchos interruptores para hacer pruebas de entrada de datos. Basta con enviar el número por el puerto serie. Usaremos esta capacidad para mover un servo a diferentes posiciones

En el menú Varios/Servos/ServoPWM-8bits, de la colección de la Academia-Jedi-HW-30.zip encontramos un controlador de servos genérico, al que le podemos introducir por una de sus entradas la posición, como un número de 8 bits.

En el caso de los servos Futaba 3003 el servo se puede llevar a cualquier posición entre 60 y 225. El periodo de la señal PWM vale por defecto 20ms (el de la mayoría de los servos), pero se puede poner otro valor como parámetro, para que funcione con cualquier servo

En este circuito de ejemplo, el dato de 8 bits que llega por el puerto serie se envía al servo para que vaya a esa posición. Si se envían los comandos 'e' (enable) o 'd' (disable) el servo se habilita o deshabilita respectivamente. En esos casos no se escribe en el servo

Desde el scriptcommunicator podemos enviar datos en decimal seleccionado en el desplegable uint8. Se introduce el valor en decimal y se pincha en send. Desde la pestaña ASCII también podemos usar las teclas para posicionar el servo y enviar los comandos 'e' y 'd'

El funcionamiento se muestra en este vídeo. Primero se lleva el servo a los extremos, introduciendo los valores 60 y 220. Luego al centro con 140. Al apretar las teclas vemos también cómo cambia su posición. Al pulsar la 'd' se deshabilita, y lo movemos con la mano

Click to see the youtube video

Funcionamiento de receptor

¿Cómo funciona el receptor serie?. Desde el menú Varios/Serial/Blocks/serial-rx tenemos acceso a los bloques que forman el receptor. Veremos su funcionamiento en detalle

Los datos llegan desde el exterior, en serie, y entran por el pin RX. Se pasan por el bloque de sincronización para evitar los problemas de metaestabilidad. La línea está a 1 en reposo. Lo primero que llega es siempre un 0: el bit start. Mediante un detector de flancos de bajada, activamos el biestable de estado del receptor cada vez que llega un dato nuevo

Este biestable está a 0 cuando NO se reciben caracteres (apagado), y se pone a 1 (encendido) en cuanto se detecta la llegada del primero. Una vez que ha llegado el bit de start, el resto de flancos de bajada que hubiese no afectan. El biestable se queda encendido hasta que se active su señal de reset

Los bits que llegan entran por la entrada serie de un registro de desplazamiento. Al activarse el biestable de estado, se habilita el bombeo de tics a la velocidad de recepción serie, para desplazar el registro y almacenar los bits que llegan. Sólo hay desplazmiento mientras que el receptor está activo. Al desactivarse, la puerta AND bloquea la llegada de más tics. Las entradas de load y datos del registro de desplazamiento NO se usan. Por q obtenemos el dato y el bit de stop, en paralelo

Cada vez que el corazón se emite un tic de lectura, se incrementa el contador de bits recibidos. Al llegar a 9 (8 bits de datos + 1 de stop) se activa su señal de overflow que inicializa el biestable de estado. Al ser 0, la señal de rst del contador se activa, por lo que se reinicia a 0 y queda listo para recibir el siguiente dato

Por último, la señal de overflow se usa para almacenar en el registro de datos los 8 bits del dato recibido, descartando el bit de stop. Esta misma señal, retrasada un ciclo, se usa para emitir el tic de recepción (rcv), para indicar que hay un dato disponible

En este receptor básico, no hay detección de error. Si el bit de stop no fuese 1, habría que indicar que el dato recibido NO es correcto.

Midiendo el receptor

Igual que hicimos con el transmisor, vamos a medir el receptor para comprobar que las señales se comportan como debería, y que todo está funcionando bien. Usamos tres canales del analizador lógico compatible Saleae, uno para Rx, otro para Busy y otro para rcv. El montaje es el siguiente

Hacemos un circuito de pruebas, con un receptor serie conectado a los LEDs, para ver el dato recibido, además de emitir un pitido y un parpadeo en el LED. Sacamos las señales a medir, Rx, busy y rcv por las salidas D1, D2 y D3 respectivamente, donde están conectados los canales 1,2, y 3 del analizador

Este es el resultado de la medición cuando enviamos la cadena "HOLA". Observamos los tics que parecen en rcv al terminar la transmisión (en mitado del bit de stop), y también la señal de Busy. Nuestro receptor está funcionando correctamete

En esta animación se muestra cómo se ha tomado la captura

Combinando transmisor y receptor

Normalmente, en nuestros circuitos integraremos tanto el emisor como el receptor. Veremos dos ejemplos de circuitos que los incluyen

Ejemplo 13: Haciendo eco de los datos recibidos

En este circuito se vuelve a transmitir todo lo que se recibe. Esto se denomina hacer eco. Además de enviar cada dato de vuelta, se muestra en los LEDs, y se emite un pitido en el zumbador y un parpadeo en el LED. La salida de datos del receptor se conecta directamente a la entrada del transmisión, y también la señal de rcv a la de txmit. El mismo tic de dato recibido se usa para transmitirlo de vuelta

Lo cargamos y lo probamos. Al escribir en el terminar escuchamos los pitidos y vemos el carácter de vuelta. También si enviamos una cadena completa

Click to see the youtube video

Ejemplo 14: mini-cifrador

A partir del mismo ejemplo del eco, podemos hacer un mini-cifrador, que modifica los bits del datos recibido y lo envíe cifrado. Mediante un interruptor externo seleccionamos el modo: cifrado o no. El montaje es el siguiente:

El dato que llega del receptor, con sus bits en paralelo, se cifra intercambiando los cables de los bits. Mediante un multiplexor a la entrada del transmisor se selecciona el dato cifrado o sin cifrar, en función de la posición del interruptor externo

Lo cargamos y lo probamos. Cuando el interruptor está a 0, se hace eco sin cifrar, como en el ejemplo anterior. Al cambiar a 1, se recibe el eco cifrado. Si en modo cifrado enviamos algo ya cifrado, se descifrará

Click to see the youtube video

Aplicaciones

El puerto serie da mucho juego. Entre otras cosas, nos permite comunicarnos con Arduino, comunicar nuestros circuitos a través de bluetooth mediante un conversor bluetooth serie o hacer programa en el PC que se comuniquen con ellos

Comunicación con Arduino por Puerto serie

Otra forma de comunicarnos con Arduino es usando el puerto serie. En vez de enviar comandos desde el PC a la FPGA, lo haremos desde el Arduino. Utilizaremos el puerto serie proporcionado por la biblioteca SoftwareSerial.h, y dejar el puerto estándar para la comunicación con el PC y poder así depurar los programas

La conexión entre Arduino y la FPGA la haremos mediante 3 cables: GND, TX y RX. La FPGA actúa como un Servidor, ofreciendo servicios al Arduino, que es el Cliente

Usaremos estos pines para el ejemplo:

Pin Arduino Pin Alhambra Descripción
D11 D11 TX. Datos: Arduino->FPGA
D10 D10 RX. Datos: FPGA->Arduino
GND GND Masa

La FPGA ofrece dos servicios al Arduino a través del puerto serie: incremento de un contador y lectura de un interruptor. Se implementan con los comandos 'i' y 'r'. Cuando el Arduino envía una 'i', la FPGA incrementa un contador módulo 10, que se muestra en el display de 7 segmentos. Cuando envía el comando 'r', la FPGA devuelve el estado del interruptor: dígito '0' cuando si está a 0, y dígito '1' si está a 1

Servidor hardware en la FPGA

El montaje es el siguiente. La FPGA está conectada al display de 7 segmentos, un zumbador, un LED y un interruptor. Cuando se recibe el comando 'i' se emite un pitido por el zumbador y un parpadeo en el LED. Además, la FPGA está conectada al Arduino mediante 2 cables y masa

Este es el circuito que implementa el servidor hardware. Mediante un comparador y una puerta AND se obtiene el tic de comando, que aparece al llegar cada comando. El tic del comando 'i' incrementa el contador, genera el pitido y el parpadeo del LED. El tic del comando 'r' se usa para transmitir el estado del interruptor. El interruptor tiene sólo 1 bit, y para enviarlo hay que rellenar hasta los 8 bits. Pero si se rellena colocando el número 3 en los 4 bits de mayor peso, conseguimos convertirlo al dígito '0' ó '1', ya que sus códigos ASCII son 0x30 y 0x31 respectivamente

Software en el Arduino

El Arduino es el cliente, que solicita los servicios al hardware. Haremos un programa que incremente el contador cada 500 ms, y que lea el estado del interruptor de la FPGA para actualizar su LED y enviar los cambios al PC para verlos en un terminal

En el Arduino se usan dos puertos serie. El implementado con la biblioteca SoftwareSerial.h es el que usaremos para comunicarnos con la FPGA, dejando el otro para enviar mensajes al PC y depurar el código. El programa es el siguiente (serial_client.ino):

#include <SoftwareSerial.h>

const int LED = 13;
const int RX = 10;
const int TX = 11;

//-- Puerto serie software
SoftwareSerial FPGA(RX, TX); 

void setup() 
{
   pinMode(LED, OUTPUT);
   FPGA.begin(115200); 
   Serial.begin(115200);
   Serial.println("Probando...");
}

void loop()
{ 
  char c;
  char old = 0;

  for(;;) {

    //-- Incrementar el Contador
    FPGA.write('i');
  
    //-- Peticion de lectura del interruptor
    FPGA.write('r');
  
    //-- Esperar la respuesta de la FPGA
    while (!FPGA.available());
    c = FPGA.read();
  
    //-- Cambiar el estado del LED en funcion de la respuesta
    //-- recibida de la FPGA
    if (c=='1') digitalWrite(13, HIGH);
    if (c=='0') digitalWrite(13, LOW);
  
    //-- Mostrar en la consola los cambios del switch
    if (c!=old) {
      Serial.print("Switch: ");
      Serial.write(c);
      Serial.println();
      old = c;
    }  
  
    //-- Esperar
    delay(500);
  }
}

Probando la aplicación

Para probar la aplición cargamos primero el hardware en la FPGA, y luego el software desde el entorno de Arduino

En este vídeo lo vemos en acción. Primero se carga el hardware y luego el software. Al hacerlo vemos cómo el contador se empieza a incrementar, y escuchamos los pitidos. Si se aprieta el pulsador de reset del Arduino, el contador dejará de incrementarse. Luego abrimos un terminal y cambiamos de posición el interruptor. Cada vez que hay un cambio aparece un mensaje en la consola. Si nos fijamos en el LED de arduino veremos que cambia su estado según el valor de este interruptor

Click to see the youtube video

Comunicando los programas del PC con los circuitos

Para comunicar el PC con los circuitos hemos usado un terminal de comunicaciones. Pero... ¿Y no podemos hacer nuestros propio programas? ¡Claro que sí! Sólo tenemos que abrir el puerto serie y realizar las operaciones de lectura y escritura. De esa forma, nuestro programa intercambiará datos con la FPGA

El cómo realizar la aplicación depende del lenguaje de programación usado. Veremos dos ejemplos en python: uno que se ejecuta desde la linea de comandos y otro en un notebook de Jupyter. Los aplicaremos al movimiento de un servo

Servidor hardware

Para nuestro servidor hardware usaremos el mismo circuito del ejemplo 11, que mueve el servo a la posición indicada. Hay dos comandos especiales: la 'e' para habilitar y la 'd' para deshabiliarlo

Software en el PC

En el ordenador tenemos que tener instalado python3, Jupyter Notebook, para hacer programas interactivos desde el navegador y la biblioteca pyserial, para acceder al puerto serie

Ejemplo 16: Secuencia de movimiento

El primer programa mueve el servo a diferentes posiciones, automáticamente, siguiendo una secuencia. Permanece durante 1 segundo en cada posición, y pasa a la siguiente. El código python es: (servo-fpga.py)

#!/usr/bin/env python3
# -*- coding: iso-8859-15 -*-
#-- Relizar una secuencia en el servo conectado a la FPGA
#-----------------------------------------------------------------------

import time
import serial

#-- Poner el nombre del puerto serie aquí
#-- En windows será COMx
SERIAL_PORT = "/dev/ttyUSB1"

#-- Abrir el puerto serie
with serial.Serial(SERIAL_PORT, 115200) as sp:

    #-- Imprimir la información del pueto serie
    print("Puerto serie: {}".format(sp.portstr))

    #-- Habilitar el servo
    sp.write(b'e')

    #-- Mover el servo según una secuencia de posiciones
    pos = [60, 94, 128, 162 ,225, 128]

    for p in pos:
        sp.write(bytes([p])) #-- Enviar la posicion actual a la FPGA
        time.sleep(1)

    #-- Deshabilitar el servo y terminar
    sp.write(b'd');

Este programa es multiplataforma. Yo lo estoy probando en Ubuntu Linux, pero funciona también en Mac y windows. Sólo hay que modificar el nombre del puerto serie. En este vídeo se muestra el programa en acción. Lo ejecutamos así:

python3 servo-fpga.py

Click to see the youtube video

El programa abre el puerto serie, a la velocidad de 115200 baudios y crea el objeto sp, con el que accederemos a él. Primero habilita el servo, enviando el comando 'e'. Esto se hace llamando al método write de sp. En python3 indicamos que un carácter es de tipo byte colocando una b delante, y luego el carácter. Así, b'e', representa el carácter ASCII e, cuyo valor es 0x65

En pos colocamos las posiciones a las que queremos que se mueva el servo en la secuencia. Para los servos Futaba 3003, estas posiciones están comprendidas entre 60 y 225. El bucle principal accede a todas las posiciones de la lista, y las envía la FPGA. Es necesario convertirlas al tipo byte usando la expresión bytes([p]), y luego se transmiten con write.

Por último se deshabilita el servo enviando el comando 'd'

Ejemplo 17: Control interactivo del servo

Usaremos un cuaderno de python en Jupyter para mover el servo de manera interactiva desde el navegador. Lazamos Jupyter y abrimos el cuaderno servo-fpga.ipynb

Una vez abierto, este es el aspecto que tendrá la página en el navegador

Conectamos la FPGA, nos aseguramos que en el código hemos puesto el nombre correcto del puerto serie y ejecutamos el cuaderno, desde la opción Cell/Run All

En la última celda tenemos una barra de desplazamiento horizontal que es la que nos permite mover el servo, y habilitarlo o deshabilitarlo con la casilla de verificación

En este vídeo lo vemos en funcionamiento. Los pitidos que se escuchan son los emitidos en el zumbador cada vez que se recibe un byte. Deshabilitando el servo lo podemos mover con la mano. Una vez habilitado lo posicionamos con la barra

Click to see the youtube video

¡Es muy divertido! :-)

Comunicación bluetooth-serie

Conectando un adaptador bluetooth-serie, podemos comunicarnos con nuestros circuitos de forma inalámbrica, por ejemplo desde un teléfono móvil. Unos módulos muy extendidos son los HC-05 y HC-06. Yo utilizaré el módulo HC-05

Módulo HC-05

El módulo que usaremos en estos ejemplos es el HC-05, pero el funcionamiento con otros módulos es similar

En este tutorial de diymakers hay más información, y en la web de prometec. El módulo se puede conseguir en muchos sitios, por ejemplo en BricoGeek

El módulo tiene un LED rojo que nos indica su estado: conectado o no conectado. La alimentación es entre 3.3v - 5v, pero los pines de transmisión (TX) y recepción (RX) son de 3.3v. En total tiene 6 pines. Sólo utilizaremos 4: VCC, GND, TX y RX

Pin Descripción
State Actividad de transmisión - recepción. Pin opcional para conectar un LED
Key Activar modo configuración del módulo
VCC Alimentación (3.3v - 5v)
GND Masa
TX Transmisión de datos (3.3v)
RX Recepción de datos (3.3v)

Como los pines de TX y RX son de 3.3v, los conectaremos a la Icezum Alhambra en los pines GP0 y GP1 respectivamente, que son también de 3.3v. Este es el esquema de conexionado:

En los ejemplos supondremos que el módulo HC-05 ya está configurado. Su configuración por defecto depende del firmware que lleven. En los míos están configurados de fábrica para trabajar a 38400 baudios

Ejemplo 18: Usando el móvil como terminal de comunicaciones

Repetiremos el ejemplo 13 del eco, pero usaremos el teléfono móvil como terminal, en vez del PC. La APP que usaremos es el BlueTerm, que es libre, y está disponible en google play para su instalación fácilmente: BlueTerm en Google Play

Este es el aspecto que tiene al abrirlo. En la parte superior derecha vemos el estado: no conectado. Tmbién entenderemos por qué se llama BlueTerm :-)

Este es el montaje para el ejemplo. Tenemos el LED que parpade al recibir un dato, el zumbador que emite un pitido también al recibir un dato, y el módulo HC-05

Este es el circuito que hace eco de los caracteres recibidos. Se ha cambiado la velocidad a 38400 baudios y los pines de recepción y transmisión por GP0 y GP1 respectivamente

Cargamos el circuito en la FPGA y arrancamos el BlueTerm. El LED rojo del módulo HC-05 estará parpadeando, el mismo tiempo encendido que apagado, indicando que NO hay conexión. Desde el BlueTerm pinchamos en el botón inferior derecho para sacar el menú.

Elegimos la opción de conectarse a un dispositivo y nos aparecezán la lista con todos los que se han encontrado. En mi caso el nombre que tiene asignado por defecto es H-C-2010-06-01

Lo seleccionamos y casi inmediatamente se conecta. El LED del módulo HC-05 ahora parpaderá de forma diferente: dos parpadeos rápidos y un segundo apagado (se repite esta secuencia). En la parte superior derecha del blueterm aparecerá el mensaje de conectado

Al apretar una tecla, el carácter correspondiente se enviará, y la FPGA lo recebirá y se mostrará en binario en los LEDs. Veremos el LED parpadear y escucharemos el pitido corto. La FPGA re-envía el carácter y lo veremos en el terminal

En este vídeo se muestra todo el proceso

Click to see the youtube video

Control de un servo desde el móvil

Como últimos ejemplos del tutorial, vamos a mover un servo desde el teléfono móvil, de dos formas: usando el BlueTerm y mediante una APP con dos botones. El montaje es el mismo del ejemplo anterior, pero añadiendo un servo:

Ejemplo 19: Control de un servo con BlueTerm

En el ejemplo 11 movimos el servo desde el terminal del PC. Hacerlo con el móvil desde BlueTerm es inmediato. Sólo hay que modificar el circuito para cambiar los pines y la velocidad

Lo cargamos y lo probamos. Con las teclas 'e' y 'd' habilitamos y deshabilitamos el servo. Con el resto de teclas el servo alcanza la posición indicada por su código ASCII

Click to see the youtube video

Ejemplo 20: Desde una APP propia del móvil

El Blueterm es una herramienta muy útil para hacer prototipado rápido, depurar y comprobar que la comunicación funciona. Sin embargo, para controlar servos u otros dipositivos es mejor hacerte tu propia APP en el móvil

Este no es un tutorial de diseños de APP para el móvil. Por eso utilizaremos una ya hecha: Arduino Bluetooth Basic de Mayoogh Girish. Es una APP "hola mundo" que tiene sólo 2 botones, para encender y apagar un LED. Se trata de una APP libre: todo su código fuente está disponible en github, y tenemos la libertad para estudiar el código y modificarlo

Además de encender y apagar un LED, añadiremos un servo, para que se mueve entre dos posiciones predeterminadas. La APP envía el dígito '1' al apretar el botón ON, y el dígito '0' al apretar OFF. El circuito que cargamos en la FPGA es el siguiente. Usamos el servobit y en función del carácter detectdo se mueve el servo a una posición u otra

En este vídeo lo vemos en acción. Una vez establecida la conexión, al apretar el botón de ON el servo se mueve, y el LED 7 se enciende. Al apretar el botón de OFF se mueve a la otra posición y el LED se apaga

Click to see the youtube video

Ejercicios propuestos (25 BitPoints)

Ver los detalles de los ejercicios y las entregas en el menú Archivos/Ejemplos/2-Ejercicios de la colección de este tutorial

Resumen:

Ejercicio 30.1 (Total 5 Bitpoints): Transmisión de dos cadenas

Diseñar un circuito digital que transmita dos cadenas por el puerto serie en función de un interruptor de selección. El final de las cadenas se determina por el número 0 (0x00), en vez de por su tamaño (como hemos hecho en los ejemplos). Es decir, que el circuito envía caracteres por el puerto serie hasta que detecta un 0. En ese momento para

Las dos cadenas deben estar almacenadas en dos ficheros: msg0.list y msg1.list. La logitud máxima de estas cadenas es de 64 bytes (necesario para dimensionar las tablas)

La cadena se envía cuando se aprieta un pulsador. Además se emite un parpadeo en un LED cuando se haya terminado de enviar la cadena

Sugerencia. Para implementar este circuito se propone lo siguiente:

  1. Basarse en el ejemplo 6-1
  2. Hacer primero un circuito que imprima una cadena acabada en 0
  3. Modificar el circuito para enviar 2 cadenas, cada una en una memoria, en
    función del selecctor
  4. Hacer la lectura desde fichero

Click to see the youtube video

Ejercicio 30.2 (Total 5 Bitpoints): Contador de pasadas del spiner

Diseñar un circuito para contar las pasadas que da un spiner sobre un sensor de infrarrojos y enviar el valor del contador por el puerto serie. La cuenta será de 00 a 99, y cuando
alcance el final volverá a comenzar. Con cada paso de un brazo del spiner por el IR se envía el valor

El dato enviado consta de los dos dígitos (unidades y decenas) y un fin de linea (\n)

Sugerencia. Basarse en el ejemplo 6-1. Por cada tic del IR hay que enviar 3 caracteres: Las decenas, las unidades y el fin de línea. En vez de almacenar la información en la memoria, los datos a enviar provienen de un multiplexor, conectado a los contadores de unidades y decenas y a la constalte de salto de línea

Click to see the youtube video

Ejercicio 30.3 (Total 10 Bitpoints): Control de Franky por puerto serie

Diseñar un circuito para controlar a Franky a través del puerto serie. Hay tres comandos de posición: q,w y e que hacen que los ojos de franky apunten en tres direcciones: izquierda, centro y derecha (son las posiciones del servo 0x3C,0xE1 y 0x80)

Mediante la barra espaciadora activamos el modo de disparo, haciendo parpadear sus ojos a la frecuencia de 10Hz y emitiendo pitidos cortos de 1Khz con una cadencia de 10Hz. Si mientras está disparando apretamos nuevamente la barra espaciadora dejará de hacerlo.

Adicionalmente, cada vez que se reciba un comando correcto (q,w,e ó espcio) enviará la cadena OK seguida del carácter de fin de línea (\n) por el puerto serie

Click to see the youtube video

Ejercicio 30.4 (5 Bitpoints). Ejercicio Libre

Premiar la creatividad. Entregar por redes sociales o github: Pantallazos, enlaces, vídeos, etc...

  • Sugerencia: Modificador cualquiera los ejercicios anteriores para poder usarse desde un móvil, con un conversor bluetooth-serie

Ejercicios entregados

Josep Montoliu (Klarojms)

Ejercicio 30.1

  • Vídeo en Youtube:

Click to see the youtube video

Ejercicio 30.2

  • Vídeo en Youtube:

Click to see the youtube video

Ejercicio 30.3

  • Vídeo en Youtube:

Click to see the youtube video

Ejercicio 30.4

  • Vídeo en Youtube:

Click to see the youtube video

Segundo

Ejercicio 30.1

  • Vídeo en Youtube:

Click to see the youtube video

Ejercicio 30.2

  • Vídeo en Youtube:

Click to see the youtube video

Ejercicio 30.3

  • Vídeo en Youtube:

Click to see the youtube video

Ejercicio 30.4

  • Vídeo en Youtube:

Click to see the youtube video

Tercero

Ejercicio 30.1

  • Vídeo en Youtube:

Click to see the youtube video

Ejercicio 30.2

  • Vídeo en Youtube:

Click to see the youtube video

Ejercicio 30.3

  • Vídeo en Youtube:

Click to see the youtube video

Ejercicio 30.4

  • Vídeo en Youtube:

Click to see the youtube video

Autor

Licencia

Créditos y agradecimientos

Enlaces

Preguntas frecuentes

  • ¿Dónde puedo conseguir la placa Icezum Alhambra?

Pueden conseguir una desde Alhambrabits

  • ¿Dónde puedo comprar material electrónico?. Hay muchos sitios. Uno muy bueno es Bricogeek

  • ¿Cómo aprendo a manejar github?

Hay mucha información en internet. En su momento hice este Tutorial: Github y FreeCAD para enseñar a manejarlo. Los ejemplos están hechos con ficheros de FreeCAD, sin embargo, lo que se enseña es genérico. También vale para las entregas de los ejercicios del tutorial de Electrónica digital para makers

  • Los pulsadores de la Icezum Alhambra no me funcionan

Eso es debido a que se han metido restos de flux y no hacen buen contacto. En el apartado ¡No me funcionan los pulsadores! del Tutorial 9 se indica cómo solucionarlo fácilmente

  • ¿Dónde puedo encontrar más información sobre las señales PWM?

Echa un vistazo a este post de Rincón Ingenieril sobre el tema

  • He conectado un pulsador externo pero no me funciona. He hecho un circuito para conectar el botón con un led, y al apretar se enciende el LED, pero luego no se apaga. NO funciona bien

Los pulsadores externos que se conecten a los pines de 5v de la Alhambra (D0 - D13) tiene que llevar una resistencia de pull-up o pull-down con valores entre 460 ohm y 2K. Típicamente usamos 1K. Esto hace que los conversores de nivel se configuren como entradas y que el pulsador funcione correctamente. Puedes encontrar más información En este enlace

Es un servo muy usado y muy estándar. Si buscar por internet encontrarás muchos sitios donde los vendes, a diferentes precios. Aquí en España se puede conseguir muy fácilmente a través de BricoGeek: Servo SM-4303R Bricogeek y también en Iberobotics: Servo SM-4303R Iberobotics

  • Parece ser que los servos Futaba 3003 se pueden trucar para convertirlos en rotación continua. ¿Conoces algún tutorial sobre como hacerlo?

El Futaba 3003 es uno de los servos que típicamente se han trucado para construir robots móviles con ellos. Robots como Tritt, El Skybot o el Miniskybot los utilizan. Existen muchísimos tutoriales para hacerlo. En esta página puedes encontrar todas las formas de trucarlos. El que recomendamos es el caso 2

Clone this wiki locally