Colour Snap - Hardware Projects - Raspberry Pi Projects (2014)

Raspberry Pi Projects (2014)

Part III. Hardware Projects

Chapter 8. Colour Snap

by Mike Cook

In This Chapter

• Make your first interactive game hardware

• Power an LED safely

• Use surface mount components

• Make boxes simply

• Implement a high-score table

The game in this chapter is just the thing to get going on your first hardware project. There does not seem to be an end to the sorts of things you can do with LEDs and switches. All the projects I have ever worked on, even highly complex transmodulation systems consisting of 8000+ components, have started with an engineer making an LED flash. By adding a bit of imagination you can make something unique with LEDs, and this project is, as far as I know, totally unique. It is a colour snap game.

I am sure that most children have played the card game snap in one form or other either with special cards or a regular pack. The procedure is simple: The pack is divided into two, and the cards are laid face up on the table by alternate players. When two of the same cards are turned up the first player to shout “SNAP!” wins all the cards, but if you shout “SNAP!” and the cards do not match, your opponent gets them. The player to lose all his cards is the loser.

You can implement this as a hardware game in many ways, but the one I have chosen here is to use a coloured light. The light flashes on and off, and each time it comes on, it is normally a different colour from the last time. However, occasionally it will be the same colour as the previous one, and that is the cue for the players to claim a snap by pushing a button. There are no arguments over who pressed first; the computer has split second timing. Also, at the same time the computer shouts out, “SNAP!” in one of two voices, depending on which player was fastest to press the button.

Implementing the Game

So how are you going to implement this game? You need two switches and a source of controllable coloured light. You could use the push switches that are already on the PiFace board, but to make a decent job of the project you will take them off the board into a separate box. (For more information on setting up PiFace, see Chapter 9, “Test Your Reactions”.) For the source of changing colour, you are going to use three LEDs. An LED, or light emitting diode, is a cheap and easy-to-drive source of light, so most hardware projects have at least a few. Moreover, LEDs come in a rich variety of colours. There is however a rather special form of LED which is known as an RGB LED. Basically this is three LEDs in one package: red, green and blue. Using these you can mix up an almost infinite number of colours. So to start off, let’s see how to drive an LED from the PiFace board.

The Theory

Unlike with a flashlight bulb, you can’t connect an LED directly to a source of power. Well, you can, but it will end up burning out. This is because LEDs have a special form of electrical characteristic: They are a nonlinear device. What this means is that unlike other components, such as resistors, the current through LEDs is not directly proportional to the voltage across them. They have an effective resistance that switches sharply depending on the voltage across them. Figure 8.1 shows the graph of voltage against current for a typical LED. You will see that at low voltages there is little or no current through them. As the voltage rises there is little change in current until a sort of threshold is reached, and then a small increase in voltage gives a large increase in current. This threshold, or breakpoint, is known as the forward voltage drop, and you need to run an LED at this voltage. This is not done by supplying a voltage of “just the right value” for various reasons – the two main ones being that producing this right voltage takes some complex electronics and the value that is “right” changes with the temperature and the age of the device.

Figure 8-1: The voltage against current relationship for an LED.

image

What you have to do is to arrange for a constant current through the device. For low-current LEDs, which is what you will be using here, it is simplest to use a resistor to simply limit the current. Most LEDs work with currents of up to a maximum of 20mA, so that is normally the target to aim for, although the more current you have, the brighter the LED will shine. Figure 8.2 shows a resistor and LED connected to a 5V power source.

Figure 8-2: How to use an LED.

image

