Yeah, it’s been quiet here. I’ve been busy doing not-pinball related things, but I shot this quick video for someone, and figured I’d share it with the rest of you lot.
This doesn’t showcase all of the features in the current build, but it’s more of a mockup of the game using a different theme which I’m considering moving to. The ZOE theme works well enough but it’s a bit hard to expand past it’s current state since most of the assets are hard to obtain, and a lot of the more simple SFX can’t be dug straight from the data files. This mockup was a quick music swap with a currently dead indie shmup, Heaven Variant. I was hoping the developer would toss me some assets to play with, but it seems they’ve been packed away.
In any event, I might keep the music, not sure yet. I’m going to look at moving the code to ARM soon, but I’m waiting for the hardware to arrive.
One of the most worrying problems with pinball systems is that your software will crash, hang, or fall into some horrible infinite loop that leave a solenoid on long past it’s duty cycle, resulting in a nice melty pile of goo.
So what can we do about it? Well, first we need to identify the cases that are likely to result in a locked coil.
1) A variable hold solenoid (such as a diverter or magnet) is on and the C# controller crashes. The arduino doesn’t monitor these solenoids (as we can hold flippers forever!) so bad things can happen. Luckily only a few of these solenoids aren’t full duty cycle.
What we need to know here is if the C# controller is still alive. To do this the arduino watches for heartbeats in the solenoid line. If the PC misses 10 heartbeats (about one second of non-stop failures) the arduino will shut down all power to the pinball machine and wait for a “Power on” signal before continuing.
2) Something goes horribly wrong in the arduino code, while a solenoid is active. This can happen to any solenoid, momentary or otherwise; so this one is a bit scarier.
The solution is however nearly identical to the previous. The C# controller monitors the heartbeats from the arduino and if it doesn’t see any for a long enough period (about 1 second) it uses serial to force a reset. This is possible due to the mega’s 2 chip design, where the serial montior chip is able to watch for the reset command and pull the reset pin on the main ATMega. This case does not however handle a case where the serial monitor chip fails; though this is hopefully a rare case.
3) A transistor shorts.
It’s possible to solve this with hardware but I took the “Use really big transistors that can take the abuse” route instead. A later design may include the ability to detect the state of all transistors and cut power if one is bad, but that’s a lot of engineering for a fairly rare problem.
The heartbeat system itself is fairly simple. There is a timer on the arduino that sends the e_HEARTBEAT signal every 100 ms. When the C# controller gets this signal, it sends it back. This allows the C# side to know if the arduino is dead (No heartbeats being sent) and the arduino to know the same (How many heartbeats we’ve sent since the last time we got a response), which is hopefully a fairly durable system.
This is one of those things that just went a bit too well.
To be fair, it was almost a catastrophe as the trough almost didn’t fit. It’s practically friction fit in against the flipper base. However even with such a narrow margin, everything lines up OK. I was even able to re-install the old back plate around the new assembly so the ball doesn’t fall through the back of the PF. It’s insane how well this all worked out, given how drastically different the old two solenoid williams design is from this modern Stern assembly.
As you you can see, even the old skirt fit back in with zero modifications. It looked like the outhole was going to clip a bit but it clears just fine. I’ve not figured out what to do with the old second solenoid yet (Maybe a flash lamp?), and I haven’t found a good hole in the matrix to squeeze in the jam opto; but it’s not super critical.
As a followup to my previous post, I went in to make some adjustments to the positioning and spotted a tiiiny little problem.
Yeah. Not going to clear the cabinet.
The problem is a number of layers deep. First, I can’t slide the bracket back any more, and even if I could, moving it enough to clear the cabinet would break alignment with the kicker assembly. This is because stern actually mounts this BEHIND the kicker, which clearly isn’t possible in RG because of the trough kicker.
My solution here is to replace the whole trough assembly. A quick set of measurements indicate I can do a complete swap of this unit with the newer Stern assembly with only minor modification to the PF. So that’s on order now… As a bonus I now have a bit more flexibility in the ball count; something I was struggling with before (I was planning on using the drain as a hold for the fourth ball hold which is a logic mess). The assembly can easily be expanded to something insane like 6 balls, so I can have some fun there. The only real annoyance is going to be getting the optos working.
Rollergames didn’t ship with an auto-launch. This is a bit limiting, in that all multiball events must come from locks, and ball saves require a manual “plunge of shame”. While it’s not something I can’t work around, I like auto launches so why not add one?
The coil I chose is very anemic for this playfield, and barely gets it to the mouth of the ramp. Some of this may be due to installation (alignment is a hair off as you can see from the second shot), so I’ll likely replace it with something beefier soon.
I’ll need to order a new switch and bracket for the shooter lane; I thought I could repurpose the old Williams one but it’s too wide; and the switch wire isn’t long enough to work in the new position. Oh well, I hadn’t coded it in yet anyway.
In other news, I ordered a new GI relay to replace the one that worked a whopping two times before never again gracing me with it’s presence. I popped the board out today to install the new one and found two very bad solder joints that just needed a bit of love. On the bright side I’ve not got a spare relay.
As someone with absolutely no experience in pinball design, a lot the design work for the rules is simply trial and error. Often the quickest way to determine if a rule or event works is by simply doing it and throwing a ball into play. However this produces some interesting later stage design challenges that often push you to be a bit more creative.
One thing I noticed early on after building the “Battleship” event was that I felt this obligation to use the drop targets for all “Destruction” events. I wanted that comfortable consistency. However, I quickly noticed that this made the game very boring and one dimensional. It rapidly became Zone of the Drop Targets.
Every time I approach the table now, I have to constantly reset my brain out of this line of thinking to really start doing anything interesting with the table. I’m actually quite happy with the PF in this respect, as Rollergames was never really an event based game. The high level goal was basically just to grab multiball and rack up jackpots. This prevents me from walking in with any pre-conceived notions of how the table should play. Obviously I still have to follow some of the table’s design as a matter of course; Mutliball locks on the right through the ramp, etc.
Well, I didn’t originally intend on going with a Zone of the Enders theme, it just kind of happened. A recent post about ZOE3 being put on hold reminded me about the game, and on a whim I ripped some sounds out of it. Two hours later I was in love.
New things in this video are some higher level things like overarching events. The battleship event takes over the normal Drop target behaviors, and has first stab at handling any switch events before they fall through to the normal event queue.
You’ll note a few bugs here (Final multiball lock) and some old sounds that are now out of place. But there’s still much work to do.
You don’t appreciate just how complex a pinball machine is until you write one. Even something as simple as powering up the machine requires event handling code.
For example, if the previous player lost (or powered the machine down) while balls were locked, we need to get those into the trough to start. There could also be a ball stuck in the second stage ball save, or the pit. Maybe one in all three!
This last state ensures we can’t just ‘Fire all the solenoids!’ as we’d quickly find ourselves with one less fuse on our hands; and for good reason. All three of those solenoids are 50v and even if the fuse was upgraded for it, the power supply would likely choke on the inrush. So we need to separate the events with timers. Not a huge deal… But we also have to consider the mutiball locks are a closed loop, so we need to kick out the diverter at the right time as well.
After solving these problems, I made sure the game state is self contained. This means we can switch in and out of the game state as needed. The idea is when we drain, we’ll hop into a “Collect bonus” state, then launch back into the game state again. The fun complexity here is monitoring and remembering how many balls counts as “drained”, especially once multiple players become involved.
After quickly realizing how much I hate writing tons of giant arrays by hand, I took some time out to write an animation editor.
The goal was simple, write a quick tool to write out lamp state buffers into a hard file. These are then loaded at runtime and can be played at any time.
Overall it was pretty straightforward. The perf of this tool is pretty damn awful and it’s very one-off, but it gets the job done. One thing I did notice is that transparent buttons load VERY slowly, which is kind of annoying since I use transparency to indicate the animation has no preference (Used for localization animations)
Importing and running the animations was dead simple with C#’s DataContractSerializer, it doesn’t even require the target class be the same code as long as the data structures match.