MicroGame: Consola de juego compatible con Arduino (Proyecto final)

Publicado por en Arduino el 21/01/2015
Comentarios:

Hace algún tiempo comentaba en este post un proyecto en el que estuve trabajando recientemente y que finalmente he terminado y me gustaría compartir con vosotros como siempre. Se trata de una cosa que he llamado MicroGame y es básicamente una pequeña consola de juegos portátil con una pantalla gráfica de 128x64 píxeles alimentada con una batería recargable y compatible con el entorno Arduino. Es un proyecto que me ha parecido muy interesante y que ha hecho que aprendiera un montón de cosas acerca de la realización de placas con componentes de superficie (SMD) así como a nivel del software necesario y requisitos para la carga de un bootloader que lo hace compatible con el entorno de Arduino y evitar el uso de un programador externo.

En mi anterior post que mencionaba, he escrito una buena cantidad de información técnica y de requisitos, así que en esta ocasión comentaré la parte del montaje final, el software y por supuesto el vídeo final de funcionamiento con su conclusiones. Como no podía ser de otra forma, este proyecto es totalmente abierto y os dejo también disponibles para su descarga todos lo ficheros de la placa PCB así como el código fuente del pequeño juego que he programado, por si alguno de vosotros quereis montar el vuestro. Por supuesto y como siempre, no dudeis en dejar vuestro comentario con vuestras opiniones!

MicroGame: Montaje final de la placa

Respecto al diseño original de la placa, he hecho algunas variaciones como la posición de la batería y también he quitado el regulador de tensión dado que la pantalla ya incluye uno así que porqué no utilizarlo. También he añadido unos agujeros en las cuatro esquinas para posteriormente intentar hacer algún tipo de caja.

MicroGame

Placa PCB MicroGame

Aunque parezca todo lo contrario, la placa es bastante sencilla y está basada casi por completo en el Pro Micro 3,3V de Sparkfun, que fué el que he utilizado para el prototipo. Simplemente un microcontrolador ATmega32U4 que incorpora ya un sistema USB para evitar utilizar un conversor FTDI, con su cristal de cuarzo a 8 Mhz y algunos componentes pasivos para su funcionamiento. Para la carga de la batería, he utilizado un integrado bastante interesante, el MCP73831 de Microchip que se encarga de todo este tema y funciona perfectamente con una pila de botón recargable de 3.6V CR2405 que he utilizado. La alimentación regulada a 3,3V ya me la proporciona la propia pantalla que lo tiene integrado. Luego los pulsadores y algunos diodos LED para generar alegría y voialà!

Os dejo unas fotos del proceso de montaje que me llevó un par de horas tomándolo con paciencia. He utilizado pasta de soldar sin plomo y una estación de aire caliente. Lo más complicado es dejar la cantidad justa de pasta sobre los pads, por lo demás fué bastante divertido. Tengo que decir que el componente más problemático fué sin duda el conector USB con el que tuve que pelearme por culpa de que sus pines de datos son tan pequeños que constantemente había puentes entre ellos, teniendo que retocarlo con el soldador de punta fina y mucho tino! Si quereis ver más imágenes a buena calidad, os dejo un album de Flickr con todas las fotos que he tomado.

El bootloader Caterina

La idea es que la placa sea programable desde el entorno de Arduino y para eso es necesario incorporar un bootloader para que no necesite un programador externo, tal y como lo hacen todas las placas Arduino. El bootloader no es más que un pequeño programa al principio de la memoria del microntrolador que se ejectuta siempre que conectamos la alimentación. Su función consiste en comprobar si por el puerto UART (pines TX/RX) se recibe una secuenta en concreto que indique que el IDE de Arduino intenta programar un nuevo programa en la memoria del microcontrolador. Si esa cadena coincide, el bootloader lee los datos y se autoprograma. Si no detecta nada, simplemente hace un salto hasta el principio del programa para ejecutarlo, que normalmente se encuentra justo despues del mismo bootloader.

Esto suena maravilloso y de hecho es extremadamente cómodo, pero irónicamente para poder aprovecharse de todas las ventajas del bootloader, necesitamos primero utilizar un programador externo para cargarlo en el microcontrolador. Yo he utilizado el programador genérico de AVR de Pololu que permite programar sin problema el bootloader o lo que queramos.

Kit programasdor AVR Pololu

Kit programador AVR Pololu

Este tipo de programadores utilizan un tipo de conector llamado ICSP (In Circuit Serial Programming) que consta simplemente de 4 pines más alimentación: MOSI, MISO, CLOCK y RESET. Hay dos variantes, uno de 6 pines y otro de 10 que es lo mismo pero por espacio no se suele utilizar mucho. Toda la plataforma Arduino utiliza el modelo de 6 pines (2x3 pines).

ISCP

ISCP - Imagen: Wikipedia

Este conector va directamente conectado a los correspondientes pines en el microcontrolador, que es mi caso es un ATmega32U4. Volviendo al bootloader, cada microcontrolador necesita de uno propio y he optado por utilizar uno bien conocido llamado Caterina y que es el mismo que utiliza el Arduino LilypadUSB ya que tiene el mismo chip. Yo he utilizado una variante de Sparkfun ya que inicialmente he hecho el prototipo en una placa Sparkfun Pro Micro 3,3V, pero realmente se puede utilizar el bootloader de LilypadUSB sin mayor problema. Debido a esto, es necesario descargar los drivers para que el ordenador lo detecte como tal y cree un puerto COM virtual que podamos seleccionar desde el entorno de Arduino. Sparkfun tiene una excelente guía donde lo explica todo al detalle. Al utilizar el bootloader de Sparkfun y para que funcione la placa desde el entorno de Arduino, es necesario descargar e instalar también el Addon para Arduino de Sparkfun. Si queremos evitar ese paso, se puede simplemente carga el bootloader de LilypadUSB yas que viene por defecto en el IDE, pero básicamente es lo mismo.

Bueno, a lo que vamos, es hora de conectar el programador a la placa, teniendo en cuenta que este programador no alimenta la placa, por lo tanto, es necesario tenerla simultáneamente conectada por USB (y encendida!) para que reciba su alimentación.

Llegado a este punto, tenemos dos opciones, cargar el bootloader desde el IDE de Arduino seleccionando el programador y con la opción "Cargar secuencia de inicio" o bien utilizar directamente avdude con la linea de comandos correcta. En concreto la linea a enviar sería esta:

avrdude -p m32u4 -P usb -c avrispv2 -P COM2 -U flash:w:Caterina-promicro8.hex -U efuse:w:0xfe:m -U hfuse:w:0xd8:m -U lfuse:w:0xff:m