You want to have 20mA flowing through the LED, and when you do there will be a voltage of 3.2V across the LED. This voltage is said to be dropped across the LED. So first off, how do you know the voltage dropped will be 3.2V? Well, you look it up in the LED’s data sheet. If you haven’t got a data sheet, you guess because the voltage drop of an LED is determined mainly by the material it is made of and the material determines the colour. So most LEDs with the same colour have the same sort of voltage drop; 3.2V is typical for a green one and the newer type of blue LEDs. Red LEDs have a much lower drop of typically 1.8V. So look at Figure 8.2: If there is 3.2V across the LED, there has to be 5 - 3.2 = 1.8V across the resistor. If you know the voltage across a resistor and you know what current you want to have flowing through it, you can calculate the resistance it has to have in Ohms by using Ohm’s law in the form of Resistance equals Voltage over Current, or

R = E / I

E is the voltage in volts, and I is the current in amps. So if you want to have 20mA flowing through the LED, which means 20mA flowing through the resistor as well because these two components are in series, which means the same current flows through both of them, you plug those figures into the formula to get the following:

R = 1.8 / 0.02 = 90 Ohms (also stated as 90R)

Unfortunately, you can’t get a 90R resistor because you can get only certain standard values, but the value closest to 90R is 91R, so you can use that. If you plug that value back into Ohm’s law, you will see that your actual current is

I = E / R = 1.8 / 91 = 19.78mA (which is almost spot on)

So let’s see what happens if the forward voltage drop changes slightly. How will that affect the current? You can plug some different values into the equation, as shown in the graph in Figure 8.3. You can see that the current through the LED doesn’t vary dramatically with small changes in forward voltage like it does when you drive the LED with a fixed voltage. The resistor has acted to minimise variations and stabilise the operating current.

To allow the PiFace board to control an LED, all you need to do is to connect the resistor not to ground but to the PiFace’s output. These outputs are what is known current sinks; that is, they allow current to flow through them to ground, or not, depending on the logic level set by the Raspberry Pi. This means that you can turn the LED on or off by setting the output high or low. When you set the PiFace output high, that makes the current sink through the output buffers and thus allows current to flow through the LED, thus allowing the LED to emit light. What you are going to do for this project is not to have one resistor to sink the current through but to have two. If you arrange the currents the resistors provide carefully, you can get three different brightness levels from one LED. This means having one resistor supply twice the current of the other to give a current of one unit, or two units or three units of current, where three units of current is less than or equal to the maximum working current.

In practice, the eye has a nonlinear response to brightness, so although you might increase the current in equal steps and the light output from the LED changes in equal steps, we do not perceive it as being in equal steps. In fact, the brighter something gets, the less a fixed step in brightness appears to make it change; this is a logarithmic law.

Figure 8-3: Voltage drop against current for an LED and resistor circuit.

image

To make your game, you are going to apply that design to an RGB LED – that is the three colours built into one package. This means that the sources of light are close together and it is easy to get them to mix or blend together. Red, green and blue are the three primary colours, although don’t tell the art department. To be more precise, they are the additive primary colours; that is, when light is added in various amounts in these colours you can make any other colour. When dealing with paint you are restricting the colours it will reflect, which is known as subtractive colour mixing.The subtractive primary colours are yellow, magenta and cyan, although they are often inaccurately referred to as yellow, red and blue.

The final design for the game, as far as the electronics is concerned, is shown in Figure 8.4. It consists of an RGB LED with two resistors on the cathode of each colour. The anodes of all three LEDs are connected to +5V. Many RGB LEDs have these connected together inside the chip and bring out only one anode connection; these are known, not unsurprisingly, as common anode LEDs. The other type you can get is where the cathodes are common. As you might guess, these are called common cathode LEDs and are not the type you want for this project.

The other part of the game is the player switches, which are simply wired between the PiFace’s input connections and ground. When they are pressed the input bit reads as a logic zero. This goes to a logic one when they are released.

Figure 8-4: The schematic for the colour snap game.

image

The construction of the game has two aspects – electrical and mechanical. The electrical is the wiring, resistors, switches and LEDs, and the mechanical is the box and light diffuser. There are many ways of making each aspect; here I will discuss two ways to make the electrical part.

