Using a 2-axis joystick and 4+1 LEDS to indicate direction

Hi all,

this is my very first forum post, I’m not sure yet how to use it properly, so forgive me if I make mistakes.

TL,DR: A relatively easy program (analogRead-map-digitalWrite) makes random mistakes.

So, I am a mechanical engineering student, and I am fairly new to electronics to or programming. I learnt the basics of Delphi in school, and started Python a few weeks ago on my own. I’ve been using Arduino for only one week tho.

I attached my code and a picture of my circuit. My goal is to make LED Xmax brighten, when the joystick is pushed in the X+ direction. If it is also pushed sideways, I also want to brighten that side too. In the serial monitor, all seems fine, but nothing seems to be happening with my LEDS after the void loop starts. One of my LEDs keep glowing ever so slightly.
The blue LED should light up when I press the center button, but it does not. (It only lights up if I handle the joystick so that my hand touches the underside of the module.)

One of my friends suggested that I might need to add a ‘104 capacitor’ between AREF and GND, but the Circuito app doesn’t indicate so.

The grayed out lines were a devastated attempt without the dim effect. (that didn’t work either)

All help would be appreciated!

Sorry if it has been asked before, I only found questions where they tried without mapping and dimming.

Ir_nyjelz_.ino (1.94 KB)


Circuit looks ok. Post your code between code tags and I'll take a look.

The blue LED should light up when I press the center button, but it does not. (It only lights up if I handle the joystick so that my hand touches the underside of the module.)

Guessing: you have set pinMode(7, INPUT) or not use pinMode() at all? The switch is connected between SW and GND, and you are expecting the pin to read HIGH when the switch is pressed?

Not a good idea to use pins 0 an 1. They're needed by Serial.

    int  Xmin = map(X, 0, 512, 0, 255); 
    int  Xmax = map(X, 513, 1023, 0, 255); 
    int  Ymin = map(Y, 0, 512, 0, 255); 
    int  Ymax = map(Y, 513, 1023, 0, 255);

You are mapping the pin NUMBERS not the values on the pins, analogRead() might be useful.

Also you are only switching the LED on for 10 milliseconds then immediately off again.

Steve

Thank you all for the quick replies, I’ll look into it later today.

For the time being, here’s my code for future reference:

int xmin=5;
int xmax=6;
int ymin=9;
int ymax=10;
int center=11;
int X=1;
int Y=0;
int SW=2;


void setup() {
 // put your setup code here, to run once:
 
 pinMode(xmin, OUTPUT);
 pinMode(xmax, OUTPUT);
 pinMode(ymin, OUTPUT);
 pinMode(ymax, OUTPUT);
 pinMode(center, OUTPUT);
 pinMode(X, INPUT);
 pinMode(Y, INPUT);
 pinMode(SW, INPUT);
 digitalWrite(xmin, HIGH);
 digitalWrite(xmax, HIGH);
 digitalWrite(ymin, HIGH);
 digitalWrite(ymax, HIGH);
 digitalWrite(center, HIGH);
 delay(1000);
 digitalWrite(xmin, LOW);
 digitalWrite(xmax, LOW);
 digitalWrite(ymin, LOW);
 digitalWrite(ymax, LOW);
 digitalWrite(center, LOW);


 pinMode(SW, INPUT);
 digitalWrite(SW, LOW);
 Serial.begin(115200);
}
void loop() {

   Serial.print("Switch:  ");
   Serial.print(digitalRead(SW));
   Serial.print("\n");
   Serial.print("X-axis: ");
   Serial.println(float(analogRead(X)* (100.0/1023.0)));
   Serial.print("\n");
   Serial.print("Y-axis: ");
   Serial.println(float(analogRead(Y)* (100.0/1023.0)));
   Serial.print("\n\n");
   delay(100);
 
   int  Xmin = map(X, 0, 512, 0, 255); 
   int  Xmax = map(X, 513, 1023, 0, 255); 
   int  Ymin = map(Y, 0, 512, 0, 255); 
   int  Ymax = map(Y, 513, 1023, 0, 255); 
   analogWrite(xmin, Xmin);
   analogWrite(xmax, Xmax);
   analogWrite(ymin, Ymin);
   analogWrite(ymax, Ymax);


if (digitalRead(SW)==HIGH){
   digitalWrite(center, HIGH);
   delay(10);
   digitalWrite(center, LOW);
 }
  /* if (analogRead(X)>512) {
   digitalWrite(xmax, HIGH);
   delay(10);
   digitalWrite(xmax, LOW);
 }
 if (analogRead(X)<512) {
   digitalWrite(xmin, HIGH);
   delay(10);
   digitalWrite(xmin, LOW);
 }
 if (analogRead(Y)>512) {
   digitalWrite(ymax, HIGH);
   delay(10);
   digitalWrite(ymax, LOW);
 }
 if (analogRead(Y)<512) {
   digitalWrite(ymax, HIGH);
   delay(10);
   digitalWrite(ymax, LOW);
 }*/

PaulRB: Post your code between code tags and I'll take a look.

Please modify & correct your post above, which is breaking forum rules. Then we will be happy to point out what needs fixing.

slipstick:
Not a good idea to use pins 0 an 1. They’re needed by Serial.

Steve, I don’t think the OP intended to use pins 0 & 1. They intended to use pins A0 & A1, not realising there is a difference.

But the other stuff Steve said is correct.

PaulRB:
Please modify & correct your post above, which is breaking forum rules. Then we will be happy to point out what needs fixing.

Sorry, my bad! I corrected it now.

dpe997: Sorry, my bad! I corrected it now.

+1 karma

Make corrections suggested by Steve. If still not working, post updated code.

Okay, so apparently my SW button doesn't work at all. I wrote a quick code to check.

int SW=8;


void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
if (SW==HIGH){
  Serial.println(1);
  delay(200);}
  else{
  Serial.println(0);
  }
}

Also, I now realize that my schematics wasn’t correct, as it was an Arduino Mega, and I have an Uno (replica).
Plus, I tried what Steve suggested, but unfortunately, it still doesn’t work. (The serial monitor shows X Y values fine).

int xmin=5;
int xmax=6;
int ymin=9;
int ymax=10;
int center=11;
int X=4;
int Y=3;
int SW=8;


void setup() {
  // put your setup code here, to run once:
  
  pinMode(xmin, OUTPUT);
  pinMode(xmax, OUTPUT);
  pinMode(ymin, OUTPUT);
  pinMode(ymax, OUTPUT);
  pinMode(center, OUTPUT);
  pinMode(X, INPUT);
  pinMode(Y, INPUT);
  pinMode(SW, INPUT);
  digitalWrite(xmin, HIGH);
  digitalWrite(xmax, HIGH);
  digitalWrite(ymin, HIGH);
  digitalWrite(ymax, HIGH);
  digitalWrite(center, HIGH);
  delay(1000);
  digitalWrite(xmin, LOW);
  digitalWrite(xmax, LOW);
  digitalWrite(ymin, LOW);
  digitalWrite(ymax, LOW);
  digitalWrite(center, LOW);


  pinMode(SW, INPUT);
  Serial.begin(115200);
}
void loop() {

    Serial.print("Switch:  ");
    Serial.print(digitalRead(SW));
    Serial.print("\n");
    Serial.print("X-axis: ");
    Serial.println(float(analogRead(X)* (100.0/1023.0)));
    Serial.print("Y-axis: ");
    Serial.println(float(analogRead(Y)* (100.0/1023.0)));
    Serial.print("\n\n");
    delay(100);
  
    int  Xmin = map(analogRead(X), 0, 512, 0, 255); 
    int  Xmax = map(analogRead(X), 513, 1023, 0, 255); 
    int  Ymin = map(analogRead(Y), 0, 512, 0, 255); 
    int  Ymax = map(analogRead(Y), 513, 1023, 0, 255); 
    digitalWrite(xmin, Xmin);
    digitalWrite(xmax, Xmax);
    digitalWrite(ymin, Ymin);
    digitalWrite(ymax, Ymax);
 

 if (digitalRead(SW)==HIGH){
    digitalWrite(center, HIGH);
    delay(100);
    digitalWrite(center, LOW);
  }
   /* if (analogRead(X)>512) {
    digitalWrite(xmax, HIGH);
    delay(10);
    digitalWrite(xmax, LOW);
  }
  if (analogRead(X)<512) {
    digitalWrite(xmin, HIGH);
    delay(10);
    digitalWrite(xmin, LOW);
  }
  if (analogRead(Y)>512) {
    digitalWrite(ymax, HIGH);
    delay(10);
    digitalWrite(ymax, LOW);
  }
  if (analogRead(Y)<512) {
    digitalWrite(ymax, HIGH);
    delay(10);
    digitalWrite(ymax, LOW);
  }*/


}

dpe997: Okay, so apparently my SW button doesn't work at all. I wrote a quick code to check.

No, your quick code is wrong. It does not even use digitalRead(). And you need to set the pin to INPUT_PULLUP mode.

I tried what Steve suggested

You fixed the first thing Steve suggested but not the second problem, that is still there.

Also, you changed

analogWrite(xmin, Xmin);

to

digitalWrite(xmin, Xmin);

That was not suggested by me or Steve.

PaulRB: No, your quick code is wrong. It does not even use digitalRead(). And you need to set the pin to INPUT_PULLUP mode.

....Right. I am sorry, I failed to proofread what I wrote. I'll correct my quick code later, however, I might have misunderstood what he meant. I corrected the 10ms delay in the "if" function for the switch. Was it not what he meant?

Also I'll need to do some research on INPUT PULLUP.

Sorry for my basic questions, I only started Arduino a week ago, and I have yet to figure out how to find the exact problems as I've come up with. When I search for what I want to achieve, I either get too easy, or too difficult tasks.

But I am working on it, and I am thankful for your support and patience! :)

Your next problem may be that you have not understood how map() and analogWrite() functions work. For example here:

int  Xmin = map(analogRead(X), 0, 512, 0, 255);

If analogRead(X) is zero, then Xmin will be zero and if analogRead(X) is 512, Xmin will be 255, and for the values between, a scaled value will be calculated. Ok, great. But what if analogRead(X) is not between 0 and 512? Then Xmin will not be between 0 and 255. For example if analogRead(X) is 513, then Xmin could be 256. If analogRead(X) is 768 then Xmin will be about 384. So map does not limit the result so that it is between 0 and 255.

analogWrite(xmin, Xmin);

When Xmin is used here, strange things may happen because analogWrite() is expecting the value to be always between 0 and 255. If Xmin is 256, that will have the same result as 0. If Xmin is 384, that will be the same as 128.

Also here:

int  Xmax = map(X, 513, 1023, 0, 255);

if analogRead(X) is 512, Xmax could be -1. If analogRead(X) is 200, Xmax could be around -50.

To stop analogWrite() getting a result which is not between 0 and 255, you can do this:

analogWrite(xmin, constrain(Xmin, 0, 255));

PaulRB: Your next problem may be that you have not understood how map() and analogWrite() functions work. For example here:

int  Xmin = map(analogRead(X), 0, 512, 0, 255);

If analogRead(X) is zero, then Xmin will be zero and if analogRead(X) is 512, Xmin will be 255, and for the values between, a scaled value will be calculated. Ok, great. But what if analogRead(X) is not between 0 and 512? Then Xmin will not be between 0 and 255. For example if analogRead(X) is 513, then Xmin could be 256. If analogRead(X) is 768 then Xmin will be about 384. So map does not limit the result so that it is between 0 and 255.

analogWrite(xmin, Xmin);

When Xmin is used here, strange things may happen because analogWrite() is expecting the value to be always between 0 and 255. If Xmin is 256, that will have the same result as 0. If Xmin is 384, that will be the same as 128.

Also here:

int  Xmax = map(X, 513, 1023, 0, 255);

if analogRead(X) is 512, Xmax could be -1. If analogRead(X) is 200, Xmax could be around -50.

To stop analogWrite() getting a result which is not between 0 and 255, you can do this:

analogWrite(xmin, constrain(Xmin, 0, 255));

Dear Paul,

I tried replying to your entry on Friday, but apparently I forgot to hit the post button, or something else went awry. Sorry about that.

I was unable to work on it yesterday, but today I tried what you have suggested, (thanks!), and I'm starting to get confused.

I read up on INPUT PULLUP, thank you!

I had to re-wire my circuit (for transportation), and for some reason, I updated the code instead of following my previous pin assignments. So, I'm going to paste you my code once again, just to make sure we're on the same page.

int xmin=5;
int xmax=6;
int ymin=9;
int ymax=10;
int center=11;
int X=4;
int Y=3;
int SW=2;


void setup() {
  // put your setup code here, to run once:
  
  pinMode(xmin, OUTPUT);
  pinMode(xmax, OUTPUT);
  pinMode(ymin, OUTPUT);
  pinMode(ymax, OUTPUT);
  pinMode(center, OUTPUT);
  pinMode(X, INPUT);
  pinMode(Y, INPUT);
  pinMode(SW, INPUT_PULLUP);
  digitalWrite(xmin, HIGH);
  digitalWrite(xmax, HIGH);
  digitalWrite(ymin, HIGH);
  digitalWrite(ymax, HIGH);
  digitalWrite(center, HIGH);
  delay(1000);
  digitalWrite(xmin, LOW);
  digitalWrite(xmax, LOW);
  digitalWrite(ymin, LOW);
  digitalWrite(ymax, LOW);
  digitalWrite(center, LOW);


 Serial.begin(115200);
}
void loop() {

    Serial.print("Switch:  ");
    Serial.print(digitalRead(SW));
    Serial.print("\n");
    Serial.print("X-axis: ");
    Serial.println(analogRead(X));
    Serial.print("Y-axis: ");
    Serial.println(analogRead(Y));
    Serial.print("\n\n");
    delay(100);
  
    int  Xmin = map(analogRead(X), 0, 512, 50, 255); 
    int  Xmax = map(analogRead(X), 513, 1023, 50, 255); 
    int  Ymin = map(analogRead(Y), 0, 512, 50, 255); 
    int  Ymax = map(analogRead(Y), 513, 1023, 50, 255); 
    digitalWrite(xmin,constrain(Xmin,0,255));
    digitalWrite(xmax,constrain(Xmax,0, 255));
    digitalWrite(ymin,constrain(Ymin,0,255));
    digitalWrite(ymax,constrain(Ymax,0, 255));

 if (digitalRead(SW)==LOW){
    digitalWrite(center, HIGH);
    delay(100);
    digitalWrite(center, LOW);
  }
  }

As you can see, I deleted my first attempt with IF conditions, to make my code more readable. I also made the thing print actual values to the Serial. I also tried messing around with the mapping function.

Now what happens is: By default, all 4 direction indicating LEDs are on, (the "center" LED is working fine), but if I move the joystick, only 2 directions make the LEDs go dark.

Also, this is clearly some mistake in my code, but what troubles me is that even the LEDs that work, only have an ON or OFF state. No dimming at all.

I am going to try to change the code, and get back to you in half an hour. All suggestions are appreciated!

Alright, for a moment I thought I was really just overcomplicating things, and tried a different approach. It didn’t give me the wanted results, so I commented it out. The current, active version uses a different method, but with this, nothing works. (only the center LED of course).

Here’s my code:

int xmin=5;
int xmax=6;
int ymin=9;
int ymax=10;
int center=11;
int X=4;
int Y=3;
int SW=2;


void setup() {
  // put your setup code here, to run once:
  
  pinMode(xmin, OUTPUT);
  pinMode(xmax, OUTPUT);
  pinMode(ymin, OUTPUT);
  pinMode(ymax, OUTPUT);
  pinMode(center, OUTPUT);
  pinMode(X, INPUT);
  pinMode(Y, INPUT);
  pinMode(SW, INPUT_PULLUP);
  digitalWrite(xmin, HIGH);
  digitalWrite(xmax, HIGH);
  digitalWrite(ymin, HIGH);
  digitalWrite(ymax, HIGH);
  digitalWrite(center, HIGH);
  delay(1000);
  digitalWrite(xmin, LOW);
  digitalWrite(xmax, LOW);
  digitalWrite(ymin, LOW);
  digitalWrite(ymax, LOW);
  digitalWrite(center, LOW);


 Serial.begin(115200);
}
void loop() {
    
    Serial.print("Switch:  ");
    Serial.print(digitalRead(SW));
    Serial.print("\n");
    Serial.print("X-axis: ");
    Serial.println(analogRead(X));
    Serial.print("Y-axis: ");
    Serial.println(analogRead(Y));
    Serial.print("\n\n");
    delay(100);
  
    int  X = analogRead(X); 
    int  Y = analogRead(Y); 
    if (400<X<600){
      digitalWrite(xmin, LOW);
    }
    else{
      analogWrite(xmin, X);
    }
     if (Y>400 or Y<600){
      digitalWrite(ymin, LOW);
    }
    else{
      analogWrite(ymin, Y);
    }
    
   /* if (X<512){
      analogWrite(xmin,X);}
    else{
      analogWrite(xmax,X);}
    
    if(Y<512){
      analogWrite(ymin,Y);}
    else{
      analogWrite(ymax,Y);}
*/
 if (digitalRead(SW)==LOW){
    digitalWrite(center, HIGH);
    delay(100);
    digitalWrite(center, LOW);
  }
  }

Please help :disappointed_relieved:

if (400<X<600){

No. That will compile but does not do what you think/hope it will. Try:

 if (400<X && X<600){
if (Y>400 or Y<600){

I’m surprised that even compiles! Does it?
The normal way to do that in C is:

if (Y>400 || Y<600){

But whichever way you do it, it doesn’t make any sense, because for any value of Y, its always going to be true, so I think you got a little confused there.

It would help if you describe what you want the LEDs to do when you move the joystick. Sorry if you explained that already and I missed it.

PaulRB:
No. That will compile but does not do what you think/hope it will. Try:

 if (400<X && X<600){
if (Y>400 or Y<600){

I’m surprised that even compiles! Does it?
The normal way to do that in C is:

if (Y>400 || Y<600){

But whichever way you do it, it doesn’t make any sense, because for any value of Y, its always going to be true, so I think you got a little confused there.

It would help if you describe what you want the LEDs to do when you move the joystick. Sorry if you explained that already and I missed it.

I might be confused actually, I started Arduino only 10 days ago. Could you please elaborate? Or give me some keywords that I can look up.

I actually started reading Arduino Inside, and I’m watching tutorials daily, but it takes time.

Well, I’m not sure, but here it is: What I want to do, is to turn on the LEDs, depending on the direction of the joystick, BUT (and I couldn’t really find similar projects when I tried looking it up), I want to do it in a way, so that the brightness of the LED indicates the “grade” or the joystick has been pushed.

My mother tongue is not English, so I’m not sure “grade” is the right word, but here’s another example: if the joystick is a streering wheel, then the LEDs’ brightness would be the angle of steering. Similarly, if my X+ value from the joystick was the accelerator on a car, the LEDs’ brightness would be the percentage of applied throttle.

I have 4 LEDs, 1-1 for “turning the wheels to left and right”, 1 for “acceleration”, and 1 for “braking.” Obviously I can only steer in one direction at once, and with this setup I can only accelerate or brake, but not at the same time.

Hope that helps, and thank you!

This issue is unfortunately still not resolved, any suggestions are appreciated!