Introduction: Pinball Project With a Arduino Mega

Who is the FunTechTeam ?

The team is composed of four students from Helha, a college located in Mons in Belgium. We will graduate as electromechanical industrial engineer specialized in automatics this year.

What is the point of the project?

The goal of this project is to create a pinball with a limited budget and this including an Arduino. The budget has to around 100 euros. The model is cheap and easily replicable with basic equipment.

Step 1: Hardware & Manufacturing

1) Tools

To manufacture our FunTechTeam’s pinball, the tools needed are :

  • - a jigsaw,
  • - a drill,
  • - a screw gun,
  • - a hammer,
  • - and a file.

2) Materials

The materials needed for the wood are :

  • - a wooden plank 2,5 x 10 x 300,
  • - a wooden plank 0,6 x 2 x 300,
  • - a wooden board 0,9 x 200 x 200,
  • - a bag of wooden bearings,
  • - a chopstick,
  • - a tube of wood glue,
  • - some nails and screws.

3) The frame

  • - Cut 2 wooden planks 2,5 x 10 x 80
  • - Cut 2 wooden planks 2,5 x 10 x 50
  • - Assemble them to make a frame

4) The support of the board

  • - Cut 2 wooden planks 0,6 x 2 x 70
  • - Cut 2 wooden planks 0,6 x 2 x 40
  • - Nail them in the frame.

5) The board

  • - Cut a board 0,9 x 50 x 78
  • - File the edges

6) The flipper bats

  • - Cut two pieces of wood 2,5 x 2 x 20
  • - Drill a hole of 2,5 x 2, height of your board and 10 centimetres to the edge of the frame
  • - Same operation the other side
  • - Cut two pieces of wood 2,5 x 2 x 17,5 and cut an angle of 30° at the end
  • - Nail them on board 15 cm after the flipper bats
  • - Cut the flipper bats in the same wood as the board following the dimensions in the picture.
  • - Nail the flipper bats on the board
  • - Cut four pieces of wood 3 x 2 x 2
  • - Nail two of them on the bottom corners of the board and two at the beginning of the flipper bats following the edge of the board.
  • - Hammer four nails following the picture, let the nailheads outside of the wood

7) The ball shooter

  • - Cut the support of the ball shooter following the dimensions of the picture
  • - Nail the support of the board
  • - Cut the ball shooter base following the dimensions of the picture
  • - Assemble the different parts with the wood glue
  • - File the chopstick with a lime to create a nick for the rubber ban

8) The ball shooter lane

  • - Cut the ball shooter lane’s parts following the dimensions of the picture
  • - Lime the lane to allow the inclination of the lane
  • - Assemble the different parts with the wood glue
  • - Glue the ball shooter lane on the board

9) The slingshots

  • - Drill the board where you want to put a bearing
  • - Drill the board following the drilling plan
  • - Place some rubber bands around the bearings to form the slingshots

Step 2: Electronic Components & Wiring

1) Tools

To install the electronic components on the FunTechTeam’s pinball, the tools needed are :

  • - a drill,
  • - a screw gun,
  • - a soldering iron.

2) Electronic components

To finish the pinball, those components are needed :

  • - a breadboard
  • - 11 LEDs RGB 3 colours
  • - 7 sensors ( ESE24MH1 DETECTOR SWITCH on Farnell)
  • - a Arduino Mega
  • - 33 resistors 200Ω
  • - some wires for Arduino board
  • - solder.

3) Wiring

Leds

The rods 1,3 and 4 pass through a resistor before the digital I/O of the board. Rod 2, the longest, is connected to the ground.

Sensors

The sensors are connected to pull up digital entries on the board. So the rod in the middle of the sensor go on the ground. The external rods are connected to the digital entries.

4) Installation

Leds

Drill the board with 5 mm drill bit where the leds will be placed. The following plan inform you about the positions of the holes.

Sensors

Drill the board with 7 mm drill bit where the sensors will be placed. The following plan inform you about the positions of the holes.

Step 3: The Software & Programming

Now the code will be explain, so you will be able to use it with your component.

As we use a screen, we need to import some libraries. In our case, we need a libraries called "LiquidCrystal_I2C.h" which can be downloaded just here : https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c

It's important to have the good libraries, so the Arduino will be able to communicate with your screen. If you don't have the same one, please ask to the manufacturer of your device to get the good one.

Here is how you import you libraries :

#include

#include

//Import librairies to use the screen

