MAGIC MIRROR

“Magic Mirror” es un espejo inteligente que te permite hacer el uso habitual de un espejo junto a otras funcionalidades como consultar el tiempo o poner música a través de una pantalla integrada. La navegación debe ser a través de gestos para dar el efecto de que es algo más allá de un simple dispositivo con botones, además de que de esta forma evitamos tocar el espejo y que pueda hacer su función de igual forma independientemente del uso.

El concepto de la idea apareció de casualidad, y quizá ha sido un proyecto demasiado ambicioso para las limitaciones presupuestarias y técnicas que hemos tenido, pero que conseguimos solventar lo suficientemente bien dadas las circunstancias. 

Si bien no es algo totalmente original, ya que investigando podemos encontrar algún proyecto similar (no como parte de esta asignatura en otros años, sino realizados por personas con conocimiento en la materia), creemos que dada la naturaleza del proyecto da pie a una cantidad muy alta de variantes que hemos tenido que ir adaptando a nuestras posibilidades.

El objetivo real de este proyecto es hacer un prototipo funcional de lo que sería el producto para su uso, ajustándonos a las funcionalidades de poder mostrar el tiempo en distintas ciudades, conectarnos a Spotify y poner música de entre una selección y consultar noticias recientes. 

Para ello haremos uso de una Raspberry Pi junto al Arduino y otros componentes de los que hablaremos a continuación.

COMPONENTES

Antes de meternos en detalles de software o similar, debemos recopilar cuáles han sido todos los componentes que forman el modelo final.

Para empezar, la estructura externa sobre la que se sustenta el espejo y en la que están todos los aparatos, cables y demás materiales ha sido realizada con impresión 3D, usando filamento PLA. 

El diseño consiste en 4 módulos que se unen a través de unos cilindros situados en los extremos (es decir, equiparando cilindros y agujeros que encajan entre piezas). De esta forma conseguimos transportarlo de forma más cómoda y no llevarlo montado siempre. Viene diseñado específicamente para que todo encaje bien, sobre todo el “espejo”.

Además, es lo suficientemente profundo para ser capaz de albergar la Raspberry Pi, Arduino, una protoboard y varios cables.

Respecto al cristal, realmente usamos un metacrilato de doble vía. El efecto conseguido es el mismo, y nos facilitaba mucho la vida en términos económicos. Otras alternativas son usar un cristal de doble vía (la opción más profesional, pero se va de presupuesto por bastante) o usar un cristal normal con un vinilo de efecto espejo. 

El tamaño es 30x30cm, un tamaño bastante válido para nuestro trabajo y sobre el que hemos construido la estructura 3D.

Ahora podemos pasar a los componentes más técnicos, y no solo partes de la estructura. 

La lista de componentes y materiales usados en la fabricación del prototipo final es la siguiente, sin incluir componentes no usados pero sí comprados para pruebas o de los que había intención de usar, como LEDs o sensores. 

Raspberry Pi Zero 2W

Esta placa es el núcleo del proyecto ya que se encarga de ejecutar la interfaz gráfica, conectarse a internet para obtener información en tiempo real y gestionar la comunicación con Arduino y el resto de componentes. 

La raspberry pi ejecuta un sistema operativo basado en Linux y sobre ella corren los scripts en Python encargados de mostrar toda la interfaz del espejo inteligente. Este sistema operativo está instalado en una tarjeta micro SD que se incorpora a la raspberry.

Pantalla

La pantalla utilizada es una pantalla TFT de 10,1 pulgadas. Esta tiene una resolución de 1024×600 píxeles y se trata de una pantalla con una tecnología IPS integrada, lo que mejora los ángulos de visión y la calidad de la imagen.

Controlador LCD

Para poder utilizar la pantalla correctamente fue necesario emplear una placa controladora LCD HDMI. Este componente actúa como intermediario entre la Raspberry Pi y la pantalla, ya que convierte la señal HDMI de la Raspberry en una señal compatible con la pantalla TFT.

El controlador viene con un mando a distancia que se utiliza para controlar parámetros como brillo, contraste o modo de imagen de la pantalla.

Sensor APDS-9960

Es el sensor principal que se conecta con Arduino. Funciona tanto como sensor de proximidad como sensor de gestos (también de colores, pero no lo usaremos). Para poder usarlo hemos tenido que soldarlo junto a los 6 pines que tiene, de forma que las conexiones fueran perfectas y no tener riesgo de que se perdiera en algún momento. Usa una interfaz de comunicación I2C a través de los pines SDA y SCL. Tiene los típicos pines de conexión a tierra y a voltaje (GND y VCC respectivamente), un pin INT que se conecta al pin digital D2 del arduino y es el que hace que funcionen los gestos. 

Por último, el pin VL es el que controla la corriente que le llega al LED infrarrojo, que precisamente es donde reside la magia del sensor. Este LED es el encargado de detectar tanto la proximidad como los gestos (es decir, a través de sus 4 receptores puede detectar movimientos hacia arriba, abajo, izquierda y derecha).

COSTES

COMPONENTEPRECIO (euros)
Raspberry Pi Zero 2W20
Pantalla TFT15
Controlador LCD30
Sensor APDS-99601,5
Tarjeta micro SD25
Metacrilato15
Cables varios15
Filamento PLA15
Soldador11
Total147,5

Al final ha quedado un presupuesto bastante por encima de lo esperado pero que aún así no nos permitió realizar el trabajo de forma óptima.

CÓDIGO

El funcionamiento del espejo se sustenta en 3 archivos de código: uno de Arduino, que controla el sensor, un script de Python que muestra la interfaz y permite navegar por ella, y otro script de Python que actúa como puente entre las señales del sensor recibidas por Arduino y el script encargado de hacer funcionar el espejo. Vamos a entrar en detalle en cada uno de ellos:

arduino_sensor.ino

El código de arduino no es muy complejo y su función es la de manejar el funcionamiento del sensor. 

La función setup() simplemente inicializa el sensor, ajusta los parámetros de sensibilidad (cómo recibe las señales tanto de proximidad como de gestos) y establece en el sensor que se active únicamente el modo de proximidad.

En la función loop() delimitamos ambos modos. Primero arranca como detector de proximidad; si alcanza un valor superior a 240 (es decir, acercamos el dedo directamente al sensor) cambiará a modo gestos y se desactivará la lectura de proximidad. 

Después entra en el modo gestos, donde se encarga de leer las direcciones de forma correcta (en el código están girados ya que la posición original del sensor es distinta a la que tenemos que usar para su disposición en el proyecto). También tiene una forma de apagar acercando el dedo al sensor de nuevo, haciendo que vuelva al estado inicial.

La vuelta a ese estado inicial se hace a través de una función resetearModo() que desactiva el modo de gestos y vuelve a activar el sensor de proximidad.

puente.py

Este archivo es bastante simple; solo recibe la señal de START de Arduino (que ya hemos visto que es cuando el valor de proximidad del sensor llega a 255, es decir, a efectos prácticos, que hemos acercado el dedo al sensor) y genera un subproceso que ejecuta el script de la interfaz. Además, genera una ventana negra para que sea más natural el paso del estado base a la interfaz real del sistema (en la práctica, por la limitada capacidad de la raspberry pi, no funciona exactamente como debería, pero esa es la idea tras esas líneas de código).

mirror_gui.py

Dentro de este script recogemos todo lo relativo a diseño, navegación, interpretación de gestos y todo lo que dirige la interfaz. 

Antes de entrar en el código, es importante hablar de los datos que se ofrecen. Tanto los datos de clima y temperatura ofrecidos, como las noticias, como las playlists y canciones que suenan a través de Spotify, se obtienen conectándonos a las respectivas APIs (API de openWeather, Spotify for Developers y de El Pais).

Además, ha sido necesario el uso de distintas librerías. Destacamos la librería spotipy, fundamental para manejar todo lo relacionado con la funcionalidad asociada a spotify (coger las playlists de la cuenta real, activar spotify y moverse entre canciones de forma real, coger imágenes de las canciones que se reproducen), y la librería tkinter, que es la encargada de hacer todo lo gráfico (colocación de los elementos, abrir la ventana con esa estética).

Respecto al código, se divide en distintas zonas que se encargan de funciones concretas dentro de la interfaz del espejo.

