Chest game Counter

Hi,
I'm new in using arduino and i have a little knowledge of C language. I tried searching but it seems hard for me to check where's the problem in my program. I don't know how to debug arduino as well..

my Project:
a Chest Game Counter
a player is given 5secs each turn
when they press the set button the remaining time is added to there next turn
they lost if the time goes 0sec.

my problem is that whenever i upload the program in the arduino it doesn't alternate the players, and it doesn't even count.
here's my code

tnx for your kind help and sorry for a newbie question..
tnx more power.

void setup() {
  pinMode(13, INPUT); //player 1 input
  pinMode(12, INPUT); //player 2 input 
  pinMode(11, OUTPUT); //player 1 indicator
  pinMode(10, OUTPUT); //player 2 indicator
  pinMode(7, OUTPUT);     
  pinMode(6, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(2, OUTPUT);
  pinMode(1, OUTPUT);
  pinMode(0, OUTPUT);
}
int pturn = 1;
int counter;
int p1global;
int p2global;

void loop() {

loop1:  //main loop, alternating turns
  pturn = pturn^1;
  switch (pturn) {
  case 0:
    digitalWrite(11, HIGH);
    digitalWrite(10, LOW);
    goto p1;
    break;
  case 1:
    digitalWrite(11, LOW);
    digitalWrite(10, HIGH);
    goto p2;
    break;
  }
p1: //computation for the timer1
  counter = 5;
  p1global = p1global + counter;
  counter = p1global;
  delay(1000);
  goto segmentout;
dlp1: 
  counter = p1global - 1;
  p1global = counter;
  delay(1000);
  goto segmentout;

p2:   //computation for the timer1
  counter = 5;
  p2global = p2global + counter;
  counter = p2global;
  delay(1000);
  goto segmentout;
dlp2: 
  counter = p2global - 1;
  p2global = counter;
  delay(1000);
  goto segmentout;

segmentout: //7-segment display
  switch (counter) {
  case 9:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, HIGH);
    digitalWrite(2, LOW);
    digitalWrite(1, LOW);
    digitalWrite(0, HIGH);
    switch (pturn){
    case 0:
      if (digitalRead(13) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(13) == LOW){ 
        goto dlp1;
      };
      break;
    case 1:
      if (digitalRead(12) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(12) == LOW){ 
        goto dlp2;
      };
      break;
    }
    break;
  case 8:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, HIGH);
    digitalWrite(2, LOW);
    digitalWrite(1, LOW);
    digitalWrite(0, LOW);
    switch (pturn){
    case 0:
      if (digitalRead(13) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(13) == LOW){ 
        goto dlp1;
      };
      break;
    case 1:
      if (digitalRead(12) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(12) == LOW){ 
        goto dlp2;
      };
      break;
    }
    break;
  case 7:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    digitalWrite(2, HIGH);
    digitalWrite(1, HIGH);
    digitalWrite(0, HIGH);
    switch (pturn){
    case 0:
      if (digitalRead(13) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(13) == LOW){ 
        goto dlp1;
      };
      break;
    case 1:
      if (digitalRead(12) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(12) == LOW){ 
        goto dlp2;
      };
      break;
    }
    break;
  case 6:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    digitalWrite(2, HIGH);
    digitalWrite(1, HIGH);
    digitalWrite(0, LOW);
    switch (pturn){
    case 0:
      if (digitalRead(13) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(13) == LOW){ 
        goto dlp1;
      };
      break;
    case 1:
      if (digitalRead(12) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(12) == LOW){ 
        goto dlp2;
      };
      break;
    }
    break;
  case 5:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    digitalWrite(2, HIGH);
    digitalWrite(1, LOW);
    digitalWrite(0, HIGH);
    switch (pturn){
    case 0:
      if (digitalRead(13) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(13) == LOW){ 
        goto dlp1;
      };
      break;
    case 1:
      if (digitalRead(12) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(12) == LOW){ 
        goto dlp2;
      };
      break;
    }
    break;
  case 4:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    digitalWrite(2, HIGH);
    digitalWrite(1, LOW);
    digitalWrite(0, LOW);
    switch (pturn){
    case 0:
      if (digitalRead(13) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(13) == LOW){ 
        goto dlp1;
      };
      break;
    case 1:
      if (digitalRead(12) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(12) == LOW){ 
        goto dlp2;
      };
      break;
    }
    break;
  case 3:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    digitalWrite(2, LOW);
    digitalWrite(1, HIGH);
    digitalWrite(0, HIGH);
    switch (pturn){
    case 0:
      if (digitalRead(13) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(13) == LOW){ 
        goto dlp1;
      };
      break;
    case 1:
      if (digitalRead(12) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(12) == LOW){ 
        goto dlp2;
      };
      break;
    }
    break;
  case 2:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    digitalWrite(2, LOW);
    digitalWrite(1, HIGH);
    digitalWrite(0, LOW);
    switch (pturn){
    case 0:
      if (digitalRead(13) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(13) == LOW){ 
        goto dlp1;
      };
      break;
    case 1:
      if (digitalRead(12) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(12) == LOW){ 
        goto dlp2;
      };
      break;
    }
    break;
  case 1:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    digitalWrite(2, LOW);
    digitalWrite(1, LOW);
    digitalWrite(0, HIGH);
    switch (pturn){
    case 0:
      if (digitalRead(13) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(13) == LOW){ 
        goto dlp1;
      };
      break;
    case 1:
      if (digitalRead(12) == HIGH){ 
        goto loop1;
      };
      if (digitalRead(12) == LOW){ 
        goto dlp2;
      };
      break;
    }
    break;
  case 0:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
    digitalWrite(2, LOW);
    digitalWrite(1, LOW);
    digitalWrite(0, LOW);
    switch (pturn){
    case 0:
      digitalWrite(11, HIGH);
      digitalWrite(10, LOW);
      digitalWrite(7, HIGH);
      digitalWrite(6, HIGH);  
      digitalWrite(5, HIGH);
      digitalWrite(4, HIGH);
      digitalWrite(3, HIGH);
      digitalWrite(2, HIGH);
      digitalWrite(1, HIGH);
      digitalWrite(0, HIGH);
      goto halt;
      break;
    case 1:
      digitalWrite(11, LOW);
      digitalWrite(10, HIGH);
      digitalWrite(7, HIGH);
      digitalWrite(6, HIGH);  
      digitalWrite(5, HIGH);
      digitalWrite(4, HIGH);
      digitalWrite(3, HIGH);
      digitalWrite(2, HIGH);
      digitalWrite(1, HIGH);
      digitalWrite(0, HIGH);
      goto halt;
      break;
    }
    break;
  }
halt: 
  delay(999999);
}

Goto? Blimey, not seen those used for a while.

More gotos than comments.

What’s the Chest Game?

First thing to do is to rewire your seven seg display so you're not using pins 0 and 1. Then you can use Serial.println to get some debugging data out to you.

(Hopefully not starting another goto war).

Next thing to do is completely rewrite without using a single "goto". You don't need them, they are confusing.

After that maybe simplify the way you do the 7-segment displays.

Goto is sometimes useful. However, probably not in this case.

Interactive, real-time code generally wants to be built as a state machine, and each iteration through "loop()" just looks for a transition from the current state to some new state.

You probably want to write loop() something simple, like:

enum {
  PRE_START, PLAYER_A, PLAYER_B, GAME_OVER
};
int state;

...

loop() {
  switch (state) {
    case PRE_START: pre_start(); break;
    case PLAYER_A: update_player(0); break;
    case PLAYER_B: update_player(1); break;
    case GAME_OVER: end_game(); break;
  }
  update_display();
}

Now, you need to declare the state you need to duplicate per player: basically just "amount of time left" and "time since last turn started." Put that in a struct or class for the player, and have an array of two of these, for player A and player B. Using the array means that update_player() can take the player argument as an index, and you don't need to duplicate code for both players.

Finally, write the functions pre_start(), update_player(), end_game() and update_display() to do the right thing. For example, update_player() might do something like:

struct PlayerData {
  unsigned long startTimeMs;
  unsigned long timeLeftMs;
};
PlayerData players[2] = { { 0, 60000 }, { 0, 60000 } };

void update_player(int p) {
  if (millis() - players[p].startTimeMs > players[p].timeLeftMs) {
    player_lost();
    return;
  }
  if (player_button_pressed(p)) {
    next_player();
  }
}

Again, break it down: player_lost() would set state to "game_over" and set some internal variable to which player lost. next_player() would switch the state from PLAYER_A to PLAYER_B or vice versa, and calculate the timeLeftMs for the player you switch away from.

Keep going, breaking each individual little thing down into a separate function, and you'll find that the structure of your program improves.

Another thing that's nice about this approach is that you can make the functions do nothing first -- or Serial.print() something -- or set an LED -- so it's easy to see that the structure behaves the way you want it, so far, before you go to the next level.

i'm really new in programming, as much as i want to try this code "jwatte" i can't understand it...is there a simpliest way to do it??

I tried breaking up the code and remove the "goto", and made the first part of my program as:

void setup() {
  pinMode(11, OUTPUT); //player 1 indicator
  pinMode(10, OUTPUT); //player 2 indicator
}

int pturn = 1;
int counter;
int p1global;
int p2global;

void loop() {
  pturn = pturn^1;
  if (pturn == 0){
    digitalWrite(11, HIGH);
    digitalWrite(10, LOW);
    counter = 5000;
    p1global = p1global + counter;
    while ( counter > 0 ){
      p1global = p1global - 1000;
      delay(1000);
    }

  }
  else {
    digitalWrite(11, LOW);
    digitalWrite(10, HIGH);
    delay(1000);
  }
}

my problem is i don't know how to display the value of p1global in the seven segment every second.
should i put codes like below.

note: i aim to use 2 BCD decoder-to-7segement tandem.

  switch (p1global) {
  case 9:
    digitalWrite(7, LOW);
    digitalWrite(6, LOW);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, HIGH);
    digitalWrite(2, LOW);
    digitalWrite(1, LOW);
    digitalWrite(0, HIGH);
}
void loop() {
  pturn = pturn^1;

This will switch the turn each time through loop(). But loop() gets run many thousands of times per second.
Instead, you want to switch the player turn only when a button is pressed. Otherwise, you want to just keep counting down for the current player.
Also, you don't want to display the time remaining once a second. You want to display the time remaining all the time. The amount of time remaining, rounded to seconds, happens to actually change only once per second. But it's perfectly fine (and common) to output the data you want to display each time through loop().

You can drive a seven-segment display from digital pins like that. However, you will find it hard to drive more than one element/digit that way. Typically, you'll want a total of 8 digits (four per player) for a chess clock. You will probably want a latching digit controller, like the 4511, one for each digit. If wiring all that up seems difficult to you, then perhaps this project is a bit too much as a beginner project?

The way it would work:
Each 7-segment display digit is driven by a 4511 BCD-to-7-segment decoder/driver.
All of the drivers are wired to take their input from the same output pins on the Arduino -- say, pins 2, 3, 4 and 5. (Save 0 and 1 for the serial port)
You select which of the 8 you want to drive using the latch function on each of the chips.
You use pins 6 .. 13 to select which digit to update. Each output should be tied into the latch function of one 4511.

Thus, to update the value of a digit, you:

  1. write the output pin of the digit you want to select low, and all other select pins (6 .. 13) high.
  2. write the value of the digit as a binary number on pins 2, 3, 4 and 5.
    To update all eight digits, you do this 8 times, with different values for the ID in step 1.

Note that the 4511 latch allows you to update the value when it is low, and stores the last written value when it's high, so the normal state for the "chip select" output pins (6 .. 13) would be "high."

Mr. jwatte thank you for enlightening me.

I'm not sure if i got it right.. but i tried to hard code the program again...and added comments.

i tried uploading it but at some point it work as I intended but randomly, there are times that after 1sec and i didn't input anything yet it will change turn. i wasn't able to check yet if it displays in the 7segment.

advance thanks for checking my codes...

code modified

void setup() {
  pinMode(12, OUTPUT);    //player turn indicator for player 1
  pinMode(11, OUTPUT);    //player turn indicator for player 1

  pinMode(10, OUTPUT);    //output MSB binary
  pinMode(9, OUTPUT); 
  pinMode(8, OUTPUT); 
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(5, OUTPUT); 
  pinMode(4, OUTPUT);
  pinMode(3, OUTPUT);    //output LSB binary
}
int p1global;
int p2global;
int out_counter;
int sensorValue = 0;
int x;
int counter1;
int counter2;
int p_turn = 1;

void loop() {
  delay(10);
  counter1 = 5;              //setting counter to 5 secs for player1
  counter2 = 5;              //setting counter to 5 secs for player2
  switch (p_turn) {         //swtitch-case for player turn
  case 1:                   //player 1 turn functions
    digitalWrite (12,HIGH); //indicates player 1 turn
    digitalWrite (11,LOW);
    p1global = p1global + counter1; //putting the current time
    for (x = p1global; x > 0; x--) { //counter loop for x is the number of times decrement
      p1global = p1global - 1;       //decrements the universal time for player1
      out_counter = p1global;        //put universal time to the out_counter for display
      out_segment();                 //call display function
      sensorValue = analogRead(A1);  //put analog A1 input to sensorValue
      if(sensorValue == 1){     //check for sensor value
       p_turn = p_turn^1;        //alternates the player turn
        x = 0;                       //stops the loop
        break;                       
      }
      else {                          
        delay(1000);                  //1 sec interval
      }     
    }
    break;
  default:                            //player 1 turn functions
    digitalWrite (12,LOW);
    digitalWrite (11,HIGH);
    p2global = p2global + counter2;
    for (x = p2global; x > 0; x--) {
      p2global = p2global - 1;
      out_counter = p2global;
      out_segment();      
      sensorValue = analogRead(A2);
      if(sensorValue == 1){
      p_turn = p_turn^1;        //alternates the player turn
        x = 0;  
        break;
      }
      else {      
        delay(1000);
      }     
    }
    break;
  }
}  

void out_segment() {
  switch (out_counter){
  case 99:
      digitalWrite(10, HIGH);
      digitalWrite(9, LOW);
      digitalWrite(8, LOW);
      digitalWrite(7, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(5, LOW);
      digitalWrite(4, LOW);
      digitalWrite(3, HIGH);

  }
}

Read jwatte's post again. You still have exactly the same issue with pturn - it changes on every iteration of loop.

wildbill...tnx for pointing it out...

i placed the pturn = pturn^1; inside the condition for the input..

will it function well now??

and how about the way i display the timer??will it work with said code?

On second thought, I suggest you start from scratch. Write a program that reads two digital inputs, representing the player's buttons and control two leds to indicate whose turn it is. Then write another that has a function that outputs a number to your seven segment displays. Once those two are working, combine them and add in the timing piece - your big bang approach is making it more difficult.

If you choose to continue as you are though, note that your reading of the buttons is currently analog - it will not do what you want.

wildbill:
Then write another that has a function that outputs a number to your seven segment displays. Once those two are working, combine them and add in the timing piece

can you please explain this...

tnx

Your code without the gotos looks much better. I suggest you, at this stage, get the hang of reading switches and just turning a single LED or two on and off. Then you will find out things like trying to toggle and LED every time through loop() is too fast.

This stuff DOES work, and it is very satisfying to make it do so, but for the sake of your sanity solve one problem at a time. For example, make a simple program that turns an LED on when you press a switch, and turn it off when you press a different switch. The things you learn there will carry you through to more complex projects.

tacet777:

wildbill:
Then write another that has a function that outputs a number to your seven segment displays. Once those two are working, combine them and add in the timing piece

can you please explain this...

tnx

In the spirit of solving one problem at a time as Nick suggested, write a sketch that controls the seven segment display. If you're only using one of them, just a loop that displays the numbers 0 to 9 on it with a delay between each. Create a function that takes an integer as a parameter and displays that number on the display to do this. When you're done, you can use that function (and its supporting data) in your chess clock sketch. This way, you can figure out using the display without being distracted by everything else you're trying to do.

finally i got some spare time to reconstruct the program from scratch. please check it now...

thanks for the guidance.

void setup() {
  pinMode(12, OUTPUT);    //player turn indicator for player 2
  pinMode(11, OUTPUT);    //player turn indicator for player 1

  pinMode(2, INPUT);      //player 2 input
  pinMode(1, INPUT);      //player 1 input

  pinMode(10, OUTPUT);    //output MSB binary
  pinMode(9, OUTPUT); 
  pinMode(8, OUTPUT); 
  pinMode(7, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(5, OUTPUT); 
  pinMode(4, OUTPUT);
  pinMode(3, OUTPUT);    //output LSB binary
}
int counter = 6;
int p1_counter = counter;
int p2_counter = counter;
int p1_in = digitalRead(1);
int p2_in = digitalRead(2);
int out_counter;
int turn = 0;


void loop(){
  switch (turn){
    case 0:              //checks for player 1 turn
    player1();           // call player 1 function
    break;
    case 1:              //checks for player 2 turn
    player2();           // call player 2 function
  }
}

void player1(){                                    //player 1 function
  while( out_counter > 0){                         //loop for down counter
    out_counter = p1_counter - 1;                  //decrement counter
    out_segment();                                 //display
    if (p1_in == HIGH){                            //player 1 input indicates finish turn
      p1_counter = p1_counter + out_counter - 1;   //store the remaining time to add to next turn
      turn = 1;                                    //changing turn
      out_counter = 0;                             //make the while command to check out_counter = 0 and stop
      break;                                       //stop loop
    }
    else{
      delay(1000);                                 // i sec interval
    }
  }
}

void player2(){                                    //same as player 1 function
  while( out_counter > 0){
    out_counter = p2_counter - 1;
    out_segment();
    if (p2_in == HIGH){
      p2_counter = p2_counter + out_counter - 1;
      turn = 0;
      out_counter = 0;
      break;  
    }
    else{
      delay(1000);
    }
  }
}


void out_segment() {                          //display for the BCD-to-7-segment
  switch (out_counter){
  case 99:
    digitalWrite(10, HIGH);
    digitalWrite(9, LOW);
    digitalWrite(8, LOW);
    digitalWrite(7, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(5, LOW);
    digitalWrite(4, LOW);
    digitalWrite(3, HIGH);
    break;
.
.
.
.
.
}
}

Why aren't you asking the compiler?

I don't think it'll be happy with the isolated periods towards the end of the sketch.

Problem #1:

int p1_in = digitalRead(1);
int p2_in = digitalRead(2);

You are only reading the player input once. Aren't you expecting them to press buttons from time to time?


Problem #2:

 if (p1_in == HIGH){                            //player 1 input indicates finish turn
...
    }
    else{
      delay(1000);                                 // i sec interval
    }

The delay of 1000 means that if they press the button halfway through a second, and then let go, you won't notice (assuming you add the button read). It will be incredibly frustrating to play.

But why not compile, test, and see for yourself? When I try doing something I write the code, compile it, and test it. I don't put some untested code on the forum and ask what people think. I'm not infallible, my code usually doesn't work the first time. But by doing it yourself you find what works, what doesn't, and learn stuff. Plus you don't wait for people to reply.

@ problem 1
i really didn't know that...tnx for pointing it out.

@problem 2
right after i posted the codes i tested it and yah your right...it didn't function as i intended it to. i'll try to fix it in my free time again..
thx for your kindness...:slight_smile:
i'm learning a lot.

AWOL:
Why aren't you asking the compiler?

I don't think it'll be happy with the isolated periods towards the end of the sketch.

what do you mean "ask the compiler"? verify the codes??
i did verify the codes and there's no error, but the problem is that it doesn't function as intended,