Joystick to LCD

Need help with end of code. I hooked up a joystick to an LCD. I want the LCD to display a sequence UP, DOWN, LEFT, RIGHT. If you do anything wrong in the sequence it will display BOOM! on the LCD. I also got a countdown timer hooked up so its hard to use delays or while functions. The problem is when I'm using the down joystick it displays boom even though it should not.

#include <LiquidCrystal.h>
#include "SevSeg.h" //Seven Segment 4 Digit Library
SevSeg sevseg;



int up;
int down;
int left;
int right;
int value;


float displayTimeSecs = 0.1; //how long do you want each number on display to show (in secs)
float displayTime = (displayTimeSecs * 5000);
long buzzerFrequency = 500;
float buzzerDuration = (displayTimeSecs * 100);
long startNumber = 500; //countdown starts with this number
long endNumber = 0; //countdown ends with this number

const int buzzerPin = 52;
const int leftButton = 50;
const int rightButton = 51;
const int rs = 22 , en = 23, d4 = 24, d5 = 25, d6 = 26, d7 = 27;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

int VRxAnalogRead;
int VRyAnalogRead;

void setup() {
  pinMode(buzzerPin,OUTPUT);
  Serial.begin(9600);
  lcd.begin(16,2);

  byte numDigits = 4;
  byte digitPins[] = {10, 11, 12, 13};
  byte segmentPins[] = {9, 2, 3, 5, 6, 8, 7, 4};

  bool resistorsOnSegments = false;
  byte hardwareConfig = COMMON_CATHODE;
  bool updateWithDelays = false;
  bool leadingZeros = false;
  bool disableDecPoint = true;
  
  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments,
  updateWithDelays, leadingZeros, disableDecPoint);
  sevseg.setBrightness(90);
}

void millisMessage1(){ //instead of delay 3 sec
if(millis()==3000){
lcd.setCursor(0,0);
lcd.print("                   ");
  } 
}

void millisMessage2(){  //instead of delay 3 sec
if(millis()>=6000){
lcd.setCursor(0,0);
lcd.print("                   ");
lcd.setCursor(0,1);
lcd.print("                    ");
  } 
}

void millisMessage3(){ //instead of delay 3 sec
if(millis()>=9000){
lcd.setCursor(0,0);
lcd.print("                   ");
lcd.setCursor(0,1);
lcd.print("                    ");
  }
}

void millisMessage4(){  //instead of delay 1 sec
if(millis()>=10000){
lcd.setCursor(0,0);
lcd.print("                   ");
lcd.setCursor(0,1);
lcd.print("                    ");
  }
}

void millisMessage5(){  //instead of delay 1 sec
if(millis()>=11000){
lcd.setCursor(0,0);
lcd.print("                   ");
lcd.setCursor(0,1);
lcd.print("                    ");
  }
}

void millisMessage6(){  //instead of delay 1 sec
  if(millis()>=12000){
  lcd.setCursor(0,0);
  lcd.print("                   ");
  lcd.setCursor(0,1);
  lcd.print("                    "); 
  }
}

void joystick(){
VRxAnalogRead = analogRead(A0);  //VRx
VRyAnalogRead = analogRead(A1);  //VRy
Serial.print("VRx Analog Value");//sets VRx as this saying when set to serial monitor
Serial.println(VRxAnalogRead);// reads VRx a new line after the end of print
Serial.print("VRy Analog Value");
Serial.println(VRyAnalogRead);
}

void lcdBoom(){ 
lcd.setCursor(0,0);
lcd.print("BOOOOOOOOOOOOOM!");
lcd.setCursor(0,1);
lcd.print("                   ");  
}

void boomUp(){ //
  if(VRxAnalogRead >=600){
  value = 1;
  thirdMessage();
 }
  else if(VRxAnalogRead<=100){
     value = 2;
    lcdBoom();
  }
  else if(VRyAnalogRead<=100){
     value = 3;
    lcdBoom();
  }
  else if(VRyAnalogRead>=600){
     value = 4;
    lcdBoom(); 
  }
}           

void boomDown(){
  if(VRxAnalogRead<=100){
    value = 5;
    fourthMessage();
  }  
  else if(VRxAnalogRead >=600){
     value = 6;
  lcdBoom();
  }
  else if(VRyAnalogRead<=100){
     value = 7;
    lcdBoom(); 
  }
  else if(VRyAnalogRead>=600){
     value = 8;
    lcdBoom();
  }
}           

void boomLeft(){
  if(VRyAnalogRead<=100){
  value = 9;
  fifthMessage();
  }
  else if(VRxAnalogRead >=600){
  value = 10;
  lcdBoom();
  }
  else if(VRxAnalogRead<=100){
  value = 11;  
  lcdBoom();
  }
  else if(VRyAnalogRead>=600){
  value = 12;
  lcdBoom();   
  }
}  

void boomRight(){
  if(VRyAnalogRead>=600){
  value = 13;
  sixthMessage();
  }
  else if(VRxAnalogRead >=600){
  value = 14;
  lcdBoom();
  }
  else if(VRxAnalogRead<=100){
  value = 15;
  lcdBoom();
  }
  else if(VRyAnalogRead<=100){
    value = 16;
    lcdBoom();
  }   
}
  
void firstMessage(){ 
lcd.print("Defuse The Bomb!");
millisMessage1();
}

void secondMessage(){
lcd.setCursor(0,0);
lcd.print("Joystick:         ");
lcd.setCursor(0,1);
lcd.print("UP Don't mess up");
millisMessage2();
}

void thirdMessage(){
millisMessage3();
lcd.setCursor(0,0);
lcd.print("Joystick:            ");
lcd.setCursor(0,1);
lcd.print("Down!               ");

}

void fourthMessage(){
millisMessage4();
lcd.setCursor(0,0);
lcd.print("Joystick:");
lcd.setCursor(0,1);
lcd.print("LEFT!               ");
millisMessage4();
}

void fifthMessage(){
millisMessage5();
lcd.setCursor(0,0);
lcd.print("Joystick:");
lcd.setCursor(0,1);
lcd.print("RIGHT!              ");
}

void sixthMessage(){
millisMessage6();
lcd.setCursor(0,0);
lcd.print("Time for Buttons       ");
lcd.setCursor(0,1);
lcd.print("                  ");
}

void loop() {
{
  joystick();
  millis();
}
{
  tone(buzzerPin,buzzerFrequency,buzzerDuration);
  
  if (startNumber >= endNumber) {
    for (long i = 0; i <= displayTime; i++){
      sevseg.setNumber(startNumber,0);
      sevseg.refreshDisplay();
        if(startNumber==0){
        sevseg.setNumber(0000,0);
        tone(buzzerPin,buzzerFrequency,buzzerDuration);    
 }    
    } 
  }
  startNumber--;
  tone(buzzerPin,buzzerFrequency,buzzerDuration);
  
  }
  
 {
sevseg.setNumber(0000,0); //after countdown shows endNumber, show this number.
sevseg.refreshDisplay();
 }
 

if(startNumber ==499){
  firstMessage(); // Defuse the bomb
  
  
}

if(startNumber ==480){ //up
  secondMessage(); // joystick up
  }

if(startNumber<=479){
  boomUp();
  
if(value==1){
boomUp();
if(value==2){

if(value==3){

if(value==4){

if(value==5){
boomDown();
if(value==6){

if(value==7){

if(value==8){

if(value==9){
boomLeft();
if(value==10){

if(value==11){

if(value==12){

if(value==13){
boomRight();
if(value==14){

if(value==15){

if(value==16){

}}}}}}}}}}}}}}}}}}

really ?

2 Likes

what you mean?

you probably meant to the Arduino not to the LCD :slight_smile:


regarding your question, how long do you give the user to do the right moves (UP, DOWN, LEFT, RIGHT) and do you allow intermediary positions on their way from UP to DOWN?

1 Like