La primera parte corresponde a toda la configuración inicial del programa. Aqui se importan las librerías necesarias y se configuran elementos como las credenciales de Spotify, la API meteorológica o las variables globales. También se inicializa la ventana principal de tkinter en pantalla completa.

Posteriormente se definen todas las variables de navegación. Estas variables almacenan información sobre el menú en el que nos encontramos actualmente, que ciudad del tiempo está seleccionada o qué playlist se encuentra activa.

Tras esto nos encontramos con la sección que inicializa Spotify. Para ello usamos la librería spotipy junto al sistema OAuth de Spotify for Developers. Luego existe una sección dedicada a la carga de imágenes cómo los iconos de tiempo y Spotify. Estas imágenes son redimensionadas automáticamente para adaptarse correctamente a la interfaz.

A continuación se construye toda la interfaz gráfica utilizando tkinter. La parte superior de la pantalla contiene la hora y la fecha. Debajo se sitúa el contenido que va cambiando dependiendo de la sección en la que se encuentre el usuario.

El sistema de comunicación con Arduino se implementa mediante la función iniciar_serial(). Esta función abre un puerto serie y mantiene un hilo secundario constantemente escuchando los datos enviados por Arduino. Cuando recibe palabras como “RIGHT”, “LEFT”, “UP” o “DOWN”, ejecuta automáticamente las funciones correspondientes de navegación.

Las funciones gesto_derecha()gesto_izquierda()gesto_arriba() y  gesto_abajo() son las encargadas de gestionar toda la navegación del sistema. Dependiendo de la vista activa, un mismo gesto puede tener distintos efectos.

La función mostrar_menu() genera la pantalla principal del sistema. En ella aparecen los accesos principales al clima y Spotify, además de una sección inferior con noticias recientes obtenidas automáticamente mediante RSS desde El País.

Por otro lado, mostrar_tiempo() se encarga de toda la interfaz meteorológica. Esta función realiza peticiones a la API de OpenWeather y muestra tanto el tiempo actual como una previsión por horas y por días. Además, se puede ver el tiempo en distintas ciudades.

La parte relacionada con Spotify se divide entre las funciones mostrar_spotify(), play() y reproductor(). La primera muestra las playlists disponibles; la segunda inicia la reproducción de la playlist seleccionada; y la tercera construye la interfaz del reproductor musical.

Finalmente, el programa se ejecuta creando una instancia de la clase principal MagicMirror, que contiene toda la lógica del sistema, y lanzando el bucle principal de tkinter mediante root.mainloop(). Esto mantiene activa la interfaz de forma permanente mientras el espejo esté funcionando.

Interfaz

Nada más arrancar, se muestra la siguiente interfaz:

La sección de noticias no es accesible más allá (lo llegamos a implementar, pero abrir la noticia de forma extensa implica una capacidad de la raspberry con la que no contamos, por lo que la experiencia de uso empeoraría bastante, ya que de hecho ya limita algo los cambios de interfaces). 

La forma de navegar a través de los gestos es:

  • Izquierda-Derecha para seleccionar las opciones de cada interfaz (en el menú principal, cambiar entre Clima y Spotify; en el menú Clima, cambiar entre ciudades; y en el menú Spotify, cambiar entre playlists o avanzar/retroceder canción)
  • Arriba para aceptar (funciona como un “Enter” una vez la opción está seleccionada)
  • Abajo para volver al menú principal, en cualquier momento

Adicionalmente y por comodidad a la hora de hacer pruebas – y detectar fallos con el sensor – es posible navegar a través de teclas (siempre y cuando estés visualizando la pantalla a través de Raspberry Connect desde el ordenador, con la cuenta vinculada a la raspberry). De hecho, la transformación de señales de Arduino a flujo en la interfaz es realmente decirle al programa que se pulse la tecla correspondiente (cada gesto equivale a su flecha). Esto hace más sencillo la conversión de un código a otro.

Más detalles del funcionamiento se pueden observar en los videos del siguiente enlace a la carpeta de Drive:

/https://drive.google.com/drive/folders/1GN1Ls8ZNRUsrXbYUYDW2-3vjfRlq9g7W?usp=drive_link

