Cuando escuchas la palabra joystick de pulgar, lo primero que te viene a la mente es un controlador de juego. Aunque se usan más comúnmente para elloss, puedes hacer muchas cosas geniales con si te gusta la electrónica de bricolaje, como controlar un robot o un rover o controlar el movimiento de la cámara.

Descripción general del hardware

Quienes estén familiarizados con el controlador de PS2 (PlayStation 2) notarán que este joystick es sorprendentemente similar al que se usa en ese dispositivo. Es un joystick autocentrante con resorte, lo que significa que cuando lo sueltes, se centrará solo. También tiene una cómoda perilla/tapa tipo copa que se siente como un pulgar.

Potenciómetros

La idea básica detrás de un joystick es convertir la posición del joystick en dos ejes, el eje X (de izquierda a derecha) y el eje Y (arriba y abajo), en una señal eléctrica que un microcontrolador pueda procesar. Esto se logra incorporando dos potenciómetros de 5K (uno para cada eje) conectados con un mecanismo cardán que separa los movimientos “horizontal” y “vertical”.

Los dos cuadros grises a ambos lados del joystick son los potenciómetros. Si mueves el joystick mientras observas el potenciómetro, notarás que cada potenciómetro solo detecta movimiento en una dirección. Veremos cómo funcionan con más detalle más adelante.

Interruptor de botón momentáneo

Esta palanca de mando también tiene un interruptor de botón pulsador momentáneo (una pequeña caja negra en un lado de la palanca de mando) que se activa cuando presionas la perilla de la palanca de mando. Al presionar, notarás una palanca que presiona la cabeza del interruptor. Está diseñado de tal manera que la palanca funciona independientemente de la posición del joystick.

¿Cómo funciona el módulo de joystick del pulgar?

Es realmente notable cómo un joystick puede traducir cada pequeño movimiento de la punta de tus dedos. Esto es posible gracias al diseño del joystick, que consta de dos potenciómetros y un mecanismo de cardán.

Mecanismo de cardán

Cuando mueves el joystick, se mueve una varilla delgada que se encuentra entre dos ejes ranurados giratorios (Gimbal o cardán). Uno de los ejes permite el movimiento a lo largo del eje X (izquierda y derecha), mientras que el otro permite el movimiento a lo largo del eje Y (arriba y abajo).

Cuando mueves el joystick hacia adelante y hacia atrás, el eje del eje Y pivota. Cuando lo mueves de izquierda a derecha, el eje del eje X gira. Y cuando lo mueves en diagonal, ambos ejes pivotan.

Cada eje está conectado a un potenciómetro, de modo que al mover el eje gira la perilla del potenciómetro correspondiente. En otras palabras, empujar la perilla completamente hacia adelante hará que el cursor del potenciómetro se mueva hacia un extremo de la pista resistiva, y tirar hacia atrás hará que se mueva hacia el extremo opuesto.

Al leer estos potenciómetros, se puede determinar la posición de la perilla.

Lectura de valores analógicos desde Joystick

El joystick emite una señal analógica cuyo voltaje varía entre 0 y 5V. Cuando mueves el joystick a lo largo del eje X de un extremo al otro, la salida X cambia de 0 a 5V, y lo mismo sucede cuando lo mueves a lo largo del eje Y. Cuando el joystick está centrado (posición de reposo), el voltaje de salida es aproximadamente la mitad de VCC o 2,5 V.

Este voltaje de salida se puede alimentar a un ADC en un microcontrolador para determinar la posición física del joystick.

Debido a que la placa Arduino tiene una resolución ADC de 10 bits, los valores en cada canal analógico (eje) pueden variar de 0 a 1023. Por lo tanto, cuando el joystick se mueve de un extremo al otro, leerá un valor entre 0 y 1023 para el canal correspondiente. Cuando el joystick está centrado, los canales vertical y horizontal mostrarán 512.

La siguiente figura muestra los ejes X e Y, así como también cómo responderán las salidas cuando el joystick se mueva en diferentes direcciones.

Configuración de pines del módulo de palanca de mando del pulgar

Echemos un vistazo al pinout del módulo Thumb Joystick.

GND es el pin de tierra.

VCC proporciona energía al módulo. Conéctalo a positivo (generalmente 5V o 3.3V dependiendo de los niveles lógicos).

VRx es el voltaje de salida horizontal. Mover el joystick de izquierda a derecha hace que el voltaje de salida cambie de 0 a VCC. El joystick leerá aproximadamente la mitad de VCC cuando esté centrado (posición de reposo).

VRy es el voltaje de salida vertical. Mover el joystick hacia arriba y hacia abajo hace que el voltaje de salida cambie de 0 a VCC. El joystick leerá aproximadamente la mitad de VCC cuando esté centrado (posición de reposo).

