"Beneath the Ice" was our entry for PyWeek 22 (September 2016), a twice yearly video game development competition that gets competitors to build a complete game from scratch in seven days using the python programming language. This competition's theme was "You can't let him in here!" and we made a submarine exploration game and puzzle solving adventure, in which you must uncover the secrets of a mysterious pariah who doesn't want to be found, who can't let you in! The game was developed under the collaboration "Team Chimera" (myself and Lucid Design Art, who did all of the game's artwork). This is Team Chimera's third game in a PyWeek comp, after "The Wizard's Data" and "Adrift".
We were super excited to win both the Team Entry and overall winner with a score of 4.41 out of 5.0. Our score also makes "Beneath the Ice" the second highest ranking game in PyWeek history! (almost one thousand games over more than ten years!), so it suffices to say we were pretty pleased with the result :).
Here you can find the latest version of the game. We are currently in the process of cleaning the game up a bit (bug fixes, graphical updates and gameplay tweaks) and this page will be updated again over the next few weeks. The game is currently available for Mac OS 10.6+, Windows or as a source code distribution (multi-platform: windows/osx/linux) that requires the pre-installation of python and pygame (see instructions below):
Game can also be downloaded from the links on the PyWeek game page here.
Instructions for running the source distribution:
(1) Install python 2.7.11 (currently not working with python 3): go to https://www.python.org/downloads/ and download the installer for your platform.
(2) Install pygame: Once python is installed, pygame 1.9.1 can be installed using these instructions.
(3) Download the zip file above, unzip to a location of choice. Open a terminal (osx) or the command prompt (windows), change directory to the path of the game and type "python run_game.py".
If you are having trouble getting the game to run, or have a bug/crash to report, please email: randomprojectlab@gmail.com
Recently I ran an introductory workshop on Arduino and wearable/softie electronics; I took a lot of inspiration from a previous wearables workshop I had attended at the MAAS. The workshop was to run for only two hours, and I wanted to have participants walk away with a finished project, so it had to be relatively uncomplicated and not too time consuming to build. I ended up making a little rainbow flower using a Gemma, tiny lipo battery, single Neopixel, conductive thread and felt.
I found from previous projects that conductive thread is a bit finicky when you are working with it for the first time, and with little sewing experience (like me!). Lots of neopixels are great, but that requires lots of sewing, so I decided to just use one, so there's only three lines that need to be made (power, ground and one data line). Neopixels are pretty bright, and I've found they can be a bit harsh on the eyes after a while, so I found that covering the Neopixel with a little bit of cotton wool/stuffing helped to scatter the light a bit. I placed white felt in front of the stuffing to hold it in place and the Neopixel still shines through well.
I've posted some step-by-step instructions on how to build the flower, plus the sketch/code below, for those interested:
Softie Rainbow Flower:
Parts:
1 x Adafruit Gemma
1 x Flora type Neopixel RGB LED
1 x Small 100mAh Lion Battery
Micro USB to USB-A cable
conductive thread, felt, small piece of stuffing/cotton wool
Code:
You can download the sketch/code to run this project here. (Update 26/10/2016: A slightly modified version of the code to run two neopixels here).
Steps:
Download and install the Arduino IDE. Open the Arduino software and you should be able to see a folder in (your home directory)/Documents/ called "Arduino".
Download the Adafruit Neopixel library from here. Unzip and copy the whole folder into the "libraries" folder within the "Arduino" folder. Close the Arduino software (if it is still open) and re-open. Click on "tools/board" and change to "Arduino Gemma". Click on "tools/programmer"and change to "USBtinyISP".
Download the sketch/code form the link above (this one for one neopixel or this one for two neopixels). Create a new folder called "simple_rainbow" in your "Arduino" folder and copy this file (simple_rainbow.ino) into this folder (if using the two pixel code, name you folder "simple_rainbow_2pixels" to match the file name).
Place the Gemma and Neopixel onto a piece of brown felt (or other colour of your choice) as shown in the picture below. The "GND" pad on the Gemma should be on the top left, "D1" pad up and the "Vout" pad on the top right. The Neopixel should have the "-" pad on the left, "+" pad on the right and in next to the arrow that points in towards the white square in the middle of the board at the bottom.
Using conductive thread, stitch three lines using three separate pieces of thread between the pads on the Gemma and neopixel as shown in the image: "GND" to "-", "D1" to "arrow" and "Vout" to "+". Make sure the thread is making a nice, tight contact with the pad and use a tight, neat running stitch along the felt. Make sure to snip off any loose bits of thread to avoid any part of the thread touching a different set of pins and potentially short-circuiting the design.
Switch the Gemma off by using the very small switch on the front. Using a micro USB cable, plug one end into the Arduino and the other end into your computer/laptop (make sure you have a USB2 port available: Gemma has been known to act-up/flat-out not work with some USB3 ports).
In the Arduino software, click on the tick button in the top left corner to compile the code. Switch on the Gemma and while the red led on the front is flashing, you can click on the arrow/upload button to upload the compiled code to the board. You get about 10 seconds to do this: if you miss it, no probs, just turn it off and on again (or press the small circle reset button on the board). If everything is working, you should have to wait a few seconds and your neopixel should start to cycle through a rainbow sequence of colours.
You can now switch off the Gemma and unplug the USB cable. Plug in the battery using the black JST connector on the Gemma (make sure the polarity is correct: the plug will only fit in one way, even if it is a little tight and difficult to get in).
You can now stitch on any design to the front of the felt using normal thread and felt. I made a little pocket (looks like a flower pot) to hide the Gemma and hold the battery out of view. You can leave the Neopixel uncovered if you like it that way, or place a small dab of cotton wool/stuffing in front of it to give it a more soft appearance (mine is stitched underneath the circle of white felt in the center of the flower). Cut away any of the excess felt that doesn't make up your design and be careful not to chop off any bits of the conductive thread!
You can modify the code to display any pattern of colours you like. Try changing the "i" in line 60 of the code (setPixelHue(0, i);) to a number between 0 and 360 to have a single static colour of your choice. Re-compile and re-upload using the USB port (you should be able to leave the battery connected while doing this).
I've just finished (mostly) a new video game project: It's an Arduino-based video game console, and I've nick-named it 'Cubey'.
Cubey plugs into a TV via a set of RCA cables to provide a low-res, black and white video game experience roughly equivalent to video game consoles of the late 1970s and early 1980s. It has a custom 3D printed case, is compatible with the Nintendo nunchuk controller (supporting two players) and currently features four built-in games (I'm in the process of working on more). On the inside Cubey uses an Arduino Mega 2560. The Mega is used to input data from the nunchuk controllers via I2C, run game logic and drive an analogue PAL video signal with two colours (black and white) at resolution of 120 by 96 pixels and a mono-audio signal with four channel sound/music.
Initial Design:
About two years ago I had been playing around with the awesome Arduino library 'TV-out' using an Arduino UNO. I was using the UNO to run an implementation of the game 'snake' using two digital input pins and two momentary buttons to turn the snake left or right. 'TV-out' provides a bunch of basic functions for generating PAL video signals using interrupts on the Arduino and a pair of digital output pins to construct a two colour video signal via a 2-bit DAC (the library documentation page provides a really good explanation on putting this together using a pair of resistors). I hadn't gone any further with this project, so I picked it back up recently and decided to make something a bit more sophisticated. I was inspired by and drew heaps of ideas from a bunch of other Arduino-based video game projects including the HackVision, The Box and Gamebuino. I wanted to make something that would support multiple games and at least two players. To reduce the complexity of the project, I decided to make the console compatible with an existing game controller, rather than build my own. I found this example for using the Nintendo nunchuk controller (an accessory that plugs into the Nintendo wii-mote) with Arduino and thought this would work perfectly. The nunchuk has two buttons, an analogue joystick and three-axis accelerometers all packaged up in something you can buy for about $5 to $7 (aftermarket models).
I started off by building a breadboarded version of the console to systematically test out the various things I wanted to get running. I started off by connecting up my UNO to an RCA output jack using a 2-pin DAC with a pair of resistors and did a test run of the TV-out library: all working fine. I downloaded a library for communicating with the nunchuk controller via I2C here and compiled this into a project to read joystick state and move a pixel around the screen: all working fine, everything compatible.
Getting two-player control to work:
I really wanted to have at least one more controller hooked in so that I could run two player games. Problem with I2C is that there is only one set of pins on the Arduino for this. Normally this would be OK: multiple I2C devices can be slaved on one line as long as they have different addresses. Unfortunately all nunchuks use the same 0x52 address, so I found I couldn't talk to two simultaneously on the same line. One option was to run a software I2C for one of the nunchuks, but this didn't seem ideal. I found this solution which connects two nunchuks to the I2C clock line (SCL) and uses a pair of transistor switches to toggle the data line (SDA) using two additional digital pins on the Arduino. I wrote up a test sketch that basically switches on the first SDA line (nunchuk A) and switches off the second line (nunchuk B) before grabbing data (nunchuk A), then reverses the switches and grabs data again (nunchuk B). Breadboarded it up and it worked perfectly! I had a couple of npn type transistors sitting around from a previous project ... probably a bit over spec'd for this, but they work! I used 1kohm resistors to connect the transistor bases to the digital output pins from the micro. Voila: two player control with two nunchuks.
So at this point I was thinking "why not put in another nunchuk for even more players?" I guess I am only limited by how many unused digital output pins I have (twelve in total on the UNO). I think the main thing stopping me here was (a) making games on a 120 x 96 pixel screen with only two colours (to specify what player is which) for more than two players is hard (b) I only own 3 nunchuks anyway (c) the likelihood of getting more than four people together to test it out seemed low ... plus the nunchuk cables are quite short, so it would start to get a bit squashy sitting around playing with that many people in close proximity (actually, I guess this could potentially enhance the 'social' experience of playing together :) ).
Initial software tests and switching over to the Mega:
I thought it prudent at this point to try and get some game code running with what I had working so far, so I started implementing a clone of the game Missile Command (a popular Atari title from 1980). Problems began. Everytime I would do any relatively larger drawing to the screen (using TV-out library functions "bitmap" or "print"), I would lose I2C connectivity with the player two nunchuk, requiring a power cycle. Eventually I found I could sort of overcome this by adding in "delay(1)" call in-between any graphics intensive call.
About halfway through programming the game, I hit a wall: running out of RAM. The Arduino IDE indicates the amount of memory being used by global variables during compilation. I was lulled into a false sense of security when I saw that my program was only using about 30-40% of available memory on global variables. Then I realised that I was not accounting for memory taken up by local variables/functions on the stack; my sketch was compiling fine but wasn't running, presumably because of stack overflow ... so I was about half way into the code for my first game and already running out of memory. This seems to confirm what I was seeing. I guess the old ATmega328 (chip inside the UNO with 2K of RAM) wasn't going to cut it. OK, so I wasn't really being super memory-conscious when writing the code, but I wanted more than one game up and running and I didn't really want to have to be skimpy with my game design, so I made the choice to switch over to the Arduino Mega (with 8K RAM), because I have two sitting around not doing anything at the moment.
3D printed case design:
I played around with a lot of ideas for the case. I had a look around on Thingiverse hoping to find a cool 3D model I could slice an enclosure into, but didn't see exactly what I wanted. I kind of had the idea that it would be cool to make the enclosure a giant dodecahedron, but it seemed like a fair bit of wasted space seeing as the mega is quite long on one axis only. At some point I was going to make a space invader shaped case, but it had to be pretty big to fit things properly, so I abandoned it. I ended up doing some sketches of some tetromino-inspired shapes, and settled on a little thing built out of cubes. I nicknamed him 'Cubey'.
I built him up in Openscad. He's broken up into a few sections so I could print him without too many supports: it was a real pain picking off the support material from my last print project (in fact most of it is still stuck on the case because it was just too damn hard to get off). I made ports for the two nunchuks, RCA cables and power and usb from the Mega. His mouth is a reset switch for the Mega and, because I had so many available ports on the Mega, I added some leds in his eyes for some blinky fun :). I printed him mostly in white except for some small detailing around the eyes which were printed in black as separate pieces and then super glued onto the final design.
Problems with the case: I had a few issues with the case after printing. Firstly, I had real problems getting the raft off the main body. There were sections that were literally fused into the case, and at some point I had to abandon a 1.5 hour effort to cut them off. I ended up filing it down as best I could. Unfortunately this interfered with the sockets for where the back legs were originally designed to fit into, so rather than reprint the piece (seven hour print and probably face the same issue), I redesigned the clearance on the leg parts before printing them. I also realised that the holes and corresponding plugs didn't fit (the tolerance on the size of these bits wasn't as tight as I thought it would be), so needed a reprint anyway! Other problems with the case: I had only allowed for a 1 mm tolerance for the space to fit the mega: not enough apparently, so I ended up breaking off the support that would have held the reset switch in place and improvising. I ended up cutting a small strip of perfboard and soldered the switch to that before sticking it in the small gap between the Mega and Mega protoboard (which was to hold all of the electrical components for nunchuk switching, the DAC etc.), held in place with a little bit of bluetac :). I redesigned the nose button so it was about 5 mm thicker at the back to compensate for the extra reach. One thing that did work was the support for the RCA cables: clipped together like dream (after a tiny bit of filing :) ). I had to print the legs a number of times due to issues with tolerances on 3D printed parts connecting together and bits in the nunchuk connector spaces that didn't fit right. Eventually they were printed such that they fit with a bit of give and I used superglue to connect them to the main body.
Putting Cubey together:
On top of the Mega I used a protoboard (especially designed to fit and line up exactly with the Mega) to hold additional electronic components. This provided space for the resistors made up the DAC and that connected up the digital pins for driving the video and audio signals to the RCA cable connectors, resistors for the led eyes and the transistor circuits. I used a female-to-female RCA adaptor to connect the lines from the board to an external plug. I got two nunchuk connector adaptors (Nunchukies) to use in my controller ports. These came with convenient "wings" at the side of the board to help click and hold the nunchuk connector into place, but I found they got in the road of my design, so I hacksawed them off and made my own indentations built into the 3D printed controller port. I screwed these boards into the cavities of Cubey's front legs such that they sat flush with the controller port/socket. I then soldered the power and data lines from these up to the Mega protoboard where they were interfaced to the Mega. The front and back legs were then super glued on and the top case just clicks into place (so I can open it up again to if I needed to).
Getting some music:
I had tested the audio through RCA jack when I setup my original breadboard model, working great with 470ohm resistor in line with pin 10, and was able to generate a single channel of sound: a square wave generated via an implementation of Arduino's 'Tone' function built into the TV-out library. I wasn't very satisfied with the ability to only play a single audio tone at a time: I wanted cool video game music and any decent music needs harmony and melody, so I wanted to have some level of polyphonic sound. Reading a bit about how the Arduino built-in tone library works, I came upon this library which seemed to be exactly what I wanted. I ported over the functionality described within to use Timer 3 on the Mega as a counter for an interrupt routine that would flip the output to produce a square wave. Everything seemed to work fine when playing tones on their own, however, when this was run alongside the video signal generation using the TV-out library, it was producing a nasty clicking mess. From what I can gather, the interrupts being driven for video signal generation were messing with the timing for the tone interrupts.
I found this library for running PWM signals using different timers on the Arduino, without the need for an explicit interrupt routine to switch the output, but instead using a PWM mode of the timers and a register value to store the direction in which to flip. I ported over this implementation, and it worked perfectly: I now had two simultaneous square wave tones that I could play. I ended up implementing an additional (third) channels using this method on Timer 4 on the Arduino such that I had three square wave generators (three simultaneous tones at any one time) and no interference with first audio channel or video signal generation. I found that I could vary the duty cycle to 25% on one of the three channels to produce a slightly different timbre of sound such that there was a bit of audible distinction between the different channels/voices in the music.
Good music requires some sort of beat or percussion, so I used my last available timer on the Mega (timer 5: Timer 0 is used for game logic timing and Timer 1 is used by the video signal generation) to do this. I used Timer 5 to drive an interupt that would randomly assign a high or low value at a fixed frequency to a fourth channel in order to create a white noise signal that would emulate the sound of a drum or other percussive instrument. I found this page on using a Fibonacci Linear Feedback Shift Register as an efficient means of generating a pseudo-random signal for the noise. I found I could emulate an acceptable kick-drum by running this routine at ~1kHz and an acceptable snare at ~5kHz. Since the video signal generation interfered with these interrupt-driven signals, I had to make the sounds limited to a duration of 20ms (inside the time between video updates), which was fine for a basic beat.
Now that I had the ability to generate three square wave tones and one percussive sound simultaneously, I was ready to make some music. I wrote a routine that would read in arrays of data containing pitch and note duration information for each channel and play them at a fixed speed of 50 Hz (in line with the video signal). I found I could store music data in the flash memory on board the Mega (256K available, also used to store image and sprite data) and read it in as it was played.
At some point I will upload my updated version of the TV-out library containing these extra functions (and my game code): stay tuned!
Games:
So far I've written four games: 'Space Blast': a two player space shooter, 'Missile Command': a clone of the popular Atari title, 'Breakout': another clone of an old Atari game, and 'Achtung!', a clone of an old DOS PC game called "Achtung, Die Kurve!". I'm currently working on a few more: I'm keen on writing something that can exploit the accelerometer/motion sensing on the nunchuk in a cool way, but haven't quite got a good game concept working yet. Work in progress!
Overall, I've had a lot of fun with this project, however it did take a decent amount of time (about 6-8 weeks total). In the end I was super hyped about getting the four channel sound to work: I learnt a lot about how old video games made the sorts of sounds they did and how composers had to work within these constraints, which I've found really interesting. I may end up trying to expand on this in a future project, perhaps some sort of Arduino-based chiptune player project. Although the black and white video was sufficient for simple games, it probably would have been nice to try and get a few more shades of gray in (or even colour signals!), however it was a bit outside of the scope of my knowledge: if I did a follow-on to this project, this is something that I would definitely attempt.
This was a project I did as a present for my young son last christmas. At the time he was really into the Octonauts. There's an episode that features a deep sea starfish called Twinkle who is lost and needs the Octonauts to help her find her way home. My son really loved this episode, so I thought it would be cool to give him his very own Twinkle with blinky eyes. I had a Gemma and some neopixels sitting around from a previous project, so electronically speaking, this project was in the bag, just needed to do some sewing.
I made a star shaped section for Twinkle's front, added a mouth and some embellishment and cut two neopixel-sized holes for the eyes. I hand stitched two black felt circles on the front of these holes that in turn had smaller holes cut into them about 4mm in diameter; big enough such that when the neopixels sat behind the black felt, the LEDs would poke through. I used a single rectangle of felt to make a sewed circuit that connected up two neo pixels and a clicky momentary button to the Gemma. I powered the whole thing using a small 300mA lipo battery. I then stitched this to the back of star such that the neopixels were positioned over the eyes and the button was Twinkle's nose. I then machine sewed this all to the back half of another star (back-to-back) and folded the whole thing inside out and stuffed it with stuffing.
Unfortunately, I didn't really have enough time to put in a proper switch on the battery line, or think about a good way to recharge it, so I left a small finger sized hole on one corner of the star so I could reach in and pull the battery out when needed and so I could switch it on and off using the very small switch on the Gemma. This was probably the most disappointing part of the final design: next time I need to look into how to design this properly with a click switch connected to the battery.
For the code, I setup Twinkle to run in two 'modes'. In the first mode, Twinkle's eyes would just run a predefined pattern. Pressing her nose would cycle through the available patterns: a rainbow sequence and pink lights that would fade in and out. In the second mode, Twinkle's eyes would display a single colour, and pressing her nose would cycle through a list of available colours. To switch between modes, one holds down Twinkle's nose for one second.
The neopixels are surprisingly bright: me and my son like to turn off all the lights and use Twinkle as a colourful torch to explore around in the dark (pretending we are deep under the ocean in the 'midnight' zone). Great fun!
This was a project I did about a year ago after attending a workshop on arduino wearables. The project was run at the MAAS, which does some great events for kids and young adults, but doesn't often run events for adults. So I was happy when I heard they were doing an adults course, and came along. I'd seen some super cool wearable projects, and the mix of electronics and textiles/soft surfaces seemed cool. During the workshop everyone was given an arduino Gemma, some neopixels, a bunch of little sensors and some conductive thread and encouraged to see what we could make. I ended up connecting four neopixels up to the Gemma with a little vibration switch and sewed them all into a beanie: voila! a jump activated rainbow beanie.
The neopixels take power, ground and are driven by one digital output pin that transmits individually addressed RGB data to each and every neopixel attached along a chain. The vibration switch is triggered when shaken or given a good jolt, and one of the Gemma pins was used to read its state. The code on the Gemma would then just trigger a preprogrammed rainbow sequence along the neopixels.
All of connections were made using conductive thread sewed into the rim of the beanie and powered from a small 500 mAh lipo battery. Because the beanie was quite stretchy, I had to sew the conductive thread lines in a sort of zig-zag fashion: this meant they would sort of flex with the beanie when someone stretched it over their head (instead of just snap). Definitely the most time consuming part of the project was sewing the conductive thread circuit!
Here's the final code for my project sketch:
/* rainbow_jump_hat.ino - arduino sketch using four neopixels
displaying a rainbow pattern triggered by a vibration switch
*/
#include
#define LED_PIN 0
#define VIBSWITCH_PIN 1
Adafruit_NeoPixel strip =
Adafruit_NeoPixel(4, LED_PIN, NEO_GRB + NEO_KHZ800);
int VibSwitchState = 0;
int event = 0;
int eventcount = 0;
void setPixelHue(int pixel, int hue)
{
while(hue < 0)
{
hue += 360;
}
float h = hue % 360;
float sectorPos = h / 60;
int sectorNumber = (int)floor(sectorPos);
float fractionalSector = sectorPos - sectorNumber;
float q = 1 - fractionalSector;
float t = fractionalSector;
switch(sectorNumber)
{
case 0:
strip.setPixelColor(pixel, 255, 255 * t, 0);
break;
case 1:
strip.setPixelColor(pixel, 255 * q, 255, 0);
break;
case 2:
strip.setPixelColor(pixel, 0, 255, 255 * t);
break;
case 3:
strip.setPixelColor(pixel, 0, 255 * q, 255);
break;
case 4:
strip.setPixelColor(pixel, 255 * t, 0, 255);
break;
case 5:
strip.setPixelColor(pixel, 255, 0, 255 * q);
break;
}
}
void DoRainbow() {
for(int i = 0; i < 360; i++) {
strip.setBrightness(255);
setPixelHue(0, i);
setPixelHue(1, i + 90);
setPixelHue(2, i + 180);
setPixelHue(3, i + 270);
strip.show();
delay(10);
}
}
void setup()
{
strip.begin();
strip.setBrightness(255);
strip.show();
pinMode(VIBSWITCH_PIN, INPUT);
}
void loop()
{
// Look for motion
VibSwitchState = digitalRead(VIBSWITCH_PIN);
if (VibSwitchState == HIGH) {
event = 1;
}
else {
event = 0;
}
if (event == 1) {
DoRainbow();
DoRainbow();
event = 0;
}
else {
for(int i = 0; i < 4; i++) {
strip.setBrightness(0);
}
strip.show();
delay(10);
}
}
Once I had the hardware finished up, I was ready to finalise the on-board software and load up a few games. I already had three ex-pyweek games ready to go: all I needed was some sort of main menu that would come up when the console was switched on and would allow the player to navigate options and choose games using the dpad and buttons. I wrote a quick and dirty main menu interface using pygame that allowed the player to choose between the three games (I will probably come back and upgrade this to something more visually impressive somewhere down the track). I added a line to the end of /etc/rc.local to run this on start-up.
To get the menu interface to quit itself and start up a selected game, I used "os.execv", a nice function that does just this: shuts down the current instance of python and finally runs another command on the shell with specified arguments. I set it up so when a game was selected, the code would run:
I used the same mechanism to get games to shift control back to the main menu when the player quit them. This was convenient, because it meant I had to make very little change to the existing game code.
All games were working nicely. I also adapted an existing game that used the mouse to work with the touchscreen input. Here's the console in action:
Current Games:
"The Wizard's Data": pyweek 20 entry by Team Chimera
"Adrift" pyweek 21 entry by Team Chimera
"Underworld": a beta version of a game I've worked with on and off for about a year :)
Overall I was super happy with the outcome for this project. There are however a few things that I learnt and would do differently for next time:
Buttons: I didn't really like the buttons in the end, they make an annoying loud clicky sound and don't depress far enough. To their credit they look nice and are responsive. They just don't feel as good as a proper games controller: next time I do this sort of thing I will definitely invest in some proper arcade buttons, or at least something that has a built-in spring or rubbery inside to produce a smooth, but still responsive feel.
Audio Volume: I don't know why, but the audio volume is super quiet. Not sure if I botched something or not. I'm pretty sure I've got the trimpot ramped up correctly ... will try to figure this out somewhere down the track.
When my case was fresh off the printer, I started lining up all the components to see that everything would fit as I'd planned. I think I had convinced myself that I would have gotten at least one measurement wrong somewhere and that this first print would be just a test run. I was happy to discover that I had actually not stuffed up anything too critical and that I could get it all to work. The thing that didn't really work as well as I had hoped was the standoffs for the smaller components (amp and boost converter): I had designed a cylinder to fit through the small mounting holes on these PCBs with a diameter of 1.6mm, but when they came out of the printer, these parts of the structure were just a stringy mess: I guess they were just a bit below the resolution the printer was capable of. The standoff cylinders for the pitft screen and RPi mounting holes were 2.5mm diameter, and these came out fine, but they were pretty fragile. In the end, I decided to break them off, drill 2 mm holes in their place and screw the pitft, RPi and larger holes on the boost converter onto the standoffs: lesson learnt for next time!
Once I was happy that everything would fit, I started assembling the buttons, RPi and screen into the case. I cut two square(ish) sections from perf board to hold the buttons (main buttons and dpad) on either side of the screen, and drilled 2 mm holes into these so I could screw them down to standoffs on the case. Buttons were then soldered on before screwing the perf board onto the case.
At this point I realised I'd miscalculated the heights of the standoffs for the dpad side: it was short by about 2 mm such that the buttons would be pressed down permanently upon screwing it in. I didn't have any washers that were small enough, so, because I'm super impatient, I improvised with snipped off bits of wall plugs :) ... Total hack, but hey, it did the job. A little bit of bluetack on the back of each button stopped them from have that slightly annoying rattle.
I then screwed in the tft screen to the case; the RPi would then slot on top of the 40 pin header; conveniently the tft also provides an additional breakout of this same header, which I connected a 40 pin ribbon cable connector to, chopped off at one end so I could feed out the GPIOs/ground to the buttons and 5V/ground in from the boost converter. I soldered up all those connections, plugged the pi on top and powered it up to check all the buttons were working well.
Next I wired up the amp to the speaker, and positioned these in the case. The standoff pins in the case for the amp hadn't come out properly in the 3d print, but it was ok with no further modification, found the board could sort of float in the case with no issue. Next step was to screw in the boost convertor to the case using two of the four mount holes. Soldered the power out pins to the RPi (via header cables) and across to the amp.
Placed the battery into the case, held in place with a tiny bit of gaffer. I fit the slide switch into its hole in the case and soldered it on to the boost convertor. Last step was to solder the signal pins from the amp to the solder points on the RPi PCB that sat adjacent to the 3.5 mm audio jack. Closed the case up, switched it on and everything was working a-ok!