Menú gráfico para pantalla OLED en Arduino

Ya se iba echando en falta algún artículo de menús, así que allí que vamos.

Antes de comenzar, recordemos los anteriores artículos. En el último de ellos pudimos ver un menú para pantallas LCD que permitía de manera bastante flexible mostrarse en pantallas con las líneas y columnas que le indicásemos en el código sin tener que tocar mucho más.

En esta ocasión tenemos un menú para pantallas OLED, que, si bien no es tan flexible en ese aspecto debido a que hay gráficos y formas geométricas que necesitan ser pintadas para el tamaño concreto de la pantalla, sí que contamos con bastante código interesante.

Antes, veamos cómo se ve en pantalla dicho menú que hice para la placa Grove de SeeedStudio:

 

Y este sería su código completo:

 


 

Revisémoslo ahora por partes:

El primer bloque a destacar es el de declaraciones de las funciones, no es nada del otro mundo, pero el hacer esto nos va a permitir en las siguientes líneas generar un array de funciones al cual podremos llamar indicándole simplemente la función (submenu) que queremos ejecutar. Todas han de tener el mismo tipo de entrada y salida.

 

Después tenemos la declaración de un conjunto de arrays: títulos, descripciones, funciones, e iconos. (Justo después de este código encontramos lo mismo para una de las opciones del menú principal que al ser pulsada abre un submenu con tres opciones!)

 

El loop de este sketch contiene dos partes importantes: Por un lado, la llamada a la función que hayamos seleccionado (o marcado por defecto en la primera ejecución) y por otro lado la ejecución del menú para seleccionar la opción/función/submenu que queremos ejecutar.

 

Hay que entender que mediante la ejecución de cualquiera de nuestras funciones, mediante el array funcDEMO, estamos haciendo que el programa permanezca dentro de la función hasta que el usuario decida regresar mediante una pulsación larga. La gestión de esos eventos se lleva dentro de la función debido a que puede ser interesante ya no solo capturar si se quiere salir si no también cualquier otro evento/pulsación para interactuar con el código que hayamos definido en la función, en un submenu por ejemplo.

Una vez que el usuario haya salido de la opción seleccionada, por el mismo o por defecto en la primera ejecución, se ejecutara el do while el cual cargara el menú principal y que permanece ahí hasta que de nuevo, el usuario seleccione otra opción. Cuando eso suceda se terminará la iteración del loop principal y se comenzara con la siguiente iteración la cual cargara la nueva función seleccionada… así una y otra vez.

 

El menú principal cuenta con tres bloques. El primero y el ultimo mostraran la opción anterior y siguiente a la opción que actualmente tengamos seleccionada siempre y cuando sea posible: si actualmente hemos seleccionando la opción 0 no podemos mostrar nada como opción previa pues no hay más, lo mismo si seleccionamos la ultima opción.

El segundo bloque mostrara la opción seleccionada con su título, descripción e icono.

 

Y prácticamente hemos terminado de revisar todo el código, ya que lo que queda corresponde al código de cada función y al de algunas subfuciones para encapsular ciertas cosas repetitivas o reutilizables.

Vamos a ver al menos una de las funciones, la mas sencilla de todas:

Si nos fijamos en el código de esta función y del resto veremos que hay ciertos bloques iguales. Por un lado, tenemos en la parte superior la declaración de las funciones. Después comienza el primer bucle el cual se ejecutará indefinidamente hasta que el usuario decida, después tenemos otro bucle que se requiere para pintar la pantalla.

Todo el código que necesitemos para hacer cálculos, preparar los datos, etc. deberá estar entre el primer bucle y el segundo, y por supuesto no debemos olvidar nunca hacer la lectura de la interfaz que le permita al usuario salir del menú… en este caso un único botón que devuelve si ha sido pulsado con una pulsación corta, larga o nada.

La placa de desarrollo que estaba usando no permitía uso de interrupciones por como estaban precableados los módulos al microcontrolador, deberías de usar interrupciones con tus botones siempre que puedas en vez de leer constantemente el estado de los botones ya que el delay que hay por el uso de algunas librerías o por tus propios delay() que incluyas harán que no siempre las pulsaciones del usuario sean leídas… cuidado con eso!

Una vez el segundo bucle comienza se procede a pintar la interfaz gráfica por pantalla. Dado que en todas las funciones se desea pintar el mismo marco y cabecera decidí encapsular ese código común en dos funciones. Justo después de eso se pinta las partes específicas de la función.

 

Y eso es todo el menú. Básicamente con 4 líneas podemos añadir nuevos submenus, solo hay que añadir una función con el comportamiento que queramos, y un título descripción e icono a los correspondientes arrays.

Escriba aquí su comentario