Intro: How to Build an Arduino Pinball Machine
If you’re like me, you love pinball, but don’t have the money to buy or space to fit a full size game. So why not build your own?
Here, we will walk through how to create your own custom pinball game powered by an Arduino. The game has lights, sounds, features real pinball parts, including bumpers, drop targets, and slingshots, and even has a ramp.
This project requires a very large amount and variety of material, so consult each subsequent section for the new materials needed to complete each step. As a start, it is very helpful if you have access to a laser cutter or CNC router as well as basic electronic and hardware toolkits.
Author's note: This instructable was very recently published and not all of the design and software files have been completely organized. If planning to use our files, please leave a comment so that we can make sure everything is in its most up-to-date state.
Step 1: Design
Pictured above is a Solidworks design of the playfield and supporting assembly. The playfield is purely custom, but the shot lines (such as the curve of the back looping shot) were designed based on real pinball machines to ensure smooth play. One difficulty here is that, due to their complexity, the actual pinball parts (e.g. the bumpers and the drop targets) were not modeled, but care still has to be taken to ensure that everything will fit underneath the playfield - the parts are much larger underneath than above.
The files are included in the repository, so feel free to adjust the design to suit your fancy.
A few highlights of the design:
The playfield is 42” by 20.25” inches, exactly the size of 1980’s Bally-style games. It is made of ½” plywood, which is standard and should not be changed as the pinball part assemblies are designed for this thickness. The walls here consist of a ½” layer on top of a ¼” layer. In the first prototype, only ½” walls were included, but these proved to be too short and could pop the pinball into the air on particularly firm shots. Secondly, this design allows for slightly raised shooter line (pictured above) which allows the ball to drop slightly into the playfield, but not fall back in.
The ramp is designed with clear acrylic and 3d-printed supports. It crosses the playfield so that it gives the player the opportunity to hit the ramp multiple times in a row from the left flipper. As such, clear acrylic is used to not obstruct the player’s view of the table:
Finally, the playfield is supported by short walls at the four corners, which keep the playfield at the standard 6.5 degrees of slope. The back wall has a bottom “shelf” that can be removed and is used to mount the electronics. This results in a game with a full-size playfield, but is much more compact than a typical game and can be carried by hand by one person. Since the playfield is a standard size, however, these supports can be removed if you want to place the playfield into a standard pinball cabinet. To do so, you may want to consider adding a ball return assembly, which is not included in this design.
Step 2: Cut the Wood
To cut the layers of the playfield, we used a laser cutter. However, a laser cutter powerful enough to cut ½” plywood is hard to find, requires high-quality plywood, and can risk starting a fire if you’re not careful. Typical playfields are cut using a CNC router - while some of the corners might not be as crisp, you should still achieve decent results. For simplicity, the steps below will assume you have access to the same laser cutter we did. There are some people who have had decent results using only a drill and jigsaw, but you must be very careful and very patient if you go this route.
The first step in creating the playfield is converting the design into .DXF files that can be fed into a laser cutter. For example, the playfield .DXF file is pictured below. The files used in this project are included in our repository.
Using the laser cutter, we cut out shapes for the playfield, the ¼” intermediate layer (we used duron, a cheaper wood-like prototyping material, but ¼” plywood will also work), the ½” top layer, and the ½” supports.
- ½” plywood for the playfield and base
- ¼” plywood or duron for the intermediate wall layer
- ½”, ¾”, and 1” wood screws
- Access to a CNC router or laser cutter
Step 3: Assemble the Playfield
Begin by clamping the pieces from the ¼” duron layer onto the plywood in their respective locations. Using a hand-drill, first drill pilot holes using a 3/32” bit, and then use flat-head ¾” wood screws to attach the ¼” layer to the playfield It is important to do this from the top-down (i.e. so that the screw first goes through the ¼” layer, then into the ½” base), since the ¼” parts are small and thin and will bend away from the base layer if drilled in the opposite direction. It is also important to make sure the screw heads are flush with the ¼” layer and don’t provide any additional thickness.
One final note: these screws can go almost anywhere, as this layer will be mostly invisible to the player once the playfield is assembled. But there is an exception -- don’t put screws into the shooter lane. (We initially made this mistake).
Next, attach the side walls, and use the longest wood screws to drill into them from the top of the board, again such that the screw heads are flush with the top. Once that is done, clamp the ½” layer pieces on top of the duron, and screw them in as before, except this time screwing in from the bottom using 1" screws. Since the top layer is ½” thick, it is less likely to bend away from the base, and screwing from the bottom ensures that the screws stay invisible to the player.
Finally, attach the shooter block (pictured above, with shooter) by screwing in from the bottom side using 2 screws so the block cannot easily twist. The shooter block has a "U"-shaped slot that fits the shooter, which can be installed by tightening the nut on the other side. You may also have to use lubricant to reduce the friction between the shooting rod and the ball.
The design may need some adjustments at this point. For example, in our design, the cut for the drop targets was too narrow and had to be expanded using a dremel. If using our files as more than a reference, do try to contact the authors who might be able to provide updated files. It is also a good idea to sand down any rough areas, particurarily where two wood pieces meet.
For the most part, this concludes the woodworking, and we can move to putting in components.
- 3/4" flat head wood screws
- Shooter assembly
- Longer (~1.5") wood screws
- Hand drill with 3/32" bit
- Lubricating oil
- 1" flat head wood screws
- A file and/or dremel, and sandpaper
Step 4: Add the Components
By this point in the design stage, you should have a general idea of the orientation required to make sure all the components actually fit underneath the playfield. (If using our design, reference the picture of the underside of our table above).
First, install the drop targets, stand-up target, and slingshot assemblies by putting ½” wood screws through the mounting holes in the assembly. Do the same with the pop bumpers, but make sure to remove the cap first, or the assembly won’t fit into its hole!
Second, install the flipper assemblies. Make sure that they rotate in the correct direction. The solenoid, when fired, will pill the pin into the coil, and this should rotate the shaft such that the flipper rotates up towards the playfield. Once the flipper assemblies are installed, attach the flipper bats in from the other side. Use a wrench on the lock nut in the assembly to tighten them into place, then use the spring that should come with the assembly to make sure the flippers are bulled back down when not being fired.
Similarly, install all the rollover switches using the 1/2" screws, ensuring that they can be easily pressed in from the top and spring back into place. Using the 6-32 bolts, also attach the gate switch at the top-left of our design. This gate switch also serves as a one-way opening, which allows shots from the right side and from the shooter to fall into the bumpers. This is a design aspect that results in shots entering the right ramp and right loop going to different places and adds more variety to the play.
To install the lights, first place the plastic inserts into their holes. These inserts are about ¼” thick. If using a CNC router, the proper way to mount these is to cut a ¼” layer slightly larger than the insert hole. In our design, since the laser cutter cannot cut partial layers, we 3D-printed brackets that support the inserts. Use epoxy to hold the inserts into place (roughen the edges first) and the sandpaper to make sure the inserts are level with the playfield.
Next, insert the LEDS into their brackets by inserting and twisting them into place. Then, screw the brackets into place such that these LEDs sit directly below each insert. The light brackets linked below are pretty thin, and actually thin enough that the 1/2" screws may pierce the top of the table. Use a couple of washers so that this doesn't happen.
The playfield posts are installed using the 6-32 bolts. Once installed, wrap rubbers from the rubber kit around them to make passive bumpers. These give the table a lot more “life” than if the design were to be completely plywood. Using the same bolts, attach the lane guides just above the flippers. Also glue the end-of-game switch into place.
Note that most games have a dedicated ball return assembly like the one here. This was not included in this design, however, primarily due to cost. The trade-off, of course, is that the player is now responsible for placing the ball back into the shooter lane once it drains. We do have a shooter, though, which is attached to the shooter block as pictured earlier.
The flipper buttons and start button are installed by placing them into the holes and locking into place with palnuts. The flipper button leaf switches are bolted inside the buttons using 6-32 bolts and will close a switch circuit when the buttons are pressed.
At this point, your playfield will (from above) resemble a nearly-complete pinball table! All that is missing is the ramp. Feel free to gloat among your friends about how awesome it looks while privately being frightened about how much wiring and soldering there is to do.
Materials needed (the majority were purchased from PinballLife.com, and can be found simply by searching the terms below).
- 1 3-bank drop target assembly
- 3x pop bumper assembly
- 1 left flipper assembly
- 1 right flipper assembly
- 2 flipper bats
- 2 flipper buttons
- 2 flipper button palnuts
- 1 start button
- 1 rubber ring set
- ~30 playfield star posts, (1 1/16" used)
- 2 lane guides
- 2 flipper button leaf switches
- 2 slingshot assemblies
- 1 standup target
- 10 rollover switches
- 8 LED #44 bayonet-style lights
- 8 bayonet-style light brackets (Miniature Bayonet Base 2-Lead Socket With Long Mounting Bracket)
- 5 1-1/2" x 13/16" blue arrow insert
- 3 1" x 3/4" clear bullet insert
- 6-32 bolts (2.5", as well as some smaller sizes), nuts, and washers
- ~2" wide gate switch (like the one here, this may be hard to find, we scrapped ours from an old broken pinball ramp purchased on ebay)
Step 5: Build the Ramp
To make the ramp, use ¼” acrylic for the base pieces and ⅛” acrylic for the side walls. The clear acrylic will give a nice, clean appearance while not blocking the view of the playfield for the player. Using colored acrylic might also be a nice-looking option, but it is not recommended to use a completely opaque material like wood.
The supports for the ramps are 3D printed using a makerbot and bolted to the playfield and the plastic using the same 6-32 bolts.
The acrylic pieces here are glued together using acrylic cement, which is a solvent that essentially melts and welds the plastic together. Make sure to use a small amount, and it will make a very strong bond that is almost invisible.
At the entrance of the ramp, we have included a ramp flap like the one in the picture above. This is a thin piece of metal that gives a very smooth transition from the playfield to the plastic of the ramp, rather than having the pinball have to “jump” up the ¼” thickness of the plastic. You can buy one of these cheaply from a pinball specialty store or Ebay (we did), or just make one of your own out of sheet metal. In commercial games, these are riveted so that the bolts do not stick up and get in the way of the ball. Since we did not have the proper equipment to do that, we made sure to use flat-head screws and properly chamfer out a hole in the plastic and in the metal to achieve the same effect.
There is a narrow gate switch attached to the 3D supports on the front-right corner of the ramp, where it turns to go across the playfield. This switch is what records when a successful ramp shot has been hit.
- 1/4" clear acrylic (12x24" sheet)
- 1/2" clear acrylic (12x24" sheet)
- Acrylic cement
- Access to a 3D printer and laser cutter
- Ramp flap
- Flat-head 6-32 bolts for the ramp flap
- Chamber drill bit or hand tool
- Narrow gate switch
Step 6: Plan the Electronics Block and Pin Layout
(Author's update: With extended use, 48V can blow some of the transistors in this configuration. I'd recommend using 35V or lower with these electronics, or using a more professional control board resource like the ones listed here: http://pinballmakers.com/wiki/index.php/Construction)
This machine has 3 voltage levels: 48V for the solenoid power, 6.3V for the LEDs, and 5V for the logic and sound. To provide these voltage levels, we used a CNC power supply for the 48V, and off-the-shelf DC adapters to provide the 6.3V and the 5V. (It could be possible to just use the 6.3V, as the Arduino down-regulates its supply voltage to its 5V output pin, but we kept those power supplies isolated). 48V is a high voltage, and while not deadly by itself can be damaging to parts and can quickly cause components to overheat if there are any problems with the circuitry. Use a 5-A slow-blow fuse on both the input and the output of the main 48V power supply to avoid starting a fire if any of the transistors short.
On the Arduino shield, we attached wires with female Molex connectors designed that matched the input and output requirements of each of the three sub-boards: the solenoid driver board, the lights/sound driver board, and the input board.
In our design, we had the following pin assignments. This, of course, is quite flexible. Pin 0 was left open. (Instructables does not let us do numberes lists starting with 0.)
- Interrupt / Input Active pin
- Encoded input pin
- Encoded input pin
- Encoded input pin
- Encoded input pin
- Encoded input pin
- Right bumper output
- Middle bumper output
- Left bumper output
- Drop target output
- Flipper master switch output
- Master light switch output
- Light output pin
- Light output pin
- Light output pin
- Sound output pin
Although not implemented in our design, the SCL and SDA pins can be used for a display and the remaining pins can be used for additional control, such as adding features (a ball return) or more lighting combinations.
Step 7: Make the Driver Boards
The driver board is responsible for turning the inputs from the Arduino, the flipper buttons, and the slingshot switches into firing the coils. Since the signals are at the 5V level and the solenoids at 48V, hefty power MOSFETS are necessary to relay the signal. The transistors used in this design are these 100V-rated MOSFETs from Mouser.
There are three schematics pictured above, which includes the flippers, the slingshots, and the bumpers/drop targets. Each has slightly different requirements, but in all of them, when the transistor is given a 5V signal, a current path opens for the solenoid and 5-8 amps are pushed through the coil to give a powerful kick. This is a lot of current! In fact, this much current will burn out the components if the transistor is kept on for more than a very brief pulse. Make sure, in testing this circuit using software or other methods, to never fully power a solenoid for more than about a second.
The main source of problems in the above circuitry is inductive kick. The solenoids are powerful inductors, and as you may know, the current in inductors cannot change instantaneously. As such, when the transistor is turned-off, there is still a brief moment where 5-8 amps is flowing through the solenoid, and all that current needs somewhere to go. If not given a path to ground, this current will drive the voltage at the transistor drain up to hundreds of volts and destroy the transistor. Furthermore, when the transistor is destroyed, it shorts all three terminals, which causes amps of continuous current to flow and can destroy the solenoid if there isn’t a proper fuse installed. (We destroyed 8 transistors in our discovery and attempts to deal with this problem, but fortunately no solenoids since we were always quick to manually disconnect the power).
There are two methods to prevent inductive kick: first, each pinball assembly should come with a diode that points from the transistor drain back up to the supply. This, in theory, should prevent the transistor drain from ever exceeding the supply voltage, as once that happens the diode will turn on and drain all the remaining energy from the inductor. Unfortunately, in reality these diodes alone do not turn on fast enough to suppress the inductive kick enough by themselves.
To solve the problem, we added an RC ‘snubber’ circuit. This circuit features a capacitor in series with a resistor. The capacitor absorbs enough current from the inductor such that the diode has time to turn on and perform its function. For more info on RC snubber circuits, check here.
The bumper/droptarget solenoid driver circuit is fairly simple and has just the transistor, the solenoid, the snubber, and a connection to receive the input from the Arduino. In this board and subsequent boards, make sure to wire the solenoid such that the diode (which is not shown in the schematic) points towards the high voltage side.
The flipper driver circuit is a bit more complicated for three reasons. First, in order to have a fast reaction between the button press and the flipper action, it is recommended to create that response directly in the circuitry rather than as separate inputs and outputs handled by the Arduino. The delay caused by the Arduino is small, but an experienced player will be able to tell immediately and will be frustrated by the lack of control.
Secondly, the flippers feature two different coils (a low-power and a high-power coil) an end-of-stroke switch which triggers when the flipper is high. This switch serves the important function of allowing the high power coil to fire initially to give a powerful stroke, but switching to the low power coil (~130 ohms vs. 4 ohms) that gives enough power to keep the flipper held ‘up’ as long as the button is placed, but does not draw so much current as to burn out the solenoid. In the picture below, the EOS switch is normally closed, but our assembly had a normally-open switch and necessitated another transistor to convert that into a normally-closed signal.
Thirdly, while we wanted the button to control the flippers directly, we also included a ‘master’ switch signal from the Arduino that could activate or deactivate the flippers depending on whether the ball was in play. This results in the use of the third transistor in the circuit.
Similarly, the slingshot board has its own complications. While it uses just one transistor, it, like the flippers, should be controlled directly by the input switches (which we wired in series) for a fast response as well as to not require additional output pins on the Arduino. Unfortunately, if the gate of the transistor is connected to the switch directly, the response is far too fast to have more than a barely-noticeable kick since the switch does not stay closed for very long. In order to have a more powerful kick (i.e. letting the slingshot solenoid "follow through"), we added a diode and a large resistor at the gate of the transistors, which allows for a quick response but creates a large time constant of voltage decay at that node so that the gate remains close to 5V (and the transistor on) long enough to have a noticeable kick, even after the slingshot switches have been re-opened. Another complication is sending this input to the Arduino, as the input board (as we will see later) requires low inputs, and the slingshot operates when an input is pushed high. To solve this problem, we included a third transistor that closes whenever either input goes high, and thus can be treated like any other input switch on the playfield
The driver board (actually two boards) consists of two flipper drivers, two slingshot drivers, and four single-switch drivers for the remaining solenoids. Rather than soldering directly, we used 0.1” molex connectors to attach this board to the solenoids, power supply, and switches, so that any repairs or adjustments could be more easily made.
We used solderable breadboards for our designs, but designing actual PCBs with these functions would have a much cleaner result and help mitigate the mess of wires that these machines inevitably have.
- 12 100V-rated power transistors
- 10-50 uF capacitors (nonpolar if possible)
- 300, 5k, and 500k, and 3M resistors
- 1 smaller transistor for slingshot switch
- Several 1N4004 diodes
- Prototype solderable breadboards (or, even better, design your own PCBs)
Step 8: Make the Sensor Input Board
Since we are using just an Arduino, we are limited to 20 digital pins. The pinball machine, however, has a few dozen unique switch inputs, not to mention outputs needed for lights, sound, and driving solenoids. To alleviate this problem, we made the assumption that no two inputs would be triggered at once (thereby limiting us to only using 1 ball). This assumption allows us to ‘encode’ the switch inputs by converting them into a 5-bit binary register with a 6th pin that triggered an interrupt whenever a valid switch input was received. To accomplish this, we used a cascade of 8-to-3 encoders to make a 24-to-5 encoder using this encoder in the layout shown in the pictures above.
This was one of the most important developments of the project, as it allowed us to greatly increase the complexity of our machine from our initial plan of just having flippers, bumpers, and one or two targets.
A second prototype board was used to place each of the 24 male Molex connectors; each switch on the playfield would have a female connector at the end of a long wire that plugs into this board. The drop targets are a unique case that can be handled in several ways. What we did was wire each drop target switch in series, so that the input is closed when they are all down and allows the Arduino to send a signal to the solenoid to fire the drop targets back up.
- 4 3-state-output priority 8-to-3 encoders
Step 9: Make the Light/sound/score Peripheral Board
To save pins in a similar manner to the encoder, we used a 3-to-8 decoder to control our lights. This provided us with the limitation that we could not light more than one light at any one time, but that was an acceptable tradeoff to free up the pins for other elements. We also included a 4th “master” light output that could control all of the lights at once. This, for example, could allow us to flash all the lights several times when the game is first turned on (giving a strong indication that something is actually happening to the player when he or she presses the start button, which is otherwise difficult without a ball trough or colorful display).
The above schematic features a transistor circuit similar to the drivers, but much simpler as the lower voltages in play (6.3V for the lights) need smaller transistors and do not necessitate as much protection circuitry. We used a diode OR gate for the transistors to isolate the master switch signal and the individual light signal. This allows us to use only one transistor per light instead of two, and prevents the Arduino and the encoder chips from ‘fighting’ to source or sink current.
While we used low-current LEDs for each of the playfield lights (the ones underneath inserts), the start button and the 3 pop bumpers each came with incandescent bulbs that draw about 250mA each. The transistors are rated for 530mA of continuous current, so to not exceed this, we made sure that only two incandescent ever went through a single transistor.
We also attached a passive 5V piezo buzzer that allows us to play rudimentary sounds to this board.
Custom light and sound sequences can be programmed using functions light_sequence + sound_sequence or through the Pinball Language interface.
- 10 lighting transistors (we used these)
- 5V Piezo buzzer
Step 10: Step 11: Design Your Game Rules
There are two options for defining the rules of the pinball game. You can interact with the game using a customizable pinball document, or hard code game rules. Hard-coded game rules allow for more flexibility, including sequential shots and timed bonuses, while using the pinball document/parser system allows for more flexible, but simpler rules. We will start with the interface for the configurable game, and then detail some of the hard-coded game rules so that you can choose which configuration you want for your own pinball game.
See the github repository here for the files referenced in this project.
Part 1. Design your game rules
The default state machine for a pinball game is provided in the picture.
This is provided in the default starter code. Now you have two options - either to write your own code for the machine, or use the specified formatting for the pinball game.
Step 11: Option 1. Write Your Own Pinball.txt File
In the pinball-text document, you will find three sections: one for parts, one for “states” and one for “actions”. Here, you can define the specific actions for each component. For most components, you’ll probably want to stick to a one-state state machine. For example, if every time a bumper is hit, the player should score 100 more points, light up a ramp light, and score 100 points, then the state diagram would look like Figure 1 with the corresponding code. If you wanted a component to have a multiple-state state machine, say, you wanted a light to turn on when a bumper is hit, and then turn off when it is hit again, your state diagram/corresponding states would look like Figure 2. Our particular machine provides the structures, as in Figure 3, for which you can define rules. Their names, internal coded macros (which you don’t need to worry about but could be useful if you decide to investigate the source code), and interrupt codes are given in Figure 3. Figure 4 connects these names to playfield components.
Tips for writing your pinball game
Since the game components are tied to specific interrupts (indicated by the “pos” field) which are in turn defined by the hardware, we don’t recommend modifying the “parts” section too much outside of the “states” field.We suggest reserving state 0 and action 0 for components which do not have effects on scoring, such as the start button and game switch. Our code looks as pictured in Figure 5.
Step 12: Define Light and Sound Sequences
The eight lights on the board are controlled using a 3-to-8 decoder + one master switch, as previously described. Specific lights can be lit by writing the pins corresponding to the binary encoded version of the part code high. The light_sequence helper function provides an interface for the user to specify the light that he/she wants to light up, and macros are defined in the state_machine_headers.h document. A table again has been provided for your programming convenience. As for Sound, we used the Arduino tone library to program short sound sequences for various game events. We have four pre-made sounds that you can choose from (using executeSound(<# of sound you want>)). These sounds correspond to a long, cheerful sequence, short cheerful sequence, short sad sequence, and long sad sequence. If you wish to program your own sounds, you can look here for how to do so (pitch.h has been included in the repository): https://www.arduino.cc/en/Reference/Tone
Step 13: Load Pinball.txt File to the Arduino
Once you’re done writing the FSM, here’s how to load your game onto your Arduino (assumes you use Mac). All files can be found on the github repository.
- Unzip the arduino-serial zip file.
- Navigate to the arduino-serial file, and save your game config file here. “Pinball.txt” provides a sample template which you can use.
- Open Arduino. Upload the pinball game sketch.
- Open terminal, and type the following commands:
- ./arduino-serial -b 9600 -p pinball.txt
- Now, we should be reading and storing data in the Arduino’s internal memory. If there are any malformed lines, the Arduino will print an error message and you can choose to re-send the file.
- When you’re done uploading the code using terminal, e.g. when Arduino prints a “finished” message, you can open the Arduino Serial to read messages from the game in progress.
Common problems/optimizations for the software game
- Hard-coded vs. configurable games - we noticed that the interrupts in the hard-coded game responded much more accurately than the one in the customizable game. This could be because the customizable game had a lot of general-purpose functions which required conditional statements. This slowed down the read speed of the loop, which caused us to miss several interrupts and affected the overall operating speed of the game. To solve this problem, we reduced some of the customizability of the config file game in order to achieve acceptable response times in the circuit. We originally had concerns about the RAM capacity of the Arduino and how much of the game rules it could store, but this turned out to be less of a problem than originally expected and it was the speed of the loop that was the bigger limiting factor.
- Debouncing interrupts - because of the quick actions of the pinball game, we had several cases during which the interrupt pin was receiving several interrupts for the pinball hitting only one game component. Additionally, because these interrupts were received before the encoder had time to correctly read all inputs, the interrupts would be linked to incorrect components. To solve this problem, we used an external debouncing library which responds 1ms after the first interrupt is received, giving time for the encoder pins to reach high before the game reads the input code.
- Display - Although serial display allows for the game to print out detailed messages, it’s hard for a player to read the output messages when playing a fast-paced game of pinball. It’s also unwieldy for the player to have to play the game with a computer attached. In the future we hope to implement a digital display that can display the score and other game information in a display that the user can see easily, such as an LED matrix or a 7-segment display.
Step 14: Option 2: Advice on Hard-coding Your Own Game
First - read through the state_machine_headers.h document to understand the global data structures that store information about the state machine. You should initialize these data structures to your game rules within the Arduino IDE before loading into the Arduino code. The following data structures are provided:
Game structs to hold information about each part States to hold information about state transitions Actions to hold information about actions to be executed\ These structures are populated by the read file. Define input/outputs for all pins. Interrupt pins should be defined as INPUT pins.
Within the main loop, check each cycle to see if an interrupt has been fired for each game component. Define each game component within a switch statement.
Helper function executeState updates the current state of the part, and performs actions based on the in-coded information.
The hard-coded first version of the game code can be found in the file “simplepinballgame.ino”
Step 15: Connect Everything
To interface the Arduino with our driver boards, we used a protoshield to more easily access the pins on the other boards. There are a lot of wires, so be careful! Follow the layout given in Electronic Pins and Layout to connect your Arduino outlets to their corresponding pins. Molex connectors should help a lot in figuring out which connectors connect with which.
Here is a short troubleshooting FAQ in case you run into any of the common problems we did:
None of the inputs are being recorded by the Arduino!
The nature of the input encoder is that there are 6 input pins into the Arduino: 5 which together show which input is triggered, and a 6th pin that goes high if any single input is triggered. The code written only detects when this sixth pin changes from low to high. So if the Arduino is not receiving any inputs, and you are sure that all or at least most of the switches work, check to see if any switches are stuck closed. For example, if all the drop targets are down and haven't been fired back up, that is a closed switch and prevents the Arduino from receiving any other inputs.
The shooter is really weak!
Check to sure that the nut that holds the shooter in place is tightened fully, or that the shooter block isn't loose. Alternatively, oil the shooter rod.
Certain inputs, like rollovers, aren't always being recorded
This can be a mechanical/design problem if the switches are placed in too wide a lane, allowing the ball to go 'around' them. Otherwise, it can be the result of too long of a delay somewhere in the code. If, for example, you are busy playing a tone using the tone library and a delay() statement, the Arduino will not be able to pick up inputs during that time. One workaround we used was to only play sounds for the ramp shot, standup target, start button, and end-of-game switch, as we knew about how much time we would have after these shots before a new input was likely to be triggered.
The wrong bumper fires when the ball is switched! OR The wrong lights go on!
Admittedly, we did not assign specific headers for specific lights or specific solenoids, meaning that the first time you plug everything in (or subsequent times if you don't label them somehow), the output pins (or output light encoding) are connected in arbitrary order. Use trial-and-error to resolve which pins correspond to which output and adjust the code accordingly. For the lights and bumpers, this isn't so bad -- but definitely label all the inputs and write down which is which, as that process can have up to 24 values and will take a bit longer to calibrate.
The inputs are fine when I press them, but sometimes are wrong during play?
The encoder has the unfortunate property of sometimes pulsing the indicator pin high before the 5 encoder pins have fully resolved their values. For us, we knew this had occurred when the number of the switch being pressed was off-by-one, but it may show up differently for you. We solved this problem by using a debouncing library to create a tiny bit of delay between when we notice that a switched has changed and when we record which switch it was. Careful, though, as too much of a delay (more than 15-20mS) can cause you to miss inputs entirely.
There are so so many wires and I can't keep them all organized please help
Sorry, but we haven't really figured out a good solution for this one yet.