Saltar a contenido

65. LVGL Libreria gráfica ligera y versatil

lvgl es una librería disponible para varios dispositivos tanto microcontroladores como MCU.

65.1 Características

  • Bloques básicos poderosos: botones, gráficos, listas, deslizadores, imágenes, entre otros.
  • Gráficos avanzados: animaciones, anti-aliasing, opacidad, desplazamiento suave.
  • Compatibilidad con diversos dispositivos de entrada: panel táctil, ratón, teclado, codificador, etc.
  • Soporte multilenguaje: codificación UTF-8.
  • Soporte para múltiples pantallas: incluso con formatos de color mixtos.
  • Elementos gráficos totalmente personalizables: estilos similares a CSS.
  • Independiente de hardware: compatible con cualquier microcontrolador o pantalla.
  • Escalable: puede funcionar con poca memoria (64 kB de Flash, 16 kB de RAM).
  • Soporte opcional para sistemas operativos, memoria externa y GPU, aunque no son necesarios.
  • Operación con un único búfer de fotogramas incluso con efectos gráficos avanzados.
  • Escrito en C para máxima compatibilidad (compatible con C++).
  • Simulador: permite diseñar interfaces gráficas embebidas en una PC sin necesidad de hardware.
  • Código reutilizable: el código desarrollado en el simulador se puede integrar en el firmware para un desarrollo más eficiente.
  • Vinculación con MicroPython.
  • Recursos para un diseño rápido de interfaces gráficas: tutoriales, ejemplos, temas.
  • Documentación disponible en línea.
  • Libre y de código abierto bajo la licencia MIT.

65.2 Bases para usar LVGL

Flujo de controls y datos:

Flujo de controls y datos

Se crear un Display (lv_display) para cada dispositivo físico.

En el Display se crean Screen Widgets o simplemente Screen y dentro de este los widgets.

Para manejar dispositivos táctiles, ratón, teclado, etc., se crea un Dispositivo de Entrada para cada uno. La Interfaz de Ticks informa a LVGL sobre el tiempo actual.
El Controlador de Temporizadores impulsa los temporizadores de LVGL, que a su vez realizan todas las tareas relacionadas con el tiempo de LVGL:

  • Refresca periódicamente las pantallas.
  • Lee los dispositivos de entrada.
  • Dispara eventos.
  • Ejecuta animaciones.
  • Ejecuta temporizadores creados por el usuario.

65.3 Tarea de la Aplicación

Después de la inicialización, la tarea de la aplicación se limita a:

  • Crear árboles de widgets cuando sean necesarios.
  • Gestionar los eventos que generan esos widgets (a través de la interacción del usuario u otras acciones).
  • Eliminar los widgets cuando ya no sean necesarios. LVGL se encarga del resto.

65.4 Conceptos Principales

65.4.1 Display vs Screen

Antes de entrar en detalles sobre los Widgets, es importante aclarar la diferencia entre dos términos clave que se mencionarán con frecuencia:

  • Display o Panel de Visualización: el hardware físico que muestra los píxeles.
  • Objeto Display (lv_display): un objeto en RAM que representa un Display y es utilizado por LVGL.
  • Screen: el Widget "raíz" en los árboles de Widgets mencionados anteriormente, que está "vinculado" a un Display específico (lv_display).

65.4.2 Display Predeterminado

Cuando se crea el primer objeto Display (lv_display), este se convierte en el Display Predeterminado. Muchas funciones relacionadas con los Widgets de tipo Screen utilizan el Display predeterminado. Consulta Default Display para más información.

65.4.3 Widgets de Tipo Screen

En esta documentación, el término Screen Widget se acorta frecuentemente a simplemente Screen. Sin embargo, es fundamental entender que un Screen es cualquier Widget creado sin un padre: la "raíz" de cada árbol de Widgets. Consulta Screens para más detalles.

65.4.4 Screen Activo

El Screen Activo es el Screen (y sus Widgets secundarios) que se está mostrando actualmente. Consulta Active Screen para más información.

65.4.5 Widgets

Después de inicializar LVGL (consulta Inicialización de LVGL), el siguiente paso para crear una interfaz de usuario interactiva es que la aplicación construya un árbol de Widgets. Este árbol puede ser procesado por LVGL en el Display asociado y permitirá la interacción del usuario.