Then you declare the screen, with its address and the size of it screen.

LiquidCrystal_I2C lcd(0x3F,20,4);

After that, we declare all the variable and constant that will be used. The difference between the two of them is that the constant will not be able to change when the code is running. So, we will use them to declare all the PINs used and some variable we know that we will not change.

We use array to declare LED for two reasons :

  • · It's faster and clear when you declare them
  • · And it will be able to switch easily from one to the other, as you will see forward in the text.

The array of LEDState hold the state of all the LED that we have, and we set them to LOW, so they are off.

// Constante

const int LED[33] = {46,47,48,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,50,49,22,23,24,25,26,27,28,29,30,31,32}; // Declare an array so it's faster to declare on easier to use

const int sens1 = 33, sens2 = 34, sens3 = 35, sens6 = 38, sens4 = 36, sens5 = 37, sens7UP = 44, sens7DOWN = 45,

sens8UP = 43, sens8DOWN = 42, sens9UP = 41, sens9DOWN = 40; // Declare the different sensor

unsigned long previousMillis[11]={0,0,0,0,0,0,0,0,0,0,0};

unsigned long currentMillis ;

const long INTERVAL[3] = {40,400,40};

const long DELAYTIME = 30;

unsigned long Score;

int Coeff1 = 1;

int Coeff2 = 1;

int Coeff3 = 1;

int Coeff4 = 1;

int Coeff5 = 1;

int LEDState[33] = {LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW,LOW}; // Start with all the LED off

In the void setup, you will tell to the Arduino how you will use its PINs. In our case, with LEDs and sensors.

As you can see, it's very fast to declare all the LED when you use an array.

We also set the score of the game to 0.

void setup() {

for (int i=0; i<=32; i++) {

pinMode(LED[i], OUTPUT);

}

pinMode(sens1, INPUT_PULLUP);

pinMode(sens2, INPUT_PULLUP);

pinMode(sens3, INPUT_PULLUP);

pinMode(sens4, INPUT_PULLUP);

pinMode(sens5, INPUT_PULLUP);

pinMode(sens6, INPUT_PULLUP);

pinMode(sens7UP, INPUT_PULLUP);

pinMode(sens7DOWN, INPUT_PULLUP);

pinMode(sens8UP, INPUT_PULLUP);

pinMode(sens8DOWN, INPUT_PULLUP);

pinMode(sens9UP, INPUT_PULLUP);

pinMode(sens9DOWN, INPUT_PULLUP);

Score = 0;

}

In the void loop, we only have the call on a function, Detected, which will say when a sensor is hit.

void loop() {

currentMillis = millis(); //Take the current time in millisecond

Detected(); // Call the function Detected

}

The function "Detected" will call different functions depending of which sensors is activated. So we start with the declaration of variables containing the information of the sensors.

boolean Pts1 = digitalRead(sens4);

boolean Pts2 = digitalRead(sens5);

boolean Pts3 = digitalRead(sens7UP);

boolean Pts4 = digitalRead(sens8UP);

boolean Pts5 = digitalRead(sens9UP);

boolean Pts6 = digitalRead(sens7DOWN);

boolean Pts7 = digitalRead(sens8DOWN);

boolean Pts8 = digitalRead(sens9DOWN);

boolean Out = digitalRead(sens2); // Ball out

boolean In = digitalRead(sens6); // Ball in

If a sensor is hit, in our case here the sensor 4, the program will enter in a loop "While". With our component, we know the sensor is hit when its state is LOW.

The loop while is used to be sure that the play of lights will be done during a chosen time. It's important because without that, the LED will be on or off one time, because the program will pass in this part of the code only one time when the sensor is hit.

When it's over, the function "Score" will be called so the program will increase the score, depending of the sensor.

if (Pts1 == LOW){ // When the sensor is activated, his state is LOW

while (currentMillis - previousMillis[1] < INTERVAL[1]) { // During the Interval, play the LED

currentMillis = millis();

LEDsPlay2(); // Call the

}

Score2();

}

previousMillis[1] = currentMillis;

It's the same kind of code for all the sensor, except for "Out" which we inform use that the ball is out, so we need to reset the score and all the coefficient.

currentMillis = millis();

OUTAnim();

}

OUTDisplay();

Score = 0; // When the ball is out, the score and the different coefficients have to be resetted

Coeff1=1;

Coeff2=1;

Coeff3=1;

Coeff4=1;

Coeff5=1;

}

previousMillis[10] = currentMillis;

}

Here is the function Score. When it is called, the score will increase depending of the sensor hit but also how many times in a row it was hit. We use that so we reward the people with a great accuracy and so it is funnier.

After that the function "ScoreDisplay" is called, so the score is displayed on the screen.

But you can ask us, why don't we just called every time this function? It is because the screen use a lot of memory of your Arduino. So if you do that, he will be to slow and a lot of things will be missed by him. And anyway, when something is display on the screen, it will change only if the program ask it to do that.

And we finish this function with a little delay, so we are sure that the program doesn't score many times in one hit.

void Score1(){

Score = Score + 1 * Coeff1; // We use this kind of Coeff so if you hit a sensor several times in a row, you will get more points (So we reward the accuracy of the player

Coeff1 = Coeff1 +1;

Coeff2 = 1;

Coeff3 = 1;

Coeff4 = 1;

Coeff5 = 1;

ScoreDisplay();

delay(DELAYTIME); // We need a delay or the program may score many times.

}

Now, I will explain how the play of lights is made. In this case, that will blink a led, the color depending with the coefficient. So the player knows if he hits the same one several time in a row. You can see we use a function "if" with different times. It is used to blink in the good timing.

But why not just use a delay?

Because when you use a delay, the program will do a break during the time you asked. So during this time, he will not do anything else, including the detection of the balls.

So we will just take the current time and the time when he enters in this part of the code. When the subtraction is higher than an interval, than you enter again in this part of the code. So you do the same as the "delay()" but you will not stop your program.

void LEDsPlay1(){ // We will blink a led

int LEDColour = 9;

if (currentMillis - previousMillis[0] >= INTERVAL[0]) {

previousMillis[0] = currentMillis;

if (Coeff1 == 1) { // We have different output. depending of the coeff, the led will have a specific colour.

LEDColour = 9; //Red

digitalWrite(LED[(LEDColour+1)], LOW);

digitalWrite(LED[(LEDColour+2)], LOW);

} else if (Coeff1 == 2){

LEDColour = 10; //Green

digitalWrite(LED[(LEDColour-1)], LOW);

digitalWrite(LED[(LEDColour+1)], LOW);

} else {

LEDColour = 11; //Blue

digitalWrite(LED[(LEDColour-1)], LOW);

digitalWrite(LED[(LEDColour-2)], LOW);

}

if (LEDState[LEDColour] == LOW) {

LEDState[LEDColour]= HIGH;

} else {

LEDState[LEDColour] = LOW;

}

}

digitalWrite(LED[LEDColour], LEDState[LEDColour]);

}

When the balls is in or out, the kind of play of lights change. Different LEDs will blink but in a chosen timing.

The first loop for is used to do the animation three times. The second one will be used to blink three LEDs with three colors. With this case, you can see how it's easier when your LEDs are declared in an array.

This time we use a delay, so you can see the different possibilities. But it's not an issue, because when the balls is out for example, it's ok that the balls is not detectable during one second.

" void INAnim(){ // A different kind of LED animation when the ball enters in the board

int LEDColour = 0;

for (int i=0; i<3; i++) {// We will do the animation 3 times

for (LEDColour=0; LEDColour<=8; LEDColour++) { // different LED and colour is used

if (LEDState[LEDColour] == LOW) {

LEDState[LEDColour]= HIGH;

} else {

LEDState[LEDColour] = LOW;

}

digitalWrite(LED[LEDColour], LEDState[LEDColour]);

delay(INTERVAL[2]);

}

}

for (int j=0; j<9; j++) {

LEDState[j] = HIGH;

digitalWrite(LED[j], LEDState[j]); // When the animation is over, put the three LEDs with the three colours.

}

}"

The final part is the use of the screen. In the beginning, we have declared the screen under "lcd". So the different part of this function used there will start with "lcd." so the Arduino knows what he will use, and that can be fine if you use more than one screen.

The setCursor is used to tell to the Arduino where it will display on the screen. Print is simply used to write something on the screen. Here is an example that we used:

void ScoreDisplay() // Use to display the score

{

lcd.init();

lcd.backlight();

lcd.setCursor(3,0);

lcd.print("Score :");

lcd.setCursor(2,1);

lcd.print(Score);

lcd.setCursor(0,2);

lcd.print("The FunTechTeam");

lcd.setCursor(2,3);

lcd.print("Pinball");

}

Thank you to read us. If you have some questions, feel free to ask us !

Have fun with the FunTechTeam.