Final Pinball Machine
#include <PinballOutputHandler.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // Changed these parameters to match our LCD - Mr. Ayers
int buttonPinT1 = 6;
int buttonPinT2 = 5;
// This object holds all of your background handlers. To execute the handlers, call outputHandler.handleAll()
// in loop().
OutputHandler outputHandler;
// Initialize all the neopixel strips and save them in an array so you can
// change values like brightness later.
#define NUM_STRIPS 6
Adafruit_NeoPixel pixels[NUM_STRIPS] = {
// Initialize the strips with the number of LEDS, pin number, and init parameters.
// Replace the pin numbers with the pins you are using for your neopixel strips
Adafruit_NeoPixel(10, 7, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(10, 8, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(10, 99, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(10, 11, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(10, 99, NEO_GRB + NEO_KHZ800),
Adafruit_NeoPixel(10, 99, NEO_GRB + NEO_KHZ800)
};
// An array to hold output handlers that correspond to the strips
NeoPixelHandler *handlers[NUM_STRIPS]; // to hold handlers that can control 6 strips
// constants won't change. They're used here to set pin numbers:
const int buttonPin1 = 2; // the number of the pushbutton pin
int solenoid1 = A2; // Moved from A5 to A2 in order to avoid conflicts with the LCD
const int buttonPin2 = 13; // the number of the pushbutton pin
int solenoid2 = A3;
const int buttonPin3 = 4; // the number of the pushbutton pin
int solenoid3 = A0;
const int flipperbutton1 = 3; // the number of the pushbutton pin
int flipper1 = A1;
const int flipperbutton2 = 12; // the number of the pushbutton pin
int flipper2 = 9;
// variables will change:
int buttonState1 = 0;
int buttonState2 = 0;
int buttonState3 = 0;
int flipperbutton1state = 0;
int flipperbutton2state = 0;
long score = 0; // A regular int counts to 16,384. A long integer counts to over 2 billion.
void setup() {
Serial.begin(9600);
lcd.init(); // This line was missing from Alexander's first program -Mr. Ayers
lcd.init(); // I don't know why the example calls this twice - Mr. Ayers
lcd.backlight();
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Abi and Dakota");
pinMode(buttonPinT1, INPUT_PULLUP);
pinMode(buttonPinT2, INPUT_PULLUP);
// initialize the LED pin as an output:
pinMode(solenoid1, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin1, INPUT_PULLUP);
pinMode(solenoid2, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin2, INPUT_PULLUP);
pinMode(solenoid3, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin3, INPUT_PULLUP);
pinMode(flipper1, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(flipperbutton1, INPUT_PULLUP);
pinMode(flipper2, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(flipperbutton2, INPUT_PULLUP);
// Initialize the output handler with the neopixel strip objects. Save the handler objects for later.
for (int i = 0; i < NUM_STRIPS; i++) {
handlers[i] = outputHandler.add(pixels[i]); // Note, this library calls begin() on the Adafruit_NeoPixel library.
pixels[i].setBrightness(25); // Set brightness to 10% to save power.
handlers[i]->rainbow();
}
}
void refreshLCD() {
lcd.setCursor(0, 0);
lcd.print("score: ");
lcd.print(score);
//lcd.setCursor(0, 1);
//lcd.print("balls left: ");
//lcd.print(balls);
lcd.setCursor(0, 2);
}
void loop() {
// read the state of the pushbutton value:
buttonState1 = digitalRead(buttonPin1);
buttonState2 = digitalRead(buttonPin2);
buttonState3 = digitalRead(buttonPin3);
flipperbutton1state = digitalRead(flipperbutton1);
flipperbutton2state = digitalRead(flipperbutton2);
int buttonValueT1 = digitalRead(buttonPinT1);
int buttonValueT2 = digitalRead(buttonPinT2);
if (buttonValueT1 == LOW) {
Serial.println("T1 hit");
score = score + 100;
refreshLCD();
}
if (buttonValueT2 == LOW) {
Serial.println("T2 hit");
score = score + 100;
refreshLCD();
}
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState1 == LOW) {
// close selenoid
Serial.println("button1hit");
handlers[3]->rainbow_cycle(1000, 5);
score += 10;
refreshLCD();
digitalWrite(solenoid1, HIGH);
} else {
// open selenoid
digitalWrite(solenoid1, LOW);
}
if (buttonState2 == LOW) {
Serial.println("button2hit");
handlers[3]->rainbow_cycle(1000, 5);
score += 10;
refreshLCD();
// close selenoid
digitalWrite(solenoid2, HIGH);
} else {
// open selenoid
digitalWrite(solenoid2, LOW);
}
if (buttonState3 == LOW) {
Serial.println("button3hit");
handlers[3]->rainbow_cycle(1000, 5);
score += 10;
refreshLCD();
// close selenoid
digitalWrite(solenoid3, HIGH);
} else {
// open selenoid
digitalWrite(solenoid3, LOW);
}
if (flipperbutton1state == LOW) {
Serial.println("flipperbutton1 LOW");
handlers[0]->blink(NeoPixelColor::YELLOW, 500, 10);
// close selenoid
digitalWrite(flipper1, HIGH);
} else {
// open selenoid
digitalWrite(flipper1, LOW);
}
// This code is always returning LOW for some reason
if (flipperbutton2state == LOW) {
Serial.println("flipperbutton2 LOW");
handlers[1]->blink(NeoPixelColor::GREEN, 500, 10);
// close selenoid
digitalWrite(flipper2, HIGH);
} else {
// open selenoid
digitalWrite(flipper2, LOW);
}
// Call the output Handler every time you go through the main loop.
outputHandler.handleAll();
}
Bumpers
In our machine we have 3 bumpers. A bumper is technically a solenoid that has a spring resting against a rod which will have to be at the appropriate height for it to hit the ball. A very important part of the bumpers is the bracket which will have to sit on the solenoid underneath the playing field, this will pull against the bottom of the play field when the spring is going off. The bumper is triggered when the spoon hits the paddle with the stripped wire underneath copper tape. The stripped wire in the paddle is connected to a button pin which will trigger the code uploaded in the Arduino to pull the selenoid down which will shoot the ball out in the playing field.
Targets
Once a ball hits the target it triggers a switch to make the points increase. There's two wires connecting the switch to the arduino and breadboard.
Flippers
Pinball flippers work by using an electromagnet to pull a rod connected to a lever, in the solenoid. The solenoid is activated when a player presses the flipper button, causing the flipper to flip up, and when the button is released, it resumes its resting position. When the coil is powered on, it becomes an electromagnet pulling the rod into the core. When the flipper button is released, the switch cuts off the electricity to the coil, letting go of the rod. A small spring on the flipper base then pulls the flipper back into its resting position.
Launcher
The launcher in our machine is made out of thin plywood with a spring attached to it. When the launcher is pulled out towards the player the spring will coil and tighten up until the player releases the launcher which will launch the ball into the machine.
Neopixels
Each of the neopixels is connected to a pin in the arduino thats been uploaded with code. In the code it tells the neopixels to light up or show a rainbow pattern when a target is hit or if a bumper slams down on the ball.
Scoreboard
The scoreboard shows the player's score and how many balls they have left. Every time the ball hits a target or bumper the score is increased by 100 points and every time the rainbow pattern is activated the score increases 10 points. From our prototype to our final machine we switched the LCD to a 4 pin screen which made wiring and remembering all the pins so much easier.
Graphic
Reflection
This project compared to other projects I've done was a lot longer and more complicated. The process of testing many iterations on multiple parts of the machine was very strenuous but still very fun. Completing this project was a very satisfying feeling, I felt like a weight lifted off my shoulders but I was still super proud of myself. What i'm most proud of in my project is our graphic because I think it's cool and cute and also how I was able to produce 3 working bumpers.