En el tutorial anterior , aprendimos sobre las características orientadas a objetos de Python, que son importantes para organizar el código y estructurar nuestras aplicaciones. Ahora, analicemos cómo diseñar interfaces gráficas en Python.
Las aplicaciones integradas desarrolladas en microcontroladores suelen tener LED, pantallas LCD de caracteres o pequeñas pantallas LCD gráficas como dispositivos de visualización. Sin embargo, estos monitores no tienen muchas interfaces sofisticadas. Pero una computadora de placa única (como Raspberry Pi) se puede configurar como un sistema de escritorio. De hecho, configuramos nuestra Raspberry Pi (RPi) usando un escritorio Linux. Como tal, es posible disfrutar de interfaces ricas y aplicaciones de gran tamaño que se ejecutan en circuitos integrados similares.
Si bien los microcontroladores ofrecen velocidad, las computadoras de placa única tienen ventajas que incluyen un sistema operativo con fácil acceso a funciones de lenguaje de alto nivel. Interfaces gráficas enriquecidas, acceso a bases de datos, visualización de datos, gráficos 3D, redes y minería de datos son solo algunas de las características de HLL que se pueden utilizar en un proyecto integrado con SBC.
Por ejemplo, al conectar un sensor con un microcontrolador, podemos simplemente recopilar datos del sensor e implementar acciones inmediatas basadas en los datos recopilados. Sin embargo, si este mismo sensor se interconecta con un ordenador de placa única (SBC), es posible realizar varias tareas.
Éstas incluyen:
- Registre y mantenga grandes cantidades de datos de sensores en bases de datos.
- Análisis en ejecución
- Ver datos
- Realizar minería de datos
- Compartir datos y cualquier resultado con otros dispositivos en una red
- Implementar acciones inmediatas y de largo plazo.
Un dispositivo basado en microcontrolador que se ejecuta con código a nivel de firmware no puede realizar estas tareas complejas por sí solo. Como máximo, se puede configurar como un dispositivo de Internet de las cosas (IoT) conectándolo a una red. Los datos físicos recopilados se pueden manipular en una plataforma en la nube. Esta es una de las principales razones por las que las computadoras de placa única desempeñan un papel distinto en el dominio integrado.
Otra razón: los usuarios trabajan con el codiseño de hardware y software en sistemas integrados cuando trabajan en SBC. Aunque las aplicaciones basadas en microcontroladores se centran en el hardware, el usuario puede centrarse en aspectos de software. Los SBC permiten la creación de software integrado de alto nivel que utiliza la potencia de un componente de hardware.
En última instancia, lo que tiene más sentido es el software que se ejecuta en el hardware. La interfaz y el control de los LED es el "Hola mundo" de los sistemas integrados.
A continuación se muestra una captura de pantalla de una interfaz gráfica de usuario (GUI) diseñada para nuestra primera receta de controlador LED. Tómate un minuto para revisar esta GUI e intenta adivinar el nivel de control que podemos ejercer sobre un componente de hardware con un SBC.

La GUI de Python Tkinter para un controlador LED RPi.
En todas nuestras recetas de RPi, a menudo utilizamos programación GUI y subprocesos múltiples. Cuando utilicemos sensores, incluiremos visualización de datos, programación de bases de datos y extracción de datos en el software integrado.
De manera similar, cuando controlamos actuadores, construimos robots o utilizamos módulos de hardware sofisticados (como una cámara o un micrófono, etc.), es posible incluir funciones de software relevantes como procesamiento de imágenes, audio, programación multimedia, gráficos 3D y programación de software. . juegos. , etc.
La programación GUI y el multiproceso son componentes de software esenciales de todas nuestras recetas.
Programación GUI en Python
Python es un potente lenguaje de muy alto nivel (VHLL). Permite el diseño de interfaces gráficas ricas y proporciona una serie de técnicas de visualización de datos con capacidades de minería de datos. Esta es una clara ventaja en aplicaciones integradas sofisticadas.
Cuando utilicemos RPi en aplicaciones integradas, trataremos los circuitos integrados como fuentes de datos físicas (cuando se interconectan con sensores) y controladores sofisticados (cuando se interconectan con actuadores).
Las interfaces gráficas diseñadas en Python interactúan con circuitos integrados, visualizan datos de sensores, manipulan datos para análisis y toma de decisiones y brindan interactividad adicional que normalmente no es posible con los microcontroladores.

