Maker.io main logo

Mini Pinball Table with Gemma M0

2020-05-05 | By Adafruit Industries

License: See Original Project Wearables

Courtesy of Adafruit

Guide by John Park

Overview

It's a lot of fun to play virtual pinball on an iPad! My favorite game is Pinball Arcade which features excellent physics and a huge host of classic table reproductions, from "Addams Family Pinball" to "Theater of Magic" and more. But, playing with the virtual, screen-tapping controls isn't as satisfying as hitting real flipper buttons. Let's solve that!

This Mini Pinball Table is pretty straightforward to build, using slotted aluminum extrusion and hardware. And, the circuit to make it all go is really easy to make -- it requires no soldering, just plug wires and clip alligator clips to the buttons and a Gemma M0 microcontroller, which takes care of the rest!

Any game that supports the iCade protocol can be controlled with the Gemma M0, Trinket M0, Circuit Playground Express, or other boards that can output HID USB keyboard strokes. See next page for more on the iCade protocol.

 

hardware_2

Control Parts

Listed below are the parts you'll need to make the controller.

parts_3

These controller parts are all you'll need should you decide to build your own table using other materials, such as LEGO, cardboard, rubber bands, and pencils, or who knows what!

Table Materials

These are the parts used to build the aluminum table:

materials_4

Additional Parts

You'll also need:

  • iPad or iPhone and a copy of The Pinball Arcade or other iCade compatible game
  • An adapter for the iOS device to connect USB to the Lightning port, such as the Apple USB to Lightning Camera Adapter. (If you have an older iPad or iPhone you will need the 30-pin dock connector version of the camera kit)

Apple USB to Lightning Camera Adapter

Tools

The only tools you'll need are the 2.5mm hex driver for the screws, a hack saw, and miter box or other tool (band saw, miter saw with metal cutting blade, Dremel, die grinder, etc.) to cut the lengths of aluminum extrusion.

Most cuts are at a 90-degree angle, but the four feet ends on the legs will be cut at an 87-degree angle to give the table it's signature tilt.

Next, let's program the Gemma M0 to turn button presses into keyboard commands!

Code the Gemma M0 with CircuitPython

Gemma M0

The Gemma M0 is just right for this project for a few reasons. It's inexpensive, has three digital input pins to read the two flippers and the plunger, it can output HID USB keyboard strokes over USB, and it draws very little power, so the iPad and iPhone won't mind powering it! Plus, it has an RGB DotStar LED that can be used as a multi-color indicator!

Coding Options

The Gemma M0 can currently be coded with either the Arduino IDE or CircuitPython. For this project, we'll use CircuitPython. It's very simple to set up -- all you need to do is plug it into your computer via USB and it shows up as a USB thumb drive. Then, you can write code in any text editor and save the file to the Gemma M0. That's all it takes, it immediately runs the code. Talk about fast iteration!

iCade Standard

Since the iPad doesn't have a game controller port on it like a video game console, game developers have come up with a few clever ways to interface physical controls with the device. One such standard is the iCade protocol, made by ION Audio for their line of iPad desktop arcade cabinets and controllers.

arcade_6

The iCade standard interfaces with iOS as an HID keyboard and is typically paired over Bluetooth. However, plugging in a wired HID keyboard works just as well, which makes it very straightforward to build your own controller!

The Gemma M0 is going to act as a USB HID keyboard so that it can "type" the keystrokes that the iCade standard uses.

example_7

Here's what the button mapping looks like for the standard iCade:

button_8

Keyboard Mapping

The first test I performed was to figure out the key mappings needed. I did so by pairing a Bluetooth keyboard to the iPad, launching Pinball Arcade, and setting the controller type to iCade in the game's settings. Then, I typed the key pairs seen in the diagram above until I knew which key combos did what.

The mapping for pinball looks like this:

mapping_9

Test Code

The next test I did was to have the Gemma M0 press the flipper buttons by telling it to "type" the "LVHR" combo over and over. Here's how you can make the Gemma M0 type the keystrokes.

First, make sure you've followed the basic guide to setting up the Gemma M0. Once you've successfully run the basic Blinky code example on your Gemma M0, move on to the next step.

If nothing happens when you plug in your Gemma M0, make sure the built-in ON/OFF switch is turned on!

The Gemma M0 ships with all of the libraries we'll need (HID library and DotStar library) already installed on the board, so we can immediately start coding this example!

With the Gemma M0 plugged into your computer, open the CIRCUTPY drive that shows up, and edit the code.py (or main.py, either will work) file in your text editor.

Copy and paste the code below into your text editor and then save the file, overwriting the existing code.py file on the root of the Gemma M0. Be careful where your cursor is when you save, since the program will cause the Gemma M0 to start spewing the letters "lhvr" as if you were banging on your keyboard!

Download: file

Copy Code
        # Gemma IO demo - Keyboard emu
# key tester

#import libraries
from board import *
import time
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
# the keyboard object
kbd = Keyboard()


##############
#the main loop
while True:
# type "l" to press right flipper
#this is actually a lower case letter, since we didn't use a shift modifier
kbd.press(Keycode.L)
kbd.release(Keycode.L)
time.sleep(0.1) #pause .1 seconds

# type "h" to press left flipper
kbd.press(Keycode.H)
kbd.release(Keycode.H)
time.sleep(0.1) #pause .1 seconds

# type "v" tor release right flipper
kbd.press(Keycode.V)
kbd.release(Keycode.V)
time.sleep(0.1) #pause .1 seconds

# type "r" tor release left flipper
kbd.press(Keycode.R)
kbd.release(Keycode.R)
time.sleep(0.1) #pause .1 seconds

#testing area:
# place cursor after comment hash symbol below before saving file to Gemma M0
# so the typed letters don't mess with your code!
#
#

If you want to test it out on your pinball game, go ahead and plug the Gemma M0 into the iPad using the USB to Lightning adapter. The iPad will autodetect the device and open a camera import window. You can ignore this and switch to your iCade compatible pinball game, such as Pinball Arcade. When you start a new game, it will immediately begin flipping the flippers for you automatically! Launch a ball onto the field with the on-screen plunger and watch it play by itself for a bit!

Button Code

Now it's time to rewrite the code so that the two flippers and the plunger aren't haunted by the ghost of Tommy, but instead, respond to your arcade buttons!

Copy and paste the code below into your text editor and save it onto your Gemma M0 as code.py

Download: file

Copy Code
# Gemma IO demo - Keyboard emu
# iCade Pinball Edition by John Park and Tod Kurt

#import libraries
import digitalio
from board import *
import time
import adafruit_dotstar as dotstar
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode

# Allows three buttons on a Gemma M0 to control iCade standard Pinball Arcade
# game on iOS using USB to Lightning "camera connector"

# iCade keyboard mappings
# See developer doc at: http://www.ionaudio.com/products/details/icade

# WE YT UF IM OG
# AQ< -->DC
# XZ HR JN KP LV

#control key is triggered by a press, doesn't repeat, second control key is
#triggered by a release

######
#setup
# The button pins we'll use, each has an internal pullup
buttonpins = [D0, D1, D2]
# our array of button objects
buttons = []

# The keycode pair sent for each button:
# D0 is left flipper - iCade key sequence (hold, release) is "hr"
# D1 is right flipper - iCade key sequence (hold, release) is "lv"
# D2 is plunger - iCade key sequence (hold, release) is "xz"

keys_pressed = [Keycode.H, Keycode.L, Keycode.X]
keys_released = [Keycode.R, Keycode.V, Keycode.Z]

# the keyboard object
kbd = Keyboard()

# make all pin objects, make them inputs w/pullups
for pin in buttonpins:
button = digitalio.DigitalInOut(pin)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP
buttons.append(button)

# which buttons have been pressed
buttons_pressed = [False] * len(buttons)

led = digitalio.DigitalInOut(D13)
led.direction = digitalio.Direction.OUTPUT

#set up on board DotStar
pixel = dotstar.DotStar(APA102_SCK, APA102_MOSI, 1, brightness=0.1)
pixel.fill([0, 50, 0]) #color in b - g - r color order
pixel.show()
###################left plunger right
pixelPressed = [ [50,50,50], [0,0,100], [100,0,0] ] #pixel colors per button
pixelReleased = [ [0,100,0], [0,100,0], [0,100,0] ] #back to green

print("Waiting for button presses")

##############
#the main loop
while True:
# check each button for press
for button in buttons:
i = buttons.index(button)
if (not button.value and not buttons_pressed[i]): # button pressed
pixel.fill([pixelPressed[i][0], pixelPressed[i][1], pixelPressed[i][2]])
pixel.show()
print("Button #%d Pressed" % i)

# save the index of the button pressed
buttons_pressed[i] = True

# turn on the LED
led.value = True

# type the "press" keycode!
k = keys_pressed[i] # get the corresp. keycode
kbd.press(k)
kbd.release(k)

# turn off the LED
led.value = False

# check pressed buttons for release
for button in buttons:
i = buttons.index(button)
if( buttons_pressed[i] and button.value): # released
pixel.fill([pixelReleased[i][0], pixelReleased[i][1], pixelReleased[i][2]])
pixel.show()
print("Button #%d Released" % i)
buttons_pressed[i] = False

# turn on the LED
led.value = True

# type the "release" keycode!
k = keys_released[i]
kbd.press(k)
kbd.release(k)

# turn off the LED
led.value = False

time.sleep(0.01)

#testing area
#

Next, we'll connect the arcade buttons to the Gemma M0.

Connect the Arcade Buttons

connect_10

No soldering required!

Using the diagram above, you can see how the three buttons will be connected. Since all buttons need to share a common ground with the Gemma M0, but we only have one available GND pad, we'll run ground to a terminal on one button (it doesn't matter which terminal) and then connect the rest of the buttons to that terminal.

You can try this arrangement out right away with the short alligator clip leads or use the longer arcade button quick connect wire pairs and alligator clip to male jumper wires for the greater length we'll need in the final table as shown below.

arrangement_11

To begin, connect the terminals of each wire pair to the lugs on the buttons.

Note: On the larger, threaded button with internal LED (which we won't be using), we'll connect only to the switch lugs which come out of the grey switch box, not the LED pair set deeper into the button housing.

connect_13

connect_14

connect_12

Next, connect the ground wires as shown here using the black short alligator clip leads.

wires_15

Connect the four wires extensions (black to GND, yellow to D1, blue to D2, and white to D0) to the alligator clip leads with male pins as shown here, being careful to connect to the correct leads, not the ground sides which will remain unused.

extensions_16

extensions_17

extensions_15

This is how the final wiring will look.

finalwire_18

Plug in the Gemma M0 to power, and you can test out the buttons. The built-in DotStar is an RGB LED, and it make for a pretty handy indicator light. The code will light the DotStar to the same color as the button pressed as a handy way to check that everything is wired properly. Plus, it adds a bit of a fun light show while you're playing!

light_19

Now, you can try it out on your iPad (or iPhone as shown here). Plug the Gemma M0 into the short USB cable and then into the USB-to-Lightning adapter and into the iOS device. The camera import screen may pop up, you can ignore it and hit the home button. Then launch the Notes app and press the buttons to type the keystrokes.

keystrokes_20

keystrokes_21

OK, enough anticipation, launch the Pinball Arcade game and in the settings, click the iCade button until it reads "iCade:iPad". Then, launch a table, and test out your buttons!

test_22

Assemble the Aluminum Table

table_23

Now we get to build the table! This part is fun, sort of like building a kit, except you'll need to do a little bit of cutting to create the proper lengths of aluminum extrusion.

aluminum_24

Cutlist

First, take one of the lengths of aluminum extrusion and measure, mark, and cut the two frame sides from it, each at 300mm.

Cutlist_25

Measure, then scribe a mark into the aluminum with a sharp tool or knife.

measure_26

measure_27

measure_28

  • Clamp the work into your miter box or fence of a miter saw
  • You can use a lubricant to keep the blade and work cool
  • Carefully cut the piece
  • File off any rough edges if needed

clamp_29

clamp_30

clamp_31

clamp_32

The aluminum extrusion comes in 610mm lengths, so even with a bit of material lost to saw blade kerf, you can cut both sides from one piece.

Next, cut the frame front and rear lengths to 197mm, also from a single 610mm length of stock.

This will leave enough remaining material to cut one of the rear legs, as well, which is 127mm, however, this one will have a 3-degree angled cut for the foot. So, set your miter angle to 3 degrees with the blade cutting the longest leg of the angle to 127mm.

blade_33

Here we can see the angled cut next to a straight cut.

angled_34

You can place the plastic end caps on the angled feet as well as the rear frame lengths.

Make the remaining cuts in the third piece of stock to create the other 127mm rear leg and both of the 102mm front legs. All legs will have the 3-degree cut to one end.

leg_35

Assembly

Now we get to put it all together! Follow the photo sections below as your guide.

Front Rail and Plunger Button

  • The plunger button will connect to the front rail using two double corner brace supports.
  • Screw in two T-nuts on each bracket as shown here.
  • Loosely attach them to the front rail, then fit them tightly to the plunger button, with the button's plastic nut helping hold it in place.
  • Tighten down all four screws.

front_rail_36

front_rail_37

front_rail_38

front_rail_39

front_rail_40

front_rail_41

front_rail_42

front_rail_43

front_rail_44

Side Flipper Buttons

  • Screw in two L-plates to the left rail making space for the left flipper button (Note the two extra screws in the forward plate which will be used to connect the front left leg later)
  • Overhang the front-most plate by 20mm, enough to over the front rail later
  • Hold the plates firmly against the button's catch tabs and then tighten the screws
  • Repeat for the right-side flipper button

side_flipper_45

side_flipper_46

side_flipper_47

side_flipper_48

side_flipper_49

side_flipper_50

side_flipper_51

Front Rail Connection to Side Rails

  • Prepare two more L-plates with screws and T-nuts
  • Connect the front rail to the right rail as shown
  • Make sure everything is nice and square, then connect the front rail to the left rail as shown

side_rails_52

side_rails_53

side_rails_54

side_rails_55

side_rails_56

side_rails_57

side_rails_58

Front Leg Attachment

  • The front legs slide into the two T-nuts that were already prepped on the L-plates
  • Make sure the foot angles are correct -- the table will have a forward lean to it
  • Set the legs up square to the undersides of the side rails, then screw down the screws
  • Repeat for both sides

front_leg_59

front_leg_60

front_leg_61

front_leg_62

front_leg_63

front_leg_64

front_leg_65

front_leg_66

Rear Leg Attachment

  • Prep two double corner brace supports, each with four screws and T-nuts
  • Attach one of the brackets to the underside of the right-side rail as shown, leaving 20mm of space for the leg to sit flush
  • Again, being mindful of the foot angle that will allow for the table to lean properly, connect the right rear leg
  • Tighten the screws, making sure everything's square
  • Repeat these steps for the other rear leg

rear_leg_67

rear_leg_68

rear_leg_69

rear_leg_70

rear_leg_71

rear_leg_72

rear_leg_73

rear_leg_74

rear_leg_75

Rear Frame Supports

  • Use two more L-plates to form supports that will hold the rear frame rail
  • This will allow for an easier time inserting and removing the iPad
  • Note the position of the single screw and T-nut inserted from the underside of each plate, this will be used to connect the rear frame rail later (it does not need to be inserted just yet, and doesn't appear in all photos)

rear_frame_76

rear_frame_77

Gemma M0 Mount

  • Connect the Gemma M0 as shown to the plastic hinge using M2.5 nylon screws and standoffs or nuts
  • The best orientation for screw clearance is to have the Gemma M0 on the side of the plastic hinge with the smaller hole diameter, not the counter-sink side
  • Attach the plastic hinge/mount to the top rail with two screws and T-nuts

GemmaM0_78

GemmaM0_79

GemmaM0_80

GemmaM0_81

GemmaM0_82

Insert iPad and Close It Up

  • Slide the iPad into the frame, keeping the Lighting port at the top/rear of the table
  • Use two screws and T-nuts from the underside of the L-plates to attach the rear rail/Gemma M0 mount

iPad_84

iPad_86

iPad_85

iPad_83

iPad_87

iPad_88

iPad_89

table_90

You're just about ready to play!

tabledisplay_91

Play Pinball!

tablebutton_92

Go ahead and re-connect the Gemma M0 to the short USB cable and USB-to-Lightning adapter, make sure the Gemma M0 is turned on, then fire up your pinball game!

There's enough space to slide the iPad up or down as needed to access the power button, and you can adjust the volume with the onscreen controls, since the physical volume buttons aren't accessible.

 

制造商零件编号 3501
ADAFRUIT GEMMA M0 - MINIATURE WE
Adafruit Industries LLC
制造商零件编号 476
SWITCH PUSHBUTTON SPST-NO BLUE
Adafruit Industries LLC
制造商零件编号 3490
SWITCH PUSH SPST-NO BLU 10MA 5V
Adafruit Industries LLC
制造商零件编号 1592
SHORT ALLIGATOR TEST LEAD 12PK
Adafruit Industries LLC
制造商零件编号 1157
HDWR T-NUT ALUM M4 20X20 50PK
Adafruit Industries LLC
制造商零件编号 LLM25
HEX KEY L-SHAPE 2.5MM 3.56"
Klein Tools, Inc.
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum