Ztronics
Published © CC BY

Arduino Pinball Machine Using a DVD Display (TM1628)

A mini Arduino pinball machine built using a recycled DVD display (TM1628), servo flippers, LEDs and sound effects with real-time scoring.

BeginnerFull instructions provided3 hours19
Arduino Pinball Machine Using a DVD Display (TM1628)

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
TM1628
×1
SG90 Micro-servo motor
SG90 Micro-servo motor
×2
LED (generic)
LED (generic)
×6
Resistor 220 ohm
Resistor 220 ohm
×6
Buzzer
Buzzer
×1
Jumper wires (generic)
Jumper wires (generic)
×1
Breadboard (generic)
Breadboard (generic)
×1
button
×2

Software apps and online services

Arduino IDE
Arduino IDE

Story

Read more

Schematics

easy

Complete wiring diagram of the Arduino pin, pinball machine system including TM1628 display, servos, LEDs, buzzer and buttons.

Code

Arduino Pimball Game

C/C++
#include <TM1628.h>
#include <Servo.h>

// ---------------- DISPLAY ----------------
#define DATA_PIN 7
#define CLOCK_PIN 6
#define STROBE_PIN 8

TM1628 display(DATA_PIN, CLOCK_PIN, STROBE_PIN);

// ---------------- LEDS ----------------
int leds[] = {A1, A2, A3, A4, A5, 12};

// ---------------- BUZZER ----------------
int buzzer = 11;

// ---------------- BUTTONS ----------------
int btnLeft = 2;
int btnRight = 3;

// ---------------- SERVOS ----------------
Servo servoLeft;
Servo servoRight;

// ---------------- GAME LOGIC ----------------
int currentLed = -1;
unsigned long lastChange = 0;
int speed = 400;

// ---------------- SCORE ----------------
int score = 0;
unsigned long lastScoreTime = 0;
int scoreStep = 1;

// ---------------- DISCO / VISUAL EFFECTS ----------------
byte discoEnd[] = {1, 3, 11, 13, 7, 9};
int discoFrame = 0;
unsigned long discoTime = 0;
int discoSpeed = 90;

// ---------------- NUMBERS (7-Segment Mapping) ----------------
const byte numbers[] = {
  0b00111111, 0b00000110, 0b01011011, 0b01001111,
  0b01100110, 0b01101101, 0b01111101, 0b00000111,
  0b01111111, 0b01101111
};

void setup() {
  display.begin(true, 7);
  clearAll();

  for(int i=0; i<6; i++) pinMode(leds[i], OUTPUT);

  pinMode(buzzer, OUTPUT);
  pinMode(btnLeft, INPUT_PULLUP);
  pinMode(btnRight, INPUT_PULLUP);

  servoLeft.attach(9);
  servoRight.attach(10);

  servoLeft.write(20);
  servoRight.write(160);

  randomSeed(analogRead(A0));
}

void loop() {
  // Random LED logic
  if(millis() - lastChange > (unsigned long)speed){
    lastChange = millis();

    for(int i=0; i<6; i++) digitalWrite(leds[i], LOW);

    currentLed = random(0, 6);
    digitalWrite(leds[currentLed], HIGH);

    speed = max(120, speed - 1);
  }

  // Input Handling
  if(digitalRead(btnLeft) == LOW){
    flipperAction(true);
  }

  if(digitalRead(btnRight) == LOW){
    flipperAction(false);
  }

  runDisco();
}

// ---------------- FLIPPER ----------------
void flipperAction(bool left){
  if(left){
    servoLeft.write(70);
    delay(60);
    servoLeft.write(20);
  } else {
    servoRight.write(110);
    delay(60);
    servoRight.write(160);
  }

  hitEffect();
  addScore();
}

// ---------------- HIT EFFECT ----------------
void hitEffect(){
  digitalWrite(leds[currentLed], LOW);

  for(int f = 1000; f < 2000; f += 150){
    tone(buzzer, f, 10);
    delay(5);
  }

  for(int i=0; i<6; i++) digitalWrite(leds[i], HIGH);
  delay(40);
  for(int i=0; i<6; i++) digitalWrite(leds[i], LOW);
}

// ---------------- SCORE ----------------
void addScore(){
  if(millis() - lastScoreTime < 200) return;
  lastScoreTime = millis();

  score += scoreStep;
  if(score > 9999) score = 0;

  // Progression: Increase points per hit every 10 points
  if(score % 10 == 0 && scoreStep < 5){
    scoreStep++;
  }

  discoSpeed = max(50, 90 - score);

  discoWaveEffect();
  numberWaveEffect(score);
  comboEffect();
}

// ---------------- DISCO ANIMATION ----------------
void runDisco(){
  if(millis() - discoTime >= (unsigned long)discoSpeed){
    discoTime = millis();

    for(int i=0; i<6; i++){
      setIcon(discoEnd[i], 0);
    }

    setIcon(discoEnd[discoFrame], 2);

    discoFrame++;
    if(discoFrame >= 6) discoFrame = 0;
  }
}

// ---------------- DISCO WAVE EFFECT ----------------
void discoWaveEffect(){
  for(int i=0; i<6; i++){
    setIcon(discoEnd[i], 2);
    tone(buzzer, 1200 + i*120, 10);
    delay(12);
  }

  for(int i=5; i>=0; i--){
    setIcon(discoEnd[i], 0);
    delay(10);
  }
}

// ---------------- NUMBER WAVE EFFECT ----------------
void numberWaveEffect(int value){
  int d1 = value % 10;
  int d2 = (value / 10) % 10;
  int d3 = (value / 100) % 10;
  int d4 = (value / 1000) % 10;

  byte digits[4] = {d1, d2, d3, d4};

  for(int seg=0; seg<7; seg++){
    byte val = 0;

    if(bitRead(numbers[digits[0]], seg)) val += 1;
    if(bitRead(numbers[digits[1]], seg)) val += 2;
    if(bitRead(numbers[digits[2]], seg)) val += 128;
    if(bitRead(numbers[digits[3]], seg)) val += 4;

    display.setSegments(val, seg);
    delay(18);
  }
}

// ---------------- COMBO EFFECTS ----------------
void comboEffect(){
  if(score % 50 == 0){
    // 💥 Explosion effect
    for(int i=0; i<3; i++){
      display.setSegments(255, i);
    }
    tone(buzzer, 2500, 100);
    delay(120);
    clearAll();
  }
  else if(score % 20 == 0){
    // ⚡ Strong flash
    display.setSegments(255, 0);
    display.setSegments(255, 1);
    tone(buzzer, 2000, 80);
    delay(80);
  }
  else if(score % 10 == 0){
    // ✨ Light flash
    display.setSegments(255, 0);
    tone(buzzer, 1500, 50);
    delay(50);
  }
}

// ---------------- LOW LEVEL COMMUNICATION ----------------
void sendRawCommand(byte cmd) {
  digitalWrite(STROBE_PIN, LOW);
  shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, cmd);
  digitalWrite(STROBE_PIN, HIGH);
}

void setIcon(byte address, byte value) {
  sendRawCommand(0x44);
  digitalWrite(STROBE_PIN, LOW);
  shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, 0xC0 + address);
  shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, value);
  digitalWrite(STROBE_PIN, HIGH);
}

// ---------------- CLEAR DISPLAY ----------------
void clearAll() {
  for (int i = 0; i <= 20; i++) {
    display.setSegments(0x00, i);
  }

  sendRawCommand(0x40);
  digitalWrite(STROBE_PIN, LOW);
  shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, 0xC0);
  for (int i = 0; i < 16; i++) shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, 0x00);
  digitalWrite(STROBE_PIN, HIGH);
}

Credits

Ztronics
1 project • 0 followers

Comments