SW es la salida del interruptor de botón. Por defecto, la salida del interruptor es flotante. Para leer el interruptor, se requiere una resistencia pull-up de modo que cuando se presiona la perilla del joystick, la salida del interruptor se vuelve BAJA; de lo contrario, permanece ALTA. Ten en cuenta que el pin de entrada al que está conectado el interruptor debe tener habilitado el pull-up interno o debe conectarse una resistencia de pull-up externa.

Cableado de un módulo de joystick de pulgar a un Arduino

Ahora que sabemos todo sobre el módulo del joystick, conectémoslo al Arduino.

Para comenzar, conecta VRx al pin analógico A0 de Arduino y VRy al pin analógico A1. Para detectar si el joystick está presionado, conectamos el pin SW del joystick al pin digital D8 de Arduino.

Finalmente, conecta el pin VCC al terminal de 5V y el pin GND al terminal de tierra del Arduino.

Eso es todo. Es hora de poner a prueba tus habilidades con el joystick.

Arduino Ejemplo 1 – Lectura del Joystick

Aquí hay un código simple de Arduino que configura el microcontrolador para leer las entradas y luego imprimir continuamente los valores en el monitor en serie.

// Arduino pin numbers
const int SW_pin = 8; // digital pin connected to switch output
const int X_pin = 0; // analog pin connected to X output
const int Y_pin = 1; // analog pin connected to Y output

void setup() {
  pinMode(SW_pin, INPUT);
  digitalWrite(SW_pin, HIGH);
  Serial.begin(9600);
}
void loop() {
  Serial.print("Switch:  ");
  Serial.print(digitalRead(SW_pin));
  Serial.print(" | ");
  Serial.print("X-axis: ");
  Serial.print(analogRead(X_pin));
  Serial.print(" | ");
  Serial.print("Y-axis: ");
  Serial.print(analogRead(Y_pin));
  Serial.println(" | ");
  delay(200);
}

Después de cargar el código, deberías ver el siguiente resultado en el monitor serie.

Explicación del código:

Como primer paso del programa, se declaran las conexiones del módulo de joystick.

// Arduino pin numbers
const int SW_pin = 8; // digital pin connected to switch output
const int X_pin = 0; // analog pin connected to X output
const int Y_pin = 1; // analog pin connected to Y output

En la sección de configuración, configuramos el pin SW para que se comporte como una ENTRADA y lo ponemos ALTO. También comenzamos la comunicación serial con la PC.

pinMode(SW_pin, INPUT);
  digitalWrite(SW_pin, HIGH);
  Serial.begin(9600);

En la sección de bucle, simplemente usamos la función digitalRead() para leer el estado del botón y la función analogRead() para leer los pines VRx y VRy. Luego, los valores se imprimen en el monitor serie.

Serial.print("Switch:  ");
  Serial.print(digitalRead(SW_pin));
  Serial.print(" | ");
  Serial.print("X-axis: ");
  Serial.print(analogRead(X_pin));
  Serial.print(" | ");
  Serial.print("Y-axis: ");
  Serial.print(analogRead(Y_pin));
Serial.println(" | ");
  delay(200);

Cuadro de texto:   Serial.println(" | ");
  delay(200);

Ejemplo 2 de Arduino: animación de movimientos de joystick en IDE de procesamiento

Vamos a crear un proyecto Arduino para demostrar cómo se puede usar un módulo de joystick para controlar animaciones en el IDE de Processing. Así es como se ve la salida.

Por supuesto, este proyecto se puede ampliar para animar personajes, realizar vigilancia o pilotar aviones no tripulados.

Código arduino

Este ejemplo envía el estado del botón pulsador y dos salidas analógicas en serie a la computadora. El programa de procesamiento asociado lee los datos en serie para animar la posición del joystick.

El esquema es idéntico al anterior, excepto que los valores impresos en el monitor serial están separados por comas. El motivo, facilitar la transferencia de datos. El concepto aquí es enviar los valores como una cadena separada por comas que podemos analizar en el IDE de Processing para recuperar los valores.

Carga el programa a continuación en tu Arduino.

int xValue = 0 ; // read value of the X axis	
int yValue = 0 ; // read value of the Y axis	
int bValue = 0 ; // value of the button reading	

void setup()	
{	
	Serial.begin(9600) ; // Open the serial port
	pinMode(8,INPUT) ; // Configure Pin 2 as input
digitalWrite(8,HIGH);	
}	

