Skip to content

How to configure a modern trough with opto switches

Related Config File Sections:

This guide will show you how to configure MPF to use a modern-style trough with opto boards. (If you have a modern-style trough which uses mechanical leaf switches, use this guide instead.)

image

The following diagram shows how the ball flow and eject coil work in a modern trough. (This is a side view)

image

And this diagram shows how the "opto boards" are typically located. Note that one of the opto boards is a "transmit" board that contains infrared LEDs which are always on, and the other side is the "receive" board which contains photo transistors which are activated when the IR beam is hitting them (i.e. when there is no ball blocking the path) and inactive when a ball is present and in the way.

image

If you got a Stern Spike Trough but are not using Stern Spike (not recommended) read the Stern Spike Trough guide.

0. Connect your trough

Skip this step if your trough is already connected. Otherwise, you need to power your opto transmitters and connect the opto receivers to your inputs. Make sure that you got proper current limiting in place. This might be already present on the trough PCB (i.e. on older Stern troughs) or you might need to add current limiting resistors. Read the Opto section for details if in doubt.

Bally/Williams Trough Opto Boards:

Part numbers:

  • Transmitter: #A-18617-1 or 5768-14121-02 or #600-0035-00 or #600-0005-00
  • Receiver: #A-18618-1 or 5768-14122-02 or #600-0036-00 or #600-0006-00
  • Transmitter/Receiver: #600-0054-00 or #600-0055-00

Those boards need an additional current limiting resistor on the transmitter. Read the Opto section for details if in doubt. You can connect the receivers one by one to your inputs. Don't forget to connect your the receiver board to ground.

FAST Trough Opto Boards:

Part numbers:

  • Transmitter: FP-AUX-001-?
  • Receiver: FP-AUX-001-2

The FAST transmitter already has parts for current limiting and you can connect it directly to 12V and ground. You can connect the receivers one by one to your inputs. Don't forget to connect your the receiver board to ground.

Stern Trough Opto Boards:

Part numbers:

  • Transmitter: 515-0173-00/520-5173-00
  • Receiver: 515-0174-00/520-5174-00

This board only covers the first ball position and the jam position. All other positions are typically covered by normal switches. Transmitter contains current limiting circuit and you can connect it directly to 5V. The receiver needs to be powered and also inverts the optos. There is typically no need to set NC on using those boards. You can follow the /mechs/plungers/index guide to configure your trough.

Spike Trough Opto Boards:

Part numbers:

  • Transmitter: 520-5344-00
  • Receiver: 520-5345-00/520-5345-01

If you got a Stern Spike Trough but are not using Stern Spike (not recommended) read the Stern Spike Trough guide.

1. Add your trough switches

The first step is to add your trough's switches to the switches: section of your machine config file. Create an entry in the switches: section for each switch in your trough, like this: (This example has six switches plus the jam switch. Yours may have more or less.)

switches:
  s_trough1:
    number: 2
    type: NC
  s_trough2:
    number: 3
    type: NC
  s_trough3:
    number: 4
    type: NC
  s_trough4:
    number: 5
    type: NC
  s_trough5:
    number: 6
    type: NC
  s_trough6:
    number: 7
    type: NC
  s_trough_jam:
    number: 8
    type: NC

Note that we configured this switches with numbers 02 through 08, but you should use the actual switch numbers for your control system that the trough optos are connected to. (See How to configure "number:" settings for instructions for each type of control system.)

It makes no difference which switch is which (in terms of whether Switch 1 is on the left side or the right side). Also the actual switch names don't really matter. We use s_trough1 through s_trough6 plus s_trough_jam, though you can call them s_ball_trough_1 or trough_ball_1 or s_mr_potatohead.

Note

The "jam" switch position is the switch which detects if a ball is sitting on top of the lowest ball. We think all modern opto troughs have optos to detect the jams, but if yours doesn't, that's fine---just don't enter it. (If you have it though you definitely want to use it because it makes MPF smarter about how it handles balls that get stacked.)

2. Add your trough eject coil

Next, create an entry in your coils: section for your trough's eject coil. Again, the name doesn't matter. We'll call this c_trough_eject and enter it like this:

coils:
  c_trough_eject:
    number: 04
    default_pulse_ms: 20

Again, the number: entries in your config will vary depending on your actual hardware, and again, you can pick whatever name you want for your coil.

You'll also note that we went ahead and entered a default_pulse_ms: value of 20 which will override the default pulse time of 10ms. It's hard to say at this point what value you'll actually need. You can always adjust this at any time. You can play with the exact values in a bit once we finish getting everything set up.

3. Add your "trough" ball device

In MPF, the trough is a ball device, so you'll add a configuration for it to the ball_devices: section of your machine config. (If you don't have that section add it now.)

Then in your ball_devices: section, create an entry called bd_trough:, like this:

#! switches:
#!   s_trough1:
#!     number: 2
#!   s_trough2:
#!     number: 3
#!   s_trough3:
#!     number: 4
#!   s_trough4:
#!     number: 5
#!   s_trough5:
#!     number: 6
#!   s_trough6:
#!     number: 7
#!   s_trough_jam:
#!     number: 8
#!   s_plunger:
#!     number: 10
#! coils:
#!   c_trough_eject:
#!     number: 4
#!     default_pulse_ms: 20
ball_devices:
  bd_trough:
#!     ball_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6, s_trough_jam
#!     eject_coil: c_trough_eject
#!     tags: trough, home, drain
#!     jam_switch: s_trough_jam
#!     eject_coil_jam_pulse: 15ms
#!     eject_targets: bd_plunger
#!     eject_timeouts: 3s
#!     # bd_plunger is a placeholder just so the trough's eject_targets are valid
#!   bd_plunger:
#!     ball_switches: s_plunger
#!     mechanical_eject: true
#!     eject_timeouts: 5s
#! playfields:
#!   playfield:
#!     default_source_device: bd_plunger
#!     tags: default
#! virtual_platform_start_active_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6

This means that you're creating a ball device called bd_trough. We use the preface bd_ to indicate that this is a ball device which makes it easier when we're referencing them later. Then under your bd_trough: entry, start entering the configuration settings for your trough ball device:

3a. Add your trough switches to your trough ball device

Indented under bd_trough:, create an entry called ball_switches: and then add a comma-separated list of all the switches in your trough, like this:

#! switches:
#!   s_trough1:
#!     number: 2
#!   s_trough2:
#!     number: 3
#!   s_trough3:
#!     number: 4
#!   s_trough4:
#!     number: 5
#!   s_trough5:
#!     number: 6
#!   s_trough6:
#!     number: 7
#!   s_trough_jam:
#!     number: 8
#!   s_plunger:
#!     number: 10
#! coils:
#!   c_trough_eject:
#!     number: 4
#!     default_pulse_ms: 20
ball_devices:
  bd_trough:
    ball_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6, s_trough_jam
#!     eject_coil: c_trough_eject
#!     tags: trough, home, drain
#!     jam_switch: s_trough_jam
#!     eject_coil_jam_pulse: 15ms
#!     eject_targets: bd_plunger
#!     eject_timeouts: 3s
#!     # bd_plunger is a placeholder just so the trough's eject_targets are valid
#!   bd_plunger:
#!     ball_switches: s_plunger
#!     mechanical_eject: true
#!     eject_timeouts: 5s
#! playfields:
#!   playfield:
#!     default_source_device: bd_plunger
#!     tags: default
#! virtual_platform_start_active_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6

So this is eight spaces, followed by the word "ball_switches", then a colon, then a space, then the name of your first switch, comma, then your second switch, comma, etc...

Again these switches can be in any order. The key is that you're entering one switch for each position that's used to detect whether a ball is in the trough at that position.

If you have the switch in the jam position, enter it in this list too, since a ball sitting on top of another one still "counts" as a ball in the trough.

The number of switches you enter here will tell MPF how many balls your trough can hold. When MPF wants to know how many balls are in the trough, it will check all these switches to see which ones are active, and the total number active represents how many balls it's holding at that moment.

3b. Add your eject coil to your trough ball device

Next create a setting called eject_coil: which will be the name of the coil that MPF should fire when it wants to eject a ball from the trough. This should be the name of the coil you added in Step 2, c_trough_eject in our case:

#! switches:
#!   s_trough1:
#!     number: 2
#!   s_trough2:
#!     number: 3
#!   s_trough3:
#!     number: 4
#!   s_trough4:
#!     number: 5
#!   s_trough5:
#!     number: 6
#!   s_trough6:
#!     number: 7
#!   s_trough_jam:
#!     number: 8
#!   s_plunger:
#!     number: 10
#! coils:
#!   c_trough_eject:
#!     number: 4
#!     default_pulse_ms: 20
ball_devices:
  bd_trough:
    ball_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6, s_trough_jam
    eject_coil: c_trough_eject
#!     tags: trough, home, drain
#!     jam_switch: s_trough_jam
#!     eject_coil_jam_pulse: 15ms
#!     eject_targets: bd_plunger
#!     eject_timeouts: 3s
#!     # bd_plunger is a placeholder just so the trough's eject_targets are valid
#!   bd_plunger:
#!     ball_switches: s_plunger
#!     mechanical_eject: true
#!     eject_timeouts: 5s
#! playfields:
#!   playfield:
#!     default_source_device: bd_plunger
#!     tags: default
#! virtual_platform_start_active_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6

Note that MPF will simply pulse the eject coil at its default pulse time when it wants to eject a ball from the trough.

3c. Add some tags to tell MPF about this device

The final configuration setting you need to enter for your trough is a list of tags which tell MPF certain things about this device.

Tags are just a comma-separated list of words you add to the tags: setting for a device. Ball devices can use some special tag names that tell MPF how it should use it.

First, add a tag called trough which tells MPF that a ball device wants to hold as many balls as it can. This probably doesn't make sense right now, which is fine, but without this tag then MPF won't know what to do with all the balls that are sitting in the trough waiting to be launched. This tag tells MPF that it's fine for this device to hold lots of balls.

Next, add a tag called home which tells MPF that any balls in this device are considered to be in their "home" positions. When MPF first starts up, and after a game ends, it will automatically eject any balls from any devices that are not tagged with "home." When a player tries to start a game, MPF will also make sure all the balls in the machine are contained in devices tagged with "home."

Finally, you need to add a tag called drain which is used to tell MPF that a ball entering this device means that a live ball has drained from the playfield. At this point you might be wondering why you have to enter all three of these tags. Why can't the simple trough tag be enough to tell MPF that a ball entering it should trigger a drain and that balls are home? This is due to the flexibility of MPF and the nearly unlimited variations of pinball machine hardware in the world. Some machines have multiple troughs. Some machines have drain devices which aren't troughs. Some machines consider balls outside the trough to be home. So even though these all might seem similar, just know that for now you have to add trough, home, and drain tags to your trough. You can specify the tags in any order, and your tags: entry should look something like this:

#! switches:
#!   s_trough1:
#!     number: 2
#!   s_trough2:
#!     number: 3
#!   s_trough3:
#!     number: 4
#!   s_trough4:
#!     number: 5
#!   s_trough5:
#!     number: 6
#!   s_trough6:
#!     number: 7
#!   s_trough_jam:
#!     number: 8
#!   s_plunger:
#!     number: 10
#! coils:
#!   c_trough_eject:
#!     number: 4
#!     default_pulse_ms: 20
ball_devices:
  bd_trough:
    ball_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6, s_trough_jam
    eject_coil: c_trough_eject
    tags: trough, home, drain
#!     jam_switch: s_trough_jam
#!     eject_coil_jam_pulse: 15ms
#!     eject_targets: bd_plunger
#!     eject_timeouts: 3s
#!     # bd_plunger is a placeholder just so the trough's eject_targets are valid
#!   bd_plunger:
#!     ball_switches: s_plunger
#!     mechanical_eject: true
#!     eject_timeouts: 5s
#! playfields:
#!   playfield:
#!     default_source_device: bd_plunger
#!     tags: default
#! virtual_platform_start_active_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6

3d. Add & configure your jam switch

If you have a jam switch, add a setting called jam_switch: and add it there, like this:

#! switches:
#!   s_trough1:
#!     number: 2
#!   s_trough2:
#!     number: 3
#!   s_trough3:
#!     number: 4
#!   s_trough4:
#!     number: 5
#!   s_trough5:
#!     number: 6
#!   s_trough6:
#!     number: 7
#!   s_trough_jam:
#!     number: 8
#!   s_plunger:
#!     number: 10
#! coils:
#!   c_trough_eject:
#!     number: 4
#!     default_pulse_ms: 20
ball_devices:
  bd_trough:
    ball_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6, s_trough_jam
    eject_coil: c_trough_eject
    tags: trough, home, drain
    jam_switch: s_trough_jam
#!     eject_coil_jam_pulse: 15ms
#!     eject_targets: bd_plunger
#!     eject_timeouts: 3s
#!     # bd_plunger is a placeholder just so the trough's eject_targets are valid
#!   bd_plunger:
#!     ball_switches: s_plunger
#!     mechanical_eject: true
#!     eject_timeouts: 5s
#! playfields:
#!   playfield:
#!     default_source_device: bd_plunger
#!     tags: default
#! virtual_platform_start_active_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6

You can also configure an eject pulse time (in ms) that will be used when the trough wants to eject a ball but the jam switch is active. You'll have to play with your actual trough to see what this time should be. In most cases it's actually less time than the regular eject pulse time, because in most cases, the regular pulse time will kick out two balls (the jammed ball and the one below it).

So for our example, we'll set the jam pulse time to 15ms.

#! switches:
#!   s_trough1:
#!     number: 2
#!   s_trough2:
#!     number: 3
#!   s_trough3:
#!     number: 4
#!   s_trough4:
#!     number: 5
#!   s_trough5:
#!     number: 6
#!   s_trough6:
#!     number: 7
#!   s_trough_jam:
#!     number: 8
#!   s_plunger:
#!     number: 10
#! coils:
#!   c_trough_eject:
#!     number: 4
#!     default_pulse_ms: 20
ball_devices:
  bd_trough:
    ball_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6, s_trough_jam
    eject_coil: c_trough_eject
    tags: trough, home, drain
    jam_switch: s_trough_jam
    eject_coil_jam_pulse: 15ms
#!     eject_targets: bd_plunger
#!     eject_timeouts: 3s
#!     # bd_plunger is a placeholder just so the trough's eject_targets are valid
#!   bd_plunger:
#!     ball_switches: s_plunger
#!     mechanical_eject: true
#!     eject_timeouts: 5s
#! playfields:
#!   playfield:
#!     default_source_device: bd_plunger
#!     tags: default
#! virtual_platform_start_active_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6

(Note that this setting is a time string, so you can include the "ms" in the setting value.)

4. Configure your virtual hardware to start with balls in the trough

While we're talking about the trough, it's probably a good idea to configure MPF so that when you start it in virtual mode (with no physical hardware) that it starts with the trough full of balls. To do this, add a new section to your config file called virtual_platform_start_active_switches:. (Sorry this entry name is hilariously long.) As its name implies, virtual_platform_start_active_switches: lets you list the names of switches that you want to start in the "active" state when you're running MPF with the virtual platform interfaces.

The reason these only work with the virtual platforms is because if you're running MPF while connected to a physical pinball machine, it doesn't really make sense to tell MPF which switches are active since MPF can read the actual switches from the physical machine. So you can add this section to your config file, but MPF only reads this section when you're running with one of the virtual hardware interfaces. To use it, simply add the section along with a list of the switches you want to start active. For example:

#! switches:
#!   s_trough1:
#!     number: 2
#!     type: NC
#!   s_trough2:
#!     number: 3
#!     type: NC
#!   s_trough3:
#!     number: 4
#!     type: NC
#!   s_trough4:
#!     number: 5
#!     type: NC
#!   s_trough5:
#!     number: 6
#!     type: NC
#!   s_trough6:
#!     number: 7
#!     type: NC
#!   s_trough_jam:
#!     number: 8
#!     type: NC
#!   s_plunger:
#!     number: 10
virtual_platform_start_active_switches:
  - s_trough1
  - s_trough2
  - s_trough3
  - s_trough4
  - s_trough5
  - s_trough6

5. Add your plunger lane

Remember that ball devices in MPF know what their "target" devices are, meaning that they understand the chain of devices the ball path takes. (For example, the trough ejects to the plunger lane which ejects to the playfield which drains to the trough...)

So in order to completely configure your trough, you need to tell it the name of thes devices that it ejects to. For the purposes of this How To guide, we'll just create a placeholder plunger lane called bd_plunger, though you should see the Plungers & Ball Launch Devices documentation for full details since there are lots of different types of plungers.

You add an eject target via the eject_targets: section, like this:

#! switches:
#!   s_trough1:
#!     number: 2
#!     type: NC
#!   s_trough2:
#!     number: 3
#!     type: NC
#!   s_trough3:
#!     number: 4
#!     type: NC
#!   s_trough4:
#!     number: 5
#!     type: NC
#!   s_trough5:
#!     number: 6
#!     type: NC
#!   s_trough6:
#!     number: 7
#!     type: NC
#!   s_trough_jam:
#!     number: 8
#!     type: NC
#!   s_plunger:
#!     number: 10
#! coils:
#!   c_trough_eject:
#!     number: 4
#!     default_pulse_ms: 20
ball_devices:
  bd_trough:
    ball_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6, s_trough_jam
    eject_coil: c_trough_eject
    tags: trough, home, drain
    jam_switch: s_trough_jam
    eject_coil_jam_pulse: 15ms
    eject_targets: bd_plunger
#!     eject_timeouts: 3s
  bd_plunger:
    ball_switches: s_plunger
    mechanical_eject: true
#!     eject_timeouts: 5s
#! playfields:
#!   playfield:
#!     default_source_device: bd_plunger
#!     tags: default
#! virtual_platform_start_active_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6

Of course you should enter the name of your actual plunger lane / ball launcher device.

Note that the eject_targets: entry is "targets" (plural), but in this case we're only adding a single target. That's fine and how you would configure a trough since it only ejects to one place (the plunger lane). Some devices eject to pathways with diverters which can direct the ball to multiple different places, so that's the scenario where you'd enter more than one target. But for the trough, it's just the one.

6. Configure eject timeouts

Your trough will try to eject as fast as possible (i.e. during a multiball) but it has to wait that ball cannot return and stack up. By default MPF will wait 10s after a ball to make sure that it settled in the shooter lane or returned (in the latter case the trough will retry the eject). For the trough this works fine if the ball actually settles in the shooter lane but sometimes a player might as well launch the ball without hitting the plunger switch. For that reason it is important to set eject_timeouts to your shooter lane and your trough. You should measure how long the maximum time is until a ball cannot possibly return to your trough and plunger (with some safety margin). Usually this is about 2s - 4s for a trough and 3s - 5s for a plunger.

#! switches:
#!   s_trough1:
#!     number: 2
#!     type: NC
#!   s_trough2:
#!     number: 3
#!     type: NC
#!   s_trough3:
#!     number: 4
#!     type: NC
#!   s_trough4:
#!     number: 5
#!     type: NC
#!   s_trough5:
#!     number: 6
#!     type: NC
#!   s_trough6:
#!     number: 7
#!     type: NC
#!   s_trough_jam:
#!     number: 8
#!     type: NC
#!   s_plunger:
#!     number: 10
#! coils:
#!   c_trough_eject:
#!     number: 4
#!     default_pulse_ms: 20
ball_devices:
  bd_trough:
    ball_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6, s_trough_jam
    eject_coil: c_trough_eject
    tags: trough, home, drain
    jam_switch: s_trough_jam
    eject_coil_jam_pulse: 15ms
    eject_targets: bd_plunger
    eject_timeouts: 3s
  bd_plunger:
    ball_switches: s_plunger
    mechanical_eject: true
    eject_timeouts: 5s
#! playfields:
#!   playfield:
#!     default_source_device: bd_plunger
#!     tags: default
#! virtual_platform_start_active_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6

Here's the complete config

switches:
  s_trough1:
    number: 2
    type: NC
  s_trough2:
    number: 3
    type: NC
  s_trough3:
    number: 4
    type: NC
  s_trough4:
    number: 5
    type: NC
  s_trough5:
    number: 6
    type: NC
  s_trough6:
    number: 7
    type: NC
  s_trough_jam:
    number: 8
    type: NC
  s_plunger:
    number: 10
coils:
  c_trough_eject:
    number: 4
    default_pulse_ms: 20
ball_devices:
  bd_trough:
    ball_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6, s_trough_jam
    eject_coil: c_trough_eject
    tags: trough, home, drain
    jam_switch: s_trough_jam
    eject_coil_jam_pulse: 15ms
    eject_targets: bd_plunger
    eject_timeouts: 3s
  bd_plunger:
    ball_switches: s_plunger
    mechanical_eject: true
    eject_timeouts: 5s
playfields:
  playfield:
    default_source_device: bd_plunger
    tags: default
virtual_platform_start_active_switches: s_trough1, s_trough2, s_trough3, s_trough4, s_trough5, s_trough6

What if it doesn't work?

Have a look at our troubleshooting guide for ball_devices.


Something missing or wrong? You can fix it!

This website is edited by people like you! Is something wrong or missing? Is something out of date, or can you explain it better?

Please help us! You can fix it yourself and be an official "open source" contributor!

It's easy! See our Beginner's guide to editing the docs.

Page navigation via the keyboard: < >

You can navigate this site via the keyboard. There are two modes:

General navigation, when search is not focused:

  • F , S , / : open search dialog
  • P , , : go to previous page
  • N , . : go to next page

While using the search function:

  • Down , Up : select next / previous result
  • Esc , Tab : close search
  • Enter : go to highlighted page in the results