Playfield :: Electronics :: Switches

Switches are probably the single-most important device on a Pinball Playfield, and are fundamental to the game itself. The entire Pinball Machine is essentially an electro-mechanical interaction, with the switch being the all-important middle-man between the ball and the active mechanisms…

Switches also pre-date a lot of the other devices we commonly associate with Pinball, like Flippers, Thumpers, Slingshots, etc. and most machines today still use some manner of the traditional wire-form activated leaf-switch we find on older games.

The focus of this blog is on solid-state based Custom Pinball Machines, and one advantage with SS when it comes to switches is that they can be scanned as a matrix. Most SS games since the 70’s have used this technique. With matrix scanning, you can read 40 switches with 5 drive lines and 8 read lines (5×8 = 40), but only use 13 digital I/Os (5+8 = 13). And just to hammer home the math, that saves 27 I/Os (40-13 = 27), putting this in the wheelhouse of a small micro-controller board like the Arduino Uno.

The Layout.

Here’s a typical schematic (below) of a switch matrix from a standard Bally 70’s solid-state (SS) game. I present this because it will serve us well even today since the principles are the same.

Switch matrix schematic

Schematic of a switch matrix designed to be scanned by solid-state electronics. For our Custom Pinball Machine, we will use a micro-controller like the Arduino Uno.


Scanning The Matrix:

In the case above, there are five drive lines and eight sense lines, which we will model for our own design. The process of scanning works like this:

  • All the drive lines are initially held low.
  • The first drive line is switched high.
  • Each of the eight sense lines are read.
  • These values then represent the state of switches 1 thru 8.
  • The first line returns low, and the second line goes high.
  • Again, read in the eight sense lines.
  • These values become the state of switches 9 thru 16.
  • And so on until all 40 switch states are read…

Notice that each switch in the schematic has a diode on the drive side. This prevents “ghosting” in the case of multiple switches being active at the same time. Without it, the current from one drive column could back-feed through any switches active on the same row, in essence driving a second (unintended) column. An active switch on the second column would create a “ghost” activation on the first (real) drive column.

Below is a spreadsheet I usually create during the design of the game, and reference for the assembly and wiring.

Switch matrix excel spreadsheet

Excel spreadsheet showing switch signal names with drive wire colors and sense line colors.

Most older games made use of two-color striped wire, so there was never a duplicate color combination for any signal. In our case, it’s more feasible to use a limited set of standard colors, and just keep track of where there might be duplicates.

I always create a chart like this early on, giving the switches logical names and grouping them based roughly on where they will be located on the playfield. It helps to use the same name later in the Arduino code that will be doing the scanning.

The Switch.

Almost all older games use leaf-switches connected to a wire-form for activation. These usually have three contacts, and the diode mentioned above is mounted directly on the switch. This make wiring easier and more mechanically stable.


Custom Pinball Switch

This is a typical “spoon” switch used to activate Thumpers. There is a built-in diode, with the drive wire coming in on the positive side (yellow), and a sense wire on the negative side (orange).

The Code.

Below can be cut-and-pasted into an Arduino project. Use this for testing and diagnostics, or as a reference for creating your own game code.

There are several features to this code aside from just scanning the switch matrix, hopefully it will become clear as you read though it:

  • The code compares the previous state of the switch to the current state to determine if the state is “new”
  • It then rotates the state for the next loop so that current becomes previous.
  • It only call the state “new” if it went low-to-high, you can change this in your own code.
  • It implements a de-bounce timer function, which is adjustable, or just comment it out.
  • Prints the “new” switch state to the serial monitor when switch is activated.
// --------------------------------------------

This code will scan a 5x8 switch matrix and print the status of new switch states.


  -  Set the first drive line output.
  -  Scan first input.
  -  If state was low, and now high, set new switch flag.
  -  Send message out to Serial Monitor (optional).
  -  Loop through all eight inputs.
  -  Loop through all five drive lines.
  -  Delay.
  -  Repeat.
For questions or comments, check the blog:


//  --------------------------

//  --------------------------
unsigned char j = 0;	//
unsigned char i = 0;	//
unsigned char k = 0;	//

//  --------------------------
unsigned char switchStateNow[40];	// start no digit selected
unsigned char switchStatePrev[40];	// start no digit selected
unsigned char switchNew[40];	//
unsigned char switchDebounce[40];
// --------------------------
// optional for this test code, but good idea
// if you are going to build on this as a game later.
SWITCH_A, // was 1
SWITCH_B, // was 2
SWITCH_C, // was 3
SWITCH_D, // was 4


SWITCH_LANE_DROP_3, // kicker / shoot again




#define SWITCH_DEBOUNCE_DURATION 10 //10 loops

void setup() 
  pinMode(14,OUTPUT); // analog in used a row drive out
  //pinMode(18,OUTPUT); // if only using four drive lines, no need to set this

  pinMode(2,INPUT); // analog in used a row drive out
  pinMode(3,INPUT); // analog in used a row drive out
  pinMode(4,INPUT); // analog in used a row drive out
  pinMode(5,INPUT); // analog in used a row drive out
  pinMode(6,INPUT); // analog in used a row drive out
  pinMode(7,INPUT); // analog in used a row drive out
  pinMode(8,INPUT); // analog in used a row drive out
  pinMode(9,INPUT); // analog in used a row drive out

  digitalWrite(2,LOW); // pull up on
  digitalWrite(3,LOW); // pull up on
  digitalWrite(4,LOW); // pull up on
  digitalWrite(5,LOW); // pull up on
  digitalWrite(6,LOW); // pull up on
  digitalWrite(7,LOW); // pull up on
  digitalWrite(8,LOW); // pull up on
  digitalWrite(9,LOW); // pull up on

  Serial.begin(9600);           // start serial for output

//  --------------------------
  for (j = 0; j < 40; j++) 
    switchStateNow[j] = 1; //
    switchStatePrev[j] = 1;//
    switchNew[j] = 0;
    switchDebounce[j] = 100;
} // end setup

void loop() 
  //  *****************************************
  //  -----------------------------------------
  //             START READ SWITCH
  //  -----------------------------------------
  //  *****************************************  

  for (j = 1; j < 5; j++) 
    // START ALL LOW (no signal)
    digitalWrite(14, LOW); // pins 14-17
    digitalWrite(15, LOW); // pins 14-17
    digitalWrite(16, LOW); // pins 14-17
    digitalWrite(17, LOW); // pins 14-17    

    digitalWrite((j+13), HIGH); // pins 14-17

    delayMicroseconds(400) ;
    for (i = 0; i < 8; i++) 
      switchStatePrev[((j*8) + i)] = switchStateNow[((j*8) + i)]; // rotate variable
      switchStateNow[((j*8) + i)] = digitalRead(i + 2); // pins 2-9

      // check for a "new" state
      if ((switchStateNow[((j*8) + i)] == switchStatePrev[((j*8) + i)]) || (switchDebounce[((j*8) + i)] > 0))
      if ( switchStateNow[((j*8) + i)] == switchStatePrev[((j*8) + i)]) 
        switchNew[((j*8) + i)] = 0; // same as old
      } // end if
      else // must be new if not old and new equals one
        if (switchStateNow[((j*8) + i)] == 1)
          switchNew[((j*8) + i)] = 1; // new
          #if (DEBOUNCE_MODE)
            switchDebounce[((j*8) + i)] = SWITCH_DEBOUNCE_DURATION; // set timer
          #if (SERIAL_MONITOR == 1)
            Serial.print("Switch = ");
            Serial.print((j*8) + i); // TODO check this formatting later
      } // end else
    } // end for i
  } // end for j    

    for (j = 0; j < 40; j++) 
      if (switchDebounce[j] > 0) 
        switchDebounce[j] -= 1; // ramp down to zero

  delay(10) ; // 10ms loop time
  // end read switches

//return;// end MAIN LOOP





  1. Hey, I really appreciate the work you have done putting this blog together. I was hoping you could touch on which elements should have a capacitor and why. I’m not sure I understand what all the labels in the Bally schematic are referring to

    1. So your comment was on the “switches” page, so I can say that for a new custom game you can probably leave out any capacitors on (most of) the switches. In the 80’s, some of these games probably needed a cap on the switches to help with “debounce”, but a modern system handles debounce pretty well in software, plus the cap may actually reduce the max speed that you can scan your switch matrix (which is faster now with an Arduino than it ever was on the old-school machines).

      The exception for switches (IMO) is on the flipper switches *IF* they are set up to drive power to the flippers directly (through a relay) instead of being software controlled. In this case, I think the cap is acting as a kind of “snubber” when the circuit makes-and-breaks contact.

      For other things like coils, *ALWAYS* use a *diode* across the power tabs to recirculate the current when the driver turns off, which reduces electromagnetic interference. Sometime you’ll find a cap across the coil as well, I don’t see a problem with leaving that on, but I wouldn’t necessarily add any caps.

      Hope this helps!


      1. Thanks! I figured it was for debounce, but it struck me odd that some switches were and others were not.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s