Luz electoral
o cómo mostrar los resultados de las elecciones autonómicas en 33 píxeles
Aprovechando nuestra asistencia como jurado al hackaton “Hacking elections”, organizado por El Confidencial y Civio, y en el que Tecnilógica participaba como colaborador, decidimos presentar fuera de la competición un proyecto de visualización de los datos electorales de las elecciones autonómicas españolas de 2015.
El único requisito — autoimpuesto — fue no utilizar la pantalla del ordenador para mostrar los datos. En vez de una pantalla, usaríamos una tira de ledes controlada por un Arduino Uno.
tl;dr: hemos subido el código a https://github.com/tecnilogica/luzelectoral
Partimos de la idea de mostrar la distribución de los escaños utilizando una resolución muy limitada: 33 ledes RGB, puestos en fila. El número 33 no tiene ningún significado especial, no es más que el tamaño de la tira que teníamos disponible en ese momento. Cada partido político iría asociado a un color y de un vistazo se podría saber la distribución aproximada de los partidos.
El primer paso consistió en analizar los datos de las elecciones. Tras un recuento rápido, encontramos que había más de treinta partidos con escaños. Relacionar cada partido con un color consumiría gran parte del tiempo disponible, así que optamos por agrupar los partidos en seis bloques: PP, PSOE, Podemos, Ciudadanos, partidos nacionalistas y otros, eligiendo colores reconocibles para los partidos “principales”.
Una vez tomada la decisión de agrupar los partidos, el siguiente paso consistió en agrupar los datos, asignando los escaños de cada municipio a una de estas seis categorías. En la fuente de datos vimos diferentes niveles de detalle (provincias, autonomías, circunscripciones…) que decidimos conservar, para ofrecer mayor detalle en los datos.
Con los datos ya en limpio, pensamos en la manera de representarlos. Electrónicamente, cualquier representación era válida: el Arduino alimentado por USB da la suficiente potencia en la salida de 5v para alimentar los 33 píxeles y que muestren el máximo brillo posible.
Al contar con 33 píxeles, si queríamos mostrar la distribución de todos los escaños, tendríamos que aplicar una escala diferente a cada región (unas tienen tres escaños, otras más de cincuenta), y eso impediría establecer relaciones entre las diferentes zonas, por lo que desechamos esta solución. La siguiente visualización valorada consistía en iluminar todos los píxeles con el color correspondiente al partido que representaban y mantenerlos iluminados según el número de escaños: a más escaños, más tiempo. Esta aproximación, aunque válida, resultaba demasiado estática y demasiado parecida a una mood light, así que también la descartamos. Finalmente, optamos por mostrar tantos píxeles como escaños y, si hubiera más escaños, hacer que los colores se desplazaran por la barra, aportando el dinamismo buscado. Esto permitía usar la misma escala en todas las regiones, y apreciar de manera más intuitiva la distribución de los votos.
Una vez decidida la visualización, empezamos a programar el Arduino. Albacete, con tres escaños para el PP, dos para el PSOE y uno para Podemos, resultó agraciada como “provincia conejillo de indias”. La solución técnica consistió en crear un array (El Array a partir de ahora) con tantos elementos como el total de escaños. El valor de cada elemento es un número entre cero y cinco (seis valores, el total de partidos), reservando el valor -1 como indicador de píxel apagado. A la hora de encender los píxeles, bastaba con recorrer El Array e iluminar el píxel con el color asociado a ese valor (el color de ese partido). En el caso de Albacete, El Array quedaría como 0 0 0 1 1 2 2 -1 -1 -1 -1 … Para evitar valores extraños cuando había menos de 33 escaños, rellenamos las posiciones sobrantes de El Array con -1 hasta llegar a los 33 píxeles. En ciertas zonas, El Array podía tener más de 33 posiciones; en esos casos no haría falta rellenar El Array con valores adicionales.
Al iluminar los píxeles nos dimos cuenta de dos cosas: por un lado, los píxeles sueltos no destacaban demasiado, así que habría que asignar al menos dos píxeles por escaño. Además, en la zona de transición entre los diferentes partidos los colores tendían a mezclarse, por lo que habría que incluir cierta separación entre los partidos. Modificamos el código para incluir dos constantes, una para indicar el número de píxeles por escaño y otra para indicar los márgenes y tuvimos en cuenta esta casuística a la hora de generar El Array. Con estos cambios, El Array de Albacete, con tres píxeles por escaño y dos huecos entre partidos, quedaría de la siguiente manera: 0 0 0 0 0 0 0 0 0 -1 -1 1 1 1 1 1 1 -1 -1 2 2 2 -1 -1 -1 -1…
Los huecos nos planteaban un problema: si hubiera circunscripciones con un escaño del PP y otro de Ciudadanos, El Array generado tendría este aspecto: 0 -1 –1 -1 3 -1 -1 -1… Es decir, acumularíamos la separación del PP con la del PSOE y la de Podemos, generando un hueco mayor de lo que corresponde. Para evitarlo, si un partido tenía cero votos, no generaríamos separación. De esta manera, El Array quedaría así: 0 -1 3 -1 -1 -1….
El siguiente paso fue implementar el scroll. Para ello usamos una constante que indicaba en milisegundos cada cuánto actualizábamos el display y una variable índice que nos indicaba qué posición de El Array era el punto de partida. Esa variable empezaba valiendo cero y se incrementaba en cada vuelta, hasta llegar al tamaño de (El Array -33), momento en que se volvía a resetear a cero. El problema es que en el momento que aparecía el último píxel, la animación volvía de golpe a la posición inicial, y el efecto era extraño; había un salto que no quedaba bien. En este caso, la solución era sencilla: bastó con añadir 33 valores en blanco al inicio y al final de El Array para conseguir un scroll continuo y sin saltos. El Array generado quedó con este aspecto: < 33 entradas con valor -1> <el meollo> < 33 entradas con valor -1>
Para obtener una visualización más agradable, pusimos los ledes frente a una pared blanca, de manera que la iluminara directamente y nosotros percibiéramos el resultado como luz indirecta (como hace Jim Campbell) Así evitábamos quedar deslumbrados por el brillo, y las zonas de color quedaban más homogéneas.
Como ya habíamos mareado bastante a Albacete, empezamos a añadir el resto de zonas, así como el código necesario para elegir una al azar y regenerar El Array cuando hubieran terminado de mostrarse los resultados de la zona anterior. Aprovechamos para refactorizar el código lo justo, añadir comentarios y ajustar mejor los colores asociados a cada partido, para conseguir una intensidad luminosa lo más homogénea posible.
Para probar la estabilidad del código y que no hubiera memory leaks montamos unas pruebas de carga: básicamente, poner el tiempo de espera a cero y dejar correr el programa. Al hacerlo, vimos que la animación se colgaba de vez en cuando. Las trazas nos indicaban que ocurría al tratar de mostrar dos zonas en concreto (que luego resultaron ser la misma, que aparecía repetida en los datos originales). Al analizar esta zona nos dimos cuenta de que El Array desbordaba la memoria que reserva Arduino para las variables, de tan solo 2048 bytes. La solución más rápida consistió en ajustar los tipos de datos, usando byte en vez de int en todos los sitios donde fuera posible, empezando por El Array. Así conseguimos ganar algunos bytes más de memoria y, al pasar El Array de int a byte, duplicar el número de datos que se podían almacenar en él. Otra posibilidad era pasar parte de las constantes (el array de colores y el array de votos por circunscripción) a la EEPROM y liberar así más memoria, pero los cambios en el código nos llevarían más tiempo del disponible para acabar el reto.
Por último, hicimos algunos ajustes de velocidad de scroll (40 ms entre desplazamientos), número de píxeles por escaño (6) y separación entre partidos (6), y dimos por terminado el proyecto.
Si queréis echar un ojo, tenéis el código disponible en https://github.com/tecnilogica/luzelectoral.