Es muy común ver anuncios que utilizan luces led, ya sea desde los más básicos que solo tienen las letras formadas por leds, hasta unos muy sofisticados que tienen varias animaciones, con esa idea en mente decidí ver qué tan fácil o difícil resulta construir uno desde cero, así es como terminé creando a Byteman, su diseño es básicamente un rectángulo con brazos y piernas, algo así como los típicos monos de círculos y palitos que dibujamos en el kinder, pero su simpleza es parte de su carisma, eso y el hecho de que es de la vieja escuela, por si no lo has notado, su nombre se conforma de la palabra byte y man o sea que es un hombrecillo virtual de 8 bits.
Antes de poner manos a la obra, hay algo de vital importancia, y es que este proyecto no está basado en arduino, por lo tanto, no cuenta con librerías mágicas ni módulos shield, también es necesario contar con un programador de picmicros, el código está creado en lenguaje de bajo nivel, la razón de porqué está escrito en ensamblador es porque cada animación ocupa un registro en la ROM por lo tanto, es importante optimizar el código, con esto conseguimos tener más animaciones comparado con un lenguaje de alto nivel.

IMPORTANTE:

Este proyecto utiliza un microcontrolador de microchip, por lo que es necesario tener un programador de picmicros.

Teoría:

Lo primero que tenemos que hacer es encontrar una manera de dibujar una imagen en la matriz led de 8x8, la opción que me viene a la mente es basarnos en como lo hacen los televisores, el primer paso es el barrido esto significa desmenuzar la imagen linea por linea y dibujarla de la misma manera en la matriz.
En la imagen puedes ver como se va dibujando linea por linea la imagen, por cierto cabe mencionar, que el sentido de barrido de la imagen no importa en la práctica, pero si a la hora de implementar el circuito, a lo que me refiero es que puedes empezar a dibujar de arriba para abajo o viceversa y no afecta en nada la imagen, lo que afectaría es que el circuito empiece desde abajo pero tu secuencia corresponda a la de arriba, así que mucho ojo con eso.
Por ahora te recomiendo que sigas mi secuencia, una vez que sepas lo que haces puedes decidir cuál elegir, que insisto, no vas a notar ningún cambio significativo.
Si esto lo implementaras en cualquier microcontrolador no verías nada, y eso se debe a que el barrido es directamente proporcional al tiempo de ejecución de la instrucción, dicho de otra forma, el microcontrolador PIC16F886 tiene una frecuencia de trabajo de 4 Mhz, debido a su ciclo Fetch cada instrucción la ejecuta en 1µseg, por lo tanto, esas ocho secuencias le toma solo 8μseg, seguramente ya has de haber encontrado una solución basada en un loop para ser capaz de ver la imágen, pues lamento decirte que no es tan fácil, porque si te basaras en loops solo serias capaz de hacer animaciones secuenciales, eso estaría bien si por ejemplo haces algún cortometraje pero si quisieras hacer animaciones aleatorias mediante el loop no serias capaz de lograrlo, por lo tanto, la solución es "retener" el mismo cuadro más de una vez, con retener me refiero a repetir la animación por más tiempo.