It all hinges on the sort of LED and resistor you use. Traditionally, components have been what is known as through-hole components. That is, they have wires, leads or legs that push though holes in a board and are soldered to a copper laminate on the other side of the board. These components are big and bulky and thus are easy to handle. The newer sort of components are known as surface mount because they are simply soldered onto the surface of a copper laminate. They are small – some say too small – so they reduce the size of the circuit. Also, surface mount LEDs offer flatter and more even illumination than a through-hole part.

Let’s look at the through-hole method of construction first (although I recommend the surface mount instead). Figure 8.5 shows the LED layout using through-hole components. This is built on a small piece of strip board, sometimes known as veroboard. You might come across this being called BusBoard Prototype System, Vectorbord, Circbord, or breadboard but not solderless breadboard.

Figure 8-5: Circuit layout using through-hole components.

image

A piece of strip board 0.8˝ long and 1.6˝ high will suffice, although you can use a bigger size. The dotted lines represent the copper strip on the other side of the board. You will not see them; this is what engineers call hidden detail. There are no tracks to cut, so it is nice and simple. Make sure that the LED is the right way around; note that all the legs are of different length and that the longest one is the anode, as marked in Figure 8.5. Just to make sure, you can test the LED with a multimeter set to resistance. Put the red lead of your meter on the anode, and then by putting the black lead on each of the other legs in turn, you should see a faint glow in the LED for each colour. Make sure that the leads of the LED are bent close to the body so that they align with the hole spacing. Then push the LED down as close as you can to the board, so the LED sits as low as possible. If you have a water-clear package, you can improve the diffusion by lightly sanding the LED with as fine a sandpaper as you can get. This makes the resulting colours blend a lot better.

However, for a much better result, you can use surface mount components. Not only will this be smaller, but the light output also will be flatter and more even, producing a much better distributed level of colour. Surface mount can be a bit scary, but it is not as difficult as you might think. Despite the fact that the RGB LED I used is not the right pitch for the strip board, you can easily make it fit using a scalpel or sharp knife.

Start off with a piece of 0.7˝ by 0.5˝ strip board with the strips running vertically, as shown in Figure 8.6. There are some shaded parts in Figure 8.6 that show the area where you are going to remove the copper. There are two types of cuts you need to make – from the hole to the edge of the strip and between holes. The first is the easiest; simply put the point of the knife in the hole and put the blade at an angle touching the side of the track. With a rotary wrist movement, cut the copper. This will leave a flake of copper standing up. Remove this by repeating the action from the other direction, and remove the copper. You need to do this on both sides of the hole to break the connection.

Figure 8-6: Cutting out some of the copper on a strip board to make the LED fit.

image

There are five holes to cut like this. The next cut is to remove a strip of copper between the holes. Start with your blade in the hole and score down to the next hole. Repeat this for the other side of the hole. Then use the blade and lift out the copper between the two score marks. This sounds complex when written down, but it is actually quite easy to do. In the end you will have split one of the 0.1˝ copper strips into two 0.05˝ spaced strips.

Next you need add the components. Figure 8.7 shows how they are arranged. You need a fine pair of tweezers and a magnifying glass. Take the 5050 LED and make sure that the polarity mark is at the top. It marks the three anodes; if you are not sure, use the multimeter test technique described earlier. The critical point is to line things up so that the left-most two anode connections connect to different strips of the half strip you have cut out. Now remove the LED and just put the smallest dab of solder on the strip board where the left cathode connection is going to be. Now with your iron in one hand and the tweezers with the LED in the other, align the LED again and touch the iron on the solder. Position the LED flat on the board and then remove the iron. Keep the LED still while the solder sets. Now check that it is aligned correctly. If not, reapply the iron and straighten it with the tweezers. Only when you are sure that it is positioned correctly apply solder to the other connections. The anodes should be joined together by applying sufficient solder so that the two tracks are bridged.

Figure 8-7: Circuit layout using surface mount components.

image