void loop()	
{	
	// Read analog port values A0 and A1	
	xValue = analogRead(A0);	
	yValue = analogRead(A1);	

	// Read the logic value on pin 2	
	bValue = digitalRead(8);	

	// We display our data separated by a comma	
	Serial.print(xValue,DEC);
	Serial.print(",");
	Serial.print(yValue,DEC);
	Serial.print(",");
	Serial.print(!bValue);

	// We end with a newline character to facilitate subsequent analysis	
	Serial.print("\n");

	// Small delay before the next measurement	
	delay(10);	
}

Código de Processing

Después de cargar el programa en Arduino, podemos comenzar a animar la posición del joystick en el IDE de Processing. Mantén el Arduino enchufado y ejecuta el código a continuación.

import processing.serial.*; //import the Serial library
Serial myPort;

int x; // variable holding the value from A0
int y; // variable holding the value from A1
int b; // variable holding the value from digital pin 2
PFont f; // define the font variable
String portName;
String val;

void setup()
{
  size ( 512 , 512 ) ; // window size
  
  // we are opening the port
   myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.bufferUntil('\n'); 
  
  // choose the font and size
  f = createFont("Arial", 16, true); // Arial, 16px, anti-aliasing
  textFont ( f, 16 ) ; // size 16px
}

// drawing loop
void draw()
{
  fill(0) ; // set the fill color to black
  clear() ; // clean the screen
  
  fill(255) ; // set the fill color to white
  
  if (b == 1) // check if the button is pressed
  {
    // draw a larger circle with specified coordinates
    ellipse(x/2,y/2, 50, 50);
  } 
  else
  {
    // we draw a circle with a certain coordinates
    ellipse(x/2,y/2, 25, 25);
  }
  
  // we display data
text("AnalogX="+(1023-x)+" AnalogY="+(1023-y),10,20);
}

// data support from the serial port
void serialEvent( Serial myPort) 
{
  // read the data until the newline n appears
  val = myPort.readStringUntil('\n');
  
  if (val != null)
  {
        val = trim(val);
        
    // break up the decimal and new line reading
    int[] vals = int(splitTokens(val, ","));
    
    // we assign to variables
    x = vals[0];
    y = vals[1] ;
    b = vals[2];
  }
}

Explicación del código:

Analicemos rápidamente el código. Primero, importamos la biblioteca serial para leer los valores del puerto serial.

import processing.serial.*; //import the Serial library
Serial myPort;

A continuación, se declaran las variables que contendrán los valores de estado del eje x, el eje y y el botón.

int x; // variable holding the value from A0
int y; // variable holding the value from A1
int b; // variable holding the value from digital pin 2
PFont f; // define the font variable
String portName;
String val;

En la función de configuración, primero establecemos el tamaño de la ventana en 512 × 512. A continuación, usamos Serial.list()[0] para abrir el primer puerto serie disponible. Si esto no funciona, seleccione el puerto al que está conectado Arduino. También seleccionamos una fuente para mostrar nuestros valores en la ventana.

size ( 512 , 512 ) ; // window size
  
  // we are opening the port
   myPort = new Serial(this, Serial.list()[0], 9600);
  myPort.bufferUntil('\n'); 
  
  // choose the font and size
  f = createFont("Arial", 16, true); // Arial, 16px, anti-aliasing
  textFont ( f, 16 ) ; // size 16px

Al comienzo de la función de dibujo, el color de fondo de la ventana se establece en negro. Luego elegimos un color blanco para dibujar un pequeño círculo para representar la posición del joystick. Para mostrar que el pulsador ha sido presionado, agrandamos el círculo.

fill(0) ; // set the fill color to black
  clear() ; // clean the screen
  
  fill(255) ; // set the fill color to white
  
  if (b == 1) // check if the button is pressed
  {
    // draw a larger circle with specified coordinates
    ellipse(x/2,y/2, 50, 50);
  } 
  else
  {
    // we draw a circle with a certain coordinates
    ellipse(x/2,y/2, 25, 25);
  }

Los valores de los ejes x e y se imprimen en la esquina superior izquierda de la ventana.

// we display data
  text("AnalogX="+(1023-x)+" AnalogY="+(1023-y),10,20);

La función personalizada serialEvent(Serial myPort) nos ayuda a analizar una lista de valores separados por comas.

void serialEvent( Serial myPort) 
{
  // read the data until the newline n appears
  val = myPort.readStringUntil('\n');
  
  if (val != null)
  {
        val = trim(val);
        
    // break up the decimal and new line reading
    int[] vals = int(splitTokens(val, ","));
    
    // we assign to variables
    x = vals[0];
    y = vals[1] ;
    b = vals[2];

  }
}

How 2-Axis joystick Works & Interface with Arduino + Processing. Last Minute Engineers. https://lastminuteengineers.com/joystick-interfacing-arduino-processing/