Introducción
La idea principal de este proyecto es que personas con movilidad reducida puedan utilizar el robot Escornabot mediante 4 simples movimientos: inclinando la cabeza hacia adelante, inclinando la cabeza hacia atrás, inclinando la cabeza hacia la izquierda e inclinando la cabeza hacia la derecha.
Aunque la idea principal es controlar el robot con los movimientos de la cabeza también lo podremos controlar con las manos ya que el circuito que construiremos lo podremos usar como si fuese un mando.
En este proyecto vamos a utilizar la IMU (Unidad de Medición Inercial) presente en la placa Arduino Nano 33 BLE Sense para controlar el robot. La idea es que en función de la inclinación que le demos a la placa generemos las instrucciones correspondientes para controlar el robot. La placa Arduino Nano 33 BLE Sense además tiene bluetooth integrado gracias al módulo NINA B306 (con calificación de Bluetooth 5.0).
La comunicación entre el Arduino Nano 33 BLE Sense y el robot se realizará mediante Bluetooth Low Energy para ello acoplaremos al Escornabot un módulo Bluetooth Low Energy (en mi caso he utilizado un módulo HM-10).
La placa Arduino Nano 33 BLE Sense actuará como nuestro mando a distancia y por tanto representará el dispositivo central o máster en la comunicación BLE (Bluetooth Low Energy) mientras que el módulo HM-10 del Escornabot será el dispositivo periférico o esclavo.
Listado de componentes
-
- Arduino Nano 33 BLE Sense.
- DFPlayer Mini MP3 Player.
- Amplificador Mono 2.5W Class D (PAM8302).
- Altavoz de 4 a 8 Ohmios y de 0,5 a 3W de potencia.
- Protoboard de 830 puntos.
- Placa PCB de doble cara para prototipos de 6×8 cm.
- Tarjeta MicroSD.
- Módulo HM-10 Bluetooth 4.0 BLE (en mi caso de la marca DSD TECH) conectado al Escornabot.
- Cable de protoboard.
- Terminal de conexión de 2 contactos para PCB.
- Portapilas 4x AAA con tapa, interruptor y cable de alimentación.
- Escornabot (en mi caso la versión Compactus).
Circuito
El circuito que tenemos que montar en la protoboard es el siguiente:
Montar el circuito en la protobard solo será práctico si queremos usarlo con las manos a modo de mando a distancia ya que acoplar esto en la cabeza sería engorroso. Para ello vamos a trasladar el circuito anterior a una PCB de prototipos de 6×8 cm que nos vendrá genial para posteriormente acoplar dicha placa a un soporte de móviles para la cabeza.
NOTA: No usar una medida inferior de placa puesto que necesitamos como mínimo unos 6 cm en un lado para que la placa quede bien sujeta al soporte de móviles que usaremos.
NOTA: Los cables con las conexiones se muestran a nivel ilustrativo en la parte superior junto con los componentes pero todo el cableado y soldaduras se realizará en la parte inferior de la placa.
Conexiones DFPlayer Mini MP3 Player con el Arduino Nano 33 BLE Sense y el Amplificador Mono 2.5W Class D Audio:
DFPlayer Mini MP3 Player | Arduino Nano 33 BLE Sense |
VCC | +3,3V |
RX | TX1 |
TX | RX0 |
DAC_R | SIN CONECTAR |
DAC_L | SIN CONECTAR |
SPK_1 | PIN A+ DEL Amplificador Mono 2.5W Class D Audio |
GND | GND |
SPK_2 | PIN A- DEL Amplificador Mono 2.5W Class D Audio |
IO_1 | SIN CONECTAR |
GND | SIN CONECTAR |
IO_2 | SIN CONECTAR |
AD_KEY_1 | SIN CONECTAR |
AD_KEY_2 | SIN CONECTAR |
USB+ | SIN CONECTAR |
USB- | SIN CONECTAR |
BUSY | SIN CONECTAR |
Conexiones Amplificador Mono 2.5W Class D Audio con el DFPlayer Mini MP3 Player:
Amplificador Mono 2.5W Class D Audio | DFPlayer Mini MP3 Player |
A+ | SPK_1 |
A- | SPK_2 |
SD | SIN CONECTAR |
VIN | +3,3V (DEL ARDUINO) |
GND | GND |
NOTA: Todo el circuito lo alimentaremos con 4 pilas AAA a través del pin Vin del Arduino. El rango de voltaje que soporta la placa Arduino Nano 33 BLE Sense en el pin Vin es de 4.5V a 21V con lo cual con 4 pilas AAA será suficiente.
NOTA: El módulo HM-10 lo conectaremos al Escornabot y es conveniente utilizar un divisor de tensión para no dañar el dispositivo si utilizamos la versión DIY. Para las versiones Compactus y Singularis esto no es necesario ya que dispone de un conector específico con un divisor de tensión ya integrado.
Montaje
Una vez creado el circuito vamos a montar todo el conjunto en un soporte universal de móviles para la cabeza (correas extensibles + soporte para móvil tipo clip) del estilo al que se muestra en la siguiente fotografía:
Lo primero que haremos será montar el soporte para móviles tipo clip y ponerlo en posición horizontal de tal manera que la parte extensible quede en la parte exterior para posteriormente poder fijar el circuito a este soporte.
Posteriormente fijaremos el portapilas mediante cinta de doble cara en la pieza metálica que se encuentra en la parte posterior de la correa. Previamente a esto hemos cambiado el cable original que trae del portapilas por un cable más largo (unos 35 cm de largo):
Ahora fijamos el circuito al soporte para móviles y conectamos el cable de alimentación procedente del portapilas:
El resultado final quedará de la siguiente manera:
Funcionamiento
Como hemos comentado en la introducción vamos a controlar el robot mediante 4 simples movimientos: inclinando la cabeza hacia adelante, inclinando la cabeza hacia atrás, inclinando la cabeza hacia la izquierda e inclinando la cabeza hacia la derecha.
La idea es que en función de la inclinación que le demos al circuito generemos las instrucciones correspondientes para controlar el robot.
En la siguiente tabla se muestra la relación de los ángulos de los ejes X e Y (inclinación del circuito) con las instrucciones que se generan en el robot:
Instrucción | Inclinación Y | Inclinación X |
avanzar / si | (y >= 20º) | (x >= -10º), ( x <= 10º) |
retroceder / no | (y <= -20º) | (x >= -10º) , ( x <= 10º) |
izquierda | (y >= -10º) , (y <= 10º) | (x >= 15º) |
derecha | (y >= -10º) , (y <= 10º) | (x <= -15º) |
centro | (y >= -10º) , (y <= 10º) | (x >= -10º), ( x <= 10º) |
Por tanto:
Avanzar / si: Se tendrá que inclinar el circuito hacia adelante con un ángulo igual o superior a 20º sin inclinar el circuito a izquierda o derecha con un ángulo mayor o igual a 10º.
Retroceder / no: Se tendrá que inclinar el circuito hacia atrás con un ángulo igual o superior a 20º sin inclinar el circuito a izquierda o derecha con un ángulo mayor o igual a 10º.
Izquierda: Se tendrá que inclinar el circuito hacia la izquierda con un ángulo igual o superior a 15º sin inclinar el circuito hacia adelante o hacia atrás con un ángulo mayor o igual a 10º.
Derecha: Se tendrá que inclinar el circuito hacia la derecha con un ángulo igual o superior a 15º sin inclinar el circuito hacia adelante o hacia atrás con un ángulo mayor o igual a 10º.
Posición central: Se tendrá que mantener el circuito sin ningún tipo de inclinación para ello no se debe inclinar el circuito hacia adelante, hacia atrás, hacia la izquierda o hacia la derecha con un ángulo mayor o igual a 10º.
¿Y cómo se envían las acciones de ejecutar y resetear las instrucciones?
La premisa es que el usuario tenga únicamente 4 movimientos disponibles, claramente diferenciados y simples de realizar.
Después de probar varias opciones la que me resultó a mi modo de entender más simple para poder realizar las acciones de ejecución y reseteado es que si el circuito se mantiene en la posición central (y por tanto no se está enviando ningún tipo de movimiento) durante 3 segundos (valor configurable) y previamente ya se ha enviado alguna instrucción, el sistema preguntará al usuario si desea ejecutar las instrucciones, si la respuesta es afirmativa, se enviará al robot la orden de ejecutar los movimientos. Si la respuesta es negativa se preguntará al usuario si quiere resetear las instrucciones, si la respuesta es afirmativa se resetearán todos los movimientos enviados. Si la respuesta es negativa el sistema quedará a la espera de recibir nuevas instrucciones de movimientos.
Para responder afirmativamente a las preguntas ¿quieres ejecutar las instrucciones? y ¿quieres borrar las instrucciones? se tendrá que hacer el movimiento de avanzar, es decir, inclinar el circuito hacia adelante. Si se quiere responder negativamente a las preguntas se tendrá que realizar el movimiento de retroceder, es decir, inclinar el circuito hacia atrás.
Todos los movimientos y acciones irán siempre acompañados de una locución.
Cuando el robot está ejecutando las órdenes el sistema no podrá enviar nuevas instrucciones hasta que todas se hayan terminado de realizar. Todos los movimientos que el robot está ejecutando se enviarán al circuito por bluetooth para que el usuario pueda escuchar la locución asociada al movimiento que en ese momento el robot esté realizando.
La placa Arduino Nano 33 BLE Sense tiene un LED RGB incorporado y lo utilizaremos para indicar los siguientes estados:
-
- Color verde: El circuito se encuentra en una posición válida (cualquiera de las posiciones descritas en la tabla).
- Color rojo:
- El circuito no se encuentra en una posición válida (ninguna posición descrita en la tabla).
- El robot se encuentra ejecutando las órdenes y por tanto no admite nuevas instrucciones para ser enviadas hasta que éstas terminen de ejecutarse.
- Color azul: Cada vez que se envía una instrucción al robot o se responde afirmativamente o negativamente a las preguntas: ¿quieres ejecutar las instrucciones? y ¿quieres borrar las instrucciones? .
Importante:
Para evitar que se produzcan movimientos no deseados hay que tener en cuenta los siguiente:
-
- Se debe mantener la posición más de medio segundo. Solo superado ese medio segundo la posición se considerará válida.
- Después de cada instrucción enviada se exige que se vuelva a la posición central durante al menos medio segundo. Es decir, si inclino el circuito hacia adelante para enviar la instrucción de avanzar después tendré que volver a la posición central para poder enviar una nueva instrucción. De esta manera evitamos que se envíen instrucciones repetidas si el usuario se mantiene sin querer en una posición.
Lo anterior es válido también al responder las preguntas ¿quieres ejecutar las instrucciones? y ¿quieres borrar las instrucciones?, es decir, si inclino el circuito hacia adelante para responder afirmativamente a la pregunta después tendré que volver a la posición central para poder seguir con el proceso.
NOTA: La posición central es la primera posición que se tiene que hacer antes de dar las instrucciones al robot por primera vez y como se ha comentado anteriormente hay que mantenerla durante al menos medio segundo para que sea válida.
Instalación
1) Lo primero de todo es instalar a través del gestor de tarjetas del IDE de Arduino el núcleo Arduino nRF528x mbed para la placa Arduino Nano 33 BLE Sense.
Importante: Instalar una versión igual o superior a la 1.1.6 ya que en versiones anteriores existía un bug que afectaba a la utilización del puerto Serial1 y haría que nuestro circuito no funcionase correctamente.
2) Instalar la librería ArduinoBLE. Se puede instalar o desde el gestor de librerías del IDE de Arduino o desde el repositorio:
https://github.com/arduino-libraries/ArduinoBLE
3) Instalar la librería Arduino LSM9DS1. Se puede instalar o desde el gestor de librerías del IDE de Arduino o desde el repositorio:
https://github.com/arduino-libraries/Arduino_LSM9DS1
Importante:
Esta librería es la que utilizamos para sacar los valores de la IMU del Arduino y poder así determinar los ángulos de inclinación.
Tenemos el problema que la librería nos proporciona los valores en el sistema internacional, es decir, los valores del acelerómetros los expresa en en G’s, el giroscopio en °/sec y el magnetómetro en uT y a nosotros nos interesan los valores en bruto (RAW) para poder utilizarlo en las fórmulas que determinan los ángulos. Por ello tendremos que modificar ligeramente la librería para que nos devuelva los valores en bruto.
Para ello tendremos que comentar el trozo de código que utiliza la librería para expresar los valores de los sensores al sistema internacional y dejar el código para que exprese los valores en bruto. Realizaremos los siguientes cambios en fichero LSM9DS1.cpp de la librería:
nt LSM9DS1Class::readAcceleration(float& x, float& y, float& z) { int16_t data[3]; if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t*)data, sizeof(data))) { x = NAN; y = NAN; z = NAN; return 0; } /* Esta parte es la que hay que comentar *//* x = data[0] * 4.0 / 32768.0; y = data[1] * 4.0 / 32768.0; z = data[2] * 4.0 / 32768.0; */ /* Esta parte es la que hay que añadir */ x = data[0]; y = data[1]; z = data[2]; return 1; } int LSM9DS1Class::readGyroscope(float& x, float& y, float& z) { int16_t data[3]; if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_G, (uint8_t*)data, sizeof(data))) { x = NAN; y = NAN; z = NAN; return 0; } /* Esta parte es la que hay que comentar *//* x = data[0] * 2000.0 / 32768.0; y = data[1] * 2000.0 / 32768.0; z = data[2] * 2000.0 / 32768.0; */ /* Esta parte es la que hay que añadir */ x = data[0]; y = data[1]; z = data[2]; return 1; } int LSM9DS1Class::readMagneticField(float& x, float& y, float& z) { int16_t data[3]; if (!readRegisters(LSM9DS1_ADDRESS_M, LSM9DS1_OUT_X_L_M, (uint8_t*)data, sizeof(data))) { x = NAN; y = NAN; z = NAN; return 0; } /* Esta parte es la que hay que comentar *//* x = data[0] * 4.0 * 100.0 / 32768.0; y = data[1] * 4.0 * 100.0 / 32768.0; z = data[2] * 4.0 * 100.0 / 32768.0; */ /* Esta parte es la que hay que añadir */ x = data[0]; y = data[1]; z = data[2]; return 1; }
NOTA: Aunque solo vamos a utilizar los valores del acelerómetro también hemos dejado los valores en bruto del giroscopio y el el magnetómetro para mantener la coherencia.
4) Instalar la librería DFRobotDFPlayerMini. Se puede instalar o desde el gestor de librerías del IDE de Arduino o desde el repositorio:
https://github.com/DFRobot/DFRobotDFPlayerMini/archive/1.0.3.zip
5) Una vez instaladas las librerías ya podemos cargar el programa (Skecth) en el Arduino Nano 33 BLE Sense que lo tenéis disponible en el siguiente repositorio:
https://github.com/avilmaru/escornabot_control_por_acelerometro/tree/master/central
NOTA: Como se ha explicado anteriormente si el circuito se mantiene en la posición central (no se está enviando ningún tipo de movimiento) durante 3 segundos y previamente ya se ha enviado alguna instrucción el sistema preguntará al usuario si desea ejecutar o resetear las instrucciones enviadas al robot. Pues bien, si se quiere modificar este tiempo bastará como modificar la constante siguiente:
const unsigned long LIMIT2= 3000;
NOTA: Si se quiere modificar el volumen del altavoz bastará modificar el valor en la instrucción siguiente (el rango de valores va del 0 a 30):
myDFPlayer.volume(20);
NOTA: En caso que vuestros identificadores de servicio y característica del módulo bluetooth acoplado en el Escornabot sean diferentes a los que contiene el Skecth debéis seguir la operativa que se explica en el ANEXO: OBTENIENDO LOS UUIDS para obtener vuestros identificadores y cambiarlos en el Skecth.
const char* deviceServiceUuid = «ffe0»;
const char* deviceServiceCharacteristicUuid = «ffe1»;
6) Copiar los audios a la tarjeta MicroSD.
Para las diferentes locuciones presentes en nuestro proyecto utilizaremos archivos en formato MP3 que grabaremos en una tarjeta MicroSD para posteriormente insertarla en el reproductor MP3.
En mi caso he utilizado una página Web (http://www.fromtexttospeech.com/) donde escribiendo el texto y seleccionando el idioma te genera el archivo MP3 correspondiente aunque también tenéis la opción de grabar vosotros mismos estas locuciones.
Importante: Los archivos MP3 se deben grabar en el directorio raíz de la tarjeta y para evitar problemas (yo los he tenido por no hacerlo así) hay que copiarlos en orden desde vuestro ordenador a la tarjeta MicroSD, es decir, primero copiar el MP3 denominado 0001.mp3, luego el 0002.mp3 y así sucesivamente.
NOTA: Si se está utilizando Mac OS X el sistema de archivos agregará automáticamente archivos tipo: «._0001.mp3». Debéis eliminarlos con la instrucción siguiente:
dot_clean / Volumes / <SDVolumeName> ( Donde <SDVolumeName> por el nombre del volumen de vuestra tarjeta SD).
En el siguiente enlace tenéis los audios que yo he generado para que los podáis descargar:
https://github.com/avilmaru/escornabot_control_por_acelerometro/tree/master/audios
7) Cargar el firmware del Escornabot modificado.
Se ha tenido que modificar el código en el firmware oficial del Escornabot para que el robot envíe los movimientos que está ejecutando al circuito. De esta manera todos los movimientos que el robot está ejecutando se enviarán al circuito por bluetooth para que el usuario pueda escuchar la locución asociada al movimiento que en ese momento el robot esté realizando.
La versión que he modificado para realizar este proyecto es la 1.6.2 y por si alguno siente curiosidad solo se ha añadido/modificado código en los siguientes ficheros del firmware original:
BluetoothInterface.cpp
EventManager.cpp
La versión modificada la podeis descargar del siguiente repositorio:
https://github.com/avilmaru/escornabot_control_por_acelerometro/tree/master/arduino-1.6.2
NOTA: Acordaros de cambiar el fichero de configuración por el vuestro o poner en el fichero los valores correspondientes de vuestro robot.