WU_HuiQiao
Published © GPL3+

Mini Table Tennis(Arduino Nano + WS2812B LED Strip Lights)

I made this project in order to experience the fun of playing table tennis anytime, anywhere, even in small places.

BeginnerFull instructions provided2 hours267

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
PTS 645 Series Switch
C&K Switches PTS 645 Series Switch
×1
WS2812 Addressable LED Strip
Digilent WS2812 Addressable LED Strip
×1
0.96" OLED 64x128 Display Module
ElectroPeak 0.96" OLED 64x128 Display Module
×1
Breadboard (generic)
Breadboard (generic)
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

10 Pc. Jumper Wire Kit, 5 cm Long
10 Pc. Jumper Wire Kit, 5 cm Long

Story

Read more

Schematics

Schematics

In Fritzing format

Code

Code

C/C++
Code to control the speed of the game on the Line 43.
/*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************BY HUIQIAO****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
#include <Arduino.h>           // Calling program    
#include <U8g2lib.h>           // Calling ICD screen library progrm  
#include <Wire.h>              // Calling I2C libray program
#include <Adafruit_NeoPixel.h> // Calling RGB libry program
#include <avr/power.h>         // Calling RGB library program




#define NumPixels    11    // Define 11 LEDs
#define winScore     11    // Define user should score 11 points to win
#define leftReadyPin  2    // Left readytoserve button connects to ArduinoD2
#define leftServePin  3    // Lefr serve button connects to ArduinoD3
#define buttonZeroPin 4    // reset button connects to ArduinoD4
#define rightServePin 7    // Right serve button connects to ArduinoD7
#define rightReadyPin 12   // Right readytoserve button connects to ArduinoD12
#define ws2812Pin     9    // RGB strip connects to ArduinoD9  




Adafruit_NeoPixel pixels(NumPixels, ws2812Pin, NEO_GRB + NEO_KHZ800);
U8G2_SSD1306_128X64_NONAME_1_SW_I2C u8g2(U8G2_R0, /* clock=*/ SCL, /* data=*/ SDA, /* reset=*/ U8X8_PIN_NONE);




int leftScore = 0;  // Left scores        
int rightScore = 0; // Right scores      
int i = 0;          // LEDs count of RGB strip from left part            
int j = 10;         // LEDs count of RGB strip from right part       
int randomNumber;   // To choose who serves first randomly




int Step_state = 0x00;    // To show which stage of the game     
int colorNumber = 0;      // color variable
long blinkTime1 = 0;      // Blink time variable 
long blinkTime2 = 0;      
long blinkTime3 = 0;
long Period1 = 500;       // Gap time before each blink 
long Period2 = 1000;      // Speed of LEDs of RGB strip 
bool endingState = false;




struct Button {
  int lastButtonState = HIGH;     // Innitialise     
  boolean flag = false;           // True-false status
  
  
  
  
  // Define long() 
  long lastDebounceTime = 0;     // Record debounce variable
  long debounceDelay = 50;       // Debounce time variable is 50ms
};
Button button[5];                // set up 3 new buttons

void setup() {
  
  Serial.begin(9600);                   // Rate  
  
  pinMode(leftReadyPin, INPUT_PULLUP);  // Set up lbutton 1 uses pullup to input     
  pinMode(leftServePin, INPUT_PULLUP);  // Set up Lbutton 2 uses......
  
  pinMode(buttonZeroPin, INPUT_PULLUP); // Set up Lbutton 3 uses......    
  
  pinMode(rightServePin, INPUT_PULLUP); // Set up Rbutton 1 uses......      
  
  pinMode(rightReadyPin, INPUT_PULLUP); // Set up Rbutton 2 uses......  
  
  pixels.begin();
  
  pixels.clear();
  
  pixels.show();
  
  u8g2.begin();
  
}

void loop() {
  
  switch (Step_state) {
    
    case 0x00: {                           // Statge is 0
    
        buttonFlag();                      // Reset button function
        
        chooseServe();                     // Choose serve function
        
      } break; 
      
    case 0x01: {                           // Stage 1
    
        buttonFlag();                      // Reset button function
        
        waitingReady();                    // Wait for ready to serve button
        
      } break;
      
    case 0x02: {                           // Stage 2
    
        buttonFlag();                      // Reset button function 
        
        Screen();                          // Screen function
        
        if (endingState == true) {         // If one user winns
        
          Step_state = 0x04;              
          
          endingState = false;
          
        } else {
          
          Step_state = 0x03;
          
        }
      } break;
      
    case 0x03: {                           // Stage 3
    
        buttonFlag();                      // Reset button clear function                         
        score();                           // Score function                         
      } break;
      
    case 0x04: {                           // Stage 4
    
        winBlink();                        // Blink RGB strip when one suer wins
        
        buttonFlag();                      // Reset button to clear                     
      } break;
      
    default: break;
  }
  
}





void  chooseServe() {
  
  randomNumber = random(0, 100);
  
  for (int m = 0; m < NumPixels; m ++) {           // RGB strip glow off            
    pixels.setPixelColor(m, pixels.Color(0, 0, 0));
    
    pixels.show();
    
  }
  
  u8g2.setFont(u8g2_font_9x15_mf);
  
  u8g2.firstPage();
  
  do {
    if (randomNumber % 2 == 0) {          // Make sure LCD scree display first              
      Serial.println("");
      
      u8g2.drawStr(20,  40, "leftServe!");       
    } 
    
    else if (randomNumber % 2 == 1) {    // Make sure LCD scree display first        
      Serial.println("");
      
      u8g2.drawStr(10,  40, "rightServe!");         
    }
    
  } while ( u8g2.nextPage() );
  
  Serial.print(button[0].flag);  
  
  Serial.print(",");
  
  Serial.println(button[4].flag);
  
  Serial.println("aaa");
  
  Step_state = 0x01;
  
}




void waitingReady() {
  
  Serial.print(button[0].flag);  
  
  Serial.print(",");
  
  Serial.println(button[4].flag);
  
  if (button[0].flag != true) {                       // if button1 doesnot down
  
    Button(leftReadyPin, 0);                          // condition of button 1
    
  }
  else {
    
    pixels.setPixelColor(0, pixels.Color(0, 0, 255));
    
    pixels.show();
    
  }
  if (button[4].flag != true) {  
    
    Button(rightReadyPin, 4);
    
  }
  else {
    
    pixels.setPixelColor(10, pixels.Color(255, 0, 0));
    
    pixels.show();
    
  }
  if ((button[0].flag == true) && (button[4].flag == true)) {   
    
    pixels.setPixelColor(10, pixels.Color(255, 0, 0));
    
    pixels.setPixelColor(0, pixels.Color(0, 0, 255));
    
    pixels.show();
    
    Serial.println("ready");
    
    Step_state = 0x02;
    
  }
}

void Screen() {
  
  u8g2.firstPage();
  
  do {
    
    u8g2.setFont(u8g2_font_9x15_mf); // scores 
    
    u8g2.drawStr(0,  10, "Left");
    
    u8g2.drawStr(80, 10, "Right");
    
    u8g2.setFont(u8g2_font_calibration_gothic_nbp_tr);
    
    u8g2.setCursor(10, 40);
    
    u8g2.print(leftScore);
    
    u8g2.setCursor(98, 40);
    
    u8g2.print(rightScore);
    
    if (leftScore == winScore) {    // when left wins
      
      u8g2.setCursor(10, 40);
      
      u8g2.print(leftScore);
      
      u8g2.drawStr(0,  60, "Win !"); // screen displays
      
      endingState = true;
      
    }
    
    if (rightScore == winScore) {   // Right wins
      
      u8g2.setCursor(98, 40);
      
      u8g2.print(rightScore);
      
      u8g2.drawStr(100,  60, "Win !"); // screen displays
      
      endingState = true;
      
    }
    
  } while ( u8g2.nextPage() );
  
}




void score() {
  
  Button(leftServePin, 1);    
  
  Button(rightServePin, 3);  
  
  if (randomNumber % 2 == 0) {    
    
    if ((button[1].flag != true) && (button[3].flag == true)) {
      
      leftScore ++; 
      
      for (int m = 0; m < 11; m ++) {
        
        pixels.setPixelColor(m, pixels.Color(0, 0, 0));
        
        pixels.show();
        
      }
      
      u8g2.firstPage();
      
      do {
        
        u8g2.drawStr(20,  40, "left+1!");
        
      } while ( u8g2.nextPage() );
      
      delay(3000);

      i = 0;
      
      j = 10;
      
      for (int m = 0; m < 5; m ++) {
        
        button[m].flag = false;
        
      }
      
      randomNumber = random(0, 100);
      
      if (leftScore != winScore) {
        
        Step_state = 0x00;
        
      } else {
        
        Step_state = 0x02;
        
      }
    }
    
    else {
      
      if (button[1].flag == true) {   
        
        leftBlink();     
        
      }
      
      if (button[3].flag == true) { 
        
        rightBlink(); 
        
      }
      
      if ((button[1].flag == true) && (button[3].flag != true) && (i >= 6)) {
        
        leftScore ++;
        
        for (int m = 0; m < i; m ++) {
          
          pixels.setPixelColor(m, pixels.Color(0, 0, 0));
          
          pixels.show();
          
        }
        
        u8g2.firstPage();
        
        do {
          
          u8g2.drawStr(20,  40, "left+1!");
          
        } 
        
        while ( u8g2.nextPage() );
        
        delay(3000);

        i = 0;
        
        j = 10;
        
        for (int m = 0; m < 5; m ++) {
          
          button[m].flag = false;
          
        }
        
        randomNumber = random(0, 100);
        
        if (leftScore != winScore) {
          
          Step_state = 0x00;
          
        } 
        else {
          
          Step_state = 0x02;
          
        }
        
      }
      
      else if ((button[1].flag == true) && (button[3].flag == true)) {
        
        if ((i == 5) && (j == 9)) { 
          
          rightScore ++;
          
          for (int m = 0; m < i; m ++) {
            
            pixels.setPixelColor(m, pixels.Color(0, 0, 0));
            
            pixels.show();
            
          }
          for (int m = 10; m > j; m --) {
            
            pixels.setPixelColor(m, pixels.Color(0, 0, 0));
            
            pixels.show();
            
          }
          
          u8g2.firstPage();
          
          do {
            
            u8g2.drawStr(20,  40, "right+1!");
            
          }
          while ( u8g2.nextPage() );
          
          delay(3000);

          i = 0;
          
          j = 10;
          
          for (int m = 0; m < 5; m ++) {
            
            button[m].flag = false;
            
          }
          
          randomNumber = random(0, 100);
          
          if (rightScore != winScore) {
            
            Step_state = 0x00;
            
          } 
          else {
            
            Step_state = 0x02;
            
          }
          
        }
        else {
          
          leftScore ++;
          
          for (int m = 0; m < i; m ++) {
            
            pixels.setPixelColor(m, pixels.Color(0, 0, 0));
            
            pixels.show();
          }
          
          for (int m = 10; m > j; m --) {
            
            pixels.setPixelColor(m, pixels.Color(0, 0, 0));
            
            pixels.show();
          }
          
          u8g2.firstPage();
          
          do {
            
            u8g2.drawStr(20,  40, "left+1!");
            
          }
          while ( u8g2.nextPage() );
          
          delay(3000);

          i = 0;
          
          j = 10;
          
          for (int m = 0; m < 5; m ++) {
            
            button[m].flag = false;
            
          }
          randomNumber = random(0, 100);
          
          if (leftScore != winScore) {
            
            Step_state = 0x00;
            
          } else {
            
            Step_state = 0x02;
            
          }
        }
      }
    }
  }
  else if (randomNumber % 2 == 1) {
    
    if ((button[1].flag == true) && (button[3].flag != true)) {
      
      rightScore ++;  
      
      for (int m = 0; m < NumPixels; m ++) {
        
        pixels.setPixelColor(m, pixels.Color(0, 0, 0));
        
        pixels.show();
        
      }
      u8g2.firstPage();
      
      do {
        
        u8g2.drawStr(20,  40, "right+1!");
        
      } while ( u8g2.nextPage() );
      
      delay(3000);
      
      i = 0;
      
      j = 10;
      
      for (int m = 0; m < 5; m ++) {
        
        button[m].flag = false;
        
      }
      
      randomNumber = random(0, 100);
      
      if (rightScore != winScore) {
        
        Step_state = 0x00;
        
      } else {
        
        Step_state = 0x02;
        
      }
    } 
    else {
      
      if (button[1].flag == true) {
        
        leftBlink();
        
      }
      
      if (button[3].flag == true) {
        
        rightBlink();
        
      }
      
      if ((button[1].flag != true) && (button[3].flag == true) && (j <= 4)) {
        
        rightScore ++; 
        
        for (int m = 10; m > j; m --) {
          
          pixels.setPixelColor(m, pixels.Color(0, 0, 0));
          
          pixels.show();
          
        }
        
        u8g2.firstPage();
        
        do {
          
          u8g2.drawStr(20,  40, "right+1!");
          
        }
        while ( u8g2.nextPage() );
        
        delay(3000);
        
        i = 0;
        
        j = 10;
        
        for (int m = 0; m < 5; m ++) {
          
          button[m].flag = false;
          
        }
        
        randomNumber = random(0, 100); 
        
        if (rightScore != winScore) {
          
          Step_state = 0x00;
          
        } 
        else {
          
          Step_state = 0x02;
          
        }
      }
      
      if ((button[1].flag == true) && (button[3].flag == true)) {
        
        if ((i == 1) && (j == 5)) { 
          
          leftScore ++;
          
          for (int m = 0; m < i; m ++) {
            
            pixels.setPixelColor(m, pixels.Color(0, 0, 0));
            
            pixels.show();
            
          }
          
          for (int m = 10; m > j; m --) {
            
            pixels.setPixelColor(m, pixels.Color(0, 0, 0));
            
            pixels.show();
            
          }
          u8g2.firstPage();
          
          do {
            
            u8g2.drawStr(20,  40, "left+1!");
            
          } 
          while ( u8g2.nextPage() );
          
          delay(3000);

          i = 0;
          
          j = 10;
          
          for (int m = 0; m < 5; m ++) {
            
            button[m].flag = false;
            
          }
         
          randomNumber = random(0, 100);
          
          if (leftScore != winScore) {
            
            Step_state = 0x00;
            
          } 
          else {
            
            Step_state = 0x02;
            
          }
          
        } else {
          
          rightScore ++;
          
          for (int m = 0; m < i; m ++) {
            
            pixels.setPixelColor(m, pixels.Color(0, 0, 0));
            
            pixels.show();
            
          }
          
          for (int m = 10; m > j; m --) {
            
            pixels.setPixelColor(m, pixels.Color(0, 0, 0));
            
            pixels.show();
            
          }
          
          u8g2.firstPage();
          
          do {
            
            u8g2.drawStr(20,  40, "right+1!");
            
          }
          while ( u8g2.nextPage() );
          
          delay(3000);

          i = 0;
          
          j = 10;
          
          for (int m = 0; m < 5; m ++) {
            
            button[m].flag = false;
            
          }
          
          randomNumber = random(0, 100);
          
          if (rightScore != winScore) {
            
            Step_state = 0x00;
            
          } else {
            
            Step_state = 0x02;
            
          }
          
        }
      }
    }
  }
}




void buttonFlag() { 
  
  Button(buttonZeroPin, 2); 
  
  if (button[2].flag == true) { 
    
    for (int m = 0; m < NumPixels; m ++) { 
      
      pixels.setPixelColor(m, pixels.Color(0, 0, 0));
      
      pixels.show();
      
    }
    leftScore = 0;  
    
    rightScore = 0;
    
    button[0].flag = false;   
    
    button[1].flag = false;
    
    button[2].flag = false;
    
    button[3].flag = false;
    
    button[4].flag = false;
    
    i = 0; 
    
    j = 10;
    
    u8g2.firstPage();
    
    do {
      
      u8g2.drawStr(0,  40, "gameRestart!");
      
    } while ( u8g2.nextPage() );
    
    delay(3000);
    
    Step_state = 0x00;
    
  }
}




void leftBlink() {
  
  
  unsigned long currentMillis = millis();    
  
  if (i < NumPixels) {
    
    if (currentMillis - blinkTime1 >= Period1) {   //period1ms
    
      for (int m = 0; m < i; m ++) {
        
        pixels.setPixelColor(m, pixels.Color(0, 0, 0)); 
        
        pixels.show();
        
      }
    }
    
    if (currentMillis - blinkTime1 >= Period2) {   //period2ms
    
      blinkTime1 = currentMillis;
      
      i++;
      
      pixels.setPixelColor(i, pixels.Color(0, 0, 255)); 
      
      pixels.show();
      
    }
  }
  
  if (i == NumPixels) {
    
    for (int m = 0; m < NumPixels; m ++) {
      
      pixels.setPixelColor(m, pixels.Color(0, 0, 0));
      
      pixels.show();
      
    }
  }
}




void rightBlink() {
  
  unsigned long currentMillis = millis(); 
  
  if (j > 0) {
    
    if (currentMillis - blinkTime2 >= Period1) {   //periodms
    
      for (int m = 10; m > j; m --) {
        
        pixels.setPixelColor(m, pixels.Color(0, 0, 0));
        
        pixels.show();
        
      }
      
    }
    
    if (currentMillis - blinkTime2 >= Period2) {   //periodms
    
      blinkTime2 = currentMillis;
      
      j--;
      
      pixels.setPixelColor(j, pixels.Color(255, 0, 0));
      
      pixels.show();
      
    }
  }
  if (j == 0) {
    
    for (int m = 0; m < NumPixels; m ++) {
      
      pixels.setPixelColor(m, pixels.Color(0, 0, 0));
      
      pixels.show();
      
    }
  }
}

void Button(int button_Pin, int button_num) {
  
  int reading = digitalRead(button_Pin); 
  
  if (reading != button[button_num].lastButtonState) {  
    
    if (reading == LOW) {                         //LOW
    
      button[button_num].flag = true;       
      
    }
    
  }
  
  button[button_num].lastButtonState = reading; 
  
}

void winBlink() {
  
  unsigned long currentMillis = millis();          // record and store time       
  if (leftScore == winScore) {
    
    if (currentMillis - blinkTime3 >= Period1) {  // check periodms
    
      for (int m = 0; m < NumPixels; m ++) {
        
        pixels.setPixelColor(m, pixels.Color(0, 0, 0));
        
        pixels.show();
        
      }
      
    }
    if (currentMillis - blinkTime3 >= Period2) {   // check periodms
    
      blinkTime3 = currentMillis;
      
      for (int m = 0; m < NumPixels; m ++) {
        
        pixels.setPixelColor(m, pixels.Color(0, 0, 255));
        
        pixels.show();
        
      }
      
    }
    
  }
  else if (rightScore == winScore) {
    
    if (currentMillis - blinkTime3 >= Period1) {   // check periodms
    
      for (int m = 0; m < NumPixels; m ++) {
        
        pixels.setPixelColor(m, pixels.Color(0, 0, 0));
        
        pixels.show();
        
      }
      
    }
    if (currentMillis - blinkTime3 >= Period2) {   // check periodms
    
      blinkTime3 = currentMillis;
      
      for (int m = 0; m < NumPixels; m ++) {
        
        pixels.setPixelColor(m, pixels.Color(255, 0, 0
        
        pixels.show();
        
      }
    }
  }
}

U8g2_Arduino-master

C/C++
Please download the ZIP library for the project from
https://github.com/olikraus/U8g2_Arduino
No preview (download only).

Adafruit_NeoPixel-master

C/C++
Please download the ZIP library for the project from
https://github.com/adafruit/Adafruit_NeoPixel/find/master
No preview (download only).

Credits

WU_HuiQiao

WU_HuiQiao

1 project • 7 followers
I like building things.

Comments

Add projectSign up / Login