Si te fijas, a esta imagen le toma exactamente el doble de tiempo completar la imagen a comparación de la de arriba, esto se debe a que estoy "reteniendo" el mismo cuadro por más tiempo, pero ambas imágenes tienen el mismo ciclo de cambio de cuadro a esto se le conoce como refresco o refresco en inglés, el refresco es la frecuencia con la cual ocurre un cambio de cuadro, se mide en hercios, para calcular el refresco solo debes recordar que la frecuencia es inversamente proporcionales al periodo, por ejemplo, la imagen de arriba tiene un periodo de .5 segundos por lo tanto, su refresco es de 2Hz, mientras que la segunda imagen tiene un periodo de 1 segundo por lo tanto, su refresco es de 1Hz, entonces ¿un refresco con una frecuencia alta termina de dibujar la imagen más rápido en comparación de un refresco con una frecuencia más lenta?, la respuesta es NO.
¿Confundido?, ¿ entonces por que estamos "reteniendo" la imagen? pues bien, no te confundas, voy a volverlo a explicar para que no queden dudas.
Un refresco rápido no significa que sea mejor por ejemplo, el refresco real de la primer imagen es de 125kHz puesto que no estamos "reteniendo" el cuadro de la animación, esa frecuencia no la puede detectar el ojo humano, por tal motivo es necesario "retener" el cuadro por más tiempo. Ahora bien, si a la primer imagen le diéramos un tiempo de "retención" de 1 segundo a cada cuadro, entonces cada 8µsegundos la pantallita estaría cambiando, pero dado que lo estamos "reteniendo" veríamos el mismo cuadro, dicho de otra forma el refresco debe de pasar 125 mil veces antes de avanzar al siguiente cuadro, por lo tanto tal vez nos convendría un refresco más lento.
El tiempo de "retención" de cada imagen tiene que ser exactamente el mismo, de lo contrario la animación no se vería fluida, el tiempo exacto de retención no lo tengo, lo que sé es que la televisión recibe el audio en AM y el vídeo en FM por lo tanto agarré frecuencias del orden de los kHz, pero eso ya lo veremos más adelante por ahora lo importante es entender lo básico.

Por fin, lo hemos logrado ahora nuestra imagen es visible, vamos a recordar los pasos:

• El primer paso corresponde al barrido que no es otra cosa que mandar la secuencia de leds a encender.

• El segundo paso es "retener" esa imagen en pantalla para que el ojo sea capaz de verlo.

• El tercer paso es hacer un refresco a la imágen para pasar a la siguiente secuencia de la animación.

Esto son prácticamente todos los pasos necesarios para mostrar imágenes en nuestra pantalla.

Hardware:

El hardware esta diseñado para ser capaz de desempeñar los tres pasos anteriores:

  1. El barrido (microcontrolador).
  2. La retención (microcontrolador).
  3. El refresco (demultiplexor).

El diagrama de conexión está creado en diptrace, presiona sobre la imagen para descargarlo.
La matriz led está creada a partir de dos headers por lo tanto, a la hora de pasarlo al pcb solo revisa las dimensiones que se encuentran en la hoja de datos, por último el header llamado TOP corresponde a la parte superior y el que se llama DOWN es la parte inferior, a que no te lo hubieras imaginado.

Lista de componentes:

• Microcontrolador (PIC16F886)
• Demultiplexor 3-a-8 (74HCT138D)
• Regulador de voltaje (LM7805)
• Matriz led 8x8 catodo a renglón (GMM2308W)
• 8 resistencias de 120 Ω @ 1/4 watt
• 1 resistencia 10kΩ @ 1/4 watt
• 8 diodos de recuperación rápida (1N5819)
• Capacitor electrolítico de 1µF @ 16 Volts
• Pila o batería de 9 Volts

Por parte del hardware lo importante es lo siguiente:
•Las secuencias de las animaciones salen por el puerto A del microcontrolador por lo tanto, debes de configurarlas como salidas digitales, el registro 0x85 = 0x00, y no olvides configurar los registros ANSELX 0x188 y 0x189.
•El demultiplexor está controlado por los 3 LSB del puerto C por lo tanto el puerto C, debe de tener una configuración de la forma 0xF8, o 0x00 para mayor facilidad.
•La frecuencia de trabajo del microcontrolador es de 4Mhz con el oscilador interno, no es necesario subirlo a 8Mhz ni tampoco utilizar un cristal.
•Ten cuidado con la dirección de los diodos, recuerda que el cátodo se dirije a las salidas del demultiplexor.
•A la hora de conectar la matriz recuerda que el pin uno corresponde a la parte inferior, si pones la matriz al reves no va a funcionar.

 

Software:

Una vez que ya tenemos claro como se dibujan imágenes en la matriz led y ya teniendo el hardware listo, ya solo queda programar el código.

