Crea menús LCD personalizados en Arduino con XOD – Sin programación
Componentes y suministros
| Componente | Descripción | Cantidad |
|---|---|---|
| Arduino UNO | 1 | |
| Shield LCD/Keypad DFRobot para Arduino | 1 |
Aplicaciones y servicios en línea
- Entorno XOD
Sobre el proyecto
Los procesadores que alimentan las placas de desarrollo Arduino no son los microcontroladores de tu abuelo: tienen una potencia de procesamiento seria y pueden usarse para monitorizar y controlar muchos tipos de hardware físico y sensores simultáneamente. El IDE de programación gráfica XOD para Arduino puede simplificar la tarea de prototipado rápido de diseños de hardware, pero a medida que un sistema crece en complejidad surge el problema del control del usuario y la gestión de información: cómo organizar la información sobre el proceso controlado para su visualización y permitir al usuario controlarlo de manera lógica. Botones e interruptores dedicados funcionan para proyectos simples, pero pronto se acaban las formas lógicas de organizarlos (o lugares para colocarlos en una carcasa). Muchos diseños usan una pantalla para dar este tipo de retroalimentación; incluso un microondas suele tener una pequeña pantalla que permite editar ajustes y tiempos de cocción, y aunque demasiado "navegación por menús" para acceder a ajustes oscuros puede comprometer la experiencia de usuario, las interfaces basadas en menús son una realidad para proyectos de todo tipo.
Los frameworks de software para desarrollar interfaces basadas en menús en C o C++ para microcontroladores suelen tener una curva de aprendizaje pronunciada y pueden ser difíciles de modificar rápidamente, ya que a menudo todo interactúa con todo. El objetivo de este proyecto fue usar el entorno de programación gráfica XOD para proporcionar la capacidad de prototipar rápidamente interfaces controladas por menús para proyectos con microcontroladores compatibles con Arduino, usando un estilo de interfaz drag-and-drop/WYSIWYG. Los parámetros de entrada y salida de la estructura de menú generada son modulares y genéricos y deberían poder usarse con una amplia variedad de fuentes de entrada (interruptores, botones, encoders) y producen una secuencia de salidas de texto plano que pueden alimentarse a una amplia variedad de tipos de pantalla compatibles con XOD, incluyendo módulos LCD de texto multilínea como se usa en este ejemplo.
Si no estás familiarizado con el entorno XOD que usa este proyecto, consulta primero los tutoriales de ese proyecto en xod.io.
Ejemplo motivacional simple
Una captura de pantalla de un boceto de ejemplo motivacional simple sigue. Recorreremos este diagrama de parches XOD sección por sección para explicar cómo encaja todo.

Sección de interfaz del controlador de menú
A la derecha de la pantalla de edición de parches en XOD hay cuatro nodos conectados en cascada. De arriba a abajo:
- Un nodo de tipo entrada analógica, seleccionado para conectarse a uno de los puertos analógicos del Arduino. En mis pruebas usé un Arduino Uno con procesador ATMega328 de 8 bits, con un shield LCD/keypad 16x2 conectado encima. El teclado del shield se conecta a través de los pines del shield a la entrada analógica "A0" del Arduino, y el hardware genera niveles de voltaje diferentes para señalar qué botones del pad están pulsados.
- El segundo nodo, alimentado por el de entrada analógica, contiene código que decodifica los diferentes voltajes correspondientes a cada tecla, y genera disparadores de tipo pulso según qué botón se presiona. Se proporciona una entrada "timeout" para que un desarrollador XOD pueda ajustar el tiempo de antirrebote del teclado del shield LCD y evitar disparos falsos, ajustado al tipo de botón o interruptor de la aplicación.
- El tercer nodo es un nodo controlador de menú, que contiene código para aceptar disparadores de pulso del panel de control y manejar la lógica de navegación del usuario por el árbol de menús y hacer selecciones que generan actualizaciones de estado del árbol de menús.
- Actualmente implementado, acepta una única entrada de tipo Número que puede ser cualquier parámetro que el usuario pueda cambiar desde un control externo, digamos un potenciómetro o dial en un panel de control que representa algún parámetro modificable. Cuando un menú de tipo hoja es seleccionado por el controlador de menú al recibir un pulso en su entrada "Invoke", el nodo de la pantalla que el usuario está viendo generará un pulso en su propia salida y también enviará un cambio de parámetro. Hay también dos entradas String para generar una pantalla de bienvenida en la pantalla al encender el Arduino.
- Siguiendo ese nodo hay un módulo controlador LCD 16x2 estándar de la librería estándar de XOD, pero cualquier tipo de pantalla que tenga un módulo disponible puede usarse para mostrar el texto de salida aquí.
Sección del árbol de menús
En la parte superior de la captura del boceto hay una estructura en forma de árbol que, al compilarse y enrutar la "raíz" final del árbol a la entrada del controlador de menú que la acepta, generará automáticamente un menú navegable tal como se ve en el diseñador gráfico. Actualmente implementados tres tipos de nodos de árbol de menús:
- Menú hoja - un submenú final, sin puertos de entrada naranjas - representa alguna acción o parámetro que el usuario puede controlar.
- Menú rama - con entrada y salida, donde el usuario puede seleccionar entre varios submenús hijos.
- Menú concat - donde los submenús se agrupan y se alimentan a la entrada de un menú tipo rama, para hacer un grupo de opciones.
Seleccionar "invoke" cuando se muestra un menú tipo "rama" desciende a su grupo de submenús asociado, en lugar de generar una salida como hace un menú tipo hoja. ¡Sub-sub-menús, sub-sub-sub-menús, etc. son posibles! Estructuras complejas pueden implementarse, limitadas principalmente por los recursos de RAM y Flash del modelo de Arduino usado.
Sección de salida
En este ejemplo, la sección de salida es donde los menús tipo hoja interfaccian con hardware externo a través de los pines de salida del Arduino. Cada menú tipo hoja tiene una salida de tipo Pulso que se conecta a un flip-flop respectivo a través de un bus, para conmutar su pin de salida digital asociado encendido/apagado. Este tipo de disposición podría usarse para controlar relés o LEDs externos, pero las salidas de pulso son muy generales, y el pulso de salida generado al seleccionar "Invoke" al acceder a la pantalla de un menú tipo hoja podría usarse para muchas tareas, como actualizar un nodo tipo buffer interno de XOD donde los datos de parámetros del puerto de entrada de parámetros del controlador de menú se retienen para uso futuro.
Problemas conocidos actuales
- Este conjunto de nodos ha sido probado y debería funcionar bien con Arduino Uno tal cual, pero quedan algunos problemas sin resolver para la fecha límite del proyecto. Actualmente debe haber un menú tipo rama en el árbol en algún lugar para que un boceto compile, aunque la mayoría de proyectos probablemente querrían tener al menos uno.
- La entrada de menú "top" al controlador de menú, destinada a volver completamente a la pantalla de título de la interfaz, no está implementada aún pero debería ser una característica fácil para la próxima revisión.
- Pantallas de cuatro líneas son compatibles con el nodo controlador de menú, pero la interfaz de menú tipo hoja con cuatro líneas de entrada de texto no se ha escrito aún.
- Se ha puesto mucho esfuerzo en reducir la sobrecarga de memoria, pero la forma en que el transpilador XOD almacena actualmente las cadenas constantes no es óptima para sobrecarga de RAM muy baja, y las interfaces basadas en menús tienden a tener mucho texto. Para este proyecto se desarrolló una solución alternativa y se añadieron nodos de tipo cadena-en-flash en el parche para asegurar que cadenas más largas no consuman RAM preciosa. Esperemos que esto se solucione en una actualización de XOD, pero la solución alternativa funciona bien por ahora.
- Usar los nodos de cadena-en-flash no es demasiado doloroso pero requiere duplicar el parche y el código para cada nueva cadena almacenada en memoria de programa, y hacer clic en el código C++ contenido en el propio nodo para editar la cadena de salida.
- La entrada "ID" de nodos hoja y rama no tiene función aún. La idea es que sería bueno que cada conjunto de submenús tuviera números ID asociados en orden para que el usuario pueda rastrear su posición en un conjunto de pantallas, pero requerirá más pensamiento sobre cómo codificar esto en C++ para que ocurra automáticamente.
Trabajo continuado
- Más pruebas de bugs y pruebas en otros dispositivos Arduino además de AVR/ATmega, como ARM.
- El conjunto actual de tipos de nodos de menú es algo limitante; debería haber más variedad de entrada y salida.
- Continuar trabajo en reducir la sobrecarga de RAM, quizás usando más metaprogramación en tiempo de compilación y almacenando tantos datos como sea posible en memoria Flash en lugar de interconectar/concatenar los componentes del árbol en tiempo de ejecución.
Segundo ejemplo (19/2/19)
Esta segunda captura de boceto muestra cómo usar el controlador de menú para tomar un valor externo o interno como entrada al controlador, mostrar los valores actual y anterior en una página de menú deseada, y seleccionar un nuevo valor y almacenarlo en un buffer.