PROBLEMAS Y SOLUCIONES

Organización

El primer problema a mencionar es posiblemente las limitaciones a la hora de plantear el sistema. Al requerir de una raspberry pi para funcionar, hemos tenido problemas para decidir cómo de necesario era usar según qué sensores u otros componentes relacionados con Arduino, ya que este era el objetivo principal de la práctica y era peligroso salirse de los márgenes delimitados. El tiempo requerido para organizar bien qué queríamos exactamente, para no pasarnos ni quedarnos cortos fue realmente un quebradero de cabeza. A lo largo del desarrollo planteamos muchas opciones, como usar sensores táctiles capacitivos (TTP223) para movernos por el espejo (descartado porque la idea de que lo movieras en el aire era bastante más atractiva), usar un sensor de movimiento PIR HC-SR501 para encender la pantalla al detectar movimiento (descartado porque la opción de acercar el dedo era más fiable) o añadir luces LED alrededor del metacrilato (descartado porque podía dar problemas con la visión de la pantalla al darle luz directa).

Optamos por hacerlo según está, manejando únicamente el sensor APDS-9960, por comodidad, ya que usar más componentes nos podía dar muchos más problemas y de esta forma es perfectamente funcional, combinando ambos mundos.

Diseño 3D

El diseño 3D también resultó ciertamente complejo, aunque no por la propia naturaleza del proyecto y la estructura sino por querer hacerlo funcional, desmontable y autosuficiente. Es decir, los principales problemas asociados a esto vienen de incluir las ranuras para el cristal, soportes para la pantalla o el hueco asociado para el sensor, todo esto mientras debía ser suficientemente grande para dar estabilidad a la estructura y poder guardar dentro los componentes. Esto hizo que, si bien el tiempo que tardó es bastante (aproximadamente 30 horas de impresión entre las 4 piezas), el tiempo inicial era algo poco sostenible, y hubo que reajustar muchos detalles del diseño así como el gramaje, número de capas y otros factores de la impresión.

Presupuesto

Muchos otros problemas han estado ligados al presupuesto. 

Para empezar, la Raspberry Pi encargada de gestionar todos los procesos operativos era una versión bastante pobre, muy lejos de las versiones caras. Por tanto, los tiempos de carga son lentos, ha habido que reducir contenido y reacondicionar algunos métodos de navegación en el producto final.

El sensor funciona pero no es totalmente fiable, sobre todo teniendo en cuenta la idea del uso. Al estar fijo en una posición, es verdaderamente difícil que capte todos los gestos bien, por simple lógica de cómo funciona el sensor infrarrojo (por ejemplo, si estás situado a la izquierda del sensor, el movimiento previo a hacer el gesto derecha-izquierda para que detecte ‘LEFT’ ya es leído por el sensor, haciendo que pueda no interpretar bien los datos). Con un presupuesto mayor habría sido posible usar una cámara que detectara bien con IA o con algún otro modo los gestos de manera más fiable (la idea original era esa, pero por el motivo del presupuesto y de productos que no eran lo que esperábamos acabó quedando así).

Montaje

El montaje también ha sido algo complicado, principalmente en 2 componentes; por un lado, la pantalla, o mejor dicho, el controlador de la pantalla, y por otro lado el sensor. 

Respecto de lo primero, por simple gravedad era muy difícil ser capaz de que se mantuviera pegado, ya que tenía que estar en la parte trasera de la pantalla (para funcionar), pero al ser la pantalla vertical, y estar atado a distintas conexiones, el peso hacía que se cayera continuamente. Finalmente conseguimos que se mantuviera pegado con más capas de cinta, pero es una solución nada óptima. 

Con el sensor la historia es parecida. El agujero en el que tiene que usarse va justo para que se vea el infrarrojo, pero es algo muy delicado, por tanto si no está suficientemente “fuera” de la estructura (es decir, debe sobresalir ligeramente) confundirá lo que recibe con la propia caja y no funcionará de forma correcta para detectar gestos. 

Esto, sumado a que ha sido necesario transportar la estructura varias veces, nos lleva a que es posiblemente el mayor problema, ya que sin que funcione se pierde toda la magia del proyecto.


También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *