ball not recognized by plunger lane (sometimes)

67 views
Skip to first unread message

Kalle Heinz

unread,
May 5, 2026, 5:14:17 AM (8 days ago) May 5
to MPF Users
Hello,

I do have a problem that sometimes  mpf doesn't recognize that my ball is in the plunger lane.

My configuration looks like this

ball_devices:
  bd_trough:
    ball_switches: s_ball_trough_1, s_ball_trough_2, s_ball_trough_3, s_ball_trough_4, s_ball_trough_jam
    eject_coil: c_ball_trough
    tags: trough, home, drain
    jam_switch: s_ball_trough_jam
    eject_coil_jam_pulse: 20ms
    eject_targets: bd_plunger
    debug: true
    confirm_eject_type: switch
    confirm_eject_switch: s_plunger
  bd_plunger:
    ball_switches: s_plunger
    mechanical_eject: true
   
Before we look into the log files, note that there a timer called plunger_inactive, that is a timer which checks if the switch s_plunger is inactive (after being activated) for more than a second to start the ball save time. I believe that can be ignored here in the logs.

In normal situations the log information look like this:

```
     1 026-04-29 20:30:42,062 : DEBUG : ball_device.bd_trough : Firing eject coil. Current balls: 3.
     2 2026-04-29 20:30:42,087 : INFO : SwitchController : <<<<<<< 's_ball_trough_1' inactive >>>>>>>
     3 2026-04-29 20:30:42,088 : INFO : SwitchController : <<<<<<< 's_ball_trough_jam' active >>>>>>>
     4 2026-04-29 20:30:42,088 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_ball_trough_jam'====== Args={'value': 3331, 'prev_value': 3330, 'change': 1}
     5 2026-04-29 20:30:42,089 : DEBUG : ball_device.bd_trough : SC: Ball left. Old count: 3
     6 2026-04-29 20:30:42,089 : DEBUG : ball_device.bd_trough : Got ball left during eject
     7 2026-04-29 20:30:42,090 : DEBUG : ball_device.bd_trough : SC: Switch 's_ball_trough_1' changed too recently. Aborting count!
     8 2026-04-29 20:30:42,090 : INFO : ball_device.bd_trough : State: ball_left
     9 2026-04-29 20:30:42,090 : INFO : ball_device.bd_trough : Ball left
    10 2026-04-29 20:30:42,090 : INFO : ball_device.bd_trough : Wait for confirm with timeout 10.0
    11 2026-04-29 20:30:42,099 : INFO : SwitchController : <<<<<<< 's_ball_trough_jam' inactive >>>>>>>
    12 2026-04-29 20:30:42,249 : INFO : SwitchController : <<<<<<< 's_ball_trough_3' inactive >>>>>>>
    13 2026-04-29 20:30:42,249 : INFO : SwitchController : <<<<<<< 's_ball_trough_2' inactive >>>>>>>
    14 2026-04-29 20:30:42,319 : INFO : SwitchController : <<<<<<< 's_ball_trough_1' active >>>>>>>
    15 2026-04-29 20:30:42,319 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_ball_trough_1'====== Args={'value': 3654, 'prev_value': 3653, 'change': 1}
    16 2026-04-29 20:30:42,341 : INFO : SwitchController : <<<<<<< 's_ball_trough_2' active >>>>>>>
    17 2026-04-29 20:30:42,341 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_ball_trough_2'====== Args={'value': 5856, 'prev_value': 5855, 'change': 1}
    18 2026-04-29 20:30:42,600 : DEBUG : ball_device.bd_trough : SC: Switch 's_ball_trough_3' changed too recently. Aborting count!
    19 2026-04-29 20:30:42,749 : DEBUG : ball_device.bd_trough : SC: Switch 's_ball_trough_2' changed too recently. Aborting count!
    20 2026-04-29 20:30:42,819 : DEBUG : ball_device.bd_trough : SC: Switch 's_ball_trough_2' changed too recently. Aborting count!
    21 2026-04-29 20:30:42,841 : DEBUG : ball_device.bd_trough : SC: Counted 2 balls. Active switches: [<switch.s_ball_trough_2>, <switch.s_ball_trough_1>]. Old: 2
    22 2026-04-29 20:30:42,842 : DEBUG : ball_device.bd_trough : SC: New count 2 last: 2
    23 2026-04-29 20:30:43,331 : INFO : SwitchController : <<<<<<< 's_plunger' active >>>>>>>
    24 2026-04-29 20:30:43,331 : INFO : EventManager : Event: ======'s_plunger_active'====== Args={}
    25 2026-04-29 20:30:43,331 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_plunger'====== Args={'value': 5700, 'prev_value': 5699, 'change': 1}
    26 2026-04-29 20:30:43,331 : INFO : Timer.plunger_inactive : Stopping Timer
    27 2026-04-29 20:30:43,331 : INFO : EventManager : Event: ======'timer_plunger_inactive_stopped'====== Args={'ticks': 1, 'ticks_remaining': 1}
    28 2026-04-29 20:30:43,332 : INFO : ball_device.bd_trough : Got eject confirm
    29 2026-04-29 20:30:43,332 : INFO : ball_device.bd_trough : Eject successful
    30 2026-04-29 20:30:43,332 : INFO : EventManager : Event: ======'balldevice_bd_trough_ball_eject_success'====== Args={'balls': 1, 'target': <ball_device.bd_plunger>}
    31 2026-04-29 20:30:43,332 : DEBUG : ball_device.bd_trough : Exited eject mode. Eject success: True
    32 2026-04-29 20:30:43,333 : INFO : EventManager : Event: ======'balldevice_bd_trough_ball_count_changed'====== Args={'balls': 2}
    33 2026-04-29 20:30:43,333 : INFO : ball_device.bd_trough : State: idle
    34 2026-04-29 20:30:43,333 : DEBUG : ball_device.bd_trough : Waiting for eject request.
    35 2026-04-29 20:30:43,333 : DEBUG : ball_device.bd_trough : BCH: Counting. New count: 2 Old count: 2
    36 2026-04-29 20:30:43,334 : DEBUG : ball_device.bd_trough : BCH: Counting. New count: 2 Old count: 2
    37 2026-04-29 20:30:43,378 : INFO : SwitchController : <<<<<<< 's_plunger' inactive >>>>>>>
    38 2026-04-29 20:30:43,379 : INFO : EventManager : Event: ======'s_plunger_inactive'====== Args={}
    39 2026-04-29 20:30:43,379 : INFO : Timer.plunger_inactive : Starting Timer.
    40 2026-04-29 20:30:43,379 : INFO : EventManager : Event: ======'timer_plunger_inactive_started'====== Args={'ticks': 1, 'ticks_remaining': 1}
    41 2026-04-29 20:30:43,379 : INFO : EventManager : Event: ======'timer_plunger_inactive_tick'====== Args={'ticks': 1, 'ticks_remaining': 1}
    42 2026-04-29 20:30:43,676 : INFO : SwitchController : <<<<<<< 's_plunger' active >>>>>>>
    43 2026-04-29 20:30:43,676 : INFO : EventManager : Event: ======'s_plunger_active'====== Args={}
    44 2026-04-29 20:30:43,677 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_plunger'====== Args={'value': 5701, 'prev_value': 5700, 'change': 1}
    45 2026-04-29 20:30:43,677 : INFO : Timer.plunger_inactive : Stopping Timer
    46 2026-04-29 20:30:43,677 : INFO : EventManager : Event: ======'timer_plunger_inactive_stopped'====== Args={'ticks': 1, 'ticks_remaining': 1}
    47 2026-04-29 20:30:44,177 : INFO : ball_device.bd_plunger : Received ball from <ball_device.bd_trough>
    48 2026-04-29 20:30:44,178 : INFO : EventManager : Event: ======'balldevice_bd_plunger_ball_enter'====== Args={'new_balls': 1, 'unclaimed_balls': 0, 'new_available_balls': 0, 'device': <ball_device.bd_plunger>}
    49 2026-04-29 20:30:44,178 : INFO : EventManager : Event: ======'balldevice_bd_plunger_ball_entered'====== Args={'new_balls': 0, 'device': <ball_device.bd_plunger>}
    50 2026-04-29 20:30:44,178 : INFO : EventManager : Event: ======'balldevice_bd_plunger_ball_count_changed'====== Args={'balls': 1}
    51 2026-04-29 20:30:44,179 : INFO : ball_device.bd_plunger : State: waiting_for_target_ready
    52 2026-04-29 20:30:44,179 : INFO : EventManager : Event: ======'balldevice_bd_plunger_ball_eject_attempt'====== Args={'balls': 1, 'target': <playfield.playfield>, 'source': <ball_device.bd_plunger>, 'mechanical_eject': False, 'num_attempts': 0}
    53 2026-04-29 20:30:44,179 : INFO : ball_device.bd_plunger : State: ejecting
    54 2026-04-29 20:30:44,179 : INFO : ball_device.bd_plunger : Ejecting ball to <playfield.playfield>
    55 2026-04-29 20:30:44,179 : INFO : EventManager : Event: ======'balldevice_bd_plunger_ejecting_ball'====== Args={'balls': 1, 'target': <playfield.playfield>, 'source': <ball_device.bd_plunger>, 'mechanical_eject': False, 'num_attempts': 0}
    56 2026-04-29 20:30:44,180 : INFO : ball_device.bd_plunger : Wait for ball to leave device
    57 2026-04-29 20:30:44,365 : INFO : SwitchController : <<<<<<< 's_plunger' inactive >>>>>>>
    58 2026-04-29 20:30:44,365 : INFO : EventManager : Event: ======'s_plunger_inactive'====== Args={}
    59 2026-04-29 20:30:44,365 : INFO : Timer.plunger_inactive : Starting Timer.
    60 2026-04-29 20:30:44,365 : INFO : EventManager : Event: ======'timer_plunger_inactive_started'====== Args={'ticks': 1, 'ticks_remaining': 1}
    61 2026-04-29 20:30:44,366 : INFO : EventManager : Event: ======'timer_plunger_inactive_tick'====== Args={'ticks': 1, 'ticks_remaining': 1}
    62 2026-04-29 20:30:44,366 : INFO : ball_device.bd_plunger : State: ball_left
    63 2026-04-29 20:30:44,366 : INFO : ball_device.bd_plunger : Ball left
    64 2026-04-29 20:30:44,366 : INFO : ball_device.bd_plunger : Wait for confirm with timeout 10.0
    65 2026-04-29 20:30:45,366 : DEBUG : Player : Setting 'base_plunger_inactive_tick' to: 0, (prior: 1, change: -1)
    66 2026-04-29 20:30:45,366 : INFO : EventManager : Event: ======'player_base_plunger_inactive_tick'====== Args={'value': 0, 'prev_value': 1, 'change': -1, 'player_num': 2}
    67 2026-04-29 20:30:45,366 : INFO : Timer.plunger_inactive : Timer Complete
    68 2026-04-29 20:30:45,366 : INFO : Timer.plunger_inactive : Stopping Timer
    69 2026-04-29 20:30:45,366 : INFO : EventManager : Event: ======'timer_plunger_inactive_stopped'====== Args={'ticks': 0, 'ticks_remaining': 1}
    70 2026-04-29 20:30:45,366 : INFO : EventManager : Event: ======'timer_plunger_inactive_complete'====== Args={'ticks': 0, 'ticks_remaining': 1}
    71 2026-04-29 20:30:45,367 : INFO : EventManager : Event: ======'ball_save_default_timer_start'====== Args={}
    72 2026-04-29 20:30:48,038 : INFO : SwitchController : <<<<<<< 's_right_flipper' active >>>>>>>
    73 2026-04-29 20:30:48,039 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_right_flipper'====== Args={'value': 16947, 'prev_value': 16946, 'change': 1}
    74 2026-04-29 20:30:49,199 : INFO : SwitchController : <<<<<<< 's_right_flipper' inactive >>>>>>>
    75 2026-04-29 20:30:49,289 : INFO : SwitchController : <<<<<<< 's_ramp' active >>>>>>>
    76 2026-04-29 20:30:49,290 : INFO : EventManager : Event: ======'playfield_active'====== Args={'source': 'ramp_sequence_shot'}
```
    
In above log file look at lines 47 - 52, here we see that the plunger has received a ball. I assumed that this is being decided based on my configured switch s_plunger, but I am not sure anymore. Now let us take a look at an example where it fails:

```
     1 026-04-29 20:33:19,417 : DEBUG : ball_device.bd_trough : Firing eject coil. Current balls: 3.
     2 2026-04-29 20:33:19,445 : INFO : SwitchController : <<<<<<< 's_ball_trough_1' inactive >>>>>>>
     3 2026-04-29 20:33:19,445 : INFO : SwitchController : <<<<<<< 's_ball_trough_jam' active >>>>>>>
     4 2026-04-29 20:33:19,446 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_ball_trough_jam'====== Args={'value': 3336, 'prev_value': 3335, 'change': 1}
     5 2026-04-29 20:33:19,446 : DEBUG : ball_device.bd_trough : SC: Ball left. Old count: 3
     6 2026-04-29 20:33:19,447 : DEBUG : ball_device.bd_trough : Got ball left during eject
     7 2026-04-29 20:33:19,447 : DEBUG : ball_device.bd_trough : SC: Switch 's_ball_trough_1' changed too recently. Aborting count!
     8 2026-04-29 20:33:19,447 : INFO : ball_device.bd_trough : State: ball_left
     9 2026-04-29 20:33:19,447 : INFO : ball_device.bd_trough : Ball left
    10 2026-04-29 20:33:19,448 : INFO : ball_device.bd_trough : Wait for confirm with timeout 10.0
    11 2026-04-29 20:33:19,458 : INFO : SwitchController : <<<<<<< 's_ball_trough_jam' inactive >>>>>>>
    12 2026-04-29 20:33:19,601 : INFO : SwitchController : <<<<<<< 's_ball_trough_3' inactive >>>>>>>
    13 2026-04-29 20:33:19,602 : INFO : SwitchController : <<<<<<< 's_ball_trough_2' inactive >>>>>>>
    14 2026-04-29 20:33:19,670 : INFO : SwitchController : <<<<<<< 's_ball_trough_1' active >>>>>>>
    15 2026-04-29 20:33:19,670 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_ball_trough_1'====== Args={'value': 3660, 'prev_value': 3659, 'change': 1}
    16 2026-04-29 20:33:19,703 : INFO : SwitchController : <<<<<<< 's_ball_trough_2' active >>>>>>>
    17 2026-04-29 20:33:19,704 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_ball_trough_2'====== Args={'value': 5862, 'prev_value': 5861, 'change': 1}
    18 2026-04-29 20:33:19,959 : DEBUG : ball_device.bd_trough : SC: Switch 's_ball_trough_3' changed too recently. Aborting count!
    19 2026-04-29 20:33:20,103 : DEBUG : ball_device.bd_trough : SC: Switch 's_ball_trough_2' changed too recently. Aborting count!
    20 2026-04-29 20:33:20,170 : DEBUG : ball_device.bd_trough : SC: Switch 's_ball_trough_2' changed too recently. Aborting count!
    21 2026-04-29 20:33:20,204 : DEBUG : ball_device.bd_trough : SC: Counted 2 balls. Active switches: [<switch.s_ball_trough_2>, <switch.s_ball_trough_1>]. Old: 2
    22 2026-04-29 20:33:20,204 : DEBUG : ball_device.bd_trough : SC: New count 2 last: 2
    23 2026-04-29 20:33:20,507 : INFO : SwitchController : <<<<<<< 's_plunger' active >>>>>>>
    24 2026-04-29 20:33:20,507 : INFO : EventManager : Event: ======'s_plunger_active'====== Args={}
    25 2026-04-29 20:33:20,507 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_plunger'====== Args={'value': 5709, 'prev_value': 5708, 'change': 1}
    26 2026-04-29 20:33:20,508 : INFO : Timer.plunger_inactive : Stopping Timer
    27 2026-04-29 20:33:20,508 : INFO : EventManager : Event: ======'timer_plunger_inactive_stopped'====== Args={'ticks': 1, 'ticks_remaining': 1}
    28 2026-04-29 20:33:20,508 : INFO : ball_device.bd_trough : Got eject confirm
    29 2026-04-29 20:33:20,509 : INFO : ball_device.bd_trough : Eject successful
    30 2026-04-29 20:33:20,509 : INFO : EventManager : Event: ======'balldevice_bd_trough_ball_eject_success'====== Args={'balls': 1, 'target': <ball_device.bd_plunger>}
    31 2026-04-29 20:33:20,509 : DEBUG : ball_device.bd_trough : Exited eject mode. Eject success: True
    32 2026-04-29 20:33:20,509 : INFO : EventManager : Event: ======'balldevice_bd_trough_ball_count_changed'====== Args={'balls': 2}
    33 2026-04-29 20:33:20,509 : INFO : ball_device.bd_trough : State: idle
    34 2026-04-29 20:33:20,509 : DEBUG : ball_device.bd_trough : Waiting for eject request.
    35 2026-04-29 20:33:20,510 : DEBUG : ball_device.bd_trough : BCH: Counting. New count: 2 Old count: 2
    36 2026-04-29 20:33:20,510 : DEBUG : ball_device.bd_trough : BCH: Counting. New count: 2 Old count: 2
    37 2026-04-29 20:33:20,825 : INFO : SwitchController : <<<<<<< 's_plunger' inactive >>>>>>>
    38 2026-04-29 20:33:20,826 : INFO : EventManager : Event: ======'s_plunger_inactive'====== Args={}
    39 2026-04-29 20:33:20,826 : INFO : Timer.plunger_inactive : Starting Timer.
    40 2026-04-29 20:33:20,826 : INFO : EventManager : Event: ======'timer_plunger_inactive_started'====== Args={'ticks': 1, 'ticks_remaining': 1}
    41 2026-04-29 20:33:20,826 : INFO : EventManager : Event: ======'timer_plunger_inactive_tick'====== Args={'ticks': 1, 'ticks_remaining': 1}
    42 2026-04-29 20:33:21,827 : DEBUG : Player : Setting 'base_plunger_inactive_tick' to: 0, (prior: 1, change: -1)
    43 2026-04-29 20:33:21,827 : INFO : EventManager : Event: ======'player_base_plunger_inactive_tick'====== Args={'value': 0, 'prev_value': 1, 'change': -1, 'player_num': 1}
    44 2026-04-29 20:33:21,827 : INFO : Timer.plunger_inactive : Timer Complete
    45 2026-04-29 20:33:21,827 : INFO : Timer.plunger_inactive : Stopping Timer
    46 2026-04-29 20:33:21,828 : INFO : EventManager : Event: ======'timer_plunger_inactive_stopped'====== Args={'ticks': 0, 'ticks_remaining': 1}
    47 2026-04-29 20:33:21,828 : INFO : EventManager : Event: ======'timer_plunger_inactive_complete'====== Args={'ticks': 0, 'ticks_remaining': 1}
    48 2026-04-29 20:33:21,828 : INFO : EventManager : Event: ======'ball_save_default_timer_start'====== Args={}
    49 2026-04-29 20:33:23,010 : INFO : SwitchController : <<<<<<< 's_slingshot_right' active >>>>>>>
    50 2026-04-29 20:33:23,010 : INFO : EventManager : Event: ======'s_slingshot_right_active'====== Args={}
    51 2026-04-29 20:33:23,010 : INFO : EventManager : Event: ======'playfield_active'====== Args={'source': 'ac_slingshot_right'}
    52 2026-04-29 20:33:23,011 : INFO : EventManager : Event: ======'unexpected_ball_on_playfield'====== Args={}
    53 2026-04-29 20:33:23,011 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_slingshot_right'====== Args={'value': 3816, 'prev_value': 3815, 'change': 1}
    54 2026-04-29 20:33:23,012 : DEBUG : Player : Setting 'score' to: 2730, (prior: 2680, change: 50)
    55 2026-04-29 20:33:23,012 : INFO : EventManager : Event: ======'player_score'====== Args={'value': 2730, 'prev_value': 2680, 'change': 50, 'player_num': 1, 'source': 'base'}
    56 2026-04-29 20:33:23,020 : INFO : EventManager : Event: ======'machine_var_machine_score_player1'====== Args={'value': 2730, 'prev_value': 2680, 'change': 50}
    57 2026-04-29 20:33:23,038 : INFO : SwitchController : <<<<<<< 's_slingshot_right' inactive >>>>>>>
```

Now there is no entry in this log file that the plunger has received a ball. We do see though, e.g. line 23, that my switch s_plunger is active. So a faulty switch I would rule out. I have no idea why it comes to that situation once in a while, my though was that s_plunger would confirm that the ball has left the trough and is on the plunger lane. Now I assume there is more behind it.

The question behind it is not of academic nature, the real problem is now the following:

- if the ball stays in play until a certain timeout is reached, mpf assumes that the ball is on the playfield --> all good (see lots of unexpected_ball_on_playfield messages until that timeout)
- if the ball drains before that timeout is reached, mpf would _not_ kick out the next ball for the next player and I have to kill mpf and restart

```
2026-04-29 20:40:23,336 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_ball_trough_4'====== Args={'value': 5472, 'prev_value': 5471, 'change': 1}
2026-04-29 20:40:23,385 : INFO : SwitchController : <<<<<<< 's_ball_trough_4' inactive >>>>>>>
2026-04-29 20:40:23,419 : INFO : SwitchController : <<<<<<< 's_ball_trough_3' active >>>>>>>
2026-04-29 20:40:23,419 : INFO : EventManager : Event: ======'machine_var_audits_switches_s_ball_trough_3'====== Args={'value': 5541, 'prev_value': 5540, 'change': 1}
2026-04-29 20:40:23,886 : DEBUG : ball_device.bd_trough : SC: Switch 's_ball_trough_3' changed too recently. Aborting count!
2026-04-29 20:40:23,919 : DEBUG : ball_device.bd_trough : SC: Counted 3 balls. Active switches: [<switch.s_ball_trough_3>, <switch.s_ball_trough_2>, <switch.s_ball_trough_1>]. Old: 2
2026-04-29 20:40:23,920 : DEBUG : ball_device.bd_trough : SC: New count 3 last: 2
2026-04-29 20:40:23,920 : DEBUG : ball_device.bd_trough : SC: Updating count to 3
2026-04-29 20:40:23,920 : DEBUG : ball_device.bd_trough : BCH: Counting. New count: 3 Old count: 2
2026-04-29 20:40:23,920 : DEBUG : ball_device.bd_trough : BCH: Found 1 new balls
2026-04-29 20:40:23,920 : INFO : EventManager : Event: ======'balldevice_bd_trough_ball_count_changed'====== Args={'balls': 3}
2026-04-29 20:40:23,920 : INFO : ball_device.bd_trough : Received unexpected ball
2026-04-29 20:40:23,921 : INFO : EventManager : Event: ======'balldevice_captured_from_playfield'====== Args={'balls': 1}
2026-04-29 20:40:23,921 : INFO : EventManager : Event: ======'sw_playfield_active'====== Args={'balls': 1}
2026-04-29 20:40:23,921 : INFO : EventManager : Event: ======'playfield_active'====== Args={'source': None}
2026-04-29 20:40:23,921 : INFO : EventManager : Event: ======'unexpected_ball_on_playfield'====== Args={}
2026-04-29 20:40:23,921 : INFO : EventManager : Event: ======'playfield_ball_count_change'====== Args={'balls': -1, 'change': -1}
```