A la derecha, el nodo controlador de menú recibe la salida de un contador, alimentado por un nodo "clock". Pero esto podría ser cualquier tipo de valor de datos interno, o un valor externo de, digamos, un potenciómetro conectado a una entrada analógica. La salida del contador también se envía a un nodo de formateo de cadena, y se concatena con texto de visualización para mostrar el valor actual recibido por el controlador en la segunda línea del LCD, cuando se muestra esa página de menú.
Las salidas "invoked" y "param" del menú hoja "A" se envían a un nodo "buffer" de la librería estándar de XOD. La salida del buffer se enruta de vuelta a una disposición similar a la anterior, excepto por el nodo "defer", necesarios para romper bucles de retroalimentación en bocetos XOD. El valor almacenado en el buffer se muestra en la primera línea del LCD.
Cuando el nodo controlador de menú recibe un pulso de disparo "invoke" del controlador de teclado, el nodo A-out emite el valor de parámetro de entrada del controlador de menú, en este caso el valor actual del contador, y un pulso de disparo "invoked" que activa la rutina de actualización del buffer y almacena el nuevo parámetro en el buffer. La pantalla se actualiza automáticamente para reflejar el nuevo valor almacenado.
El puerto de salida del buffer puede enrutarse luego a cualquier número de otros nodos para cambiar su comportamiento reflejando el nuevo valor de datos que el usuario ha seleccionado.

Código
Librería XOD Menu System
Disponible en: https://xod.io/libs/bitrex/xod-menu-system-11
Añade bitrex/xod-menu-system a las librerías del boceto desde el navegador de librerías en Archivo → Añadir librerías... dentro del entorno XOD.
No hay vista previa (solo descarga).
Esquemáticos
Abrir directamente con el IDE XOD: xodmenusystemrev1_1_4-1-19_fLVYrcSgbX.xodball
Proceso de manufactura
- Construye un Decodificador DTMF Solo con Arduino – Sin CI Externos
- Crea un Impresionante Sistema Ambilight para Monitor con Arduino
- Construye un Dispositivo de Levitación Ultrasónica con Arduino – Guía Paso a Paso
- Crea Animaciones y Juegos en LCD 16×2 con Arduino UNO
- Construye un Voltímetro Inteligente con Arduino y Smartphone – Proyecto DIY Fácil
- Monitor de Frecuencia Cardíaca IoT en Tiempo Real con Arduino y MAX30100
- Servidor Web Arduino Uno WiFi: Controla un LED desde el Navegador
- Contador Inteligente de Plazas de Aparcamiento: Seguimiento en Tiempo Real con Arduino, Processing y PHP
- Automatiza el Juego del Dinosaurio de Chrome con Arduino y Python
- Construye una Radio FM Compacta con Arduino Nano y RDA5807M
- Shield de Programación Inalámbrica para Arduino con HC-05 Bluetooth – Sin Cable USB