Ventana principal de Python Tkinter GUI para la aplicación de electrónica integrada RPi.
Hay varias opciones en Python para desarrollar interfaces gráficas de usuario. Los más populares incluyen:
Tkinter: la interfaz estándar de Python para el kit de herramientas Tk GUI y el estándar GUI de facto en Python. Tkinter es gratuito y se incluye automáticamente con la instalación de Python en Linux, Microsoft Windows y Mac OS X. Sin embargo, para usarlo en una aplicación, se debe importar el paquete Tkinter.
WxPython: un kit de herramientas GUI multiplataforma de código abierto para Python. Su principal ventaja son los widgets nativos (widgets nativos específicos del sistema operativo).
PyQT: enlace para el kit de herramientas GUI multiplataforma Qt. Probablemente sea la GUI más potente y sustancial para Python. PyQT es ideal para aplicaciones grandes y está disponible bajo GPL y licencias comerciales. Puede ser complicado de usar para aplicaciones comerciales.
PySide: similar a PyQT en funcionalidad, pero PySide está cubierto por la licencia LGPL. Por lo tanto, está fácilmente disponible para su uso en aplicaciones comerciales.
Hay muchos otros paquetes de GUI para Python. Antes de utilizar una aplicación, es importante conocer sus características, portabilidad, herramientas de desarrollo, licencias y limitaciones. Para aplicaciones grandes, PyQT y PySide suelen ser las mejores opciones (y PySide tiene una licencia más liberal).
También hay editores WYSIWYG disponibles para PyQT y PySide que hacen que el diseño de interfaces sea rápido y sencillo. Tkinter es la mejor opción para aplicaciones básicas.
Usaremos Tkinter para diseñar la GUI para recetas RPi. Ocupa poco espacio y se ejecuta relativamente rápido en comparación con otros paquetes. La gestión del diseño también es bastante eficiente. Estas características hacen de Tkinter una opción ideal para la interfaz de usuario integrada.
Sin embargo, tendremos que escribir código para cada widget y el manejo de eventos a veces resulta complicado. Estos esfuerzos tendrán como objetivo acelerar nuestras pequeñas aplicaciones integradas.
Tareas multiproceso integradas
En aplicaciones integradas, es común repetir ciertas tareas. Por ejemplo, es posible que necesitemos obtener datos repetidamente de un sensor o mostrar mensajes en un dispositivo de visualización. Pero las aplicaciones de escritorio rara vez involucran tales tareas: nunca querrás que el código de una aplicación de escritorio se ejecute en un bucle infinito sin fin.
En nuestras recetas RPi, implementaremos bucles infinitos típicos de aplicaciones integradas. Sin embargo, si ejecutamos estos bucles desde la aplicación GUI, nuestra interfaz se congelará y no podremos ingresar ningún otro comando.
Entonces, para cada tarea integrada crearemos un hilo separado y la GUI se ejecutará como un proceso diferente en Linux. Podemos pasar comandos para eliminar estos subprocesos con un pequeño truco de codificación para detener las tareas cuando sea necesario. Con los subprocesos, podemos tratar recetas RPi como aplicaciones integradas basadas en microcontroladores, pero de manera más eficiente.
Con el subproceso múltiple, también existen las ventajas de manejar múltiples componentes de hardware de manera simultánea e independiente. El subproceso múltiple no es posible en los microcontroladores, lo que demuestra que el SBC que ejecuta un sistema operativo integrado es fundamental.
Tkinter
Tkinter es la biblioteca GUI estándar para Python. Proporciona una interfaz orientada a objetos para el kit de herramientas Tk GUI. Cualquier GUI consta de una ventana principal en la que se muestran diferentes elementos gráficos, como etiquetas, cuadros de texto, botones, botones de radio, botones de verificación, pantallas, etc.
Estos elementos gráficos, incluida la ventana principal y otras ventanas, se denominan widgets. Las acciones del usuario, como hacer clic en un botón, centrarse en un cuadro de texto, seleccionar un botón de opción, etc., se denominan eventos. En respuesta a un evento, es posible abrir otra ventana, que luego se denomina ventana secundaria de la ventana principal.
Para crear una interfaz de usuario con Tkinter, primero importe el módulo Tkinter, lo que se puede hacer en código Python como cualquier otro módulo. El nombre del módulo es "Tkinter" en Python 2 y "tkinter" en Python 3.
Estas son instrucciones válidas para importar el módulo Tkinter en Python 3:
importar tkinter
o
desde la importación de tkinter *
o
importar tkinter como tk
En el tercer ejemplo anterior, "tk" es la referencia definida para la clase Tk. Esta referencia puede ser cualquier identificador. Después de importar el módulo Tkinter, cree una ventana principal de la aplicación GUI. Esto se puede hacer creando un objeto de instancia de la clase Tk. Para la ventana principal (que no es hija de ninguna otra ventana), el objeto Tk se crea sin ningún argumento.
Estas son declaraciones válidas para crear la ventana principal.
raíz = Tk
o
raíz = tkinter.Tk
o
root = tk.Tk # tk es una referencia a la clase Tk en la declaración de importación
Para crear una ventana secundaria, primero se debe crear el objeto de instancia con el método Toplevel, que se debe pasar a la ventana principal (objeto) como argumento.
Aquí hay una declaración válida para crear una ventana secundaria:
LED_window = nivel superior (raíz)
Todos los widgets de ventana, incluida la ventana principal, admiten múltiples métodos. De todos los métodos, el método del bucle principal es el más importante.
Hasta que se llame al método mainloop en un widget de ventana, no aparecerá en la pantalla. El método mainloop inicia un bucle infinito para ejecutar la ventana GUI, esperar a que ocurra un evento y procesar el evento mientras la ventana no está cerrada.
Por lo tanto, el método mainloop debe ser la última instrucción que se llame en un widget de ventana. Cualquier otro método llamado en el widget después del bucle principal no se ejecutará y devolverá un error.
Estas son declaraciones válidas para abrir la ventana principal de Tkinter:
raíz = Tk
raíz.mainloop
Estas son instrucciones válidas para iniciar una ventana secundaria:
LED_window = nivel superior (raíz)
ventana_LED.mainloop
Se puede destruir una ventana llamando al método de destrucción.
Aquí hay una instrucción válida para destruir una ventana (llamada ventana):
ventana.destruir
El estilo y el comportamiento de una ventana se pueden cambiar llamando a diferentes métodos. Por ejemplo, para configurar el título de la ventana, el método del título está disponible.
Esta es una declaración válida para establecer el título de una ventana (llamada ventana):
window.title (“Aplicación de control de electrónica integrada Raspberry Pi”)
Para definir el tamaño y la posición de la ventana en la pantalla, se puede utilizar el método de geometría. El método de geometría puede tomar cuatro argumentos opcionales de la siguiente manera:
ventana.geometría(“anchoxalto+/-posición_horizontal+/-posición_vertical”)
Esta es una declaración válida para definir el tamaño y la posición de una ventana (llamada ventana):
ventana.geometría (“300×300+100+50”)
Los cuatro argumentos (ancho de ventana, alto de ventana, posición horizontal y posición vertical) aceptan valores enteros en píxeles.
Observación:
- Si la posición horizontal tiene un signo más a la izquierda, el borde izquierdo de la ventana estará a tantos píxeles del borde izquierdo de la pantalla.
- Si la posición horizontal tiene un signo menos a la izquierda, el borde derecho de la ventana estará a tantos píxeles del borde derecho de la pantalla.
- Del mismo modo, si la vertical tiene un signo más a la izquierda, el borde superior de la ventana estará a tantos píxeles del borde superior de la pantalla, y si la vertical tiene un signo menos a la izquierda, el borde inferior de la ventana tendrá esta cantidad de píxeles. . desde el borde inferior de la pantalla.
El tamaño mínimo y máximo de una ventana también se puede establecer utilizando los métodos minsize y maxsize. Ambos métodos toman el ancho y el alto de la ventana en píxeles y como argumentos.
Aquí hay una declaración válida para establecer el tamaño mínimo de una ventana (llamada ventana):
ventana.minsize(480, 480)
De forma predeterminada, se puede cambiar el tamaño de una ventana y un usuario puede cambiar el tamaño de la ventana arrastrando sus bordes. El comportamiento de cambio de tamaño de una ventana se puede cambiar utilizando el método de cambio de tamaño.
Este método toma dos argumentos booleanos para establecer el ancho y el alto de la ventana redimensionable en Verdadero o Falso.
El módulo Tkinter también permite la creación de interfaces estáticas. Cuando el usuario cambia el tamaño de una ventana, su diseño puede volverse torpe debido a la naturaleza estática de la interfaz. Por lo tanto, es recomendable establecer el cambio de tamaño de una ventana en False de la siguiente manera:
ventana.resizable (Falso, Falso)
Una ventana cambia de tamaño automáticamente según los widgets secundarios que contiene. Si se establece el tamaño máximo para una ventana, es posible que algunos de los widgets secundarios no sean visibles. Como resultado, nunca se recomienda establecer el tamaño máximo de una ventana.
Una ventana puede tener varios estados, como por ejemplo:
- Normal: se muestra en la pantalla en su tamaño y posición predeterminados.
- Ampliado: se muestra cubriendo toda la pantalla
- Icono: minimizado en la barra de tareas
- Eliminado – ventana cerrada
De forma predeterminada, la ventana aparece en su estado "normal". Si está configurado para cambiar de tamaño horizontal y verticalmente, se puede ampliar al tamaño de pantalla completa haciendo clic en el botón maximizar. También se puede "ampliar" desde dentro del código configurándolo en su estado, como por ejemplo:
ventana.estado('ampliada')
Se puede minimizar una ventana al icono haciendo clic en el botón minimizar. Se puede minimizar a un ícono desde el código usando el método iconify o estableciendo su estado en 'icono' de la siguiente manera:
ventana.estado('icono')
o
ventana.iconificar
Se puede restaurar una ventana a su estado normal haciendo clic en su icono en la barra de tareas. Se puede restaurar a un estado normal desde el código usando el método deiconificar o estableciendo su estado en "normal":
ventana.estado('normal')
o
ventana.deiconificar
Usaremos los widgets temáticos ttk en nuestras ventanas GUI. ttk es un módulo independiente que proporciona acceso a widgets temáticos de Tk. Separa el código que implementa la apariencia de los widgets así como el código que implementa el comportamiento de los widgets.
Esto significa que necesitaremos importar ttk por separado con Tkinter. Aquí hay instrucciones válidas para importar ttk:
importar ttk
o
importación ttk *
o
desde tkinter importar ttk
Las siguientes son instrucciones válidas para iniciar una ventana principal en blanco:
desde la importación de tkinter *
desde tkinter importar ttk
raíz = Tk
root.title (“APLICACIÓN de control electrónico integrado RPi”)
raíz.minsize(480, 480)
raíz.resizable(0, 0)
raíz.mainloop
Esta es una ventana GUI principal en blanco que no contiene otros widgets. Tenga en cuenta que el método mainloop se llama en la última declaración de la ventana principal.

Menús de la ventana principal de Python Tkinter GUI para una aplicación de electrónica integrada RPi.
Mantente conectado. Está a punto de ser testigo de un enfoque de subprocesos múltiples para aplicaciones integradas que utilizan Raspberry Pi. Controlaremos los circuitos integrados a través de una aplicación GUI de escritorio mientras implementamos las operaciones integradas del microcontrolador en una computadora de placa única.
En el próximo tutorial , aprenderemos más sobre los widgets Tkinter y ttk agregando un menú a nuestra aplicación de control electrónico integrado RPi. También continuaremos agregando marcos GUI a nuestra aplicación para cada componente electrónico integrado (dispositivos de visualización, sensores, módulos, motores e interfaces de comunicación) controlados por la aplicación.