Now you need to add the resistors. You could use through hole at this point, but you might as well go for surface mount. A surface mount resistor should sit nicely between the tracks of 0.1˝ pitch strips. Note how surface mount resistors are labeled. They use three numbers: The first two are actual numbers, and the third one says how many zeros there are. So a resistor marked “471” is 470 ohms. There are two sizes that will do this: The larger is known as 0806, and the smaller as 0604; either size will do. (I used the smaller resistor size.) A photograph of the final layout is shown in Figure 8.8. For a prediffuser you can either sand the surface of the LED or glue a small piece of translucent plastic over the top of it.

Figure 8-8: A photograph of the surface mount circuit layout.

image

This LED board, however you make it, will require fixing to a base. You can either use hot melt glue or a larger piece of strip board and drill some holes for fixing. Finally there is the matter of the player switches. I have found that the tactile switches made by NKK are rather good-looking and not too expensive. They come in a round or rectangular style with a variety of coloured tops. For this project I used the JF15SP1C with a red top and the JF15SP1G with the blue top. Of course, you can use any other type of switch you like, as long as it is a momentary push-to-make type. Many switches like this have four connections, and the ones on each side are electrically joined; when the button is pressed one side electrically connects to the other. To prevent confusion about which side is which, I have developed a neat trick: Always connect the wires to two opposite corners and leave the other two unconnected, so you will always have the correct connections.

Creating the Box

The mechanical construction of the box is vital to the final look and feel of the project. Don’t be tempted to skimp here if you want a top-notch result. You can make or buy a box, but by far the most satisfactory choice is to make one. There are many construction techniques you can use as well. With the advent of fab labs and hackspaces, many ordinary people have access to laser cutters, and they can make a very neat job. However, I want to show you a simple but effective method of box construction using only small hand tools and low-cost materials.

You can make the box from 6 mm (1/4˝) plywood. Start by simply cutting out two rectangles 92 mm (3 5/8˝) by 180 mm (7˝). Then clamp them together, and making sure that they are square, drill a 3 mm (1/8˝) hole 10 mm in from each corner. After you drill the first hole remove the clamp and put a nut and bolt to temporary hold the two pieces together while you drill the next hole. Use a nut and bolt for the second hole as well to keep the pieces together while you drill the last two holes. This ensures that your holes line up. You can then use hexagonal tapped spacers to hold the two sheets apart. Make the sides from four lengths of strip pine. The exact height of the strip pine depends on the construction method you used to make the LED board. If you used the surface mount technique, you can make your box nice and thin, using 5 mm strip pine. However, if you used a through-hole LED, you need to use 12 mm strip pine. This is because you want the LED at the same level or slightly below the lid of the box to get good coverage of light on the diffuser. Glue the four pieces of strip pine to the base, and make sure that they are level with the edge of the base. This sandwich arrangement is shown in Figure 8.9.

Figure 8-9: How to put your box together.

image

Mark out four holes for each switch and drill them at 0.8 mm. When fitting the switches, solder some thin wires to the connections in the opposite corners, thread the wires through the holes and push them into place. It should hold simply by the fit, but you can add a blob of glue at the switch center first. Don’t do it yet, though, until the box is finished and painted.

To act as the diffuser and place to see the colour, I used a half table tennis ball. You can cut one in half using various methods, but I found the best way is by using a hot wire cutter of the type sold in hobby shops for cutting expanded polystyrene. Clamp the cutter so that the wire is horizontal to the table, and put the ball in the hole of a stick tape reel to stop it from moving. Then adjust the height of the wire so that it comes as close as possible to the center of the ball, and slide the ball through the wire. Keep your fingers out of the way – that wire is hot! (The clue is in the name –hot wire cutter.) You now have enough half balls to make two games.

Table tennis balls are a standard size of 40 mm, so you need to cut a 40 mm hole in the middle of the top of the box. You can do this easily with a saw drill. Then you have to fix the half ball into this hole. What I did was to take a small square of 1 mm thick styrene sheet, trace a pencil line around the ball and cut out the hole with a scalpel (see Figure 8.10). Then using model airplane glue, I attached the ball to the sheet, as shown in Figure 8.11.

Figure 8-10: The half ball ready to be glued into the supporting base.

image

It is time to paint the box. I decided to make mine a two-tone finish to emphasise the two player’s sides. First give the top and sides of the box a coat of wood primer. Then lightly sand it down and apply the top coat. I used a water-based enamel paint sold in hobby shops. I bought two pots, black and white, and used black for the sides and then mixed a portion of black and white together to make a light grey. I masked off half the top along the middle with painter’s tape and painted the other half grey. I removed the tape while the paint was still wet. When the paint dried, I mixed a little more black with the grey I had made for the first half, masked the join and painted the other side – and again removed the tape while the paint was still wet. This produced a very pleasing effect, and the colours show up well against a grey background.

Figure 8-11: The ball and supporting base resting on the underside of the box’s lid.

image

It’s time to put it all together! Figure 8.12 shows the view with the lid off.

Mount the LED board in the center of the base with either two screws as shown here or a spot of glue. You can glue the diffuser table tennis board and its sheet through the hole in the lid. The wires from the switches can go to the LED board as well. (They are kept tidy by small spots of hot melt glue.) Finally, make the connections out to the PiFace board using a length of 10-way flat ribbon cable. Just cut a slot in the top of a side piece to allow the cable to sit just under the lid when it is screwed on. The ribbon cable has a red stripe on one wire that is useful as a marker. It doesn’t matter what order the wires are in as long as you know what wire to connect to what terminal on the PiFace module. I used the sequence shown in Figure 8.13. As the two switches are around the other side of the board, I extended those two wires by soldering an extra length on and putting some heat shrink sleeving over the joint to insulate it. You can make the sleeving shrink by applying a hot hair dryer to it. The finished unit is shown in Figure 8.14.

Figure 8-12: The box with its lid off.

image

Figure 8-13: The wire connections to the PiFace board.

image

Figure 8-14: The finished box for the game.

image

The Software for Testing the Game

All that you need now is the software to bring your game to life, but before you write that let’s write some software to test the hardware. It is vital that before you delve into the complexities of making anything work you have confidence that the hardware is working properly. Therefore, it is common when working on a project to write some simple software to exercise the hardware. Then you have the confidence that if the project doesn’t do what you expect it to in the end, it is the software that is wrong, not the hardware. Although Figure 8.4, earlier, showed the schematic of the hardware, how that hardware looks to a programmer is totally different. Figure 8.15 shows that. You can see here that there is a byte that represents the output to the PiFace module. The top two bits are shown as X, which means that you don’t care what state they are in. The other bytes are shown in groups of two, each group controlling the intensity of one of the LED colours.

Figure 8-15: This top byte shows the output to PiFace.

image

Although it might be tempting to write a program that cycles through all the colours, what you actually want to see is if each colour works at each of its intensities. It is also helpful to know that the switches are working as well. The test program is shown in Listing 8.1.

Listing 8.1 Colour Snap Hardware Test

#!/usr/bin/env python

"""

Colour Snap test

"""

import time # for delays

import piface.pfio as pfio # piface library

pfio.init() # initialise piface

def main():

print"Testing the colour snap hardware Ctrl C to quit"

print"showing the three intensity levels for each colour"

print"& showing buttons pressed"

while True:

for led in range(0,6,2) :

for c in range(1,4) :

pfio.write_output(c << led) # turn on the colour

time.sleep(.5)

switchState = pfio.read_input() & 3

if switchState & 1 :

print "blue button held down"

if switchState & 2 :

print "red button held down"

pfio.write_output(0) # turn off the light

time.sleep(0.8)

if __name__ == '__main__':

main()

Listing 8.1 is simply a loop that turns on each colour at the three intensities in turn. This is done with two for loops. The first uses the variable led as an index and counts up in two, so it gives you the bit position of the first of the two control bits for each colour of LED in turn. The next forloop generates the numbers 1 to 3 in a variable called c (for “colour”). Then you combine these two numbers by shifting c to the left by the led number. That gives the bit pattern you need to write out to the PiFace board to light only one LED at a specific level. When you run this you should see the red colour first in three intensities, the green colour in three intensities and finally the blue colour in three intensities. If you don’t see this, check the wiring, soldering and PiFace connections.

The colour changing the state of the input switches is checked, and a message is printed out if a button is held down. You will notice there is some bit manipulation code in this part that you might not have come across before – the use of the bitwise AND operation; in Python and many other languages the symbol to do this is the ampersand (&). Basically, an AND operation is used to selectively zero bits so that you are left with just the bits you are interested in. The AND operation is performed between two numbers or bit patterns; one is called the subject and the other the mask,although these names are arbitrary. The AND rules are simple: There will be a logic one in the result if there is a logic one in that bit position in both the subject AND the mask. So if you have a zero in the mask, you have a zero in the result; if you have a one in the mask, you will have that position in the result, depending on what the bit was in the subject. In effect you use it for selectively clearing bits. So the line

switchState = pfio.read_input() & 3

sets the variable switchState to whatever is on the two least significant bits of the PiFace input connectors. The 3 is the mask that is zeroing out all the other bits except bits zero and one. If you write the number 3 in binary, you will see that it looks like 0000011, with ones in the positions you are interested in. To test a bit, you can use another AND operation; the line

if switchState & 1 :

takes the switchState variable and ANDs it with 1 (or in binary, 00000001). If the result of doing this is a zero, the if operator sees a false; with any other result, it sees a true. So there is no need, for example, to say in this line

if (switchState & 1) == True :

although the result would be the same. The same augment applies to looking at the switch on bit 1: You simply AND the switchState variable with the number 2 (or in binary, 00000010).

Now go on and succumb to the temptation of showing all the colours just for fun. The simplified program in Listing 8.2 does this.

Listing 8.2 Colour Snap Hardware Test 2

#!/usr/bin/env python

"""

Colour Snap test 2

"""

import time # for delays

import piface.pfio as pfio # piface library

pfio.init() # initialise piface

def main():

print"Testing the colour snap hardware Ctrl C to quit"

print"showing all the colours"

while True :

for c in range(1,63) :

pfio.write_output(c) # turn on the colour

time.sleep(.5)

pfio.write_output(0) # turn off the light

time.sleep(0.8)

print "repeating sequence"

if __name__ == '__main__':

main()

If you find that colours such as yellow look a little mottled, try a bit more prediffusion of the LED – either sand it some more or find a bit of more textured translucent plastic to put over it. The colours seen on the table tennis ball should be smooth and even.

The Software for the Game

Now on to the full game! There are many ways this game could be programmed to play, so what I give here is just one implementation. It is important, when writing any piece of software, to have the numbers that define it stored in a variable name at the start of the code so that it can be easily changed with an edit in only one line. The way this is set up is that there are two players and the program asks for their names first. It looks up their score in the high-score table and makes an entry for them if they are not in it already. There are three rounds, and the player that wins a round by correctly pressing the Snap button is awarded points based on the difficulty level of the game. At the end of the game, a winner is announced, and the points acquired in the game are transferred to the high-score table. After the names have been inputted, you are asked to enter a difficulty level, which is a number from one to three and refers to how much a colour can change from one presentation to the next. In the easiest level, the colours displayed are only the primary and secondary colours, so it is simple to distinguish one from the other. In the middle level, any colour can be chosen from the 63 possible colours; however, because these are picked at random, most of the time they are very different colours. In the advanced level, only one bit in the colour is changed from one presentation to the next, so this means that there is a good chance of getting a slightly different colour, fooling you into thinking it is the same as the previous one. If you press the Snap button and it is not snap, points are deducted.

All the sounds the game produces are stored in a folder called sounds. They are all .ogg format sounds and are mainly self-explanatory. There are two “snap” sounds (one for each player), a success and fail sound called applause and doh and finally a “tick” sound. This sound should be very short and is played just before a new colour is displayed.

The inner workings of the game might surprise you as you might think that this way of doing things is counterintuitive. However, it is actually simpler to program the game this way. First of all, a random number function makes a number from 3 to 10 to control how many colour presentations there will be before a match. There is a new colour function whose job is to generate a colour that is different from the last one according to an algorithm chosen by the difficulty level. The program goes on presenting these colours until the number of presentations has been reached; then the last colour is simply repeated. If no player sees the matching colour, the process repeats. You could have the program penalise both players if this happens, but that is not how I have written this code. The full listing is shown in Listing 8.3.

Listing 8.3 The Colour Snap Game

#!/usr/bin/env python

"""

Colour Snap

"""

import time # for delays

import piface.pfio as pfio # piface library

import sys

import os

import random

import pygame

from pygame.locals import *

import shelve

pygame.init()

pygame.mixer.quit()

pygame.mixer.init()

pfio.init() # initialise piface

snapSound1 = pygame.mixer.Sound("sounds/snap1.ogg")

snapSound2 = pygame.mixer.Sound("sounds/snap2.ogg")

tickSound = pygame.mixer.Sound("sounds/tick.ogg")

applauseSound = pygame.mixer.Sound("sounds/applause.ogg")

dohSound = pygame.mixer.Sound("sounds/doh.ogg")

easyCols = [ 0x3, 0xC, 0xF, 0x30, 0x33, 0x3C, 0x3F ]

intCols = [ 0x3, 0xC, 0xF, 0x30, 0x33, 0x3C, 0x3F,

0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15]

colours = [ easyCols, intCols ]

level = 2 # 0 = easest level 2 = hardset

playerName = ["no player", "Blue player","Red Player"]

countToMatch = 0

roundToPlay = 1 # current round number

maxRound = 5 # number of rounds to play

redScore = 0

blueScore = 0

def main():

global level

print"Colour Snap, ctrl C to quit"

show_table()

playerName[1] = raw_input("Enter the name image

of the player using the blue button ")

p1Score = set_table(playerName[1], 0); image

#make sure player is in database

print "The score for",playerName[1],"so far is ",p1Score

playerName[2] = raw_input("Enter the name of the image

player using the red button ")

p2Score = set_table(playerName[2], 0); image

#make sure player is in database

print "The score for",playerName[2],"so far is ",p2Score

il = raw_input ("Enter a difficulty level 1 Easy image

to 3 Hard ")

level = int(il)-1

#make sure the level is within range

if level>2:

level=2

if level < 0:

level = 0

lc = random.randint(0,63) # the last colour shown

while roundToPlay <= maxRound :

print "Round ",roundToPlay, " of ",maxRound

countToMatch = random.randint(3, 10)

while countToMatch !=0 : image

# do this until you get a match

countToMatch -= 1

if countToMatch != 0 : image

#don't generate a new colour on last turn

c = newColour(lc);

tickSound.play()

time.sleep(0.5)

pfio.write_output(c) # turn on the colour

checkInput(0.8, c, lc)

pfio.write_output(0) # turn off the light

checkInput(0.9, c, lc)

lc = c # record the last colour

print "End of the game"

if blueScore == redScore:

print"It is a DRAW!!! "

else:

win = 2

if blueScore > redScore:

win = 1

print"The winner is ",playerName[win]

p1Score += blueScore

set_table(playerName[1], p1Score);

p2Score += redScore

set_table(playerName[2], p2Score);

print"Updating high score table"

show_table()

# end of main function

def newColour(lastColour):

nc = lastColour

if level == 2 : # hardest

nc ^= 1 << random.randint(0,5) image

# change by only a single bit

else:

while nc == lastColour : image

# repeat until you find a new colour

nc = colours[level][random.randint image

(0,len(colours[level])-1)]

return nc

def checkInput(delay, c, lc) : # has someone pressed a button

nextTime = time.time() + delay

buttonPress = 0

while nextTime > time.time() and buttonPress == 0 :

buttonPress = pfio.read_input() & 3

if buttonPress != 0 :

if buttonPress & 1 :

snapSound1.play()

else :

snapSound2.play()

checkResult(buttonPress, c, lc)

while buttonPress !=0 : image

# hold until button is released

buttonPress = pfio.read_input() & 3

def checkResult(player, newColour, lastColour) :

global countToMatch, roundToPlay, blueScore, image

redScore, level

pfio.write_output(0) # turn off the light

time.sleep(0.8)

count = 0 # minimum number of flashes

print playerName[player],

if lastColour == newColour :

print"yes"

applauseSound.play()

roundToPlay += 1

# add successful player score

if player == 1 :

blueScore += level +1

else:

redScore += level +1

else :

print "sorry not snap"

dohSound.play()

# penalise wrong press

if player == 1 :

blueScore -= 1 * (level +1)

else:

redScore -= 1 * (level +1)

while player !=0 or count < 6: image

#until button is released or 6 flashes

pfio.write_output(lastColour)

time.sleep(0.3)

pfio.write_output(newColour)

time.sleep(0.3)

player = pfio.read_input() & 3

count +=1

pfio.write_output(0) # turn off the light

time.sleep(2)

countToMatch = random.randint(3, 10)

def set_table(name, score):

scoreTable = shelve.open('score_table.snap')

if not name in scoreTable:

scoreTable[name] = score

elif score > scoreTable[name]:

scoreTable[name] = score

else :

score = scoreTable[name]

scoreTable.close()

return score

def show_table():

print

print "The current high scores are"

scoreTable = shelve.open('score_table.snap')

highscores = scoreTable.items()

highscores.sort(key=lambda elem: elem[1], reverse=True)

for entry in highscores:

print entry[0], "has a score of",entry[1]

scoreTable.close()

print

if __name__ == '__main__':

main()

First off, you will see that you use the pygame module, but you are using that only for the generation of sound. The main function starts off by asking for all the user input and then enters an outer while loop that plays all the rounds. This is followed by another while loop that does the actual playing of the round; this calls up the generation of the colours and the checking of the user input in addition to playing the appropriate sound. At the end of all the rounds, one player is declared the winner, and the updated high-score table is displayed.

In order to implement the high-score table, I have used the shelve module, which is a useful module that handles most of the work in making a persistent database. Basically, it maintains a dictionary and stores its entries in an unsorted manner. It is a simple enough matter to transfer this to a list, and sort the list before displaying it. When you run this code for the first time a file containing the high-score table will be generated; subsequently, the file will be used. If you want to start afresh, simply delete this file.

Generating the next colour is done in the newColour function. For the two simplest levels, it simply picks a colour from a list defined at the start of the code as easyCols and intCols. However, if the game is running at the most complex level, a random bit is toggled or changed. This function generates a number with only a single bit set in it by shifting a one a random number of places to the left; it then uses the exclusive or function, or XOR, to change that bit in the colour number.

The checkInput function does two jobs: First it acts as a delay, and while it is delaying it constantly checks to see if a button has been pressed. If a button has been pressed, it triggers the snap sound and calls the checkResult function to see if the call is correct. If the snap is correct, an applause sound is played, along with a printout of the successful player’s name; otherwise, a fail sound is played, and the incorrect player’s score is decremented. Then the last two colours are alternated; you will see them flash if they are different.

Over to You

The first thing you can customise are the sounds, especially the snap sounds. It is great to have those said by a person you actually recognise. You could change colours in the colour list. You could even add an extra resistor to two of the LEDs to get an even wider range of subtle colour variations.

You could make the scoring more sophisticated so that instead of simply storing the score of a player, you also stored the number of rounds he or she has played and sorted the list on the ratio of score-to-rounds played.