LED Matrix 7219 controlled by Joystick

Hello All,

Project title: Controlling each LED in a 7219 LED Matrix using Joystick.
Objective: Every time I move the thumb joystick towards left, right, top, bottom, one LED should get lite and go to the left, right, top and bottom and remain there even when the joystick comes back.

For instance, if the thumb joystick is moved to the left the LED should jump/transfer to the left and stay there HIGH even if the joystick returns to its original position. Again when the joystick is moved to the left it should move the LED to the further left and stay HIGH on the recently moved position.

Here is the code:

int Xpin=A0; // X pin of joystick is connected to A0
int Ypin=A1; // Y pin of joystick is connected to A1
int readXval;
int readYval;
float Vx;
float Vy;
int hold = 100;
#include "LedControl.h" // need the library
int DIN=11 ;
int CS=10;
int CLK=13;
LedControl lc=LedControl(11,13,10,1); //10 is to CLOCK, 9 = CS, 8=DIN//

void setup() {
Serial.begin(9600);
lc.shutdown(0,false);// turn off power saving, enables display
lc.setIntensity(0,8);// sets brightness (0~15 possible values)
lc.clearDisplay(0);// clear screen
}
void loop() {
readXval=analogRead(Xpin); // Joystick X movement read value//
Serial.print("readXval = ");
Serial.println(readXval, DEC);
delay(hold);
Vx=(3.3/798.)*readXval; // 3.3 is the max volt and 798. is the joystick X coordinate maximum//
Serial.print("Voltage at Vx = ");
Serial.println(Vx);
delay(hold);
readYval=analogRead(Ypin); // Joystick Y movement read value//
Serial.print("readYval = ");
Serial.println(readYval, DEC);
delay(hold);
Vy=(3.3/797.)*readYval; // 3.3 is the max volt and 797. is the joystick Y coordinate maximum //
Serial.print("Voltage at Vy = ");
Serial.println(Vy);
delay(hold);
char x_translate = map(readXval, 798, 0, 7, 0); //This maps the values//
char y_translate = map(readYval, 797, 0, 0, 7);
Serial.print("x = ");
Serial.println(x_translate, DEC);//Joystick X coordinate
delay(hold);
Serial.print("y = ");
Serial.println(y_translate, DEC);//Joystick Y coordinate
delay(hold);
lc.clearDisplay(0);
lc.setLed(0,x_translate,y_translate,true);
while(Vx>1.39){
Serial.println ("Joystick is in at X =3 & Y =2");
delay(hold);
x_translate=3; // Joystick X coordinate is translated in to x
y_translate=2;
lc.clearDisplay(0);Use code tags to format code for the forum
lc.setLed(0,x_translate,y_translate,true);
readXval=analogRead(Xpin);
Vx=(3.3/798.)*readXval;
}
}

Code Explanation:

When the Vx (voltage at X) goes more than 1.38 the X pixle or X coordinate moves to 3 while Y pixel or Y coordinates remains same at 2.

Bottom line: I need the LED to jump or transfer in the direction of the the joystick's direction movement and the LED should stay in the last location even though the joystick returns to its original position.

Help will be highly appreciated.

-UK

How does your sketch behave as it is, and how does it not work as expected? I see you call lc.clearDisplay(0); which will not allow you to leave a "trail" of dots from your previous location. I am not fully understanding your request, but, maybe you can use the Select (pushbutton) of the joystick to alternate between "draw" (leave a trail) and "move" (no trail).

#include "LedControl.h" // need the library
int DIN=11 ;
int CS=10;
int CLK=13;
LedControl lc=LedControl(11,13,10,1); //10 is to CLOCK, 9 = CS, 8=DIN//

const byte aX=A0;
const byte aY=A1;

void setup(){
  lc.shutdown(0,false);// turn off power saving, enables display
  lc.setIntensity(0,8);// sets brightness (0~15 possible values)
  lc.clearDisplay(0);// clear screen
}

void loop(){
  static byte cX=4;
  static byte cY=4;
  static int bX;
  static int bY;
  static char commando='0';

  do {
    bX=analogRead(aX)-512;
    bY=analogRead(aY)-512;
  }while (abs(bX)<5 && abs(bY)<5);
  
  if(bX<-15)commando='L';
  if(bX>15)commando='R';
  if(bY<-15)commando='D';
  if(bX>15)commando='U';

  switch (commando){
    case 'L':
      if(cX>0)cX--;
      break;
    case 'R':
      if(cX<7)cX++;
      break;
    case 'D':
      if(cY>0)cY--;
      break;
    case 'U':
      if(cY<7)cY++;
      break;
  }
  showPixel(cX,cY);

  do {
    bX=analogRead(aX)-512;
    bY=analogRead(aY)-512;
  }while (!abs(bX)<5 && !abs(bY)<5);
}

void showPixel(int x, int y){
  lc.clearDisplay(0);
  lc.setLed(0,x,y,true);
}
1 Like

Hi xfpd,

Thanks for giving the new "draw and move". I will check it out.
I removed the lc.clearDisplay(0); but as I expected it didn't change anything.

Hi Kolaha,

