Table Tennis Scoreboard

Hello!

This will be a quick explanation of how i built the ping pong scoreboard.

Pictures:

Video:

Parts:

  • 1 x 32×8 Led Matrix Display (5mm) – Red – Link
  • 1 x Arduino Nano (I used a cheap imitator from eBay)
  • 2 x Arcade push-buttons (momentary on type) – Something like this, although I found mine on eBay
  • Mounting method for the push-buttons under the table
  • DPST switch (for mode selection)
  • 5V Power supply, fed directly into the matrix power input, the Arduino can get the power from here too, but dont run the matrix from the regulator on the Arduino. These Displays can draw a lot of current.
  • Other miscellaneous wires, strip board, etc.

Method:

  1. Connect the centre pin of the mode switch to a digital read pin on the Arduino, and GND and +5V to the other two.
  2. Connect the 3 pins for the matrix to the arduino:
    1. pinCS1
    2. pinWR
    3. pinDATA
  3. Connect the pushbuttons to the 5V and two digital input pins, with a pull-down resistor to GND on each.
  4. I added a speaker to give audio feedback when the buttons are pressed.
  5. Thats about it!

Notes on the code:

  • I believe there might be a small error when the game is run in “to 11” mode, when the game reaches deuce. If anyone finds it let me know.
  • It certainly isn’t efficient, optimized or anything like that but I think I have commented it enough for people to understand what is happening.
#include <HT1632.h>

#define IMG_ARROW_WIDTH 4
#define IMG_ARROW_HEIGHT 8

char IMG_ARROW_DR [] = {0b0100, 0b0000, 0b1000, 0b0010, 0b0000, 0b0011, 0b1000, 0b0011};

char IMG_ARROW_DL [] = {0b1000, 0b0011, 0b0000, 0b0011, 0b1000, 0b0010, 0b0100, 0b0000};

char IMG_ARROW_UR [] = {0b0000, 0b0010, 0b0100, 0b0001, 0b1100, 0b0000, 0b1100, 0b0001};

char IMG_ARROW_UL [] = {0b1100, 0b0001, 0b1100, 0b0000, 0b0100, 0b0001, 0b0000, 0b0010};

#define DIGIT_WIDTH 6
#define DIGIT_HEIGHT 8

char DIGIT_0 [] = {0b1110, 0b0111, 0b1111, 0b1111, 0b0001, 0b1000, 0b0001, 0b1000, 0b1111, 0b1111, 0b1110, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000};

char DIGIT_1 [] = {0b0000, 0b0000, 0b0010, 0b0000, 0b0010, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000};

char DIGIT_2 [] = {0b0010, 0b1100, 0b0011, 0b1110, 0b0001, 0b1011, 0b1001, 0b1001, 0b1111, 0b1000, 0b0110, 0b1000, 0b0000, 0b0000, 0b0000, 0b0000};

char DIGIT_3 [] = {0b0010, 0b0100, 0b0011, 0b1100, 0b1001, 0b1000, 0b1001, 0b1000, 0b1111, 0b1111, 0b0110, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000};

char DIGIT_4 [] = {0b1000, 0b0011, 0b1100, 0b0011, 0b0010, 0b0010, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b0010, 0b0000, 0b0000, 0b0000, 0b0000};

char DIGIT_5 [] = {0b1111, 0b0100, 0b1111, 0b1100, 0b1001, 0b1000, 0b1001, 0b1000, 0b1001, 0b1111, 0b0001, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000};

char DIGIT_6 [] = {0b1000, 0b0111, 0b1110, 0b1111, 0b0011, 0b1001, 0b0001, 0b1001, 0b0001, 0b1111, 0b0000, 0b0110, 0b0000, 0b0000, 0b0000, 0b0000};

char DIGIT_7 [] = {0b0001, 0b0000, 0b0001, 0b1100, 0b0001, 0b1111, 0b1101, 0b0011, 0b1111, 0b0000, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000};

char DIGIT_8 [] = {0b0110, 0b0111, 0b1111, 0b1111, 0b1001, 0b1000, 0b1001, 0b1000, 0b1111, 0b1111, 0b0110, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000};

char DIGIT_9 [] = {0b0110, 0b0000, 0b1111, 0b1000, 0b1001, 0b1000, 0b1001, 0b1100, 0b1111, 0b0111, 0b1110, 0b0001, 0b0000, 0b0000, 0b0000, 0b0000};

#define TEXT_WIDTH 32
#define TEXT_HEIGHT 8

char TEXT_Rally []   = {0b1111, 0b1111, 0b1111, 0b1111, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b0001, 0b1111, 0b1111, 0b1110, 0b1110, 0b0000, 0b0000, 0b0000, 0b1111, 0b1100, 0b1111, 0b1111, 0b0010, 0b1111, 0b0010, 0b1100, 0b1111, 0b0000, 0b1111, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b1000, 0b0000, 0b1000, 0b0000, 0b1000, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b1000, 0b0011, 0b1000, 0b0111, 0b1000, 0b1100, 0b0000, 0b1000, 0b1111, 0b1000, 0b1111, 0b1100, 0b0000, 0b0111, 0b0000, 0b0011, 0b0000};

char TEXT_L_WIN []   = {0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b1000, 0b0001, 0b1100, 0b0011, 0b1110, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000, 0b1111, 0b0001, 0b1111, 0b0111, 0b0000, 0b1110, 0b0000, 0b1110, 0b1100, 0b0111, 0b1100, 0b0111, 0b0000, 0b1110, 0b0000, 0b1110, 0b1111, 0b0111, 0b1111, 0b0001, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b1110, 0b0001, 0b1000, 0b0011, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000};

char TEXT_R_WIN []   = {0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b1111, 0b0001, 0b1111, 0b0111, 0b0000, 0b1110, 0b0000, 0b1110, 0b1100, 0b0111, 0b1100, 0b0111, 0b0000, 0b1110, 0b0000, 0b1110, 0b1111, 0b0111, 0b1111, 0b0001, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b1110, 0b0001, 0b1000, 0b0011, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b0000, 0b0000, 0b0000, 0b1110, 0b0111, 0b1100, 0b0011, 0b1000, 0b0001, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000};

char TEXT_GAME_21 [] = {0b0000, 0b0000, 0b0000, 0b0000, 0b0001, 0b0000, 0b0001, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0001, 0b0000, 0b0001, 0b0000, 0b0000, 0b0000, 0b1110, 0b0111, 0b1111, 0b1111, 0b0001, 0b1000, 0b0001, 0b1000, 0b1111, 0b1111, 0b1110, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0010, 0b1100, 0b0011, 0b1110, 0b0001, 0b1011, 0b1001, 0b1001, 0b1111, 0b1000, 0b0110, 0b1000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0010, 0b0000, 0b0010, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b0000, 0b0000, 0b0000};

char TEXT_GAME_11 [] = {0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0001, 0b0000, 0b0001, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0001, 0b0000, 0b0001, 0b0000, 0b0000, 0b0000, 0b1110, 0b0111, 0b1111, 0b1111, 0b0001, 0b1000, 0b0001, 0b1000, 0b1111, 0b1111, 0b1110, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0010, 0b0000, 0b0010, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0010, 0b0000, 0b0010, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000};

char TEXT_DEUCE []   = {0b1111, 0b1111, 0b1111, 0b1111, 0b0001, 0b1000, 0b0011, 0b1100, 0b1110, 0b0111, 0b1100, 0b0011, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b1001, 0b1000, 0b1001, 0b1000, 0b0001, 0b1000, 0b0000, 0b0000, 0b1111, 0b0111, 0b1111, 0b1111, 0b0000, 0b1000, 0b0000, 0b1000, 0b1111, 0b1111, 0b1111, 0b0111, 0b0000, 0b0000, 0b1110, 0b0111, 0b1111, 0b1111, 0b0001, 0b1000, 0b0001, 0b1000, 0b0011, 0b1100, 0b0010, 0b0100, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b1001, 0b1000, 0b1001, 0b1000, 0b0001, 0b1000};

char TEXT_R_ADV []   = {0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b1111, 0b1100, 0b1111, 0b1111, 0b0010, 0b1111, 0b0010, 0b1100, 0b1111, 0b0000, 0b1111, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0001, 0b1000, 0b0011, 0b1100, 0b1110, 0b0111, 0b1100, 0b0011, 0b0000, 0b0000, 0b0011, 0b0000, 0b1111, 0b0001, 0b1100, 0b0111, 0b0000, 0b1110, 0b0000, 0b1110, 0b1100, 0b0111, 0b1111, 0b0001, 0b0011, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b1110, 0b0111, 0b1100, 0b0011, 0b1000, 0b0001, 0b0000, 0b0000, 0b0000, 0b0000};

char TEXT_L_ADV []   = {0b0000, 0b0000, 0b0000, 0b0000, 0b1000, 0b0001, 0b1100, 0b0011, 0b1110, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b1111, 0b1100, 0b1111, 0b1111, 0b0010, 0b1111, 0b0010, 0b1100, 0b1111, 0b0000, 0b1111, 0b0000, 0b0000, 0b1111, 0b1111, 0b1111, 0b1111, 0b0001, 0b1000, 0b0011, 0b1100, 0b1110, 0b0111, 0b1100, 0b0011, 0b0000, 0b0000, 0b0011, 0b0000, 0b1111, 0b0001, 0b1100, 0b0111, 0b0000, 0b1110, 0b0000, 0b1110, 0b1100, 0b0111, 0b1111, 0b0001, 0b0011, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000};

int modeswitch = 4;
int speaker = 5;

volatile int buzz;

volatile int l_player;
volatile int r_player;

volatile boolean serve_end;
volatile boolean serve_side;

volatile boolean first_point;
volatile boolean reset;

volatile boolean delay_disp;

volatile int serves_pp;
volatile int target_score;

void setup () {
    HT1632.begin(11, 10, 9);
    // Where pinCS1, pinWR and pinDATA are the numbers of the output pins
    // that are connected to the appropriate pins on the HT1632.

    noTone(speaker);

    delay_disp = false;

    // sets the mode switch pin to input
    pinMode(modeswitch, INPUT);  // sets the digital pin 8 as input

    l_player = 0;
    r_player = 0;

    //adjust this for rally to serve match
    serve_end = true;
    serve_side = true;
    first_point = true;
    reset = false;

    if (digitalRead(modeswitch)){
    // if toggle is high, game ends at 21 and server changes ever 5 points
      target_score = 21;
      serves_pp = 5;
      HT1632.drawImage(TEXT_GAME_21, TEXT_WIDTH,  TEXT_HEIGHT, 0, 0);
      HT1632.render();
      delay (2000);
    }else{
    // if toggle is low, game ends at 11 and server changes ever 2 points
      target_score = 11;
      serves_pp = 2;
      HT1632.drawImage(TEXT_GAME_11, TEXT_WIDTH,  TEXT_HEIGHT, 0, 0);
      HT1632.render();
      delay (2000);
    }

    HT1632.drawImage(TEXT_Rally, TEXT_WIDTH,  TEXT_HEIGHT, 0, 0);
    HT1632.render();

    // creates interupts for the two player buttons
    // when interupt 0 (pin 2) is triggered (player 1 button gos low) call function increaseplayer1()
    attachInterrupt(1, l_player_button, LOW);
    // when interupt 1 (pin 3) is triggered (player 2 button gos low) call function increaseplayer2()
    attachInterrupt(0, r_player_button, LOW);
}

void l_player_button(){

  // variables used for debounce
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();

  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200){
    if (reset){asm volatile("  jmp 0");}else{
      if (first_point){
        first_point = !first_point;
        HT1632.clear();
        display();
        buzz = 1;
      }else{
        l_player++;
        if ((l_player >= target_score)&&(l_player >= (r_player + 2))){
          HT1632.drawImage(TEXT_L_WIN, TEXT_WIDTH,  TEXT_HEIGHT, 0, 0);
          HT1632.render();
          buzz = 3;
          reset = true;
        }else{
          serve_brain();
          if (!delay_disp){
            display();
          }
        }
      }
    }
   }
  // debounce variable reset
  last_interrupt_time = interrupt_time;
}

void r_player_button(){

  // variables used for debounce
  static unsigned long last_interrupt_time = 0;
  unsigned long interrupt_time = millis();

  // If interrupts come faster than 200ms, assume it's a bounce and ignore
  if (interrupt_time - last_interrupt_time > 200){
    if (reset){asm volatile("  jmp 0");}else{
      if (first_point){
        serve_end = false;
        first_point = !first_point;
        HT1632.clear();
        display();
        buzz = 1;
      }else{
        r_player++;
        if ((r_player >= target_score)&&(r_player >= (l_player + 2))){
          HT1632.drawImage(TEXT_R_WIN, TEXT_WIDTH,  TEXT_HEIGHT, 0, 0);
          HT1632.render();
          buzz = 3;
          reset = true;
        }else{
          serve_brain();
          if (!delay_disp){
            display();
          }
        }
      }
    }
  }
  // debounce variable reset
  last_interrupt_time = interrupt_time;
}

void serve_brain(){
  if (!((l_player >= (target_score-1))&&(r_player >= (target_score-1)))||((l_player == r_player) && (r_player == (target_score-1)))){
    if (((l_player+r_player)%serves_pp)==0){
      serve_end = !serve_end;
      serve_side = true;
      buzz = 2;
    }
    else{
      buzz = 1;
      serve_side = !serve_side;
    }
  }else{
    if (((l_player+r_player)%2)==1){
      serve_end = !serve_end;
      serve_side = true;
      buzz = 2;
    }else{
      buzz = 1;
      serve_side = !serve_side;
    }
  }
  if ((l_player == r_player) && (r_player >= (target_score-1))){
    HT1632.drawImage(TEXT_DEUCE, TEXT_WIDTH,  TEXT_HEIGHT, 0, 0);
    HT1632.render();
    delay_disp = true;
  }
  if ((r_player == (l_player+1)) && (l_player >= (target_score-1))){
    HT1632.drawImage(TEXT_R_ADV, TEXT_WIDTH,  TEXT_HEIGHT, 0, 0);
    HT1632.render();
    delay_disp = true;
  }
  if ((l_player == (r_player+1)) && (r_player >= (target_score-1))){
    HT1632.drawImage(TEXT_L_ADV, TEXT_WIDTH,  TEXT_HEIGHT, 0, 0);
    HT1632.render();
    delay_disp = true;
    serves_pp = 2;
  }
}

void display(){
  HT1632.clear();
  if (serve_end){
    if (serve_side){
    HT1632.drawImage(IMG_ARROW_UR, IMG_ARROW_WIDTH,  IMG_ARROW_HEIGHT, 14, 0);
    }
    else{
    HT1632.drawImage(IMG_ARROW_DR, IMG_ARROW_WIDTH,  IMG_ARROW_HEIGHT, 14, 0);
    }
  }
  else {
    if (serve_side){
    HT1632.drawImage(IMG_ARROW_DL, IMG_ARROW_WIDTH,  IMG_ARROW_HEIGHT, 14, 0);
    }
    else{
    HT1632.drawImage(IMG_ARROW_UL, IMG_ARROW_WIDTH,  IMG_ARROW_HEIGHT, 14, 0);
    }
  }
  switch ((l_player/10)){ // update left tens
    case 0:
      HT1632.drawImage(DIGIT_0, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
    case 1:
      HT1632.drawImage(DIGIT_1, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
    case 2:
      HT1632.drawImage(DIGIT_2, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
    case 3:
      HT1632.drawImage(DIGIT_3, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
    case 4:
      HT1632.drawImage(DIGIT_4, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
    case 5:
      HT1632.drawImage(DIGIT_5, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
    case 6:
      HT1632.drawImage(DIGIT_6, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
    case 7:
      HT1632.drawImage(DIGIT_7, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
    case 8:
      HT1632.drawImage(DIGIT_8, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
    case 9:
      HT1632.drawImage(DIGIT_9, DIGIT_WIDTH,  DIGIT_HEIGHT, 0, 0);
    break;
  }
  switch ((l_player%10)){
    case 0:
      HT1632.drawImage(DIGIT_0, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
    case 1:
      HT1632.drawImage(DIGIT_1, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
    case 2:
      HT1632.drawImage(DIGIT_2, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
    case 3:
      HT1632.drawImage(DIGIT_3, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
    case 4:
      HT1632.drawImage(DIGIT_4, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
    case 5:
      HT1632.drawImage(DIGIT_5, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
    case 6:
      HT1632.drawImage(DIGIT_6, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
    case 7:
      HT1632.drawImage(DIGIT_7, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
    case 8:
      HT1632.drawImage(DIGIT_8, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
    case 9:
      HT1632.drawImage(DIGIT_9, DIGIT_WIDTH,  DIGIT_HEIGHT, 7, 0);
    break;
  }
  switch ((r_player/10)){ // update right tens
    case 0:
      HT1632.drawImage(DIGIT_0, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
    case 1:
      HT1632.drawImage(DIGIT_1, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
    case 2:
      HT1632.drawImage(DIGIT_2, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
    case 3:
      HT1632.drawImage(DIGIT_3, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
    case 4:
      HT1632.drawImage(DIGIT_4, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
    case 5:
      HT1632.drawImage(DIGIT_5, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
    case 6:
      HT1632.drawImage(DIGIT_6, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
    case 7:
      HT1632.drawImage(DIGIT_7, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
    case 8:
      HT1632.drawImage(DIGIT_8, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
    case 9:
      HT1632.drawImage(DIGIT_9, DIGIT_WIDTH,  DIGIT_HEIGHT, 19, 0);
    break;
  }
  switch ((r_player%10)){
    case 0:
      HT1632.drawImage(DIGIT_0, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
    case 1:
      HT1632.drawImage(DIGIT_1, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
    case 2:
      HT1632.drawImage(DIGIT_2, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
    case 3:
      HT1632.drawImage(DIGIT_3, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
    case 4:
      HT1632.drawImage(DIGIT_4, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
    case 5:
      HT1632.drawImage(DIGIT_5, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
    case 6:
      HT1632.drawImage(DIGIT_6, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
    case 7:
      HT1632.drawImage(DIGIT_7, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
    case 8:
      HT1632.drawImage(DIGIT_8, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
    case 9:
      HT1632.drawImage(DIGIT_9, DIGIT_WIDTH,  DIGIT_HEIGHT, 26, 0);
    break;
  }

  HT1632.render();
}

void loop () {
  switch (buzz){
    case 1:
      for (int i=2000;i<3000;i=i+10){
        tone(speaker, i);
        delay(1);
      }
      noTone(speaker);
      buzz = 0;
    break;
    case 2:
      for (int i=1000;i<3000;i=i+10){
        tone(speaker, i);
        delay(1);
      }
      for (int i=3000;i>1000;i=i-10){
        tone(speaker, i);
        delay(1);
      }
      noTone(speaker);
      buzz = 0;
    break;
    case 3:
      for (int j=0;j<5;j++){
        for (int i=2000;i<3000;i=i+10){
          tone(speaker, i);
          delay(1);
        }
        for (int i=3000;i>2000;i=i-10){
          tone(speaker, i);
          delay(1);
        }
      }
      noTone(speaker);
      buzz = 0;
    break;
  }
  if (delay_disp){
    if (buzz==0){
      delay(1000);
      HT1632.clear();
      display();
      delay_disp = false;
    }
  }
}

Advertisements

7 responses to “Table Tennis Scoreboard

  1. Total arduino newbee here.

    Is it possible to add:
    1. a way to set who is making the first serve? This could be done with the player buttons, once started, the very first signal indicates who serves, and the rest are for the score
    2. a way to decrease the count in case of a mistake
    ?

    Other than that, AWESOME project!

    Thanks!

    • Also, I forgot, how difficult would it be to have TWO displays instead of one? They would show the same thing, of course.

      The reason I ask is because then I would place them on either side of the net and would just have to make sure they are both low enough below the top of the net to not interfere with the game.

    • Hi Predrag,

      The first point is already how it works.
      The second could be a simple modification of the code along the lines of whenever the button is held for longer than x seconds, remove a point.

      Thanks for the comment!

      • Oh, NICE.

        Actually, DUH, if I read the code:
        }else{
                  serve_brain();

        So, if I understood you correctly, it would be something like:

        if (interrupt_time – last_interrupt_time > 2000) {
        r_player–;
        serve_brain();
        if (!delay_disp){
        display();
        }
        } else if (interrupt_time – last_interrupt_time > 200) { …
        }

        for holding it 2 secons for example?

      • That looks correct but I can’t be sure as it programmed it a LONG time ago 🙂

        As for multiple displays, it would be no problem. You would either update two separate displays and daisy chain them (think series) or split each of the three lines which control them to each display (parallel).
        Parallel would allow quicker updates.

        Hope that helps!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s