In above log at the top you see that the trough switches get activated, so the ball drained. In the last line you see that we have -1 balls on the playfield.

Anyone any idea how it can come to such a situation, what I can do about it or even someone who know what I made wrong?

Any help is highly appreciated ! Killing a game just before a new highscore is really frustrating :-(

Thanks!

Ben Tripoli

unread,
May 6, 2026, 9:33:07 PM (6 days ago) May 6
to MPF Users
Try a confirm eject on your plunger. I think you can use 'confirm_eject_event' and maybe use the event 'playfield_active'
I also use a timeout, my config below

  bd_plunger:
    ball_switches: s_shooter_lane
    mechanical_eject: true
    eject_coil: c_autolaunch
    confirm_eject_type: switch
    confirm_eject_switch: s_gate
    eject_timeouts: 3s

Kalle Heinz

unread,
May 7, 2026, 12:53:06 PM (5 days ago) May 7
to MPF Users
Hi,

thanks for the suggestion, that is a good work around. I have used as event my timer which checks if the s_plunger is inactive for a second, playfield_active is not good for me in case the ball drains without that the playfield is active. Yes unlikely, but you never know.

Now my curiosity kicks in to understand this all a bit better. Your suggestions are only a work around, don't get me wrong probably works for me and I am grateful for the suggestion. What I would like to understand are the following things:

- Why does a plunger with mechanical_eject: true needs to have a confirmation that the ball has left? If fired by a coil yes, because the player has no control and a ball search might have to kick in, but for mechanical plungers?
- My behavior is somewhat erratic (at least to me), is there some bug in mpf or is there some condition I am not able to see?
- In my logs I find

2026-05-02 18:38:15,318 : INFO : EventManager : Event: ======'balldevice_bd_plunger_ball_eject_attempt'====== Args={'balls': 1, 'target': <playfield.playfield>, 'source': <ball_device.bd_plunger>, 'mechanical_eject': False, 'num_attempts': 0}

It claims mechanical_eject: false, but it is set to true in my config. Am I misunderstanding something here, or is here something fishy?
- why do I need a timeout? I get now every 3s a message in the log that the eject failed (if I leave the ball in the plunger lane), but it doesn't seem to have any effect. I would have thought that the timeout would then tell mpf to assume that the ball jumped onto the playfield.

Thanks!

Kalle Heinz

unread,
May 10, 2026, 2:22:04 PM (2 days ago) May 10
to MPF Users
Spoken too soon, issue came back with that new proposed setting. It seems like that the event to confirm the ball left the plunger lane is lost. I do see that the event is fired. But not sure why the confirm is missing.

Philip Dixon

unread,
May 12, 2026, 9:13:00 AM (16 hours ago) May 12
to MPF Users
where to begin.

Ball tough to plunger:

  bd_trough:
    ball_switches: s_ball_trough_1, s_ball_trough_2, s_ball_trough_3, s_ball_trough_4, s_ball_trough_jam
    eject_coil: c_ball_trough
    tags: trough, home, drain
    jam_switch: s_ball_trough_jam
    eject_coil_jam_pulse: 20ms
    eject_targets: bd_plunger
    debug: true
    confirm_eject_type: switch
    confirm_eject_switch: s_plunger

   captures_from: playfield
This closes the loop  trough>plunger>playfield>>trough

  bd_plunger:
    ball_switches: s_plunger
    mechanical_eject: true

but how does the device know if the ball has left the device? Where does it eject to?
Typically you need to have some form of event that signals eject success. Ideally a switch that it must roll over. Remember, never assume!
so add:
    eject_targets: playfield
    ball_missing_timeouts: 3s

so if the ball goes missing from the switch for more than 3 seconds it will flag as left. Not ideal but better.

Ditch the ball save timer and use ball_saves:
ball_saves:
  default:
    active_time: 10s
    hurry_up_time: 2s
    grace_period: 2s
    enable_events: s_plunger_active    
    timer_start_events: s_plunger_inactive
    auto_launch: true
    balls_to_save: 1

This allows for the ball to sit in the plunger lane and not activate the ball save until it leaves. Using a timer assumes that the player immediatley plunges. Maybe they are away from the machine for some reason?

Your game not serving a ball is caused by the machine not knowing what is where, it assumes that there is already a ball in the plunger because it doesnt know it left. It took me 2 years to figure out that the ball_devices code can't quite cope. I had to add a routine to recalculate all the ball device states anytime the ball devices changed:

in python:
        self.machine.ball_controller.dump_ball_counts()

This forces mpf to wipe and reset the devices. 

This line is called each time the base mode starts i.e. every ball start. This 100% fixed the issue for me.

Hope any of this helps, it may or may not fix your problems...
Reply all
Reply to author
Forward
0 new messages