Curial Iglesias
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    2
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # G4 - スマルト Touch ![](https://i.imgur.com/chD7W2b.png) ## Explicación del proyecto スマルト Touch (o Smart Touch) es una herramienta de escritura digital que permite transcribir de forma fácil y rápida carácteres o palabras escritas en una pantalla táctil y guardarlos en un formato digital o visualizarlos en otro dispositivo. Con スマルト Touch, se pretende dar visibilidad y concienciar sobre los problemas de discapacidad física a nivel de escritura y mejorar la accesibilidad e inclusión de las personas con dichas discapacidades de cara al uso de las tecnologías que nos rodean hoy en día. ## Casos de uso / interacción Para darle una utilidad a nuestro prototipo, hemos planteado 5 escenarios/casos de uso ideales para sacarle el máximo provecho. Estos casos incluyen el uso del text-to-speech, botones, etc., además de funcionalidades futuras a implementar que podrían mejorar aún más la experiencia e interacción del usuario. ### Caso 1 - Dinámica educativa-pedagógica ![](https://i.imgur.com/dHVApGX.jpeg) En una hipotética situación de ubicarnos en una clase con una maestra y un grupo de niños que sufren de discapacidades relacionadas con la dificultad de lectura de textos o escritura, este prototipo les ayudaría a mejorar esas facultades gracias a una dinámica de aprendizaje que consiste en un alumno, con dificultad de escritura, practicando su caligrafía en el prototipo, pasa el mensaje mal escrito a un formato legible que luego a través del portal web desarrollado por nosotros también, el mensaje pasa a un ordenador conectado a una pizarra digital que permite pues mostrar los contenidos del mensaje a toda la clase. Esto permite que el resto de alumnos puedan aprender a leer leyendo lo se ha escrito en la pantalla de su compañero, además de habilitar a la profesora un proceso de análisis más ágil y eficiente a la hora de valorar el progreso que hacen tanto los alumnos que ven el mensaje en pantalla como el alumno que practica su escritura. ### Caso 2 - Evento social ![](https://i.imgur.com/fUTitlF.jpeg) En un evento social donde haya gente con diferentes tipos de discapacidades diferentes, que hay gente sorda, ciega, etc. como nuestra aplicación es todoterreno, todo el mundo podrá socializar, ya que si uno no ve, puede escuchar los mensajes, que uno que no puede escuchar, podrá leerlos, etc, etc. En general, permite habilitar la comunicación entre todos los participantes del evento, con o sin uso del text-to-speech. ### Caso 3 - Defensa judicial ![](https://i.imgur.com/UdxFk3Q.jpeg) En un escenario de carácter judicial como es el caso de una sala de juicio donde están presentes tanto el juez como ambos bandos (criminal y víctima) con sus respectivos abogados, aquella persona (sea criminal o víctima) que sufre de discapacidad (muda para ser más exactos), le ayudaría tener nuestro prototipo en mano al ponerse al estrado para defenderse de las preguntas de la oposición, que normalmente lo haría el abogado porque es el que está "capacitado" para poder responder a las respuestas de la oposición. En general, en este caso particular, utilizando nuestro prototipo, permitiríamos al mudo que pudiese defenderse a sí mismo, y utilizar el texto to speech para que todo el mundo en la sala pudiese oir su versión de la historia sin tener que recurrir a un elemento intermediario como es el abogado. ### Caso 4 - Rehabilitación médica ![](https://i.imgur.com/Zqfs7VX.jpeg) En un escenario hipotético de un paciente que es soldado de guerra, es decir, que sufre heridas tanto físicas como psicológicas, al tener dificultad para poder transmitir sus pensamientos a los médicos a la hora de escribir (mal) o hablar, nuestro prototipo le ayudaría a poder transcribir los mensajes de forma eficiente y utilizar la funcionalidad de text-to-speech para poder comunicarse con el personal médico de forma ágil, sin necesidad de tener que recurrir a otros medios tradicionales como es el papel, ya que no permite la legibilidad que tanto el paciente como el personal médico desearían tener. ### Caso 5 - Comunicación sordo-ciega ![](https://i.imgur.com/s7L68Ho.jpeg) En un escenario donde se presentan un ciego y un sordo-mudo para comunicarse, nuestro prototipo ayudaría a solventar ese problema gracias a que, por un lado, el ciego con un teléfono móvil puede escuchar a través del text-to-speech del portal web desarrollado, el mensaje que el ciego escribe con el prototipo. A su vez, el sordo-mudo puede recibir los mensajes del ciego con una funcionalidad futura a implementar que consiste en la transcripción de audio a texto para que le pueda llegar los mensajes hablados al sordo-mudo y habilite la comprensión lectora de forma ágil. ## Departamento de Pantalla ### Objetivo El objetivo del departamento de pantalla es conseguir que al encender la Raspberry Pi automaticamente aparezca una ventana con un terminal conectado a un tópico mqtt y otra ventana con una aplicación de escritura. ### Material * Raspberry Pi model 4 * Pantalla tactil: [ELECROW - Pantalla táctil de 5 pulgadas 800x480px](https://www.amazon.es/elecrow-Raspberry-Pantalla-Windows-Widerstand/dp/B07H7899W5) * Botones para PCB: [RUNCCI-YUN - Botón interruptor 80pcs 12 x 12 x 7.3 mm 5 colores](https://www.amazon.es/dp/B07WPBQXJ9) * Mini ventilador: [GeeekPi - Ventilador Raspberry Pi 30x30x7mm DC 5V](https://www.amazon.es/dp/B07FVR3TB8) * Placa PCB y cables ### Preparación Descargar [Raspberry Pi Imager](https://www.raspberrypi.com/software/) para poder crear una imagen la SD. Nosotros elegimos instalar SO Lite de 64 Bits, porque no necesitamos un entorno de escritorio completo. Una vez configurada y creada la imagen, pasamos a la instalación de la pantalla. ### Montaje de la pantalla La pantalla se conecta a la Pi usando el socket de 13x2 pines y queda perfectamente encajada. La caja de la pantalla trae un lapiz de tipo nintendo DS y dos adaptadores, uno de HDMI a HDMI (Para Raspberry Pi model 3) y otro HDMI a micro-HDMI (Para Raspberry Pi model 4). El adaptador HDMI tambien queda perfectamente encajado en la Raspberry Pi. ### Instalación y configuración de la pantalla Encendemos la Raspberry Pi y nos conectamos mediante SSH: ``` SSH g4@touch.local ``` En nuestro caso g4 es el nombre de nuestro usuario y touch el nombre de nuestro dispositivo Raspberry Pi. Alternativamente también se podria acceder usando la dirección IP del dispositivo. Una vez abierto el terminal, accedemos al archivo de configuración del booteo `sudo nano /boot/config.txt` y añadimos las siguientes lineas de codigo al final del archivo: ``` # --- added by elecrow-pitft-setup --- hdmi_force_hotplug=1 max_usb_current=1 hdmi_drive=1 hdmi_group=2 hdmi_mode=1 hdmi_mode=87 hdmi_cvt 800 480 60 6 0 0 0 dtoverlay=ads7846,cs=1,penirq=25,penirq_pull=2,speed=50000,keep_vref_on=0,swapxy=0,pmax=255,xohms=150,xmin=200,xmax=3900,ymin=200,ymax=3900 display_rotate=0 # --- end elecrow-pitft-setup --- ``` Si estamos usando una Raspberry Pi 4 también tenemos que comentar la linea de codigo del archivo que pone `dtoverlay = vc4-fkms-V3D` A continuación, ejecutamos las siguientes comandas para poder instalar los drivers de la pantalla: ``` sudo apt-get update sudo apt-get install git git clone https://github.com/goodtft/LCD-show.git chmod -R 755 LCD-show cd LCD-show sudo ./LCD5-show ``` Despues reiniciamos la Pi y ya deberiamos ver la pantalla en funcionamiento. ### Instalación de MQTT y Node-red Mosquitto (MQTT) es un software que nos permite conectarnos a un broker , en nuestro caso será nuestra propia Pi. Para instalar MQTT ejecutamos en el terminal: ``` sudo apt install mosquitto mosquitto-clients ``` Para permitir que cualquiera pueda publicar y recibir mensajes hay que editar el archivo de configuración de MQTT `sudo nano /etc/mosquitto/mosquitto.conf` Y agregamos estas lineas al final del archivo: ``` listener 1883 allow_anonymous true listener 9001 protocol websockets ``` Finalmente reiniciamos MQTT con `sudo systemctl restart mosquitto` Node-RED es una herramienta de desarrollo basada en flujos para programación visual que usaremos para el software de este proyecto. Para instalar Node-RED ejecutamos la siguiente comanda: ``` bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered) ``` Una vez terminada la instalación, para iniciar el servidor node-red podemos ejecutar: ``` sudo systemctl start nodered.service ``` Y para que se inicie siempre al arrancar nuestra raspberry ejecutamos: ``` sudo systemctl enable nodered.service ``` ### Instalación y configuración de Xorg Xorg es un entorno gráfico que usaremos como base para los siguientes procesos de nuestro proyecto. Para instalar Xorg, abrimos un terminal y ejecutamos: ``` sudo apt-get install xorg ``` Para iniciar Xorg ejecutamos: ``` startx ``` Como nuestro objetivo es que al encender la Pi directamente se ejecute Xorg, tenemos que editar el archivo bashrc `sudo nano ~/.bashrc` Y añadimos al final del archivo: ``` if [[ -z $DISPLAY ]] && [[ $(tty) = /dev/tty1 ]]; then startx fi ``` Ahora si reiniciamos la Pi veremos que accede directamente a Xorg. ### Instalación y configuración de Xournal++ Xournal++ es una aplicación de escritura que usaremos para capturar el texto escrito. Para instalar Xournal++ abrimos un terminal y ejecutamos: ``` sudo apt-get install xournalpp ``` Nosotros tuvimos problemas con las dependencias así que optamos por una alternativa que es instalar Xournal++ desde la [Snap Store](https://snapcraft.io/install/xournalpp/raspbian): ``` sudo apt-get update sudo apt install snapd sudo reboot sudo snap install core sudo snap install xournalpp ``` Para abrir Xournal++ ejecutamos: ``` sudo snap run xournalpp ``` Dentro de Xournal++ debemos ir a preferencias y activar la opción de permitir la escritura usando el lapiz tactil y también activar alguno de los métodos de smoothing a nuestro gusto. ### Instalación y configuración de i3 i3 es un gestor de ventanas para Linux que usaremos para poder visualizar en la pantalla a la vez un terminal suscrito a un tópico MQTT y Xournal++ Para instalar i3 abrimos un terminal y ejecutamos: ``` sudo apt-get install i3 ``` Para conseguir que al encender la Raspberry Pi aparezca en la pantalla una ventana en la parte superior con un terminal suscrito a un tópico MQTT y una ventana en la parte inferior con Xournal++, tenemos que hacer unas configuraciones. En el archivo de configuración de i3 `sudo nano /etc/i3/config` añadimos al final: ``` # exec i3-config-wizard # Configuración para las ventanas de xterm y Xournal++ set $mod Mod1 # floating_modifier $mod # workspace "1" exec_always /home/g4/startup.sh exec_always /home/g4/buttons.sh for_window [class="XTerm"] floating enable, move position 0px 0px, resize set 800px 60px, border none for_window [class="Xournalpp"] floating enable, move position 0px 60px, resize set 800px 420px, border none ``` Creamos un script startup `sudo nano /home/g4/startup.sh` con el siguiente contenido: ``` #!/bin/bash # Establecer la variable de entorno DISPLAY en la pantalla predeterminada export DISPLAY=:0.0 # Abrir terminal en la parte superior de la pantalla i3-msg 'exec xterm -e /usr/bin/mosquitto_sub -h touch.local -t touch_topic' # Abrir Xournal++ en la parte inferior de la pantalla i3-msg 'exec xournalpp; floating enable' # Configurar la disposición de las ventanas i3-msg "workspace 1; layout splitv; split v" ``` Este script ejecuta los comandos i3-msg para abrir un terminal suscrito al topico MQTT y la aplicación Xournal++ tal y como hemos configurado anteriormente en el archivo de configuración de i3. Ahora si reiniciamos la Raspberry Pi deberiamos tener las ventanas configuradas como deseamos. ### Instalación y configuración de los botones Tenemos que conectar los botones siguiendo este esquema: ![Datasheet botones](https://i.imgur.com/ggL7tzU.jpg) * PIN 4 (5V): Pin de 5 Voltios para conectar el ventilador * PIN 6 (Tierra): Pin de tierra para conectar el ventilador * PIN 7 (GPIO 4): Botón verde * PIN 9 (Tierra): Conexión de tierra para los botones * PIN 11 (GPIO 17): Botón amarillo * PIN 13 (GPIO 27): Botón rojo * PIN 15 (GPIO 22): Botón negro Hemos decidido soldar unos pines en la pantalla para poder hacer las conexiones facilmente usando cables en vez de soldar directamente cada cable a la pantalla: ![Soldadura1](https://i.imgur.com/99eLAcQ.jpg) Los botones los soldamos en una placa PCB con un circuito que conecte una pata de cada botón a tierra y la otra en el GPIO correspondiente. Tambien soldamos un mínimo de 5 pines (4 para GPIO y 1 para Tierra). De esta forma para hacer la conexión de la PCB a la pantalla solo necesitamos 5 cables hembra a hembra. ![Soldadura2](https://i.imgur.com/qAk6Gpg.jpg) ![Soldadura3](https://i.imgur.com/c3k2Nkk.jpg) Finalmente así queda el resultado con todos los componentes conectados: ![Soldadura4](https://i.imgur.com/Q1j4NqB.jpg) Para detectar los botones y darles una funcionalidad creamos un script de python buttons `sudo nano /home/g4/buttons.sh` con el siguiente contenido: ``` #!/usr/bin/env python3 import os os.environ['DISPLAY'] = ':0' import subprocess from gpiozero import Button from time import sleep button4 = Button(4) button17 = Button(17) button27 = Button(27) button22 = Button(22) while True: if button4.is_pressed: print("Green Pressed") subprocess.run(["import", "-window", "root", "-crop", "760x360+20+120", "/home/g4/images"]) subprocess.run(["xdotool", "key", "--clearmodifiers", "ctrl+d"]) sleep(1) if button17.is_pressed: print("Yellow Pressed") subprocess.run(["xdotool", "key", "--clearmodifiers", "ctrl+d"]) sleep(1) if button27.is_pressed: print("Red Pressed") sleep(1) if button22.is_pressed: print("Black Pressed") sleep(1) ``` Con este script detectamos si se pulsa un botón en el GPIO 4, 17, 27 y 24 que es donde tenemos conectados los botones fisicamente y realizamos una función concreta con cada uno: * Botón verde (GPIO 4): Hacemos una captura de la pantalla en la zona de la aplicación Xournal++ y borramos todo el contenido escrito en ella. La captura es detectada y procesada por node-red automaticamente. * Botón amarillo (GPIO 17): Borramos todo el contenido escrito en la aplicación Xournal++ pero esta vez sin hacer captura. * Botón rojo (GPIO 27): En este script simplemente lo detectamos pero no tiene ninguna funcionalidad. Node-red detecta cuando se pulsa este botón y borra la ultima letra escrita del mensaje. * Botón negro (GPIO 22): En este script simplemente lo detectamos pero no tiene ninguna funcionalidad. Node-red detecta cuando se pulsa este botón y borra todo mensaje escrito ahora. ### Realización de la maqueta Para poder realizar la maqueta, primero se hizo un diseño con todas las medidas de la carcasa juntamente con las medidas de la pantalla y los botones para poder crear los agujeros. ![](https://hackmd.io/_uploads/ryy79IbSn.png) ![](https://hackmd.io/_uploads/ryRQqUbB2.png) ![](https://hackmd.io/_uploads/SkSr5IZBh.png) Una vez teníamos el diseño hecho, procedimos a realizar la primera maqueta. La carcasa la hicimos con una caja de Amazon de cartón y SuperGlue para poder unir cada parte de la carcasa. ![](https://hackmd.io/_uploads/SJmwFLZrh.jpg) Una vez teníamos la maqueta hecha, hicimos test de usabilidad, en la que se llegó a dos conclusiones. La primera conclusión fué hacer más grande el agujero de la parte de atrás de la carcasa porque no había espacio para el cable de alimentación. ![](https://hackmd.io/_uploads/By4hF8WH2.jpg) Y la segunda conclusión fué decidir donde iban a ir los agujeros para la correcta ventilación de la Raspberry Pi. ![](https://hackmd.io/_uploads/r1ACF8WSh.jpg) ### Modelaje e impresión 3D de la carcasa Siguiendo las medidas de los bocetos se empezó a desarrollar un modelo 3D de la carcasa. **Primera Versión:** ![](https://hackmd.io/_uploads/BJe19adSn.png) ![](https://hackmd.io/_uploads/H1zH96OB3.png) ![](https://hackmd.io/_uploads/rJ-w5aur3.png) ![](https://hackmd.io/_uploads/BJBF5auB3.png) Después de modelar esta primera versión vimos que el saliente superior era un poco innecesario y que con dejar solo el hueco ya nos iba bien (y facilitaba la posterior impresión 3D). Al hacer el test de usabilidad con la caja de cartón nos dimos cuenta de que había que hacer algún cambio en algunas medidas y que hacía falta ampliar el agujero de arriba. Esos cambios se aplicaron al modelo de cara a la siguiente versión. También cambiamos los agujeros inferiores para la ventilación y las esquinas de la caja, ya que con ese perfil de curva el plástico no tiene apoyo suficiente y la impresión 3D no habría salido bien. Finalmente, separamos la parte trasera de la carcasa para que hiciera de tapa y añadimos cuatro piezas en la otra parte de la carcasa para así poder ponerle los tornillos para cerrarla. **Segunda Versión:** ![](https://hackmd.io/_uploads/Bk0BCauBh.png) ![](https://hackmd.io/_uploads/BJtPAauS2.png) ![](https://hackmd.io/_uploads/S1NUyC_r2.png) ![](https://hackmd.io/_uploads/Skl6Cp_r2.png) ![](https://hackmd.io/_uploads/rJTOJAOS3.png) Una vez acabada y revisada esta segunda versión pasamos ya a imprimir la carcasa. **Primera impresión:** ![](https://hackmd.io/_uploads/S162b0OB3.png) Como se puede apreciar en la imagen, la primera impresión no salió bien debido a que la impresora 3D se quedó sin hilo y no acabo toda la carcasa. Aun así nos sirvió para ver que los botones encajaban perfectamente y que hacía falta incrementar un poco la distancia del marco de la pantalla, tanto por arriba como por abajo. **Segunda impresión:** ![](https://hackmd.io/_uploads/SJJwbAdHh.png) ![](https://hackmd.io/_uploads/S1V_W0_rh.png) ![](https://hackmd.io/_uploads/rkgEWCdr2.png) ![](https://hackmd.io/_uploads/SyLtbCuB3.png) Esta segunda impresión se pudo realizar con éxito y, como se puede ver en las imágenes, el resultado final fue bastante bueno. ## Departamento de Software ### Objetivo El objetivo del departamento de software es el conseguir que, todo aquello que se escriba en la pantalla se interprete, se pase a texto y se limpie de incorrecciones para luego ser publicado en un tópico MQTT y se pueda ver de vuelta en la pantalla. ### Material - Un ordenador - Software de Node-RED - Una raspberry pi para su implementación ### Preparación y problemas iniciales Para poder empezar con la parte de software del proyecto, se necesitaba instalar Node-RED en la Raspberry Pi, pues es donde estaría corriendo el código en el proyecto final. No obstante, fue aquí donde nos encontramos con un problema el cual, mientras su soloción era fácil, volvía la implementación un proceso tedioso. Resulta que sólo disponíamos de una Raspberry Pi, por lo que todo el código tenía que ser desarrollado y comprobado desde un ordenador externo, sin saber si la Raspberry podría correr el código. No obstante, el procedimiento a la hora de desarrollar resultaba el mismo, con la única diferencia siendo que tendríamos que copiar los nodos manualmente a la hora de juntar los avances de software y hardware, por lo que no hubo parón alguno. ### Nodos utilizados - Inject node: Este nodo es usado cuando se quiere ejecutar una parte del código mediante el envío de datos (que activan los nodos siguientes) o cuando se requiere insertar contenido específico en el payload del mensaje (como se ha hecho para el caso de querer borrar el mensaje). - Watch node: Este nodo es utilizado cuando se quiere una observación de un archivo del sistema, enviando una señal cuando se ha cometido un cambio en el fichero observado (parecido en modo al inyector, pero en modo automático). En nuestro caso se ha utilizado para la detección de una nueva imagen a analizar. - Read file node: Este nodo es utilizado cuando, tal como indica su nombre, se quiere leer un fichero del sistema para ser usado en node-red. Esta lectura se puede llevar a cabo de divrsas maneras, siendo la escogida la lectura en formato *buffer*, pues era el método más fácil para la lectura de imágenes. El problema que conlleva este nodo es que necesita de un trigger para activarse, y es por ello que se tuvo que añadir el inyector/watcher. - Image Tools Nodes: Esta [libreria de nodos](https://flows.nodered.org/node/node-red-contrib-image-tools) aporta diferentes aplicaciones para las imágenes que se leen en node red, ya sea desde un visualizador hasta un procesador de imágenes (para recortar, pixelar, subir o bajar el contraste...). Mientras que se hicieron diversas pruebas para mejorar la lectura y la eficacia del algoritmo (ver [Implementación](#Implementación-en-la-Raspberry-Pi), al final solamente se usó el visualizador, pues nos facilitaba el trabajo dentro de node-red) - Tesseract node: Este nodo es el encargado de realizar la fuerza bruta del proyecto, pues es el encargado de la detección de texto en la imagen. Aunque la librería utilizada te permite introducir diferentes tipos de información, al final decidimos usar el *buffer binario*, pues no tendríamos que realizar ningún cambio. (más información en [Tesseract](#Tesseract-y-la-búsqueda-de-un-OCR)) - Function nodes: Estos nodos se han utilizado cuando se requería de código para llevar a cabo una fase del proyecto. En este caso, se han utilizado para la [limpieza de las string](#Limpieza-del-mensaje) que exporta el algoritmo de Tesseract y para algunas de las [acciones extra](#Acciones-extra), tales como el borrar el mensaje. - Debug nodes: Estos nodos son utilizados como soporte en el desarrollo de proyectos de node-red, pues te permiten mostrar la información del mensaje que pasa por el nodo, ya sea el tópico o la payload, en formato de consola web o la consola propia de node-red. En este caso en concreto se han utilizado, no sólo para estar seguros que cada paso se está realizando correctamente, sino que permite saber cierta información del output del algoritmo, como por ejemplo el *Confidence Level* de una transcripción, siendo este nodo el único que puede mostrarlo. - MQTT nodes: Los nodos MQTT de node-red tienen como funcionalidad actuar como publisher de un tópico (MQTT Out) o como listener (MQTT In). Dentro de dichos nodos tienes la opción no sólo de indicar el *Broker* al que conectarse, sino también a qué tópico tienen que enviar información / escuchar. En este caso, se ha usado el nodo MQTT Out para devolver el mensaje generado de vuelta a la pantalla. ![](https://i.imgur.com/VgepP9a.jpg) ### Tesseract y la búsqueda de un OCR Uno de los pasos del proyecto, y de hecho el más vital, era no solo encontrar la manera de cómo podíamos leer el texto de una imagen, sino el cómo podíamos hacerlo desde un proyecto de node-red conectado a una raspberry pi la cual, aunque relativamente capaz y útil, no es tan potente como un ordenador. Este punto se consideró vital en el inicio del proyecto debido a que el objetivo y el desarrollo de la práctica era directamente dependiente del hecho de que este paso fuera posible, ya que en caso contrario tendríamos que replantear el proyecto. La primera idea que se barajó fue, mediante un algoritmo de inteligencia artificial creado en python, crear un modelo entrenado con la base de datos del [EMNIST](https://www.nist.gov/itl/products-and-services/emnist-dataset) (una base de datos de números y letras) que fuera capaz de detectar lo que se escribiera. No obstante, a la que se empezó a investigar, rápidamente nos dimos cuenta de que la complejidad estaba muy por encima de los requeridos por el proyecto, por lo que fue rápidamente descartada. El paso siguiente fue, viendo que no íbamos a poder crear nosotros el modelo, intentar buscar alguno público que ya estuviera creado, y simplemente retocarlo para nuestras necesidades. Fue en este entonces cuando encontramos los OCR (Optical Character Recognition), de los cuales ya había modelos. Después de buscar y de disponer de varias opciones, el siguiente paso era su importación a node-red. Y allí nos encontramos con otro problema, pues no solo la implementación de python en node-red es excesivamente compleja (ya sin contar el tener que leer y ejecutar un script externo a node-red) sino que estos modelos eran más pesados de lo que la memoria de la raspberry pi podía soportar, ya que están pensados para ser ejecutados en ordenadores o servidores. Lo que hicimos entonces fue buscar directamente en el buscador de nodos de node-red, pues si encontrábamos algún modelo allí, significaría que estaría suficientemente optimizado para su uso en el proyecto, más allá de facilitarnos muco el proceso a nosotros. Aunque no encontramos ningún OCR de python, nos encontramos con [Tesseract](https://tesseract.projectnaptha.com/). Tesseract es un OCR desarrollado por Google el cual dispone de un port completo a Javascript, lenguaje utilizado por defecto en node-red (puesto que está construido sobre node, el cual está creado con javascript) y del que se disponía deferentes nodos creados por la comunidad. ![node-red library](https://i.imgur.com/mpQiZyd.jpg) Después de investigar sobre cuál nos iría mejor, obtuvimos dos finalistas: [node-red-contrib-tesseract](https://flows.nodered.org/node/node-red-contrib-tesseract) y [@martip/node-red-ocr](https://flows.nodered.org/node/@martip/node-red-ocr), ya que eran los más completo, los que tenían más descargas, y los que estaban mejor documentados. Al final acabamos decantándonos por el primero por una razón muy simple. Aunque no perfecto (pues las transcripcioes rondan la media del 60% de *Confidence Level*), era el único que funcionaba, ya que el segundo no aceptaba la imagen (aunque se introdujera en el modo indicado en la documentación). ![tesseract node](https://github.com/sjoerdvanderhoorn/node-red-contrib-tesseract/raw/master/tesseract-flow.png) ### Limpieza del mensaje Uno de los problemas que representaba la no-óptima transcripción del modelo era que en muchos casos no devolvía lo que se había escrito. Aunque en los casos menos precisos simplemente con borrar el mensaje o letra y reescribirlo ya servía, había muchos casos donde el mensaje sí era correcto, pero había ruido. Entre este ruido, destacaban la aparición de comillas (') o puntos (.) extra, debido a posibles temblores a la hora de escribir o de algún trazo extra que se hubiera realizado en la pantalla. Además, también destaca la aparición de carácteres de fin de línea (\n, p.ex.), los cuales eran introducidos por el algoritmo debido a su característica de detección de texto multi-línea (el cual no utilizábamos en nuestro caso, por lo que para nosotros contaba como ruido). La solución que decidimos utilizar fue el análisis y formateo del output del algoritmo mediante el uso de una función directamente en node-red, aprovechándonos de las capacidades de javascript. ![](https://i.imgur.com/dBK497w.jpg) En resumen, lo que se está llevando a cabo en esta función es el reemplazo de los carácteres no deseados en favor de espacio en blanco, lo que en la práctica los elimina. Para evitar mensajes potencialmente maliciosos o corruptos, se usa la función try-catch, permitiendo correr código en caso de que la función de reemplazar fallase. Una de las ventajas que conlleva esta forma de formateo de strings, es que es ampliable, lo que te permite poner más detalle en la corrección, como sería el caso de corregir el caso de @ a o (un error que nos hemos encontrado más de una vez). No sólo esto, también se podría usar para poder eliminar mensajes maliciosos en caso de que el usuario final pudiese ser una persona menor o en riesgo (con el uso de ****, por ejemplo). ### Acciones extra Aunque en este punto ya disponíamos de una imagen pasada a texto y disponible para ser enviada de vuelta a la pantalla, aún le faltaban diversos requisitos y características que queríamos que tuviera la aplicación, y que tendríamos que añadir a mano. Una de estas er la opción de poder borrar lo que se escribiera, ya fuese sólo la última letra como si se quería borrar todo el mensaje, así como la capacidad de ir alineando outputs del algoritmo por si se quería crear una oración entera compuesta de múltiples palabras escritas una a una (y no sólo la última palabra que se ha escrito), con su respectivo espacio. Para la realización de este paso, se utilizó un método muy parecido al método utilizado en la limpieza de strings, es decir, también se hizo uso de un nodo de función y se aprovechó las capacidades de javascript para el formateo de strings. ![](https://i.imgur.com/LWCFv1K.jpg) En el caso de esta función, lo que se está realizando es, según el payload del input que se recibe, se ejecuta una opción u otra, en este caso el borrar o el concatenar el mensaje del algoritmo. Este método, al igual que el anterior, es ampliable a nuevas características, ya que al nodo de funcion se le pueden introducir múltiples entradas, cada una con una payload diferente caracterizado por una palabra clave indicativa (como "CLEAN") y (en caso de cambiar el if a un switch, mucho más óptimo) su funcionalidad correspondiente, como sería el añadir espacios, borrar carácteres... ### Implementación en la Raspberry Pi Una vez el código estuvo desarrollado, sólo quedaba un paso más: implementarlo en la raspberry para no necesitar de un ordenador al ejecutar el proyecto. Para dicha implementación, teníamos que seguir ciertos pasos. El primer paso de todos, era conseguir que la imagen se leyera correctamente y que el mensaje se mostrara en la pantalla. Mientras que la parte de la imagen fue fácil, ya que sólo teníamos que cambiar el *path* de la imagen, la pantalla dio más problemas. En un principio, la idea que se tenía era utilizar una aplicación y mostrar por allí el texto, pero eso conllevaba un nivel de complejidad que, como el caso del modelo, no era necesario en el proyecto. Al final se utilizó MQTT en parte también al hecho de que node-red ya incorpora nodos de MQTT, por lo que enviar el mensaje de vuelta a la pantalla se transformaba en un trabajo mucho más asequible. ![](https://i.imgur.com/SSA8LSH.jpg) Una vez estuvieran todos los nodos, quedava pasarlo a la raspberry pi. Para esto, fuimos copiando los nodos a mano, funciones incluidas, desde el node-red del ordenador al node-red de la raspberry pi. Hasta que vimos la opción de importar y exportar flows, lo que nos permitía incluso no tener que estar físicamente los dos departamentos a la vez ya que podíamos enviar el fichero a traves de mail o un chat (ya que la exportación en en formato JSON). Sin embargo, no todo fue como queríamos. dadas las limitaciones de la pantalla a la hora de escribir el texto, la imagen generada no era leída correctamente por el algoritmo, por lo que no exportaba nada, o exportaba mucho ruido (que no era nada parecido a lo que se había escrito). Una de las soluciones que se internaron llevar a cabo fue mediante nodos de procesamiento de imagen, utilizando funciones tales como la pixelación, compresión, convolución, erosión... Sin embargo, ninguna combinación que utilizamos nos daba el resultado que queríamos, ya que las pocas veces que sí exportaba información, no lo hacía de manera consistente. El resultado llegó casi por accidente, pues un día, haciendo pruebas con la aplicación de escribir (probando colores, tamaños de lápiz...) se decidió hacer una captura para ver qué exportaba si tenía como input una imagen random. Fue entonces cuando nos dimos cuenta que con ampliar al tamaño del lápiz ya bastaba para leer la imagen consistentemente, y que no se necesitaba el aplicar procesado de imagen. Ejemplo de lo que se vería (aunque sin la patalla): ![](https://i.imgur.com/UJeBSoY.jpg) ### Retoques del modelo de Node-Red Dado que en lo que hace referencia al Node-Red ya estaba casi completo, lo único que se hizo fue retocar un par de funciones existentes, y añadir un par de nodos más: los GPIO in. ![](https://hackmd.io/_uploads/BJcGqZO43.png) Los nodos GPIO in eran necesarios para poder “comunicarnos” con el modelo creado en Node-Red de manera externa al programa, es decir, mediante botones conectados directamente a la Raspberry PI. La única dificultad que se encontró al añadir estos nuevos nodos fue que los números de los pines no correspondían al numero identificativo del pin, por lo que tuvimos que ayudarnos de una imagen de internet (por ejemplo, el pin número 15 de la imagen tenía como identificativo GPIO27). Con la nueva implementación de los nodos, también se tuvo que crear funciones adaptativas (nodos de función “ERASE” y “CLEAN”), puesto que los nodos GPIO solo exportan como payload el valor 0 o 1 dependiendo de si están activados o no, mientras que, tal y como teníamos estructurado el código en la función “Message”, necesitábamos que el payload y el tópico tuvieran unos valores concretos, pues si no podría llegar a exportar cosas que no querríamos. La función “Message” también ha recibido algún que otro cambio, de los cuales destacan el cambio de “ifs” a un “switch” para añadirle más escalabilidad al modelo, así como la creación del nuevo método “ERASE”, el cual borra la última letra del mensaje en vez de borrarlo entero. ![](https://hackmd.io/_uploads/ByHv9Wd4n.png) ### Aplicación web de soporte para el sistema Otra de las características del proyecto a nivel de software, más allá del modelo creado en Node-Red, es la creación de una página web de soporte donde se puedan llevar a cabo otras dos actividades diferentes. Por una parte, está el poder conectarse a una IP para escuchar un bróker de MQTT y así poder ver qué mensajes están apareciendo en un tópico en concreto (el cual lo llamamos “touch_topic”), apareciendo en la página web, cambiando cada vez que hay un mensaje nuevo. Por otra parte, otra de las características que dispone la aplicación web es, una vez se ha recibido un mensaje, tener la posibilidad de que un sistema de text-to-speech que lo diga en voz alta solo apretando un botón. Para lo que representa la página web, esta se tuvo que estructurar un poco, pensando sobretodo en que pudiera ser usable y no muy incómoda de navegar y de ver. Es por eso que la aplicación en si está estructurada en diferentes páginas: - La página de inicio, donde como usuario debes introducir la IP donde se sitúa el bróker MQTT (debes estar en la misma red que el bróker para que esto funcione). Si introduces una IP equivocada, aparecerá un error explicando cómo tienes que hacerlo. - La página de error, que aparece en caso de que no puedas conectarte al bróker, ya sea porque no está encendido, te has equivocado de IP o estés en otra red, desde donde vas a poder volver a la pantalla principal. - La pantalla del mensaje, donde van apareciendo los nuevos mensajes del tópico, y donde hay un botón para poder decirlo en voz alta. ![](https://hackmd.io/_uploads/BkgcnVd42.png) Para la realización de la aplicación se han utilizado todo tipo de tecnologías del ámbito de la programación web, siendo varias de ellas tecnologías punta. Se puede separar la aplicación en 3 grandes apartados: - Para la creación de la web en si, se ha utilizado Vue, así como sus librerías auxiliares tales como vue-router (para poder tener varias páginas web dentro de una misma aplicación). Se ha utilizado este framework en concreto más que nada por la habitualidad de los desarrolladores con esta tecnología, pues ha se han realizado otros proyectos y la tecnología es conocida y cómoda. - Para el apartado de diseño, primero se han dibujado los sketches y wireframes de como queríamos que se viera la aplicación y cada una de las pantallas, para luego ser pasadas a código. Para esta parte, se ha hecho uso de una librería llamada Vuetify, un design system que nos provee de componentes estándar (aunque altamente customizables) de modo que la aplicación tendría una sensación de unidad, integridad y profesionalidad. - Para hacer el deployment de la aplicación a internet se acabó utilizando Vercel y, aunque había otras alternativas tales como Heroku o GitHub Pages, ésta resultó la única que nos daba lo que pedíamos. Para lo que es el deploy en sí, o único que tendríamos que hacer nosotros como desarrolladores sería publicar el proyecto en GitHub, y Vercel ya se encargaría de subirlo a internet. La página web se puede encontrar [aquí](https://smart-touch.vercel.app/). ![](https://hackmd.io/_uploads/SkazpVdEn.png) No obstante, también se hace uso de otras tecnologías y librerías las cuales, aunque no destacan mucho a primera vista, son las que hacen todo el trabajo sucio de la aplicación. De estas, destacan la librería para las conexiones MQTT, y la librería del text-to speech. ![](https://hackmd.io/_uploads/B11cRE_N3.png) Para las conexiones MQTT, se hace uso de una librería de node llamada “mqtt”, la cual se conecta con el bróker mediante un protocolo WebSockets (debido a ejecutarse desde un navegador), aunque a nivel práctico no haya diferencia con una conexión directa. Inicialmente no se iba a utilizar esta, sino que la aplicación se estaba desarrollando originalmente con una librería llamada PAHOMqtt pero, como con la implementación de HTTPS se requieren de protocolos más seguros (y PAHO solo disponía de ws://), se tuvo que descartar en frente de esta otra. Aun así, hubo bastantes problemas en lo que refiere a poder hacer uso de la librería, debido a algunas incompatibilidades con los builders (en esta ocasión se utiliza uno llamado Vite, que es el predeterminado en una aplicación hecha con Vue), ya que no nos permitía hacer uso de las variables de la librería, como el poder llamar a la variable “Client”. Tras investigar por mucho tiempo, nos dimos cuenta de que, si en vez de instalar e importar la librería en el proyecto, utilizábamos un CDN (el mismo código, pero subido a internet), no nos aparecían más errores ya que conseguíamos dar la vuelta. Para las librerías de text-to-speech, también tuvimos diversos problemas hasta encontrar la solución. ![](https://hackmd.io/_uploads/S19hANON3.png) El primero de todos, es el hecho de que hay mucha escasez de librerías de text-to-speech que funcionen en un navegador ya que, mientras que desde una aplicación uno puede acceder al sistema de audio de un dispositivo, no es el caso cuando hay un navegador de por medio. Además, de las de por si pocas librerías que existen, hay algunas que están o bien obsoletas o bien directamente no funcionan por problemas internos, como fue el caso de una de las librerías que probamos, llamada “text-to-speech-js”. Al final, tras mucho tiempo también, conseguimos encontrar una que no solo cumplía con lo que queríamos, sino que además nos daba un abanico de customización muy grande, aunque solo fuéramos a utilizar una parte pequeña de la librería. Esta se llama “speak-tts”, y dispone de más de 15 idiomas diferentes (incluido el catalán), capacidad para poner audios en búfer para que vayan sonando y capacidad para alterar características de los audios tales como el pitch o el volumen. Con todo puesto en su sitio y funcionando correctamente, ya se puede dar por acabada la primera versión de nuestra aplicación web de soporte para el sistema de la Raspberry PI. Aún así, aún se pueden ir añadiendo funcionalidades, así como retocar y pulir aquellas que no acaban de convencer por el momento. ### Retoques de la aplicación web Aunque a grandes rasgos la aplicación ya estaba acabada, pues ya disponía de todas sus características importantes (recibir y mostrar el mensaje y poder escucharlo mediante text-to-speech), nos dimos cuenta de que teníamos un problema, sobre todo en el contexto en el que se iba a utilizar nuestro proyecto: la aplicación web no era muy usable. No obstante, dada nuestra experiencia estudiando ingeniería multimedia, teníamos bastante claro qué podíamos retocar al fin de conseguir una aplicación usable finalmente. El primer cambio que se hizo fue el añadir una pantalla de bienvenida al portal web ya que antes no existía, haciendo que nuestra aplicación tuviese un aire mucho más profesional a la vez que la hacía mucho más agradable en su uso. ![](https://hackmd.io/_uploads/SkfH5-Yr2.png) Aunque la paleta de colores no la cambiamos ya que ya disponía del contraste que buscábamos, sí que hicimos la aplicación “más grande”. Ampliamos el tamaño de los botones, así como el tamaño del texto y la separación entre ellos ya que, si la aplicación iba a ser potencialmente usada con gente con problemas o discapacidad, queríamos reducir al máximo la confusión y errores generados por la aplicación. ## Vídeo de demostración del proyecto [Vídeo aquí](https://youtu.be/m3UxLZgIkvw)

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully