Welcome to Hackster!
Hackster is a community dedicated to learning hardware, from beginner to pro. Join us, it's free!
Hackster is hosting Impact Spotlights: Industrial Automation. Watch the stream live on Thursday!Hackster is hosting Impact Spotlights: Industrial Automation. Stream on Thursday!
NilsSchuenemannHeinzKetschupEsdx
Created June 11, 2019

Digitalised table football

A table football game with automated goal-counter, Bluetooth, sound effects, OLEDs and lights.

BeginnerShowcase (no instructions)201
Digitalised table football

Things used in this project

Hardware components

Arduino Nano R3
Arduino Nano R3
×1
IR Obstacle Sensor
×2
Capacitive Touch Sensor
×4
Adafruit SSD1306 164x64 OLED
×2
Portable Stereo Lautsprecher Mini
×1
goooaliat Tischkicker
×1
SanDisk MicroSD 2GB
×1
3.5 mm headphone jack
×1
TC74HC4072P Dual Quad OR
×1
Several resistors and capacitors SMD1206
×1
LEDs
×10
DFPlayer Mini
×1
Male-Header 36 Position 1 Row- Long (0.1")
Male-Header 36 Position 1 Row- Long (0.1")
×1
Female Header 8 Position 1 Row (0.1")
Female Header 8 Position 1 Row (0.1")
×3
USB Connector, USB Type B
USB Connector, USB Type B
×1
USB Cable Assembly, USB Type A Plug to Micro USB Type B Plug
USB Cable Assembly, USB Type A Plug to Micro USB Type B Plug
×1
USB Type B for power
×1
PLA filament
×1
Wire, Wrapping Wire
Wire, Wrapping Wire
×1

Software apps and online services

Android Studio
Android Studio
Ultimaker Cura
Arduino IDE
Arduino IDE
Eagle 5.10.0

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
Solder Flux, Soldering
Solder Flux, Soldering
Solder Wire, Lead Free
Solder Wire, Lead Free
Precision Tweezer, Hand-Piece
Precision Tweezer, Hand-Piece
3D Printer (generic)
3D Printer (generic)
Hot glue gun (generic)
Hot glue gun (generic)

Story

Read more

Custom parts and enclosures

3D OLED-case

Ramp

Schematics

BRD PDF

SCH PDF

BRD Eagle 5.10.0

SCH Eagle 5.10.0

Code

DigitalerTischkicker.ino

Arduino
Code for the Arduino Nanp
// "Digitaler Tischkicker" der WNJM GmbH
// Code designed by Nils Schuenemann 

#include <Arduino.h>
#include <SoftwareSerial.h>
#include <DFRobotDFPlayerMini.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

Adafruit_SSD1306 OLED_TEAM1(-1);
Adafruit_SSD1306 OLED_TEAM2(-1);

uint8_t volume = 10;
uint8_t uintScore[2] = {0, 0};
uint8_t uintState[6] = {255, 255, 255, 255, 255, 255};
uint8_t uintMaxPunkte = 10;
char blData = ' ';
bool playMusic = true;

// Prototypen
void setup();
void loop();
void serialEvent();
void changeScore();
void win(uint8_t team);
void scr_reset();
void scoreTeam(uint8_t team, char plusMinus);
void show(uint8_t uintOLED, String text);
void led(uint8_t uintLED);
void setupOLED();

// Debug-mode (remove "//" to start the debug-mode)
//#define DEBUG_SETUP
//#define DEBUG_BL
//#define DEBUG_SCORE
//#define DEBUG_WIN
//#define DEBUG_SCORE_TEAM
//#define DEBUG_SHOW
//#define DEBGU_OLED

// Display
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
uint8_t X_POS = 0;
#define Y_POS 10
#define SIZE 2

// Teams
#define TEAM1 0
#define TEAM2 1

// Sound files
#define MUSIC  1
#define POMMES 2
#define SIEG   3
#define TOR    4
#define PFIFF  5

// Lautstrke
#define V_MIN 0
#define V_MAX 30

// Taster, Sensoren
#define UP1       3
#define UP2       4
#define DOWN1     5
#define DOWN2     6
#define IR1       7
#define IR2       8

// Torbeleuchtung
#define TOR1 11
#define TOR2 12

SoftwareSerial mySoftwareSerial(A2, A1);
DFRobotDFPlayerMini myDFPlayer;

void setup()
{
  Serial.begin(9600);
  #ifdef DEBUG_SETUP
    Serial.println("Starting setup...");
  #endif
  // LED I/O
  pinMode(TOR1, OUTPUT);
  pinMode(TOR2, OUTPUT);

  setupOLED();
  
  // I/O
  pinMode(UP1, INPUT);
  pinMode(UP2, INPUT);
  pinMode(DOWN1, INPUT);
  pinMode(DOWN2, INPUT);
  pinMode(IR1, INPUT);
  pinMode(IR2, INPUT);

  // UART
  mySoftwareSerial.begin(9600);
  myDFPlayer.begin(mySoftwareSerial);

  // DFPlayer
  myDFPlayer.volume(volume);
  #ifdef DEBUG_SETUP  
    Serial.print(F("Volume: "));        
    Serial.println(volume);
  #endif
  myDFPlayer.play(PFIFF);
  delay(1500);
  if (playMusic)
    myDFPlayer.loop(MUSIC);
  
  show(0, "0");
  show(1, "0");  
  led(TOR1);
  led(TOR2);
  #ifdef DEBUG_SETUP
    Serial.println(F("Setup finished"));
  #endif 
}

void loop()
{
  // Polling 
  changeScore();
  delay(125);
}

void serialEvent()
{
  // Empfangen von Seriellen Daten per Bluetooth (ausgelst per Interrupt)
  blData = Serial.read();
  #ifdef DEBUG_BL
    Serial.print(F("Received: <"));
    Serial.print(blData);
    Serial.println(F(">"));      
  #endif
  switch (blData)
  {  
    // r+
    case 'a':
      scoreTeam(TEAM2, '+');
      break;
    // r-
    case 'b':
      scoreTeam(TEAM2, '-');
      break;
    // l+
    case 'c':
      scoreTeam(TEAM1, '+');
      break;
    // l-
    case 'd':
      scoreTeam(TEAM1, '-');
      break; 
    // reset         
    case 'n':
      scr_reset();
      break;    
      
    // Lautstrke erhhen
    case '+':
      if (volume < V_MAX)
      {
        volume++;
        myDFPlayer.volume(volume);
        #ifdef DEBUG_BL  
          Serial.print(F("Volume: "));        
          Serial.println(volume);
        #endif
      }
      break;
    // Lautstrke verringern
    case '-':
      if (volume > V_MIN)
      {
        volume--;
        myDFPlayer.volume(volume);
        #ifdef DEBUG_BL    
          Serial.print(F("Volume: "));      
          Serial.println(volume);
        #endif
      }
      break; 
    // Turn on / off music
    case 'm':
      if (playMusic)
        playMusic = false;
      else
        playMusic = true;        

        myDFPlayer.stop();
      break;   
             
    default:
      #ifdef DEBUG_BL        
        Serial.println(F("nada"));
      #endif
      break;
  }
}

void changeScore()
{
  // Status der Pins 6 - 11 einlesen
  uint8_t pin = UP1;
  for (uint8_t i = 0; i < 6; i++)
  {
    uintState[i] = digitalRead(pin);
    #ifdef DEBUG_SCORE
      Serial.print(String(uintState[i]) + " ");
    #endif
    pin++;
  }
  #ifdef DEBUG_SCORE
    Serial.println("");
  #endif

  // UP1
  if (uintState[0] == 1)
  {
    #ifdef DEBUG_SCORE
      Serial.println(F("UP1"));
    #endif
    scoreTeam(TEAM1, '+');
  }

  // IR1
  else if (uintState[4] == 0) // inverted
  //else if (uintState[4] == 1)
  {
    #ifdef DEBUG_SCORE
      Serial.println(F("IR1"));
    #endif
    scoreTeam(TEAM1, '+');
    myDFPlayer.play(TOR);
    led(TOR1);
    delay(500);
    myDFPlayer.play(PFIFF);
    delay(1500);
    if (playMusic)
      myDFPlayer.loop(MUSIC);
  }

  // DOWN1
  else if (uintState[2] == 1)
  {
    #ifdef DEBUG_SCORE
      Serial.println(F("DOWN1"));
    #endif
    scoreTeam(TEAM1, '-');
  }

  // UP2
  else if (uintState[1] == 1 )
  {
    #ifdef DEBUG_SCORE
      Serial.println(F("UP2"));
    #endif
    scoreTeam(TEAM2, '+');
  }

  // IR2
  else if (uintState[5] == 0) // inverted
  //else if (uintState[5] == 1)
  {
    #ifdef DEBUG_SCORE
      Serial.println(F("IR2"));
    #endif
    scoreTeam(TEAM2, '+');
    myDFPlayer.play(TOR);
    led(TOR2);
    delay(500);   
    myDFPlayer.play(PFIFF);
    delay(1500);    
    if (playMusic)
      myDFPlayer.loop(MUSIC);    
  }

  // DOWN2
  else if (uintState[3] == 1)
  {
    #ifdef DEBUG_SCORE
      Serial.println(F("DOWN2"));
    #endif
    scoreTeam(TEAM2, '-');
  }  
}

void win(uint8_t team)
{
  #ifdef DEBUG_WIN
    Serial.println("WIN: " + String(team));
  #endif

  // 10:0 oder 0:10
  if (((uintScore[0] == 10) && (uintScore[1] == 0)) || ((uintScore[1] == 10) && (uintScore[0] == 0)))
  {
    myDFPlayer.volume(25);
    myDFPlayer.play(POMMES);   
    myDFPlayer.volume(volume);
  }
  else 
    myDFPlayer.play(SIEG);

  if (team == TEAM1)
  {
    show(TEAM1, "WIN!");
    show(TEAM2, "DEFEAT!");
  }
  else if (team == TEAM2)
  {
    show(TEAM1, "DEFEAT!");
    show(TEAM2, "WIN!");
  }  
  scr_reset();
}

void scr_reset()
{
  uintScore[TEAM1] = 0;
  uintScore[TEAM2] = 0;
  delay(3000);
  show(TEAM1, "0");
  show(TEAM2, "0");
  myDFPlayer.play(PFIFF);
  delay(1500);
  if (playMusic)
    myDFPlayer.loop(MUSIC);
}

void scoreTeam(uint8_t team, char plusMinus)
{
  #ifdef DEBUG_SCORE_TEAM
    Serial.println(F("scoreTeam"));
    Serial.print(F("uintScore[TEAM1]: "));
    Serial.println(uintScore[TEAM1]);
  
    Serial.print(F("uintScore[TEAM2]: "));
    Serial.println(uintScore[TEAM2]);
  
    Serial.print(F("Team: "));
    Serial.println(team);
  
    Serial.print(F("plusMinus: "));
    Serial.println(plusMinus);
  #endif
  
  if (plusMinus == '+')
  {
    uintScore[team]++;
    show(team, String(uintScore[team]));

    if ((uintScore[0] >= 10) || (uintScore[1] >= 10))   
      win(team);    
  }
  else if (plusMinus == '-')  
  {
    if (uintScore[team] > 0)
    {
      uintScore[team]--;
      show(team, String(uintScore[team]));
    }
  }
}

void show(uint8_t uintOLED = 255, String text = "-")
{
  // Punktestand an App senden
  Serial.print(uintScore[0]);
  Serial.print(";");
  Serial.println((uintScore[1]));
  
  #ifdef DEBUG_SHOW
    Serial.print(F("uintOLED: "));
    Serial.println(uintOLED);
    Serial.print(F("text: "));
    Serial.println(text);
  #endif

  // Zentrierung des Textes
  // Firmenname
  if (text.equals("WNJM GmbH"))
    X_POS = 12;
  else if (text.equals("WIN!"))
    X_POS = 37;
  else if (text.equals("DEFEAT!"))
    X_POS = 22;
  // 10 Punkte (zweistellig)
  else if (text.equals("10")) 
    X_POS = 50;
  // 0 bis 9 Punkte
  else  
    X_POS = 55;  
    
  if (uintOLED == TEAM1)
  {   
    OLED_TEAM1.clearDisplay();
    OLED_TEAM1.setCursor(X_POS, Y_POS);
    OLED_TEAM1.print(text);
    OLED_TEAM1.display();
  }
  else if (uintOLED == TEAM2)
  {    
    OLED_TEAM2.clearDisplay();
    OLED_TEAM2.setCursor(X_POS, Y_POS);
    OLED_TEAM2.print(text);
    OLED_TEAM2.display();
  }
}

void led(uint8_t uintLED)
{
  for (int i = 0; i < 10; i++)
  {
    digitalWrite(uintLED, HIGH);
    delay(50);
    digitalWrite(uintLED, LOW);
    delay(50);
  }
}

void setupOLED()
{
  // I2C  
  pinMode(SCL, OUTPUT);
  pinMode(SDA, OUTPUT);  

  if (!OLED_TEAM1.begin(SSD1306_SWITCHCAPVCC, 0x3C)) 
  {
    #ifdef DEBGU_OLED
      Serial.println(F("OLED_TEAM1 allocation failed - 0x3C"));    
    #endif
    while(1)
    {
      digitalWrite(TOR1, HIGH);
      delay(1000);
      digitalWrite(TOR1, LOW);
      delay(1000);
    }
  }  
  
  OLED_TEAM1.clearDisplay();
  OLED_TEAM1.setCursor(X_POS, Y_POS);
  OLED_TEAM1.setTextSize(SIZE);
  OLED_TEAM1.setTextColor(WHITE);
  show(TEAM1, "WNJM GmbH");  

  if (!OLED_TEAM2.begin(SSD1306_SWITCHCAPVCC, 0x3D)) 
  {
    #ifdef DEBGU_OLED
      Serial.println(F("OLED_TEAM2 allocation failed - 0x3D"));
    #endif
    while(1)
    {
      digitalWrite(TOR2, HIGH);
      delay(1000);
      digitalWrite(TOR2, LOW);
      delay(1000);
    }
  }
  
  OLED_TEAM2.clearDisplay(); 
  OLED_TEAM2.setCursor(X_POS, Y_POS);
  OLED_TEAM2.setTextSize(SIZE);
  OLED_TEAM2.setTextColor(WHITE);
  show(TEAM2, "WNJM GmbH");    
  #ifdef DEBGU_OLED
      Serial.println(F("OLED-setup finished"));    
  #endif
}

Credits

NilsSchuenemann
0 projects • 1 follower
Contact
HeinzKetschup
1 project • 7 followers
Contact
Esdx
1 project • 1 follower
Contact

Comments

Please log in or sign up to comment.