- Rules of the Game
- User Interface
- Building It
- How does it Work?
- How was it created?
- Hardware Design
- Prototype PCB
- PCB and Case Assembly
- Bill of Materials
- Programming the Microcontroller
- Working with the DAVE Development Environment
I had the pleasure of working with two little boys – nephews - an 8-year old, and a 6-year old, and together we assembled a radio kit. They now know that electronic products have circuit boards and resistors and capacitors, and they know how to solder.
But what next? They had ideas. Such as a television. I didn't know what to do : ) So, when this month's Electronic Toys Project14 theme came around, I decided a pocket game could be the next stepping-stone! The question was, what game to choose? And how to build it?
In order to improve their math abilities, I decided it should be a puzzle or logic game. Perusing literature revealed that Martin Gardner (famous on this side of the pond too) in 1958 wrote a really nice Scientific American article (he wrote a whole series on Mathematical Games than ran for decades) on the Chinese game of Nim, and how through a binary arithmetic procedure it could be solved. With computers the required arithmetic can reduce to Exclusive OR (XOR) operations. Without the procedure the game is really hard, even for adults! For kids, I’d need to implement some deliberate weakening of the algorithm to give them a chance to succeed.
Source: Scientific American, Feb 1958
So, I set to work on building Electronic Pocket Nim. The children watched me finish off the circuit board design using EAGLE CAD software, and fitting to an enclosure visually using Fusion 360, so really they’ve seen a large chunk of the product development process, and insisted on playing with the early perfboard prototype each week they visited.
This article discusses how to build this project for $20, but it also covers some steps on how to design such games in the first place.
There’s an 8-minute video that covers the physical construction of it all:
I decided to write this article in some detail because the fascination in the game surprised me. No-one I’ve asked to play it has been able to win at first go, and often they get suspicious, thinking that the game is impossible to win. At the easier levels, kids can win occasionally, and the difficulty can be fine-tuned in software. Pretty soon the kids recognise winning or losing moves one or two steps in advance because they’re mentally subtracting what they predict the computer will do on the next move. The game also self-teaches them, because if they need suggestions on good moves, they don’t need to ask an adult; the kids eventually realize they can skip a go and see what the computer feels is a move that they should have made!
Rules of the Game
The game is ordinarily played with any small objects like matchsticks as this article assumes, or pennies, and they are placed in rows. There are different versions of Nim but typically players take turns in removing any number sticks, provided they are all taken from the same row (any row can be chosen). The loser is the player who picks up the last stick : )
The electronic version uses these same rules, except it is a one-player game (played against the computer) and the sticks are replaced with LEDs on a display.
An LED matrix forms the screen! There is one button per row, for taking sticks (well, dots in this case). There is one Computer button (which is pressed after you’ve taken as many sticks as you want) for passing control to the microcontroller’s algorithm for it to make its move. The game ping-pongs between the user and the computer in this manner.
To change levels (this will abort the current game), the Computer button is held down while pressing any of the other buttons, to choose level 1-4 (4 is hardest).
There’s also sound capability. A stretch goal would be to make it do the Pacman sound when its game over. Clearly the best sound effect ever.
There are a few steps to building Nim. First, take the CAD files attached at the bottom of this blog post and go to a printed circuit board (PCB) manufacturer website (such as JLC PCB or Elecrow) and specify the size of the PCB to be 60 x 69 mm and upload the file. For about $5-$10, they will send you ten PCBs in return. Order the components listed at the end of this article (they are all commonly available parts, purchasable from Newark or Farnell websites, except the LED matrix, which is available from Amazon or Aliexpress.
Soldering this project is child-friendly (except for one optional wire to reduce current consumption – that may need an adult to solder). Check out the video for a fast play of the soldering process.
This project uses a tiny microcontroller board from Infineon with built-in micro USB port for uploading the firmware.
After the project has been soldered up, the microcontroller can be programmed in-circuit (or you can do it before it is soldered, because kids may be impatient to try out the game immediately after soldering). There’s a jumper on the PCB that is left disconnected when you wish to program the chip.
To program up the chip, download the development environment software from the Infineon website. The software is called Infineon Digital Application Virtual Engineer (DAVE). Install it, and then download the pocket nim source code zip file from github by clicking on Clone or Download and selecting Download ZIP. Extract it anywhere on your computer (e.g. create a folder C:\myprojects and extract it there, so the path is C:\myprojects\pocket-nim-master, and then rename it to something more sensible like DAVE_workspace, so that the path is now C:\myprojects\DAVE_workspace), and then when you start DAVE, you’ll be prompted to locate and specify that extracted folder (e.g. pocket-nim-master, or DAVE_workspace if you renamed it) as your workspace. When DAVE has fully started up, you’ll see the Nim project already selected as the Active project in the left-hand pane. From the top menu click on Project -> Clean for the first time. It will build the software, and you should see no errors in the output window at the bottom.
Ensuring that no battery is connected and the jumper mentioned earlier is disconnected, connect up the board to the computer using a micro USB cable. Then click on the icon that looks like a green Play button (it is the Run icon). After a short while (you may be prompted to upgrade the debugger firmware the first time around, so do that – and if it fails, that’s ok, just click through and then press Run again – it fixes itself) the software will get uploaded to the board, and the LED display should light up! Now the USB connector can be removed, and the jumper can be shorted on the board. The game is now ready for running from batteries!
That’s it : )
The rest of this article just discusses it all in more detail, as well as looking at how the game works and how this game was created. If you want only some additional practical build detail, you can skip most of it, and just concentrate on the sections titled PCB and Case Assembly, Bill of Materials and Programming the Microcontroller.
How does it Work?
The heart of Pocket Nim is a microcontroller, running code written in C.
This project uses an Infineon ARM chip, with plenty of power and code space for improving the current game or adding new games. Getting started with the Infineon development environment is discussed in this blog post too - it is quite a fast way of creating projects.
For those interested in delving in the code, the main program just does a few things. There are only three key functions it calls.
Firstly, it calls setup_game which sets up the initial conditions for the game (i.e. how many rows will be available to play based on the difficulty level, and starting number of sticks in each row), and then it alternatively calls two functions, user_play and computer_play, until there is a winner. The core variable which is manipulated by user_play and computer_play is numsticks, which is an array containing the number of sticks in each row. It is the single most important variable in this game.
The user_play Function
While user_play is executing, the user can press any button repeatedly to take as many sticks as desired from a row. Once you’re done, press the Computer button, and then the function exits, so that the main program can then call the computer_play function. The cycle repeats until there is a winner.
In summary this user_play function doesn’t do a lot. It just waits for button presses, and minor bits of additional functionality such as checks to see that you’re not cheating by trying to remove sticks from more than one row during your go.
The actual button presses are detected from a timer routine called fast_tick. It runs repeatedly a thousand times a second.
The computer_play Algorithm
The overall algorithm is partially described in the Wikipedia article for Nim. The general idea is that on each go, the microcontroller counts up the sticks in each row as multiples of powers of two (in other words, binary!) and then sees which powers of two can be cancelled out with another row. This is very easy for a computer to do, because it is an exclusive OR function (XOR) – one of the building blocks of electronics. It repeats this for all rows, leaving a single binary number. The number of bits set to 1 in that binary number is the value that ideally one of the rows should be set to, by taking away as many sticks as required to do so. It gets a little more complicated, to handle the corner cases. My implementation might not be elegant (I’m not a computer scientist or mathematician). Anyway, to make a decision, a ‘weighting’ or quality is given to each candidate number of sticks that could be removed by the microcontroller. Once the microcontroller has evaluated all rows and built its candidates list, it looks at the quality value for each candidate, and picks the highest quality one from the list, and makes its move.
By adjusting these values, such as inserting some randomness in there and not always picking the highest quality move, the computer play can be made less predictable, and easier to defeat. The computer play is deliberately weakened in this manner, for levels 1 and 2. This randomness takes Pocket-Nim from being a purely combinatorial game at its hardest levels, to slightly becoming a game of chance at its weakest levels. To generate the random numbers a linear feedback shift register was used.
Interrupt Function (fast_ticks)
In a puzzle game like Nim, there isn’t much timed stuff occurring. The Linux prototype of Pocket Nim (see below) didn’t have any timed functions at all. However, with the microcontroller implementation, a single timer interrupt is needed for button debounce and a few other purposes. The timer interrupt runs permanently while Pocket Nim is switched on, causing a function called fast_ticks to execute every millisecond. Several different variables are updated by fast_ticks, to handle things like the debounce as mentioned, and also for blinking a heartbeat LED on the microcontroller board, or for implementing delays to display update commands (the display chip doesn’t like being fed with data too fast) or for inserting deliberate pauses in game announcements (the computer doesn’t like losing, and it deliberately sulks for a second or so, before it indicates that the user has won).
The button debounce is important for Nim, and some thought was given to when events should occur (such as: should sticks be taken away on button-press, or on button-release?) to make the user interface feel ok for kids to play.
How was it created?
The easiest way to design a game like this is to do it as a Linux game first, before any hardware is developed. I wrote the algorithm and tested it on a Linux machine (a Raspberry Pi is very suitable for this). The command line is used instead of buttons and an LED display.
The software prototype could be done in any programming language. In my case I used C just to make it quicker to port to the microcontroller. Python could be used too. The standard C library printf and scanf statements (or if you’re doing it in Python it would be print and input) can be for displaying text and getting user input. It is a lot quicker to develop in this way, rather than keep downloading code into a microcontroller. As a result the algorithm was written and tested in under five hours work overall.
If you wish to play the game, the source code of the command line version of nim is available on github, ready to run on (say) Ubuntu or on a Raspberry Pi. Type the following in a command prompt window to download, build and run it:
mkdir nim cd nim wget https://raw.githubusercontent.com/shabaz123/pocket-nim/master/nim_desktop.c gcc nim_desktop.c -o nim ./nim
Press numbers 1-4 (and press Enter) to take sticks from any column and repeat if you want to take more. Once you're done, press 9 (and then Enter) to pass control to the computer.
An example execution is shown below, where the rows initially had 3, 5, 2 and 1 sticks. I typed 2 and hit return to reduce the second row of sticks down to 4. Then I typed 9 to indicate that the computer should make its move. The algorithm debug output is shown, and eventually the computer decided to take sticks from the same row too (the row indices start from zero, so candidate 1 is really the second row), and the microcontroller decided to take all the sticks in that row.
The quality table values are 0, 9, 0 0, and this indicates that the algorithm greatly favoured taking sticks from the second row, since that has the highest quality value.
Incidentally, from the values in the screenshot above, the user has already likely lost from this position. After the computer makes a move from this point on, regardless of what decisions the user makes, the computer can win provided it is not deliberately weakened (the computer is not totally invincible; some games at the highest difficulty level can be won by the user).
Next, the code was copy-pasted into the microcontroller development environment, and the areas of code that had the printf and scanf functions were extended with the code to interact with the hardware (display and buttons). The printf statements can be left in, because when the microcontroller software is running in debug mode, the software development environment can output text into a console window. This too speeds up development. The scanf statements were replaced with code that would wait for button presses.
The code is quite relaxed on who plays first (the Computer button can be pressed at the start of the game, to force the computer to play first), and, either as a bug or feature (different points of view : ) it is possible to skip your go and press the Computer button again. That way you’re either cheating, or allowing the computer to play against itself, or exploring what the computer would have thought was a good move for you.
For this project, Infineon’s XMC 2Go microcontroller board was used. Like an Arduino, it has an on-board USB connector for directly programming it from a PC. The board is tiny, not much bigger than a dual-in-line IC package. The microcontroller, part of the XMC1100 family, has an ARM Cortex-M0 core, 64 kbytes Flash memory and 16 kbyte RAM in a 24-pin QFN package.
The on-chip serial I2C interface is used for connecting to the 8x8 LED display, and some general-purpose pins are used for connecting to buttons. There is a 3.3V supply output exposed on one of the pins on the board, and for the prototype, that is used for powering the 8x8 display. This is outside the specification of the display driver chip (it is specified as 4.5V supply minimum to guarantee operation across its entire temperature range) but operating it at the correct supply will then require logic level translation too. For a non-critical application like this game, I think it’s ok to cut this corner. In fact, the display board that I tried continues to function down to 1.8V (at this extreme the display is very dim though). At 3.3V, the display was brighter than expected for indoor use (it can be dimmed in software by configuring a register via I2C).
For the PCB version, I wanted it all powered from a battery, and not the USB connector. At this point the XMC 2Go board was closely examined. It turns out, if there is no USB power source then the board can be powered by attaching a supply to the 3.3V rail, and that will operate the XMC1100 microcontroller, and the on-board debugger chip too. However, the debugger chip consumes a lot of current. There is a debugger reset connection on a tiny pad on the edge of the board, and that was wired to a jumper that can be shorted to ground to stop the debugger chip from booting, and saving lots of power. It is a shame that is not brought out to a larger pad. Anyway, it is possible to solder that with a bit of care. With that done, current consumption of Pocket Nim drops a lot!
The XMC1100 chip operates down to 1.8V which is awesome. A couple of AA or AAA alkaline cells will directly operate Pocket Nim for a long time (at least a whole day powered up using AAA cells, since it consumes around 25mA at 3V) and will still result in a bright display. So, considering all this, the final design has no voltage regulator. It doesn’t need it.
To help with cutting the front of the case, a PDF file is attached to this blog post that can be used as a template. The file is to double scale, so it needs to be printed at 50%. A 3D printed case might be another option.
I wanted the project completed quickly, and I took a risk and ordered the PCB before I had all the parts. It turned out that the LED matrix board was a couple of millimetres too thick for the chosen enclosure! Some hobby parts like pre-built modules are not always well dimensioned in datasheets : ( So, I had to cut out the PCB to make the matrix board sit flush. My board also has a bodge wire as a result of the cutout going over a vital trace.
The attached PCB files are corrected, so boards made using them will not require any cutting.
PCB and Case Assembly
The easiest way to build Pocket Nim is to order a PCB using the files attached to this blog post. Any PCB factory like Elecrow will accept the files and for $5-10 plus postage, will provide around 10 PCBs.
The PDF file attached to this blog post was used to cut the holes.
The power switch location needs some filing to make a notch. The display cut-out had a 1.5mm thick piece of translucent plastic fitted flush (anything thicker will not leave enough space for the LED matrix, because it is quite tall).
Matching caps for the push-switches were hard to find. Depending on what you use, the caps may need gluing. Also, check the height using the enclosure. If the buttons need raising, one way is shown in the photo below.
The LED matrix comes with a driver board. I used an Adafruit version initially but a drop-in replacement second source is available from Amazon and Aliexpress at $3 (if three are purchased – total of $9), the search term is keyestudio matrix module HT16K33. The Adafruit version needs the LED matrix to be soldered to the driver board in the correct orientation as shown in the photo below. The Keyestudio Aliexpress version comes entirely soldered.
Disabling the debugger on the microcontroller board (to reduce power consumption for battery use) needs some care soldering a wire strand.
After assembly, the microcontroller can be programmed in-circuit if desired (see below); or it could be pre-programmed in advance, if children are going to be assembling it, because they may want to try it out immediately.
The final result, ready to play! Now that this prototype is ironed out, I will get the kids to solder their one, since they will enjoy that more.
Bill of Materials
|C1 10u Aluminium||Kemet||1|
|J1, J3 2-pin SIL Header||Multicomp||2|
|Shorting Link 2.54mm||Harwin||1|
|20-way SIL header (break into 8/8/4)||Multicomp||1|
|Piezo Disc||Pro Signal||1|
|2 x AAA Battery Holder||Keystone||1|
|U1 XMC 2Go XMC1100 Board||Infineon||1|
|D1 8x8 LED Matrix||Adafruit or Keyestudio||1|
|PCB 69 x 60 mm||Various (e.g. Elecrow, JLC)||1|
|Plastic button caps||Aliexpress||5|
Programming the Microcontroller
The microcontroller can be programmed in-circuit. First, download and install the development environment called Infineon DAVE.
Download the Pocket Nim code bundle from github, extract it somewhere. The extracted folder has a name like pocket-nim-master. Your entire path may be (say) C:\myprojects\pocket-nim-master. Change the name of the folder from pocket-nim-master to DAVE_workspace, so that it is more descriptive.
Run DAVE and choose that workspace folder when prompted.
You should see the project appear in the left hand pane, shown in red on the left here, and the code can be displayed on the right by expanding the project and double-clicking the main.c file. The two important icons, also shown in red, are the hammer icon for building (compiling) the code, and the run icon for programming the chip.
Ensure no battery is attached to Pocket Nim (or turn off its power switch), and that the Debug jumper is not shorted on the board, and then plug in a Micro USB cable and connect it to the PC.
After you have built the code (for the first time, go to Project->Clean to do a clean build but subsequently you can use the hammer icon), click on the run icon and within 15 seconds or so the code will transfer into the microcontroller and start running (it will be powered by USB). The display will light up and the game will run. Note that the first time, DAVE may take longer, and it may prompt to upgrade the debugger software. Click Yes to that. In my case, I get an error (I’m running a slightly older version of DAVE software), but it seems to correct itself the next time I try to click on the run icon.
Once you’re happy with it all, unplug the USB cable and plug in the jumper so that the pins are shorted. This will disable the debugger and lower the current consumption to about 25mA. It is now ready for running from batteries.
Working with the DAVE Development Environment
(Note: This section is not necessary to read to build or understand Pocket Nim. It is only useful if you’re keen to do your own software development with the Infineon board).
It is worth exploring Infineon’s XMC 1100 ARM-based processor and development environment called DAVE. I really like it. It comes with lots of automated code elements (known as DAVE Apps – see the list below) that can be instantiated for dozens of different purposes, such as I2C control, pulse width modulation (PWM) and timers, but also code elements for industrial purposes such as DMX or data encoding or even graphical user interface (GUI) creation. It is surprisingly easy to use.
The following icons are used frequently. While coding, if you need a DAVE app, click on the Add DAVE App button as shown below, and then you can go through the palette of different apps, using the help button that also appears, to read up on each app before finally adding it to your project.
The screenshot below shows some of the key areas of the development environment. The top-right contains the perspectives, which are different ‘modes’ of using the IDE. The DAVE CE perspective is the one usually used to do your coding.
The DAVE apps that are added are listed at the bottom-right (circled in blue in the screenshot above). These are the DAVE apps that were used for Pocket Nim. Pocket Nim used Digital I/O, I2C, PWM and System Timer DAVE apps.
By right-clicking or double-clicking on these app instances in the APP Dependency pane, they can be renamed or configured. So, in the screenshot above, by right-clicking a digital I/O DAVE app was renamed to led2, and then by double-clicking it was configured as an output.
The Pin Mapping Perspective icon (shown circled in an earlier screenshot above) was used to display an image of the chip, and the app input or output is tied to a pin by right-clicking on the pin and selecting the app instance’s name for the pin.
After any DAVE app has been added, the system needs to be told to generate the source code for the app (the generated code of the DAVE app will then appear in files in the project files area, but it is unnecessary to view it to use it, because the help pages contain all the application programming interface [API] information required to use the DAVE app successfully). To generate the app source code, click on the Generate Code icon shown in an earlier screenshot above. The API can be then be used in your code. So, for the led2 example, I was able to type this into my code to turn on that output:
This is remarkably easy; in some ways easier than Arduino, because I did not need to type any code to choose the pin, nor to set the pin as an output. All of this was done graphically by using the Pin Mapping perspective and by double-clicking on the DAVE app instance.
When it comes to debugging code, right-click on the project name in the project files pane, and select Build Configurations -> Manage to change from Active to Debug. Then click on the Debug icon rather than the run icon.
Pocket Nim was constructed using easy-to-solder parts, and I hope should keep kids entertained for a while. The game is really challenging on levels 3 and 4. The PCB files and source code has been published (including a Linux version), it appears to run well, but if you fix any bugs or add new features, please do share the code! The microcontroller is powerful, and there is lots of scope for improving Pocket Nim and adding new functionality.
The Infineon XMC1100 microcontroller performance is overkill for this project, but the XMC 2Go board is extremely low cost, and worth it to get going with Infineon microcontrollers. The DAVE apps make light work of dozens of different functions. It helped me to speed up getting this project completed.
Thanks for reading!