Thank you for sharing the code.
The LED at 4,4 is lite other than that it's not it's location to UP, DOWN, LEFT or RIGHT.
I am checking the parameters.
Can you please let me know what is bX< -15? I mean what is that 15?
I hope with your help, I can be successful in this project.

15 is small area near joystick's null position, it will awaiting the release, return joystick to middle, before next commando will awaited. you are free to adjust the 5 and 15 values for better control needs or feelings.

@thatsudaya

The joystick is noisy at the center (not steady at X=512, Y=512), so ignoring X and Y less than "+/-15" removes that noise problem, only registering L/R/U/D outside the +/-15 range.
see next post

actually +/-5 is noise removing, and 15 is detecting of moving to middle

Hi Kolaha,

Thanks for clarifying.
I am still struggling to make it the code work for my project.

Can you please explain this piece of the code?

do {
    bX=analogRead(aX)-512;
    bY=analogRead(aY)-512;
  }while (abs(bX)<5 && abs(bY)<5);

this cycle checks position of sticks and repeat when sticks are in middle position(value is near zero)

The Switch position is moving by itself without joystick input.

I think the Switch-Case is keep looping and not letting to go to the next commando.

I tried bracketing each switch case separately but it still keep looping only for the first commando.

#include "LedControl.h" // need the library
const byte  DIN=11 ;
const byte  CS=10;
const byte  CLK=13;
LedControl lc=LedControl(11,13,10,1); //10 is to CLOCK, 9 = CS, 8=DIN//

const byte aX=A0;
const byte aY=A1;
const byte treshold=50;

void setup(){
  lc.shutdown(0,false);// turn off power saving, enables display
  lc.setIntensity(0,8);// sets brightness (0~15 possible values)
  lc.clearDisplay(0);// clear screen
}

void loop(){
  static byte cX=4;
  static byte cY=4;
  static int bX;
  static int bY;

  do {
    bX=analogRead(aX)-512;
    bY=analogRead(aY)-512;
  }while (abs(bX)<treshold && abs(bY)<treshold);
  
  if(bX<-treshold)if(cX>0)cX--;
  if(bX>treshold) if(cX<7)cX++;
  if(bY<-treshold)if(cY>0)cY--;
  if(bX>treshold) if(cY<7)cY++;

  showPixel(cX,cY);

  do {
    bX=analogRead(aX)-512;
    bY=analogRead(aY)-512;
  }while (!abs(bX)<treshold && !abs(bY)<treshold);
}

void showPixel(int x, int y){
  lc.clearDisplay(0);
  lc.setLed(0,x,y,true);
}

Thank you, Kolaha.

I managed to move the LED with the "Switch-Case" method. Thanks again.

Now that I have to get the code for moving the LED over the 4 segments of the 8by8 LED 7219 Matrix.
Please see the below picture for a better idea.

The code currently I have is able to move the LED only in one segment of 8by8 LED Matrix.
Please give some inputs on how to move the LED for the entire segment.
Thanks for helping. I am almost getting there with your help.

for 4 devises this lines should be:

LedControl lc=LedControl(11,13,10,4);
if(bX>treshold) if(cX<31)cX++;

Hi Kolaha,

Thanks for the inputs.
I tried modifying the code as you said and even included the MAX7219 library also, but instead of moving to the next segment it's just running all the way to the first segment and disappeared.

#include "LedControl.h" // need the library
#include <MD_MAX72xx.h>
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 4
int DIN=11 ;
int CS=10;
int CLK=13;
int dt=300;
LedControl lc=LedControl(11,13,10,4); //10 is to CLOCK, 9 = CS, 8=DIN//
const byte aX=A0;
const byte aY=A1;

void setup(){
  Serial.begin(9600);
  lc.shutdown(0,false);// turn off power saving, enables display
  lc.setIntensity(0,8);// sets brightness (0~15 possible values)
  lc.clearDisplay(0);// clear screen
}