Lo primero que tenemos que hacer es crear nuestra animación, puede ser una simple figurita sin movimiento, o bien, algo un poco más sofisticado, ya depende de ti.
Para diseñar las animaciones recomiendo que utilicen el siguiente software:

Matriz Led Studio

Este programa es gratuito, está especialmente diseñado para trabajar con matrices de todo tipo desde 7x7 hasta 64x64, ofrece herramientas como flips, mirrors, gradientes, figuras geométricas y demás opciones que te pueden ser de gran utilidad a la hora de modelar tus animaciones.
Cuenta con varias opciones de exportación, soporta configuraciones little indian y big indian, macros, y una cantidad de opciones que no he encontrado en ningún otro software libre de este tipo.
Una de las características que más me ha gustado es el soporte para exportar en formato ensamblador de microchip, ahorrando horas de trabajo.

Ya que hayas terminado tu animación, expórtalo presionando F3
Yo utilizo el formato pequeño indio, por lo tanto, el LSB está a la derecha.
La animación se desplaza de arriba para abajo, ¿ recuerdas que lo había comentado al principio?.
Los números se van a agrupar por bytes (8 bits).
Cada linea de salida establécelo en frame.
El formato de número no es importante, pero recomiendo ponerlo en hexadecimal.
Si tienes alguna duda presiona sobre la imágen para verla más grande.Voy a dejar mi archivo de animación para que te sirva de guia: byteman.leds

 

Te recomiendo que tu animación por ahora sea menor de 10 cuadros, una vez que sepas como funciona el motor ya puedes hacer animaciones más grandes, entonces vamos a lo que sigue, que es programar el algoritmo para mostrar tu animación en la matriz led.

Código ASM:

NOTA: El código no utiliza las definiciones del archivo inc.

Barrido: Vamos a mandar las secuencias de la animación por el puerto A.

Utilizamos un registro general para guardar el número de cuadros de animación, puedes elegir cualquier registro, yo elegí el 0x25, en mi caso el numero total de animaciones son ocho:

movlw 0x08
movwf 0x25

Definimos cinco registros, contador vertical(0x20), indexador(0x21), control de marco(0x23), contador aux(0x24) y switch(0x2A).

clrf 0x20
clrf 0x21
clrf 0x23
clrf 0x24
movlw 0x10
movwf 0x2A

Definimos los cuadros de la animación y utilizamos el PC como index.

byte_man addwf 0x02,1
dt .0, .24, .24, .60, .90, .24, .36, .102
dt .0, .24, .24, .62, .88, .24, .36, .102
dt .0, .24, .26, .62, .88, .24, .36, .102
dt .0, .24, .25, .62, .88, .24, .36, .102
dt .0, .24, .26, .62, .88, .24, .36, .102
dt .0, .24, .25, .62, .88, .24, .36, .102
dt .0, .24, .24, .62, .88, .24, .36, .102
dt .0, .24, .24, .60, .90, .24, .36, .102

Lo más seguro es que hagamos diferentes animaciones por lo tanto, conviene crear una subrutina para inicializar los registros.

recarga clrf 0x20
clrf 0x21
movlw .8
movwf 0x23
clrf 0x24
swapf 0x2A,1
return

Mandamos los datos de animación por el puerto.

anim_byteman movf 0x21,0
call byte_man
movwf 0x05
call sec_ani
btfss 0x2A,0
goto anim_byteman
call recarga
return

Hemos terminado con el primer paso, ahora vamos al siguiente.

Refresco: Antes de "retener" necesitamos controlar el demultiplexor para que haga los cambios de cuadros de la animación.

Vamos a utilizar el TMR0 para controlar la velocidad de refresco (a mayor pre-escalador más lento el refresco):

movlw 0x82
movwf 0x81

Establecemos la subrutina de refresco:

refresh clrf 0x01
btfss 0x0B,2
goto $-1
bcf 0x0B,2
return

Ahora incrementamos el demultiplexor para que pase al siguiente cuadro de animación:

sec_ver movf 0x20,0
movwf 0x07
incf 0x20,1
xorlw 0x07
btfss 0x03,2
return
clrf 0x20
return