Yeah im pretty new so I dont know a whole bunch of complex code. There is no time limit for the user to do the UP, DOWN, LEFT, RIGHT. I don't know what you mean for the second part of the question.

can you explain your code in the loop?

for example how do you interpret this

    if (value == 1) {
      boomUp();
      if (value == 2) {
        if (value == 3) {
          if (value == 4) {
            if (value == 5) {
              boomDown();

say if value is 1 and boomUp() changes it conveniently to 2, you enter the second if and check if the value is 2. It is so you go into the next if... but nothing can change the value there, so if value was 2 - what's the likelihood it is suddenly 3 and then 4 and then 5 ???

Does UP mean a movement in one direction or an arbitrary position of the joystick's Y value?

if this is the former, then you need to track position changes. If it's the latter, just reading the position gives you the indication you need. (this is what you do at the moment)

Say I meet this condition and the Y axis read gave me 900 which is above the threshold 600 you decided.

Now you want to read DOWN. if this means an arbitrary position on the Y axis say below the threshold 100. ➜ on my way from 900 to 100 I'll hit 800, 700, 600 and those reading will still record as UP, but when I hit 500, 400, 300, 200 I will still be on my course to going down but you won't record UP nor record down ➜ this should not trigger the boom

I think the way your code is architected won't work and you need to clarify how you detect the right move pattern. Reading about state machines and clarifying exactly how you record a position and a transition will be key in getting this to work.

1 Like

My trouble is just running one function once and never running it again.

if you want to run this function at the start of the code, then put it in the setup(). This is called only once.

if it's not part of the setup and you want to call once a function within the loop(), as the loop repeats, you need to make a note that the function was called

define a globale Boolean variable, with an initial value of true

bool firstFunctionCall = true;

then in the loop you check that variable

void loop() {
  ...
  if (firstFunctionCall) {
    // the function has never been called
    myFunction();               //  ➜ call it
    firstFunctionCall = false;  // make a note that now it has been called
  }
  ...
}

this way the second time the loop comes to the if, the variable firstFunctionCall will have been updated and became false and so you don't call the function anymore.

Hello brandonv111

I have done a small code review.

The programme looks like it has grown organically, as already mentioned. I haven´t said it´s spaghetti code. :slight_smile:

My recommendation:
Read and study the IPO model to restructure the program logically and functionally.
A very general programme structure would be:

INPUT: Read analog pots, save status.
PROCESSING: use the save status to execute some game logics.
OUTPUT: use the results to control the outputs and the LCD when the status changes.

Try it out.
Arrays and structs are your friends.

Have a nice day and enjoy coding in C++.

https://www.learncpp.com/

Work on getting some program logic together that requires pressing four pushbuttons in the correct order, or entering four characters in the correct order using the serial monitor

Leave off all the fiddling with the LCD until you have. Just use serial printing to provide what will be the feedback messages, while also at this point giving you confidence that the program flow is correct.

It will be easier to take such a simpler a working defusing sketch and fit all the LCD stuff to it.

Divide and conquer.


All this kinda stuff will only work from a restart. If you learn a bit about timing and a few other essential techniques for writing this, you might be able to have the sketch work beyond the first 11 seconds since power up or restart.

Then again, if it is a bomb, maybe it only needs to work until it explodes or is defused. :expressionless:

a7

That’s not solving the main problem
What OP needs to resolve is the proper definition and identification of what UP DOWN etc means.

It’s not straightforward

When formatted, your last "IF" tree got out of control...

    if (value == 1) {
      boomUp();
      if (value == 2) {
        if (value == 3) {
          if (value == 4) {
            if (value == 5) {
              boomDown();
              if (value == 6) {
                if (value == 7) {
                  if (value == 8) {
                    if (value == 9) {
                      boomLeft();
                      if (value == 10) {
                        if (value == 11) {
                          if (value == 12) {
                            if (value == 13) {
                              boomRight();
                              if (value == 14) {
                                if (value == 15) {
                                  if (value == 16) {

                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

I also think your VRyAnalogRead was originally written VRy.AnalogRead as part of an object. Check the original KY-023 sketch again.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.