This electronics and software project was suggested by an excellent article in the MagPi magazine, issue 5. It's called "Steady Hands", and basically involves trying to move a small wire loop along a bendy wire without touching it. Typically it should have a buzzer and a red light on top which both go crazy if you accidentally touch the wire.
The MagPi article starts very simply and gives a starting point for any Pi owner to take further. You could of course just build the electronics side with the buzzer and not use a Pi at all, but the Pi lets us use the tv screen to guide the player to the start, time how long it takes to get to the other end, and perhaps impose time penalties for every time that the wire was touched.
This picture shows MagPi's setup, from the cover of issue 5. It shows the bendy wire and the handle, with contacts attached to a block of wood for a base. All four of those wires then get attached to the GPIO pins of the Raspberry Pi. On the screen you can see the output of the included python program, which just uses a terminal window to write out the current status.
There's lots more about this, very well explained, in Issue 5 of the free MagPi magazine. And the author, Mike Cook, has even produced a delightful video demonstrating his creation, containing additional sound effects which weren't covered in the original article.
There are several aspects to a little project like this, and the descriptions in the MagPi article provide an excellent starting point. The three main areas to consider, which can be more or less done in parallel at the beginning, are as follows:
I considered that polystyrene would be easy to work with (and I had some spare from box packaging), but thought it would be too light and possibly prone to tipping over. A plastic box would have probably been ok, but I came across a little piece of firewood which fit the bill. I decided to feed the connections through the base rather than just have dangling wires on the top, so I drilled access holes through the wood.
I wanted the wire to be fairly stable, so I got a 1 metre long 2mm threaded wire from the local DIY shop. I also got a 1 metre length of thin plastic pipe to use for the "collars" around the wire and for the handle. Finally, to form the start and end connectors, I considered using nails, hooks, big washers or even metal thimbles, but finally settled on beer bottle tops. These had to have holes drilled through for the collars, and their painted coating removed with a file, on the top and on the base where the wires were going to be attached, because otherwise there would be no electrical connection. For the collars I just sawed the plastic pipe to size with a hacksaw. For the connection to the Pi I needed four wires (start, end, bent wire and handle) so used two lengths of two-core speaker wire.
The main thing here was connecting the wires to the bottle tops, the threaded wire, and the Raspberry Pi. By using the Pi's internal pull-up resistors on the GPIO inputs, I avoid the need for any kind of resistors, capacitors or any other kind of component, we're just interested in electrical connections here.
I found a short 10-pin ribbon cable used for some kind of internal computer connection, which was about to be thrown out. So I cut one end off this, stripped the wires bare and examined which of the wires were connected to which of the connectors. Then I just took the four I needed (deduced from playing with the MagPi software) and soldered them to the speaker wire. For lack of electrical insulating tape or heat-shrink sleeving, I used sellotape to protect these connections from each other. The other ends of the speaker wire got soldered to the bottle tops (relatively easy) and to the threaded wire (not so easy).
For the visuals, I decided not to go with LEDs but to use the tv screen to flash red instead. And no buzzer, just an audio output to the stereo. So that made everything simpler.
As already noted, the MagPi software worked fine and I could play with that easily using little wires attached directly to the GPIO pins. The handle is attached to the ground, and the other wires are connected to three GPIO pins configured to inputs with internal pull-up resistors.
The next step was to get PyQt working, and show a clock using the QLCDNumber. This is where QStopWatch came to the rescue, offering an easy way to show such a clock on the tv screen. By merging bits of these two programs together, and extending it to use Rpi.GPIO's new event detection callbacks (and PyQt's signals and slots), I arrived at the simple, full-screen GUI shown here. On the tv there's no LXDE taskbar visible, just the clock and the message area below.
One important addition was the sounds. Especially when you accidentally touch the wire, I wanted a "Bzzzz" sound. This was done by recording vocal sound effects with Audacity, saving as 16-bit wavs and playing them back using
pygame. These sounds then come through the Pi's headphone socket to an adaptor, and from there into the Line-In of a stereo amplifier. There are also sound effects for starting and finishing a game. Maybe there could be different effects for a new high-score.
After you successfully reach the end, you're ready to start the next game. It would be awkward to make you go all the way back to the start again, so why not just reverse direction? This simple change to the program makes it much faster to "just have another go", so you can easily go backwards and forwards.
To make it more addictive, I also added a high-score table to remember the best times. In fact, I ended up adding two high-score tables, one for the best times without any buzzes at all, and another for the best times with buzzes. So it's easy for younger players to get on the high-score table, but there's still the challenge of getting to the top of the buzz-free table. I guess you could convert the number of buzzes into a number of penalty seconds, and just keep them all in the same table, but this way avoids the arbitrary conversion factor. Currently these high-scores are only held in memory, so they're forgotten when you exit the game. One possible extension would be to save these to a file and load them up again next time it's run.