Eso sería todo en cuanto al refresco, ahora solo queda la última etapa.

Retención: Para retener el cuadro hice un algoritmo que retenga el bloque actual y aparte pueda acceder a cualquier cuadro de la animación.

Establecemos el número de veces que se va a repetir el mismo cuadro:

movlw 0x40
movwf 0x22

Ahora creamos el algoritmo para retener el cuadro:

sec_ani call sec_ver
call refresh
decfsz 0x22,1
goto $+2
goto $+9
incf 0x21,1
movf 0x21,0
xorwf 0x23,0
btfss 0x03,2
return
movf 0x24,0
movwf 0x21
return
movlw .64
movwf 0x22
movf 0x23,0
movwf 0x24
movwf 0x21
movlw .8
addwf 0x23,1
decfsz 0x25,1
return
swapf 0x2A,1
return

Eso es todo, ya solo queda llamar la subrutina para que empiece la animación:

call anim_byteman

¿Pero qué está pasando? después de ver la animación la pantalla se queda en negro :'(
Es por eso que implementé en el algoritmo la capacidad de acceder al número de cuadro que queramos que se repita :B.
Como son 8 cuadros totales, quiero que se repita el último por lo tanto, 8*7 = 56 los límites serían 56 y 64, cargamos esos números a los registros de control:

recarga_byte clrf 0x20
movlw .1
movwf 0x25
movlw .64
movwf 0x23
movlw .56
movwf 0x24
movwf 0x21
return

Si te preguntas por qué multipliqué por 8, es simple, recuerda que cada cuadro de animación es de 1 byte (8 bits).
Llamamos la nueva subrutina y veamos que pasa:

call anim_byteman
call recarga_byte
call anim_byteman
goto $-2

Resultado y palabras finales:

Si hiciste bien todos los pasos deberías de ver la imagen que diseñaste en la matriz led, si por algún motivo no es así, revisa primero lo "obvio"
Revisa si está conectado el circuito y que tienes energía en la linea, polaridad de los circuitos integrados, revisa de nuevo las conexiones, si todo está bien conectado y en su lugar, lo más probable es que sea error de programación.
Depura tu código utilizando las herramientas del IDE que estés utilizando, en mi caso, estoy utilizando Mplab versión 8.92, debo de admitir que el MplabX me recuerda un tanto a mikroC, en ese aspecto MplabX tiene nuevas funciones que ayuda en la depuración, lo que sigue sin convencerme es tener todas los registros de depuración importantes (al menos para mi) SFR, ROM y Watch en una sola ventana, supongo que es cuestión de gustos.

Una vez revisado tu código, ya que esté libre de errores y estés 100% seguro que todo está correcto vuelve a programar el microcontrolador, seguro que esta vez seras capaz de ver tu animación en la matriz led.
De todas maneras aquí les dejo el archivo asm: byteman.asm
Y el archivo hex para que prueben su hardware antes de seguir adelante byteman.hex

Con esto hemos terminado, ahora solo dedícate a diseñar tus animaciones, logotipos o cualquier cosa que se te ocurra.
No se olviden de recomendar esta pagina en facebook, twitter, google plus o cualquier otra red social, foro, pagina web, o medio de comunicación, también pueden seguirme en twitter @edx_twin3 donde pongo las ultimas noticias sobre la página.
Como siempre cualquier duda, sugerencia, comentario, etc ...., la pueden enviar ya sea mediante la pagina de contacto, mediante correo electrónico edx@edx-twin3.org o utilizando el blog.
Por último pero no menos importante cualquier donativo es de gran ayuda para seguir haciendo tutoriales como este, gracias :1.

Licencia de Creative Commons
Byteman by E. David Rojas Serrano is licensed under a Creative Commons Reconocimiento-CompartirIgual 4.0 Internacional License.
Creado a partir de la obra en www.edx-twin3.org/byteman.html.
Puede hallar permisos más allá de los concedidos con esta licencia en www.edx-twin3.org/