¿Qué son los Widgets? Los Widgets son elementos gráficos "inteligentes" de LVGL, como:

  • Widgets Base: rectángulos simples y Screens.
  • Widgets interactivos: botones, etiquetas, casillas de verificación, interruptores, deslizadores, gráficos, entre otros.

Construcción del Árbol de Widgets Para construir un árbol de Widgets, la aplicación debe:

  1. Obtener un puntero a un Widget de tipo Screen.
  2. Se puede utilizar el Screen predeterminado creado con el Display (lv_display).
  3. También se pueden crear nuevos Widgets de tipo Screen.
  4. Para crear un nuevo Screen Widget, simplemente crea un Widget pasando NULL como argumento del padre.
  5. Nota técnica: Aunque técnicamente cualquier tipo de Widget puede ser usado como Screen, en la mayoría de los casos se utiliza un Widget Base.
  6. Ejemplo especial: En algunos casos, un tipo diferente de Widget, como una imagen, puede ser usado como Screen.

La aplicación añade Widgets al Screen como hijos dentro del árbol de Widgets. Los Widgets se añaden automáticamente como hijos de su Widget padre al momento de su creación. El padre del Widget se pasa como primer argumento a la función que crea el Widget. Una vez añadido, se dice que el Widget padre "contiene" al Widget hijo.

Relación entre Widgets * Cualquier Widget puede contener otros Widgets. * Ejemplo: Si deseas que un botón tenga texto, crea un Widget de tipo Label y añádelo como hijo del botón. * Relaciones y efectos de los Widgets padre-hijo: * Movimiento: Cuando el Widget padre se mueve, sus hijos también se mueven. * Eliminación: Al eliminar un Widget padre, todos sus hijos también se eliminan. * Visibilidad y recorte: * Un Widget hijo es visible únicamente dentro de los límites de su padre. * Cualquier parte del Widget hijo que esté fuera de los límites del Widget padre será recortada (es decir, no se renderizará).

Gestión de Screens Creación y Eliminación de Screens

  • Los Screens (y sus Widgets hijos) pueden ser creados y eliminados en cualquier momento, excepto cuando el Screen es el Screen Activo.
  • Si deseas eliminar el Screen actual al cargar uno nuevo:
    • Usa la función lv_screen_load_anim() y pasa true como argumento en auto_del.
  • Si prefieres mantener el Screen actual en RAM al cargar uno nuevo:
    • Pasa false como argumento en auto_del o utiliza lv_screen_active() para cargar el nuevo Screen.

Mantener Screens en RAM Un diseñador del sistema puede optar por mantener varios Screens (y sus Widgets hijos) en RAM, por ejemplo, para volver a mostrarlos rápidamente más adelante.

Ventajas y desventajas de esta estrategia:

  • Mayor consumo de RAM: Almacenar varios Screens simultáneamente requiere más memoria.
  • Ahorro de tiempo: Evita la necesidad de crear repetidamente el Screen y sus Widgets hijos.
  • Utilidad en Screens complejos: Es especialmente útil si el Screen es complejo y/o necesita ser el Screen Activo con frecuencia.

Gestión de Screens en RAM

Cuando se mantienen múltiples Screens en RAM simultáneamente, la responsabilidad de su gestión recae en el diseñador del sistema. Es importante planificar cuidadosamente cómo y cuándo se crean, almacenan y eliminan los Screens para optimizar el uso de recursos.

65.4.6 Creación de widgets

Los Widgets se crear con funciones de este tipo:

lv_<type>_create(parent)
Donde <type> es el tipo del Widget que se quiere crear.

Que devuelve lv_obj_t *

Ejemplo:

lv_obj_t * slider1 = lv_slider_create(lv_screen_active());

65.4.7 Propiedades de los widgets

Los atributos comunes a todos los widgets se establecen con funciones del tipo:

lv_obj_set_<attribute_name>(widget, <value>)
ejemplo:

lv_obj_set_x(slider1, 30);
lv_obj_set_y(slider1, 10);
lv_obj_set_size(slider1, 200, 50);
Tambien hay atributos propios que se modifican con las funciones:

lv_<type>_set_<attribute_name>(widget, <value>)
Ejemplo:
lv_slider_set_value(slider1, 70, LV_ANIM_ON);

65.4.8 Borrado de Widgets.

Para borrar un widget y sus hijos:

lv_obj_delete(lv_obj_t * widget)

65.5 Eventos

65.6 Apendice

Enlaces * https://lvgl.io/ * Documentación