Duda con Módulo joystick + LEDs + Arduino UNO

Buenas,

En este proyecto estoy intentando hacer que en base a cómo se mueva un módulo joystick (como este) he dividido las posiciones del joystick en 8 direcciones (arriba, abajo, derecha, izquierda, izquierda+arriba, izquierda+abajo, derecha+arriba, derecha+abajo) y en función de la posición en la que se encuentre el joystick, que se encienda uno de los 4 leds que he colocado (o dos en caso de que sea una posición combinada).

Para definir cada una de las posiciones tomé datos de los ejes X e Y (ya que el joystick son dos potenciómetros). Los datos que tomé son los siguientes:

El código que he escrito es el siguiente:

const int xPin = A4;
const int yPin = A5;
const int ledIzquierda = 13;
const int ledDerecha = 11;
const int ledArriba = 12;
const int ledAbajo = 10;

int xpos = 0;
int ypos = 0;

void setup() {

  pinMode(ledIzquierda, OUTPUT);
  pinMode(ledDerecha, OUTPUT);
  pinMode(ledArriba, OUTPUT);
  pinMode(ledAbajo, OUTPUT);
  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);
  
}

void loop() {
  xpos = analogRead(xPin);
  ypos = analogRead(yPin);
  
  // ARRIBA + IZQUIERDA
  if(xpos >= 650 && ypos <= 15);{
    digitalWrite(ledArriba, HIGH);
    digitalWrite(ledIzquierda, HIGH);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
    }
  //ARRIBA   
  if(xpos >= 650 && ypos >= 320);{
    digitalWrite(ledArriba, HIGH);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
    }  
  //ARRIBA + DERECHA
   if(xpos >= 650 && ypos >= 650);{
    digitalWrite(ledArriba, HIGH);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, HIGH);
    }
  //DERECHA  
 if(xpos >= 320 && ypos >= 650);{
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, HIGH);
    }
  //ABAJO + DERECHA   
  if(xpos <= 15 && ypos >= 650);{
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, HIGH);
    digitalWrite(ledDerecha, HIGH);
    }
  //ABAJO   
  if(xpos <= 15 && ypos >= 320);{
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, HIGH);
    digitalWrite(ledDerecha, LOW);
    }
  //ABAJO + IZQUIERDA
  if(xpos <= 15 && ypos <= 15);{
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, HIGH);
    digitalWrite(ledAbajo, HIGH);
    digitalWrite(ledDerecha, LOW);
    }
  //IZQUIERDA  
  if(xpos >= 320 && ypos <= 15);{
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, HIGH);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
    }
  //CENTRO 
  if(xpos >= 320 && ypos >= 320);{
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
    }          
  
  delay(100);
}

En vez de realizar lo que he descrito anteriormente, al cargar el código al arduino UNO los leds parpadean rápidamente (¿cada 0’1 segundos del delay?), y continúan así independientemente de en qué posición coloque el módulo joystick. ¿Podríais ayudarme?

Muchas gracias de antemano :slight_smile:

Creo que el problema son los valores intermedios, ya que al ponerlos con >=320, se cumplen otras condiciones, de forma que cuando tengas que poner ese valor di que sea mayor que 310 Y menor que 330, vamos, así:

const int xPin = A4;
const int yPin = A5;
const int ledIzquierda = 13;
const int ledDerecha = 11;
const int ledArriba = 12;
const int ledAbajo = 10;

int xpos = 0;
int ypos = 0;

void setup() {

  pinMode(ledIzquierda, OUTPUT);
  pinMode(ledDerecha, OUTPUT);
  pinMode(ledArriba, OUTPUT);
  pinMode(ledAbajo, OUTPUT);
  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);

}

void loop() {
  xpos = analogRead(xPin);
  ypos = analogRead(yPin);

  // ARRIBA + IZQUIERDA
  if (xpos >= 650 && ypos <= 15); {
    digitalWrite(ledArriba, HIGH);
    digitalWrite(ledIzquierda, HIGH);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
  }
  //ARRIBA
  if (xpos >= 650 && ypos > 310 && ypos < 330); {
    digitalWrite(ledArriba, HIGH);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
  }
  //ARRIBA + DERECHA
  if (xpos >= 650 && ypos >= 650); {
    digitalWrite(ledArriba, HIGH);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, HIGH);
  }
  //DERECHA
  if (xpos > 310 && xpos < 330 && ypos >= 650); {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, HIGH);
  }
  //ABAJO + DERECHA
  if (xpos <= 15 && ypos >= 650); {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, HIGH);
    digitalWrite(ledDerecha, HIGH);
  }
  //ABAJO
  if (xpos <= 15 && ypos > 310 && ypos < 330); {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, HIGH);
    digitalWrite(ledDerecha, LOW);
  }
  //ABAJO + IZQUIERDA
  if (xpos <= 15 && ypos <= 15); {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, HIGH);
    digitalWrite(ledAbajo, HIGH);
    digitalWrite(ledDerecha, LOW);
  }
  //IZQUIERDA
  if (xpos > 310 && xpos < 330 && ypos <= 15); {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, HIGH);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
  }
  //CENTRO
  if (xpos > 310 && xpos < 330 && ypos > 310 && ypos < 330); {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
  }

  delay(100);
}

Buenas, carmeloco

He subido el código que me has proporcionado a mi arduino y los LEDs se comportan de manera idéntica a como lo hacía con el código que subí. Lo que tú has dicho tiene sentido, así que no sé cuál es el problema. :/

Bueno, ya he encontrado los fallos en tu código, que paso a explicar.

El gran fallo que había, era que habías puesto ; después de la condición de cada if. Por ejemplo:

if (xpos >= 650 && ypos <= 15); {

Con eso, lo que consigues es finalizar el if, de la misma forma que se finaliza cada linea con el ; de forma que siempre se ejecutaban los comandos de todos los if, sin tenerse en cuenta, las condiciones de estos.

El siguiente error, es en los rangos. Si tenemos un rango, que va de 0 a 690, me parece correcto que se defina el límite superior en >= 650 , pero lo que no tiene sentido, es definir el límite inferior en <= 15. ¿Por qué por arriba tenemos un margen de 40 puntos y por abajo solo de 15? Mejor definamos el margen inferior en <=40.

El siguiente error, también me lo atribuyo a mi, ya que si fijamos el margen intermedio entre 310 y 330, ¿qué pasa si uno de los ejes está en 400? pues sencillo, que habrá situaciones que no se cumplan nunca, de forma que, paso a marcar el valor intermedio, entre >40 y <650 de forma que cubrimos todas las posibles posiciones del joystick, y encendemos los leds solamente cuando estamos en los límites de este (bueno, o casi en los límites realmente, pero hay que dar margen para evitar errores).

Hay un error menor, que es este::

 pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);

Si se va a hacer un analogRead, no es necesario declarar el pin analógico como input.

Otra cosa que puede parecer un error es esta:

const int xPin = A4;
const int yPin = A5;

En un principio, no tiene sentido asignar letras a una variable int, pero el IDE, traduce A4 como 18 y A5 como 19. La realidad de esto, es que en el IDE, hay una serie de constantes por defecto, de las cuales, unas de ellas son A0=14, A1=15, A2=16, A3=17, A4=18, A5=19… De forma que lo que estamos asignando al valor de xPin, es el valor de la constante A4.
Los pines analógicos, en el arduino uno, van del A0 al A5, pero también pueden ser nombrados del 14 al 19 (que es su nomenclatura real), de forma que esta parte, funciona, y no es un error.

Otra cosa que se puede eliminar, es esta:

delay(100);

No es necesario. El código funciona perfectamente sin ese delay, pero tampoco pasa nada si se deja.

Por último, considero un error esto:

int xpos = 0;
int ypos = 0;

No es exactamente un error, pero podemos perfectamente declarar estas variables sin valor:

int xpos;
int ypos;

Ya que no sabemos que qué posición estará inicialmente el joystick, y de todas formas, lo primero que hace el loop, es asignar el valor de los analogRead a esas variables.

Bien, una vez explicado todo, paso a poner el código completo corregido:

const int xPin = A4;
const int yPin = A5;
const int ledIzquierda = 13;
const int ledDerecha = 11;
const int ledArriba = 12;
const int ledAbajo = 10;

int xpos;
int ypos;

void setup() {
  pinMode(ledIzquierda, OUTPUT);
  pinMode(ledDerecha, OUTPUT);
  pinMode(ledArriba, OUTPUT);
  pinMode(ledAbajo, OUTPUT);
}

void loop() {
  xpos = analogRead(xPin);
  ypos = analogRead(yPin);

  // ARRIBA + IZQUIERDA
  if (xpos >= 650 && ypos <= 40) {
    digitalWrite(ledArriba, HIGH);
    digitalWrite(ledIzquierda, HIGH);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
  }
  //ARRIBA
  if (xpos >= 650 && ypos >40 && ypos <650) {
    digitalWrite(ledArriba, HIGH);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
  }
  //ARRIBA + DERECHA
  if (xpos >= 650 && ypos >= 650) {
    digitalWrite(ledArriba, HIGH);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, HIGH);
  }
  //DERECHA
  if (xpos >40 && xpos <650 && ypos >= 650) {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, HIGH);
  }
  //ABAJO + DERECHA
  if (xpos <= 40 && ypos >= 650) {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, HIGH);
    digitalWrite(ledDerecha, HIGH);
  }
  //ABAJO
  if (xpos <= 40 && ypos >40 && ypos <650) {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, HIGH);
    digitalWrite(ledDerecha, LOW);
  }
  //ABAJO + IZQUIERDA
  if (xpos <= 40 && ypos <= 40) {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, HIGH);
    digitalWrite(ledAbajo, HIGH);
    digitalWrite(ledDerecha, LOW);
  }
  //IZQUIERDA
  if (xpos >40 && xpos <650 && ypos <= 40) {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, HIGH);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
  }
  //CENTRO
  if (xpos >40 && xpos <650 && ypos >40 && ypos <650) {
    digitalWrite(ledArriba, LOW);
    digitalWrite(ledIzquierda, LOW);
    digitalWrite(ledAbajo, LOW);
    digitalWrite(ledDerecha, LOW);
  }
  
  delay(100);
}

Hola de nuevo, carmeloco

Gracias por corregirme los errores, que si bien no son errores como tal, ayudan a tener el código mucho más limpio y entendible. Lo que más me ha sorprendido es que puse ; tras el if, lo cual causaba el problema con el código. ¡Qué error más tonto! Cargué el código que posteé inicialmente corrigiendo este fallo y aunque sigue habiendo conflictos con los intervalos, funciona de manera mucho más cercana a como estaba planeado. Cargando el último código que me has proporcionado funciona a la perfección, así que lo importante era definir bien los intervalos.

Muchísimas gracias por tu ayuda!