INTRODUCCIÓN
En esta práctica vamos a desarrollar el diseño de un JoyStick WiFi. El motivo es que las aplicaciones Web implementadas con HTML, CSS y JavaScript son cada vez más populares especialmente por su portabilidad, una vez escritas se pueden ejecutar en cualquier plataforma (android, windows, ios, etc.) a través de un navegador Web, con esto evitamos el principal problema de la tecnología Bluetooth, que precisa de un controlador es específico para cada una.
Los procesadores ESP8266 se pueden configurar como puntos de acceso WiFi y se puede configurar en ellos un servidor HTTP de páginas estáticas.
Esa es la idea clave del proyecto del ESPway que presentó Sakari Kapanen (flannelhead) recientemente a la comunidad a través de GitHub: https://github.com/flannelhead/espway
Por supuesto, el procesador ESP8266 no depende de ninguna red WiFi existente, es el propio procesador quien crea la red (punto de acceso –access point-), con la que nos conectamos para acceder a la página HTML que genera el JoyStick.
El proyecto ESPway es bastante complejo. En este artículo únicamente se va a utilizar su idea para crear un JoyStick, lo más sencillo y funcional posible, que servirá de base para el control de nuestros propios robots.
MATERIAL NECESARIO
JOYSTICK A UTILIZAR
Crear un JoyStick de cero sería bastante laborioso. Para evitar este trabajo, vamos a recurrir a un JoyStick creado por Jerome Etienne (jerommeetinne) en GitHub: https://github.com/jeromeetienne/virtualjoystick.js
De los tres ejemplos de que dispone, seleccionamos el modelo básico, aunque será necesario hacer algunas modificaciones para adaptarlo.
Inicialmente el JoyStick se vería así:
Haciendo click con el ratón sobre la superficie gris o tocando con el dedo, si la pantalla es táctil, veremos como se desplaza el «stick» del JoyStick.
Este modelo se genera a partir de dos ficheros:
Son un fichero HTML y un fichero JavaScript, que es el que contiene en realidad el código del JoyStick.
Abriendo el fichero HTML vemos que en su línea 55 se realiza la llamada al fichero virtualjoystick.js:
<script src="../virtualjoystick.js"></script>
Para poder utilizar el JoyStick almacenado en el sistema de archivos para memoria flash SPI (SPIFFS) necesitamos unir estos dos ficheros en uno solo.
Esto se hace de una manera muy sencilla. Únicamente tendremos que eliminar la llamada al fichero virtualjoystick.js (src=»../virtualjoystick.js») e incluir entre las etiquetas <script> y </script> todo el código que incluye en el propio fichero.
Este es el punto de partida.
Una vez realizado, adecuaremos el JoyStick a unas necesidades comunes de uso, para ello seguiremos los siguientes pasos:
Cambiaremos las siguientes líneas del código:
this._limitStickTravel= opts.limitStickTravel || false this._stickRadius = opts.stickRadius !== undefined ? opts.stickRadius : 100
Por:
this._limitStickTravel = opts.limitStickTravel || true; if (screen.width >= screen.height){ this._stickRadius = opts.stickRadius !== undefined ? opts.stickRadius : screen.height*0.35; } else { this._stickRadius = opts.stickRadius !== undefined ? opts.stickRadius : screen.width*0.35; };
Quedaría como vemos a continuación.
Con ello hemos establecido un límite que es una barrera circular alrededor de la base, cuyo radio es el 35% (0.35) del valor del lado más corto de la pantalla en que se visualice el JoyStick (anchura o altura).
[/ultimate_icon_list_item][ultimate_icon_list_item icon=»Defaults-check»]
Para que podamos ver de una manera gráfica el límite que hemos creado modificamos la forma de representar la “base” en la pantalla.
Cambiaremos las siguientes líneas del código:
/* * build the canvas for joystick base */ VirtualJoystick.prototype._buildJoystickBase = function() { var canvas = document.createElement( 'canvas' ); canvas.width = 126; canvas.height = 126; var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.strokeStyle = this._strokeStyle; ctx.lineWidth = 6; ctx.arc( canvas.width/2, canvas.width/2, 40, 0, Math.PI*2, true); ctx.stroke(); ctx.beginPath(); ctx.lineWidth = 2; ctx.lineWidth = 2; ctx.arc( canvas.width/2, canvas.width/2, 60, 0, Math.PI*2, true); ctx.stroke(); return canvas; }
Por:
/** * build the canvas for joystick base */ VirtualJoystick.prototype._buildJoystickBase = function() { var canvas = document.createElement( 'canvas' ); if (screen.width >= screen.height){ canvas.width = screen.height*0.7; } else { canvas.width = screen.width*0.7; }; canvas.height = canvas.width; var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.fillStyle = "#AAA"; ctx.arc(canvas.width/2, canvas.width/2,canvas.width/2,0,Math.PI*2,true); ctx.closePath(); ctx.fill(); ctx.beginPath(); ctx.strokeStyle = this._strokeStyle; ctx.lineWidth = 6; ctx.arc( canvas.width/2, canvas.width/2, 40, 0, Math.PI*2, true); ctx.stroke(); ctx.beginPath(); ctx.strokeStyle = "#69C"; ctx.lineWidth = 4; ctx.arc( canvas.width/2, canvas.width/2, canvas.width/2-2, 0, Math.PI*2, true); ctx.stroke(); ctx.beginPath(); ctx.lineWidth = 3; ctx.moveTo(canvas.width/2,0); ctx.lineTo(canvas.width/2,canvas.width/2); ctx.stroke(); ctx.lineWidth = 1; ctx.moveTo(canvas.width/2,0); ctx.lineTo(canvas.width/2,canvas.width); ctx.moveTo(0,canvas.width/2); ctx.lineTo(canvas.width,canvas.width/2); ctx.stroke(); return canvas; }
Quedaría como vemos a continuación.
De esta manera visualizaremos un círculo con cuatro cuadrantes en color gris oscuro, que será el área sobre el que podemos desplazar el “stick”.
[/ultimate_icon_list_item][ultimate_icon_list_item icon=»Defaults-check»]
Lo siguiente será hacer que visualicemos en la pantalla los siguientes valores:
- Desplazamiento horizontal del “stick” desde la base –dx–. Haremos que el valor esté comprendido entre 0 y 255.
- Desplazamiento vertical del “stick” desde la base –dy–. También haremos que el valor esté comprendido entre 0 y 255.
- Longitud del “stick”. –Vector (stick)–. Es la distancia entre la «base» y el «stick«. Este valor se calcula a partir de los valores dx y dy.
- Ángulo de giro (sexagesimal) del “stick. –Ángulo–. Este ángulo se mide entre la horizontal y la línea que une «base» y el «stick«. También este valor se calcula a partir de los valores dx y dy.
Cambiaremos las siguientes líneas del código:
setInterval(function(){ var outputEl = document.getElementById('result'); outputEl.innerHTML = '<b>Result: </b>' + ' dx:'+joystick.deltaX() + ' dy:'+joystick.deltaY() + (joystick.right() ? ' right' : '') + (joystick.up() ? ' up' : '') + (joystick.left() ? ' left' : '') + (joystick.down() ? ' down' : '') }, 1/30 * 1000);
Por:
var deltaX_corregida = 0; var deltaY_corregida = 0; setInterval(function(){ if (screen.width >= screen.height){ var stickRadius = screen.height*0.35; } else { var stickRadius = screen.width*0.35; }; var deltaX_corregida=(joystick.deltaX()/stickRadius*255).toFixed(); var deltaY_corregida=(-joystick.deltaY()/stickRadius*255).toFixed(); var stick = Math.sqrt((deltaX_corregida*deltaX_corregida)+(deltaY_corregida*deltaY_corregida)).toFixed(); if (deltaX_corregida >= 0 & deltaY_corregida >= 0){ var angulo = (Math.atan(deltaY_corregida/deltaX_corregida)/(2*Math.PI)*360).toFixed() } if (deltaX_corregida < 0) { var angulo = ((Math.atan(deltaY_corregida/deltaX_corregida)/(2*Math.PI)*360)+180).toFixed() } if (deltaX_corregida >= 0 & deltaY_corregida < 0){ var angulo = ((Math.atan(deltaY_corregida/deltaX_corregida)/(2*Math.PI)*360)+360).toFixed() } var outputEl = document.getElementById('result'); outputEl.innerHTML = '<b>RESULTADO: </b>' + '<b> dx:</b>'+deltaX_corregida + '<b> dy:</b>'+deltaY_corregida + '<b> Vector (stick):</b>'+stick + '<br><b> Ángulo:</b>'+angulo + '<b> Orientación:</b>' + (joystick.right() ? ' Derecha' : '') + (joystick.up() ? ' Arriba' : '') + (joystick.left() ? ' Izquierda' : '') + (joystick.down() ? ' Abajo' : '') }, 1/30 * 1000);
El resultado quedaría así:
[/ultimate_icon_list_item][ultimate_icon_list_item icon=»Defaults-check»]
El último paso es sin duda el más importante, el envío de los datos al procesador ESP8266 mediante el método HTTP GET, para que el robot reciba las instrucciones de funcionamiento.
Únicamente se envían los valores dx y dy. Sería muy sencillo implementar el envío de más valores, pero también se pueden calcular en el script de Arduino.
Simplemente añadimos a la función modificada en el apartado anterior las siguientes líneas de código:
var deltaX_corregida = 0; var deltaY_corregida = 0; setInterval(function(){ if (deltaX_corregida != deltaXprevia || deltaY_corregida != deltaYprevia ){ var req = new XMLHttpRequest(); req.open('GET', '/stick?dx=' + deltaX_corregida + '&dy=' + deltaY_corregida); req.send(null); deltaXprevia = deltaX_corregida; deltaYprevia = deltaY_corregida; } }
Como se puede ver en el código, se han utilizado las variables deltaX_corregida y deltaY_corregida como referencia para evitar el envío de datos cuando el “stick” no se mueve, y por tanto no cambian los valores dx y dy.[/ultimate_icon_list_item][/ultimate_icon_list]
SKETCH A UTILIZAR
/* JOYSTICK VIRTUAL Para su funcionamiento es necesario guardar el fichero index.html (https://www.esploradores.com/wp-content/uploads/2017/03/index.zip) en el Sistema de Archivos para Memoria Flash (SPIFF). Esto se realiza utilizando el complemento del IDE de Arduino ESP8266FS (https://github.com/esp8266/arduino-esp8266fs-plugin/releases/download/0.3.0/ESP8266FS-0.3.0.zip) Este código de ejemplo es de público dominio. Dani No www.esploradores.com */ #include <ESP8266WiFi.h> //Librería de conexión WiFi del módulo ESP8266 #include <ESP8266WebServer.h> //Librería ESP8266WebServer (simplifica la creación del servidor) #include "FS.h" //Librería del Sistema de Archivos para Memoria Flash (SPIFFS) const char *ssid = "JOYSTICK_VIRTUAL", // Credenciales del Punto de Acceso *password = "12345678"; ESP8266WebServer server(80); void setup() { Serial.begin(115200); Serial.println(""); // Inicialización del Puerto Serie SPIFFS.begin(); // Inicializamos el sistema de Archivos para Memoria Flash (SPIFFS) WiFi.softAP(ssid, password); // La IP del Punto de Acceso será 192.168.4.1 server.on("/", []() { // Sirve la página index.html desde el SPIFFS cuando se solicita File index = SPIFFS.open("/index.html", "r"); server.streamFile(index, "text/html"); index.close(); }); server.on("/stick", []() { // Recibe los datos (dx y dy) String dx=server.arg("dx"); String dy=server.arg("dy"); server.send(200); int x = dx.toInt(); // Convierte los datos de tipo String a Int int y = dy.toInt(); Serial.print(x); Serial.print(" "); Serial.println(y); }); server.begin(); // Inicializa el servidor } void loop() { server.handleClient(); }
Hagamos un repaso del funcionamiento del sketch y los pasos para instalar el JoyStick.
El sketch utiliza tres librerías:
ESP8266WiFi.h: librería para gestionar las conexiones WiFi del módulo ESP8266.
[/ultimate_icon_list_item][ultimate_icon_list_item icon=»Defaults-minus»]ESP8266WebServer.h: para simplificar la creación del creación del servidor Web.
[/ultimate_icon_list_item][ultimate_icon_list_item icon=»Defaults-minus»]FS.h: para la gestión de archivos del Sistema de Archivos de la Memoria Flash (SPIFFS).
[/ultimate_icon_list_item][/ultimate_icon_list]LIBRERÍA ESP8266WiFi.h
La primera librería se utiliza para crear el punto de acceso de la conexión WiFi (access point). Podemos encontrar una explicación detallada de esta modo de conexión en el siguiente enlace.
Cuando hayamos finalizado la configuración podremos acceder de la siguiente forma:
Buscaremos la red WiFi del punto de acceso que genera el procesador ESP8266 (JOYSTICK_VIRTUAL), con el dispositivo con el que deseemos conectarnos (smartphone, ordenador, tablet…)
[/ultimate_icon_list_item][ultimate_icon_list_item icon=»Defaults-minus»]Introduciremos la clave establecida en el sketch (12345678).
[/ultimate_icon_list_item][ultimate_icon_list_item icon=»Defaults-minus»]Abriremos un navegador Web (Internet Explorer, Google Chrome, Mozzilla, Opera…) y escribiremos la dirección IP del punto de acceso (192.168.4.1).
[/ultimate_icon_list_item][/ultimate_icon_list]Establecer como puerto de comunicaciones el número 80:
ESP8266WebServer server(80)
Indicar mediante la función server.on las posibles opciones (paths) de comunicación entre navegador y servidor y la respuesta a cada opción. Hemos establecido dos posibilidades:
- Cuando escribimos en el navegador la dirección IP del punto de acceso (192.168.4.1), o lo que es lo mismo (192.168.4.1/) el servidor reconoce la barra que hay a continuación de la dirección IP «/«, al haberse implementado esta opción y ejecuta las instrucciones de envío del fichero index.html al navegador.
server.on("/", []() { File index = SPIFFS.open("/index.html", "r"); server.streamFile(index, "text/html"); index.close(); })
- Cuando se mueve el JoyStick, el navegador envía al servidor los datos de las coordenadas. Por ejemplo, para la coordenada dx=10 y dy=20 enviaría: 192.168.4.1/stick?dx=10&dy=20.
El servidor reconoce la clave «/stick» y ejecuta la extracción de los datos por nombre de variables (dx y dy), devolviendo al servidor el OK de recepción correcta (200). Al recibir los datos como cadenas (string) es necesario convertirlos a números (int) para poder trabajar con ellos.
server.on("/stick", []() { String dx=server.arg("dx"); String dy=server.arg("dy"); server.send(200); int x = dx.toInt(); int y = dy.toInt(); Serial.print(x); Serial.print(" "); Serial.println(y); });
ES EN ESTE APARTADO DONDE TENEMOS QUE PONER LAS INSTRUCCIONES QUE QUEREMOS QUE EJECUTE NUESTRO ROBOT A PARTIR DE LOS DATOS RECIBIDOS
LIBRERÍA FS.h
Esta tercera librería habilita disponibilidad del Sistema de Archivos para Memoria Flash SPI (SPIFFS). Esto significa que los datos y las secuencias de comandos del JoyStick (index.html) se pueden escribir en la memoria flash y leer cuando se necesitan, utilizando el concepto de archivos.
Las instrucciones completas relativas al funcionamientos del SPIFFS lo podemos encontrar en GitHub: https://github.com/esp8266/Arduino/blob/master/doc/filesystem.md
La memoria Flash disponible para el Sistema de Archivos depende del modelo de procesador ESP8266 que utilicemos:
Procesador ESP8266 en función
del tamaño de la memoria Flash |
Memoria disponible para
el Sistema de Archivos |
Placas que utilizan
este procesador |
512 kB | 64kB, 128kB |
|
1 MB | 64kB, 128kB, 256kB y 512kB | |
2 MB | 1 MB |
|
4MB | 3 MB |
|
Aunque el sistema de archivos se almacena en el mismo chip flash que el programa, la programación de un nuevo boceto no modificará el contenido del sistema de archivos. Esto permite utilizar el sistema de archivos para almacenar datos de boceto, archivos de configuración o contenido para el servidor Web.
Para poder guardar archivos en el sistema de archivos es necesario utilizar la aplicación ESP8266FS. Esta aplicación que se integra en el IDE de Arduino añadiendo una opción de menú para copiar en el sistema de archivos los archivos guardados en la carpeta data del sketch.
Para instalar esta aplicación debemos:
Descargar el archivo: https://github.com/esp8266/arduino-esp8266fs-plugin/releases/download/0.3.0/ESP8266FS-0.3.0.zip.
[/ultimate_icon_list_item][ultimate_icon_list_item icon=»Defaults-minus»]Descomprimir el archivo en la carpeta tools del IDE de Arduino. El camino tiene que ser similar al siguiente: <home_dir>/Arduino/tools/ESP8266FS/tool/esp8266fs.jar
Cuando volvamos a abrir el IDE de Arduino veremos que en el menú Tools se ha añadido la opción de menú ESP8266 Sketch Data Upload.
Ahora ya podremos copiar los archivos en el SPIFFS. Para copiar el fichero index.html deberemos:
Una vez subido el sketch al procesador ESP8266 y copiado el archivo index.html en el SPIFFS podremos iniciar el JoyStick como se había indicado en el apartado de la librería ESP8266WiFi.h.
6 Comments
Leave your reply.