Utilizar un Joystick con Arduino y OpenCV

En este artículo aprenderás a utilizar una herramienta de manipulación conocida como joystick, aprenderás a conectarla con tu placa Arduino y a realizar control con ella.

¿Qué es un joystick?

Seguramente si te pregunto si conoces un control de consola, ya sea PlayStation®, Nintendo®, Xbox® o cualquier otra, reconoces que tienen botones y una pequeña palanca con la que puedes controlar a tus personajes en el videojuego. Esta pequeña palanca la llamamos joystick. Con ella, podremos generar mayor información que con un simple botón, ya que cuenta con una mayor cantidad de posiciones.

Existen distintos tipos de joysticks, pero el que utilizaremos el día de hoy, será el que viene en un módulo pensado para utilizarse con Arduino.

Imagen de un módulo joystick
Imagen de un módulo joystick

El joystick está compuesto por un sistema de ejes balanceados acoplados mecánicamente con un potenciómetro (resistencia variable), al mover su posición, cambiará la resistencia y por lo tanto el voltaje que produce. Como tiene dos ejes, podremos generar movimientos en horizontal y en vertical; pero sobre todo, combinación de estos.

Imagina que tienes un plano cartesiano como el de la siguiente imagen, podrás generar combinaciones como si fueran coordenadas en un plano, partiendo del origen que sería el centro del plano cuando la palanca está en la posición de reposo.

Plano de referencia
Plano de referencia

Además de los movimientos en el eje x y en el eje y, el módulo incluye un pulsador, que se activa al precisamente pulsar o presionar la palanca hacia abajo.

¿Cómo utilizar un joystick analógico?

El joystick es un control analógico, esto quiere decir que al moverlo de posición, producirá un nivel de voltaje. Entonces el módulo tiene que tener salidas analógicas; y como también incluye un botón, incluye una salida digital.

Los pines de conexión que tiene un módulo joystick son los mostrados en la siguiente imagen.

Pines de conexión de un joystick
Pines de conexión de un joystick

Pines del módulo joystick:

  • GND.- Terminal de conexión de tierra.
  • +5V.- Terminal de conexión de 5 VCD.
  • VRX.- Salida de voltaje analógico correspondiente al movimiento en el eje x.
  • VRY.- Salida de voltaje analógico correspondiente al movimiento en el eje y.
  • SW.- Salida digital correspondiente al pulsador.

¿Cómo utilizar el módulo joystick con Arduino?

Para interpretar los movimientos del joystick con nuestra placa Arduino, simplemente tendremos que conectar las salidas analógicas del módulo a entradas analógicas de la placa Arduino.

Para este primer ejercicio, conectaremos el sistema de la siguiente manera.

Diagrama de conexiones visto desde el módulo

Conexiones de un joystick con Arduino
Conexiones de un joystick con Arduino

Diagrama de conexiones visto desde el Arduino

Conexiones de un joystick con Arduino

El código que utilizaremos es el siguiente:

Declaramos variables para las conexiones de acuerdo al diagrama que te mostré anteriormente. Creamos también, variables para almacenar las lecturas de los ejes x y y, así como una variable de tipo bool para almacenar el estado del botón. El la función de configuración, declaramos los pines como entradas, y para el botón, declaramos el pin como entrada y activamos la resistencia interna PULLUP. Recuerda que cuando conectamos botones necesitamos una resistencia para que sobre ella esté el voltaje detectado correspondiente a uno (5 V) o cero (0 V), si queremos ahorrarnos el tener que conectar una resistencia física, utilizamos la interna que trae la placa Arduino. Te dejo el enlace al artículo donde vimos algo de resistencias y botones.

En el monitor serie observaremos las conversiones y los valores equivalentes a la posición del joystick. Si observas, te darás cuenta de que cuando el joystick está en la posición central, ya tendrá valores en la salida, por lo que deberás tomar en cuenta esto. Para que sirva como guía, te dejo este diagrama.

Coordenadas cuando tenemos el joystick en reposo
Coordenadas cuando tenemos el joystick en reposo

Si observas, cuando el joystick está hasta la izquierda, e valor es de 0, en el centro es de 500, y hasta la derecha es de 1023.

En las posiciones verticales; es decir, en el eje y, el valor será de 0 cuando está hasta arriba, 524 en el centro, y 1023 cuando está hasta abajo.

Ya te podrás imaginar que posiciones intermedias tendrán distintos valores, creados por la combinación de ambos ejes, como coordenadas.

También te podrás preguntar, ¿en el módulo cuál es el movimiento en x y cuál en y? Te dejo esta imagen de referencia:

Referencia de movimiento en el joystick
Referencia de movimiento en el joystick

Por otro lado, cuando presionamos el botón obtendremos un estado lógico de 0, equivalente a 0 VCD.

¿Te está gustando este artículo?

Te invito a descargar totalmente gratis la Guía de Inicio en Arduino

Encontrarás mucha información extra, conceptos y sobre todo podrás llevarla contigo en todo momento

Conectar un Joystick a una computadora utilizando Python y OpenCV

¡Quizá no es muy interesante ver los numeritos en la pantalla corriendo como locos… entonces, se me ocurre una mejor manera de mostrarte la aplicación que tiene el joystick, que te parece dibujar en un recuadro la posición!

