Run Void *** when button is pressed

Im nearing the end of my project an urgently need some help please.

I have code setup for an 8x8 matrix, one set plays pong, the other displays a pattern. They are called "void pong" and "void pattern"

I have button setup and need to know what to write in my "void loop" section to switch between the two "void ****" above.

I need a command which says,
On bootup (start) play the "void pattern"
if button is pressed, turn off "void pattern" and start "void pong"
when the button is pressed again to go back to pattern etc.

Heres the loop code I have which isnt switching correctly;

void loop()
{
//Serial.print(currState != prevState);
//Serial.println();

  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {  
      pattern();
}
else
{
    pong();
}
     lastButton = currentButton;
}

All help will be gratefully received.

You need to show more of your code as how the pattern() and pong() function behave could be an issue.

Either you are spending all your time in one function (ie, the code to detect the change is hardly ever run) or, if you do come back to loop() the code to run pattern() is hardly ever run as the edge detection is too fleeting compared to running pong() as a default case.

Is it that it is not switching or that you never come back to the point in loop() where it can switch?

They are called "void pong" and "void pattern"

No, they are called "pong" and "pattern".
"void" describes the return type of the function.

This bit of code looks as if it will detect when the button is pressed:

  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {  
      // code here executes once when the button changes state
  }
  lastButton = currentButton;

Define a global variable that records which game you are playing. For the sake of argument, let's suppose you called it currentGame. Since you only have two games currently, it could be a boolean variable. If you plan to have more games in future, it might make sense for it to be an integer (although currently you would only need values 0 and 1). When the button press occurs, change currentGame. You might also want to reset any global variables holding the state of that game so that you effectively start a new game - but that's up to you.

Later on in loop() you test the value of currentGame and call the corresponding function. For two games, a simple IF statement would be all you need. If you had more than two games to choose from it would make more sense to use a SWITCH statement instead of the IF.

Thanks for the replies.

Here is a copy of all the code;

int cols[9] = {1,2,4,8,16,32,64,128, 0};
int rows[9] = {1,2,4,8,16,32,64,128, 0};

const int latchPin = 10;
const int clockPin = 9;
const int dataPin = 11;

int buzz = 3;
int bleep = 5;
int switchPin = 6;

boolean lastButton = LOW;
boolean currentButton = LOW;
boolean pongGame = false;

int player_one = A1; //red-left
int player_two = A0; //blue-right
int p1_pos, p2_pos;

int ball_x=3, ball_y=3;
int ball_dir_x=1, ball_dir_y=-1;
int count = 0;


void setup() 
{
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);    
  pinMode(clockPin, OUTPUT); 
  pinMode(bleep, OUTPUT);
  pinMode(switchPin, INPUT);
  digitalWrite(switchPin, HIGH); // after the pinMode statement
  pinMode(buzz, OUTPUT);
  randomSeed(analogRead(5));
  //Serial.begin(115200);
}


boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}


void registerWrite(int rows,  int cols)
{
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, MSBFIRST, rows);
  shiftOut(dataPin, clockPin, MSBFIRST, cols);
  digitalWrite(latchPin, 1);
}

void resetAnim()
{
  digitalWrite(buzz, HIGH);
  delay(150);
  digitalWrite(buzz, LOW);
  delay(20);
  digitalWrite(buzz, HIGH);
  delay(150);
  digitalWrite(buzz, LOW);
  delay(20);
  digitalWrite(buzz, HIGH);
  delay(150);
  digitalWrite(buzz, LOW);
}

void resetBall()
{
  resetAnim();

  ball_x=3; 
  ball_y = 4;
  ball_dir_x = 1; 
  ball_dir_y = -1;
}

void getPlayerPositions()
{
  p1_pos = analogRead(player_one);
  p1_pos = p1_pos/128;
  p2_pos = analogRead(player_two);
  p2_pos = p2_pos/128;  
}

void renderBall()
{
  registerWrite(rows[ball_y], cols[ball_x]);
  delay(3);
  registerWrite(rows[8], cols[8]);
  delay(3);  
}  

void moveBall()
{
  digitalWrite(bleep, HIGH);
  delay(2);
  digitalWrite(bleep, LOW);
  ball_x += ball_dir_x;
  ball_y += ball_dir_y;

}

void checkLocationAndBounce()
{
  // bounce on y
  if(ball_y >= 7)
    ball_dir_y= -1;
  else if(ball_y <= 0)
    ball_dir_y = 1;

  // on x only bounce if player
  // paddle is on same spot
  if(ball_x == 7 && ball_y == p1_pos)
  {
    randomBounceBack();
    ball_dir_x= -1;
  }
  else if(ball_x == 7)
  {
    resetBall();
  }
  else if(ball_x == 0 && ball_y == p2_pos) {
    randomBounceBack();
    ball_dir_x = 1;   
  }  
  else if(ball_x == 0)
  {
    resetBall();
  }
}

void randomBounceBack()
{
  // set a random Y direction when we
  // bounce on a paddle
  int y_dir = random(3);
  switch(y_dir)
  {
  case 0:
    ball_dir_y = -1;
    break;
  case 1:
    ball_dir_y = 0;
    break;
  case 2:
    ball_dir_y = 1;
    break;
  }  
}

void renderPlayerPaddles()
{
  getPlayerPositions();
  registerWrite(rows[p2_pos], cols[0]);
  delay(3);
  registerWrite(rows[8], cols[8]);
  delay(3);
  registerWrite(rows[p1_pos], cols[7]);  
  delay(3);
  registerWrite(rows[8], cols[8]);
  delay(3);
}

void pong()
{  
  renderBall();
  renderPlayerPaddles();
  if(count >10)
  {  
    moveBall();
    checkLocationAndBounce();
    count = 0;
  }
  count++; 
}

void pattern()
{
  for (int character = 0; character < 8; character ++)
  {
    switch (character)
    {
    case 0:
      rows[7] = 0b10100011;
      rows[6] = 0b10001001;
      rows[5] = 0b10010001;
      rows[4] = 0b11000101;
      rows[3] = 0b10001011;
      rows[2] = 0b10100001;
      rows[1] = 0b11001001;
      rows[0] = 0b10000001;
      break;

    case 1:
      rows[0] = 0b10100011;
      rows[7] = 0b10001001;
      rows[6] = 0b10010001;
      rows[5] = 0b11000101;
      rows[4] = 0b10001011;
      rows[3] = 0b10100001;
      rows[2] = 0b11001001;
      rows[1] = 0b10000001;
      break;

    case 2:
      rows[1] = 0b10100011;
      rows[0] = 0b10001001;
      rows[7] = 0b10010001;
      rows[6] = 0b11000101;
      rows[5] = 0b10001011;
      rows[4] = 0b10100001;
      rows[3] = 0b11001001;
      rows[2] = 0b10000001;
      break;

    case 3:
      rows[2] = 0b10100011;
      rows[1] = 0b10001001;
      rows[0] = 0b10010001;
      rows[7] = 0b11000101;
      rows[6] = 0b10001011;
      rows[5] = 0b10100001;
      rows[4] = 0b11001001;
      rows[3] = 0b10000001;
      break;

    case 4:
      rows[3] = 0b10100011;
      rows[2] = 0b10001001;
      rows[1] = 0b10010001;
      rows[0] = 0b11000101;
      rows[7] = 0b10001011;
      rows[6] = 0b10100001;
      rows[5] = 0b11001001;
      rows[4] = 0b10000001;
      break;

    case 5:
      rows[4] = 0b10100011;
      rows[3] = 0b10001001;
      rows[2] = 0b10010001;
      rows[1] = 0b11000101;
      rows[0] = 0b10001011;
      rows[7] = 0b10100001;
      rows[6] = 0b11001001;
      rows[5] = 0b10000001;
      break;

    case 6:
      rows[5] = 0b10100011;
      rows[4] = 0b10001001;
      rows[3] = 0b10010001;
      rows[2] = 0b11000101;
      rows[1] = 0b10001011;
      rows[0] = 0b10100001;
      rows[7] = 0b11001001;
      rows[6] = 0b10000001;
      break;

    case 7:
      rows[6] = 0b10100011;
      rows[5] = 0b10001001;
      rows[4] = 0b10010001;
      rows[3] = 0b11000101;
      rows[2] = 0b10001011;
      rows[1] = 0b10100001;
      rows[0] = 0b11001001;
      rows[7] = 0b10000001;
      break;
    }

    for (int refreshed = 0; refreshed < 200; refreshed++)
    {
      for (int count = 0; count < 8; count ++)
      {
        digitalWrite(latchPin, LOW);
        shiftOut(dataPin, clockPin, MSBFIRST, cols[count]);
        shiftOut(dataPin, clockPin, LSBFIRST, rows[count]);
        digitalWrite(latchPin, HIGH);
      }
    }
  }
}


void loop()
{
//Serial.print(currState != prevState);
//Serial.println();

  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {  
      pattern();
}
else
{
    pong();
}
     lastButton = currentButton;
}

Im not a coder, I find this really hard to get my head round. Thanks everyone for the help and advice.

AWOL:

They are called "void pong" and "void pattern"

No, they are called "pong" and "pattern".
"void" describes the return type of the function.

Thanks, Yes I understand that, I just typed it to help get my issue across.

PMKimpton:
Im not a coder, I find this really hard to get my head round. Thanks everyone for the help and advice.

There is rather a lot of code there and, given that you are 'not a coder' and presumably didn't write this code, you have set yourself a difficult task to change how these two games work.

I suggest you write a much simpler sketch that just reads the input and switches between two modes that do something simple, such as printing "I'm running game 1" and "I'm running game 2" so that you can solve this part of the problem in isolation before you try to adopt that solution into the full sketch.

In fact this code is made from two other scripts. I have cut and pasted bits to try and get it working without really understanding whats going on.

I agree with your suggestion. I had started already. I setup a breadboard with a button and led and got the code to switch the led on/off. This works well. What I would need from this is to learn how to change the command from ledPin command to running void pattern() or void pong()

heres the button code:

int switchPin = 7;
int ledPin = 13;

boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;

void setup()
{
  pinMode(switchPin, INPUT);
  pinMode(ledPin, OUTPUT);
}

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current = digitalRead(switchPin);
  }
  return current;
}

void loop()
{
  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    ledOn = !ledOn;
}

     lastButton = currentButton;
  digitalWrite(ledPin, ledOn);
}

Say I wanted to have this in the button code above,

void flashslow() {
  digitalWrite(ledPin, HIGH);   
  delay(2000);             
  digitalWrite(ledPin, LOW);   
  delay(2000);            
}

void flashfast() {
  digitalWrite(ledPin, HIGH);   
  delay(100);               
  digitalWrite(ledPin, LOW);   
  delay(100);             
}

Instead of the button code turning on/off the led, how would i get it to switch between the two codes above? If I could figure this out Im sure I can get my pong code working.

This seems to be one of those Give me the code for it to do what I want, I don't want to actually how to code type of posts.

Arrch:
This seems to be one of those Give me the code for it to do what I want, I don't want to actually how to code type of posts.

In some ways it may appear like that. I've been working on this project for 8 weeks and have built a fine matrix with over 620 led's, had to learn to solder correctly, design circuit boards after learning the software to do that, had to learn about transistors, IC's, power management, resistors, diodes, you name it. I'm studying as fast as I can and have come a long way in those 8 weeks.

My back is against the way, I have to get this finished in the next day or two as it's a CHRISTMAS DISPLAY and a present for someone. There's no point in me finishing it in February.

I have managed to learn everything I can in these past weeks and this is the first time I've honestly needed some help.

I understand the reasons for "guiding" people and helping them to learn, and I will, but as for this project....... I NEED HELP TODAY

Arrch:
This seems to be one of those Give me the code for it to do what I want, I don't want to actually how to code type of posts.

In some ways it may appear like that. I've been working on this project for 8 weeks and have built a fine matrix with over 620 led's, had to learn to solder correctly, design circuit boards after learning the software to do that, had to learn about transistors, IC's, power management, resistors, diodes, you name it. I'm studying as fast as I can and have come a long way in those 8 weeks.

My back is against the way, I have to get this finished in the next day or two as it's a CHRISTMAS DISPLAY and a present for someone. There's no point in me finishing it in February.

Ok, so it's Give me the code for it to do what I want, I don't have time to learn how to do it myself.

I understand the reasons for "guiding" people and helping them to learn, and I will, but as for this project....... I NEED HELP TODAY

And you're getting help TODAY.

In order to have a responsive momentary switch that changes states you need to have those "states" to run non-blocking code. That typically means no non-trivial delays(), and very limited usage of for/while loops. In the flashSlow() and flashFast() code that you posted, that would mean you would need to redo those functions to not use delays. The blink without delay example shows you how to do just that. Another observation is that in the original code you posted, you run pattern() only during the rising edge once, and and pong all the other times. Assuming pattern() and pong() are non-blocking, you would be better off setting a state variable when you detect the transition. Then outside of the if statements, have your code check the state and run either pattern() or pong() based on its value.

Arrch:
In order to have a responsive momentary switch that changes states you need to have those "states" to run non-blocking code. That typically means no non-trivial delays(), and very limited usage of for/while loops. In the flashSlow() and flashFast() code that you posted, that would mean you would need to redo those functions to not use delays. The blink without delay example shows you how to do just that. Another observation is that in the original code you posted, you run pattern() only during the rising edge once, and and pong all the other times. Assuming pattern() and pong() are non-blocking, you would be better off setting a state variable when you detect the transition. Then outside of the if statements, have your code check the state and run either pattern() or pong() based on its value.

Thank you for your understanding Arrch, I was on the verge of binning all my Arduino kit, giving up and buying my mum a kindle!
I'm not a scrounger, I am reading everything I can but I'm really struggling with the code concept.
Whilst your comments above sort of make sense to me, I haven't a clue where to begin to implement them. Straight over my head mate :slight_smile:

I posted up the simple LED flash code to better understand what I'm doing wrong in my main project code.

Would you kindly re-write the code for the example LED flash code so that it would switch back and forth when a button is pressed? then I'll have some code to study so as to make the changes to my main code.

Thanks Arrch,

PMKimpton:
Would you kindly re-write the code for the example LED flash code so that it would switch back and forth when a button is pressed? then I'll have some code to study so as to make the changes to my main code.

The main code should look something like this

set state to 0

get the current button state
if the current button state high and the previous one low?
   is the state 0?
      set the state to 1
   otherwise
      set the state to 0

is the state 0?
  run non-blocking long blink code
otherwise
  run non-blocking short blink code

set last button state to current one

In order to get the long blink and short blink code to be non-blocking, they will need to be re-written using using the concepts in the Blink Without Delay example.

Thanks Arrch, I will study this all night because I'm not under any pressure.

I appreciate your time & comments, but you may as well written them in Spanish, I don't understand code...

Seeing as I don't understand how to resolve this simple button issue using code, I going to solve it by doubling up my hardware and then just turn off one arduino and turn another one on.

Solved.