void loop(){
  static byte cX=4;
  static byte cY=4;
  static int bX;
  static int bY;
  static char commando='0';

  do {
    bX=516-analogRead(aX);
    Serial.print("bX position= ");
    Serial.println(bX);
    delay(dt);
    bY=507-analogRead(aY);
    Serial.print("bY position= ");
    Serial.println(bY);
    delay(dt);
  }while ((bX)<5 && (bY)<5);

  if(bX>190)commando='L';
  switch (commando){
    case 'L':
      if(cX>0)cY--;
      break;}
  if(bX>16 && bX<10)commando='R';
  switch (commando){
    case 'R':
      if(cX<7)cY++;
      break;
  }
  if(bX>178 && bX<184)commando='0';
  switch (commando){
    case 'O':
      cX=4;
      cY=4;
      break;}

  if(bY>0 && bY<5)commando='U';
  switch (commando){
  case 'U':
      if(cY>0)cX--;
      break;
  }
   if(bY>345 && bY<350)commando='D';
   switch (commando){
   case 'D':
      if(cY<7)cX++;
      break;
   }
  showPixel(cX,cY);

  do {
    bX=516-analogRead(aX);
    bY=507-analogRead(aY);
  }while (abs(bX)<5 && abs(bY)<5);
}
void showPixel(int x, int y){
  lc.clearDisplay(0);
  lc.setLed(0,x,y,true);
}```

you should examine which axis are and which direction is positive. i have suggested left bottom corner is coordinate 1:1 and X goes to right, to position 32.

My left bottom corner is 0:7. For x=0, and y=7.
If i keep the cX and cY more than 7 as shown below, the LED disappears.

void loop(){ static byte cX=7; static byte cY=31;

So I just kept x=0,y=7 to start with from the bottom left.
I can able to control one LED square (8by8), however I need to control 4 segments of 8by8dot matrix. 7219
When I change the number of device to 4, the LED keeps running with our control of the joystick. Second, the LED disappears once its pass the 1st 8by.
Please help me in fixing this issue.

This one?

#include "LedControl.h" // need the library
const byte  DIN=11 ;
const byte  CS=10;
const byte  CLK=13;
LedControl lc(11,13,10,4); //10 is to CLOCK, 9 = CS, 8=DIN//

const byte aX=A0;
const byte aY=A1;
const byte treshold=50;

void setup(){
  lc.shutdown(0,false);// turn off power saving, enables display
  lc.setIntensity(0,8);// sets brightness (0~15 possible values)
  lc.clearDisplay(0);// clear screen
}

void loop(){
  static byte cX=4;
  static byte cY=4;
  static int bX;
  static int bY;

  do {
    bX=analogRead(aX)-512;
    bY=analogRead(aY)-512;
  }while (abs(bX)<treshold && abs(bY)<treshold);
  
  if(bX<-treshold)if(cX>0)cX--;
  if(bX>treshold) if(cX<31)cX++;
  if(bY<-treshold)if(cY>0)cY--;
  if(bX>treshold) if(cY<7)cY++;

  showPixel(cX,cY);

  do {
    bX=analogRead(aX)-512;
    bY=analogRead(aY)-512;
  }while (!abs(bX)<treshold && !abs(bY)<treshold);
}

void showPixel(int x, int y){
  lc.clearDisplay(0);
  lc.setLed(x/8,x%8,y,true);
}

Hi Kolaha,

Thank you for sharing the code. It's really helping and as you said, I am messing up with axis and positive direction.
Joystick position @ Center the reading at X = 182
Joystick position @ Left and the reading at X =334 (516-182) (typical - left)
Joystick position @ Right and the reading at X = 15 (182-167).

Joystick position @ Center the reading at Y= 183
Joystick position @ Left and the reading at X =323 (506-183) (typical - left)
Joystick position @ Top and the reading at Y = 4 (183-179).

The joystick analog output value (X coordinate is Min = 206, Typical = 516 and Max =798).
The joystick analog output value (Y coordinate is Min = 203, Typical = 507 and Max =797).

My 1st segment top left is 0, 0 and then if I move bottom it's working, but for the next device (segment) it's not moving. I understand you told me to keep the bottom left corner as the 1:1,
I don't know how to do that.

Please help me to move the starting position to the left most bottom and keep going X up to the fourth segment (4th device) and same for Y up to the top.

Do I need to use the for loop to change the address so that the LED will jump to the next device?

#include "LedControl.h" // need the library
const byte  DIN=11 ;
const byte  CS=10;
const byte  CLK=13;
int dt=1000;
LedControl lc(11,13,10,4); //10 is to CLOCK, 9 = CS, 8=DIN//

const byte aX=A0;
const byte aY=A1;
const byte treshold=50;

void setup(){
  Serial.begin(9600);
  lc.shutdown(0,false);// turn off power saving, enables display
  lc.setIntensity(0,8);// sets brightness (0~15 possible values)
  lc.clearDisplay(0);// clear screen
}

void loop(){
  static byte cX=0;
  static byte cY=0;
  static int bX;
  static int bY;

  do {
    bX=516-analogRead(aX);
    Serial.print("bX= ");
    Serial.println(bX);
    delay(dt);
    bY=507-analogRead(aY);
    Serial.print("bY= ");
    Serial.println(bY);
    delay(dt);
  }while (abs(bX)<5&& abs(bY)<5);
  if(bX>350 && bX<360) if(cY>0)cY--;
  Serial.print("cY=");
  Serial.println(cY);
  if(abs(bX)>10 && bX<16) if(cY>0)cY++;
  Serial.print("cY=");
  Serial.println(cY);
  if(bY>0 && bY<8) if(cY>0)cX--;
  Serial.print("cX=");
  Serial.println(cX);
  if(bY>345 && bY<350) if(cY<7)cX++;
  Serial.print("cX=");
  Serial.println(cX);
  showPixel(cX,cY);
  do {
    bX=analogRead(aX)-516;
    bY=analogRead(aY)-507;
  }while (abs(bX)<5 && abs(bY)<5);
}
void showPixel(int x, int y){
  lc.clearDisplay(0);
  lc.setLed(x/8,x%8,y,true);
}

You used bX=analogRead(aX)-512; bY=analogRead(aY)-507; but I changed to the other way to match my joystick.

Please help once again.
I am really sorry for taking your time.
Thanks