Para esto, nos apoyaremos de recursos de procesamiento de imágenes y Python, como lo hicimos en este artículo. Utilizaremos una computadora con Python instalado, en mi caso Python3, y OpenCV. Si quieres implementar este ejemplo y no tienes instaladas estas herramientas y aún con la ayuda del link que te acabo de mostrar tienes algunas dudas, siempre puedes dejarme tu comentario o escribirme a mi correo 😄

Necesitamos modificar un poco nuestro código en el Arduino, como te muestro a continuación:

Si observas, lo que hicimos fue mapear las lecturas del joystick de 0 a 1023 (que es el rango de lecturas que entrega) a un rango de 0 a 600, lo anterior, para el eje X. Y mapear de 0 a 1023 a un rango de 0 a 400, para el eje y. ¿Porqué elegí estos rangos de salida? Porque pretendo realizar un dibujo de un tamaño de 400×600 (400 filas y 600 columnas), por lo que el tamaño en x será 600 y en y será de 400. Ahorita te muestro.

Estos datos los convertimos a String para poderlos interpretar como texto y los mandamos por el puerto serie acomodados de la siguiente manera: Serial.println(x + " " + y + " " + boton); primero mandamos el dato de x luego un espacio el dato de y un espacio y luego el estado del botón. Recuerda que cuando «sumamos» Strings, lo que hacemos es simplemente concatenarlos, unirlos uno tras otro.

Con esto la placa Arduino estará enviando cada 100ms (por el delay, aproximadamente) las conversiones por el puerto Serie. Estos datos los recibirá la computadora donde estará corriendo el siguiente programa en Python:

Primero estamos configurando el puerto Serie, esto depende de el nombre que tenga el puerto serie en tu computadora, en mi caso, que estoy utilizando un adaptador para mi USBC en Mac OS X, se llama cu.usbserial-14310, pero esto puede variar en tu caso. Si quieres listar los puertos que tienes conectados utiliza el siguiente código:

Siguiendo con la explicación del código principal, una vez que abrimos el puerto serie, creamos una imagen de tamaño 400x600x3:

El formato para crear una matriz que represente una imagen es con una herramienta integrada en la paquetería numpy, que también importamos, estamos creando una matriz llena de valores 255 (que representaría un blanco), con la siguiente sintaxis np.ones((filas,columnas,dimensión), formato) nosotros le estamos dando un tamaño de 400 filas, 600 columnas, 3 dimensiones para los colores BGR (recuerda que en OpenCV el formato de colores es blue, green, red), y con un formato de tipo entero sin signo de 8 bits.

Después trazamos dos líneas en la imagen en blanco:

Utilizando OpenCV dibujamos la línea con la siguiente sintaxis cv2.line(imagen_donde_se_dibujará, coordenadas_x_y_del_origen, coordenadas_x_y_del_final, color_en_BGR, grosor_de_la_línea) estaremos dibujando justo por el centro dos líneas para que sean nuestra referencia.

Imagen de referencia
Imagen de referencia

Ahora recibiremos lo que esté llegando por el puerto serie, leyendolo, codificándolo a 8 bits (ya que así lo envía el Arduino), y con la función .rstrip() vamos a cortar la cadena que llega hasta donde detecte un \n ya que estará recibiendo los números que manda el Arduino mas un caracter de salto de línea, o enter (\n), así tendremos guardado en la variable linea lo que está mandando por puerto Serie el Arduino.

Como estamos utilizando espacios para separar las coordenadas X y Y y el estado del botón, utilizaremos la función :

donde nos separará en tres variables valorx, valory, boton la información correspondiente, recordando que la información que podrá contener la variable boton será 0 o 1 (presionado o no_presionado, correspondientemente).

Después, lo que hacemos es volver a dibujar la misma imagen de original, con los ejes azules, esto es porque cada vez que llegue algo por el puerto, dibujaremos un círculo con origen en las coordenadas X y Y que está enviando el Arduino con el joystick, y el círculo será vacío si no se hace click, y relleno si se hace click, esto lo logramos así:

Cuando la variable boton == 1 significa que el botón no está presionado, entonces dibujamos el círculo sin relleno, cualquier otro valor de la variable boton entonces dibujamos el círculo relleno. Esto nos estamos basando en la siguiente sintaxis para dibujar círculos con OpenCV:

cv2.circle(imagen_donde_se_dibujarña, coordenada_X, coordenada_Y, tamaño, (B,G,R), grosor) para el grosor, si le enviamos -1 lo tomará como completamente relleno.

Finalmente mostraremos la imagen, y revisaremos si presionamos la tecla s que se cierre la ventana y se cierre el puerto serie, para finalmente destruir la ventana que dibujamos y cerrar todo.

Si todo sale bien, tendrías que ver algo como esto:

Imagen final
Imagen final

Ahora solo resta hacer pruebas y mover el joystick!!


¿Qué te ha parecido este artículo? Cuéntame en qué se te ocurre utilizar un joystick, déjame tus preguntas y comentarios. ¡Por cierto, quiero darles las gracias por todos sus comentarios y preguntas, recuerda que también puedes enviarme tus sugerencias, reviso todos los correos y comentarios que me dejan, muchas gracias a todos y todas!

Hasta la próxima!

Recuerda visitar nuestras redes sociales

Deja un comentario