Este programador se identifica como avrispv2 y en la misma linea se envían los fuses correctos para la configuración del microcontrolador (por cierto, os recomiendo esta web sobre los fuses. También hay que indicar el puerto virtual del programador que en mi caso es el COM2 y pasados unos segundos, el micro queda programado, o por lo menos en teoría ya que aquí tuve algunos problemas de timeout con avrdude que tardé en descubrir. Esto es lo que mostraba le proceso:

Por alguna oscura razón el programador parece que hacía lo que tenía que hacer pero tardaba un tiempo exageradamente grande y además constantemente aparecían mensajes de timeout. A pesar de tardar entre 3 o 4 minutos en programar el bootloader, donde normalmente serían poco más de 15 o 20 segundos, una vez hecho la placa tampoco era detectada correctamente como un puerto COM virtual. Tras vueltas y vueltas durantes varios días, decidí probar el mismo proceso a la desesperada en otro equipo y funcionó correctamente y a la primera. Tanto la programación del bootloader como la creación del COM virtual indicando que el bootloader está vivo han funcionado a la perfección. Entonces ¿por qué no ha funcionado desde un principio? Pues bien, llegué a la conclusión que en mi PC he conectado todo el sistema en los puertos USB 3.0 y aunque no debería tener problema alguno ya que ahora practicamente todos los equipos nuevos traen este puerto, resulta que mi equipo del taller es ya algo antiguo y no dispone la placa base de puertos USB 3.0, sino que tengo conectada una controladora PCIe que me ofrece 4 puertos USB 3.0. Al no ir directamente en la placa base, es posible que la controladora se haga un lío, no detecte bien el dispositivo y ahí los errores de comunicación con la MicroGame. Para salir de dudas, he vuelto a hacer el mismo proceso en el PC del taller, pero utilizando los puertos USB 2.0 convencionales y todo ha funcionado correctamente y a la primera!

La conclusión es que he perdido unos días investigando este tema y de hecho llegué a pensar que la pequeña placa tenía algún problema ya sea a nivel de diseño o bien de hardware. Finalmente confirmado eso y llegado a este punto, se puede decir que todo el diseño funciona estupendamente tal y como esperaba!

Galaxian: El juego

Quizás sea mucho pretender llamarle Galaxian ya que mi versión no le hace gloria ninguna y solamente se parece de forma remota, pero es una pequeña prueba para ver cómo funciona todo y de paso tener la oportunidad de echar una partida y disfrutar haciendo un juego recordando los viejos tiempos! El juego es muy sencillo y se basa en una nave con forma ligeramente fálica que es capaz de disparar hasta 3 tiros simultáneos. El juego funciona en modo scroll con un pequeño campo de estrellas de fondo para dar la impresión de desplazamiento. Sobre la parte derecha aparecen "los malos". Hay un total de 5 enemigos distintos cada uno con una forma de moverse diferente para darle un poco de emoción al asunto. Disponemos de un total de 3 vidas para matar a todo bicho viviente que aparezca por delante. La mayor puntuación será almacenada en la EEPROM interna de forma permanente y se mostrará cada vez que se enciende la placa. He utilizado principalmente la librería GFX de Adafruit que es genérica para casi todas sus pantallas y también una específica para la que he utilizado llamada Adafruit_SSD1306.

Por supuesto el juego no es perfecto y tienes algunos fallos por aquí y por allí pero está estructurado en clases para poder configurarlo a gusto de cada uno. Una cosa importante si os fijais en el código es que la pantalla OLED se inicializa mediante Software SPI, no por hardware. Eso es mucho más lento y hace que actualmente este juego ande sobre los 19 o 20 fps, sin embargo pruebas posteriores que he hecho con hardware SPI en el prototipo demostraron que el mismo juego funciona perfectamente a cerca de 40fps. Esto fué desde luego un grave error de diseño que no pude solucionar porque que había enviado ya la placa a fabricar cuando realicé esas pruebas. Es una pena pero bueno, va un poco más lento de lo que puede llegar a dar pero también me fuerza a quizás hacer en un futuro una segunda versión del hardware para mejorar este aspecto y aprovechar mejor el hardware. ¡Quién sabe!

En su momento he publicado un par de vídeos mientras desarrollaba el juego, que podeis ver aquí por si quereis echar un vistazo.

Conclusiones

Conclusiones finales hay muchas. Desde luego ahora tengo mucho más claro cómo funciona todo el tema de los bootloader, sus ventajas y desventajas y el proceso de hacer una placa desde cero con componentes de superficie. Es algo tenioso y requiere de cierta paciencia pero es una aventura que me ha gusta mucho. Podría añadir que al verlo todo porfin funcionando, me doy cuenta de muchas mejoras que se le podría hacer, como por ejemplo dejar algún "test point" (puntos de prueba) para poder hacer debug en caso de ser necesario. Eso lo eché en falta cuando pensaba que la placa no funcionaba por el tema del USB. O el interruptor de encendido y apagado que debería ser lateral no vertical y es bastante frágil. También tengo que señalar que la idea era colocarle un pequeño trozo por encima de la pantalla cubriendola y dejando solo pasar los pulsadores a la superficie pero desgraciadamente los pulsadores no son lo suficientemente altos para hacerlo, así que tan solo le dejé un trozo de metacrilato por debajo para cubrir la electrónica un mínimo.

Por supuesto podreis encontrar todos los archivos del diseño así como el código fuente en Github por si quereis cotillear, copiarlo o hacer vuestra propia versión. Y de paso he dejado para el final un pequeño vídeo de todo el invento funcionando. Espero que os haya gustado y espero vuestro comentarios! :)

Si te ha gustado, compártelo con tus amigos!
Google Plus