Tomy Mr Money Google AIY Assistant

If you are a regular MagPi magazine subscriber, you’ll know in issue 57 they had their most popular giveaway with the Google AIY Project Voice Kit. Unfortunately, I was one of those unlucky people not to get my hands one. After seeing all the fun everyone was having on twitter though, I decided to do what I do best and make my own. Now, if you know me at all by now, you know I like my retro tech, so for this project, rather than just creating a plain old box for it I decided to repurpose another beloved 80s toy of mine, my Mr Money moneybox. The result? Hilarious :D

The Build

The Core

To start with, I carefully opened up my Mr Money money bank and removed all the insides to leave me with the basic shell. The inside surface of the base was pretty uneven, so I started by cutting a circular piece of acrylic to place on top of this to give a nice clean surface on which I could mount all the internals components.

Given the limited internal space, my only choice was going to be a Raspberry Pi Zero. Thankfully the new “W” versions have wifi built in, so this allowed me to leave the USB port free for a USB microphone.

Even using a Pi Zero, placement of the Pi was still pretty tight, so the only real option was to mount it centrally. I knew I was going to need space either side for cables and things, so this dictated that it would need to face front to back. To fix into place I used some nylon stand offs and stacked the Speaker pHat on top. On top of this, I added an extra plate to allow me to zip tie the mic to it, which I connected to the Pi via a short micro USB to USB female cable. Finally, a short right angled micro USB extension cable was fed out the back to act as a USB power connector.

The Arm

If you are familiar with the original Mr Money, you’ll know his arm was spring mounted to feed money into the money bank. Well, this seemed a prime candidate to convert into the button to trigger the AIY into action.

Looking inside, there was already an attachment to the arm socket with a little nub which triggered a switch from before (though it wasn’t permanently attached so I JB Welded it) which luckily was at just about the same height as the top plate, so re-cutting a new top plate with a “wing” created a perfect mounting position for a micro switch. I love it when things just line up :D

Whilst the arm was originally spring mounted, unfortunately the spring mechanism was part of the guts of the original toy which I had removed so I had to come up with an alternative. On inspection, there were a few nubs on the inside of the chassis and on the arm socket which I could just fit a small rubber band around so this worked great.

On testing the arm though, I found its travel was a bit too much. Before, it used to feed money into the mouth, so it needed to go pretty high, whereas now I really just wanted it to stop at body level. Looking inside the arms shoulder cover, I noticed this is where they limited this before with another nub to stop the arm traveling too far. To limit this further then, I drilled a small hole a little further in and JB Welded a small nylon shaft to act as a new nub.

With the arm sitting where I wanted it, and suitably springy, the final touch was to change the old “£” sign printed on the hand, to a question mark which I did by printing a replacement onto some sticker vinyl and cutting it out by hand.

The Head

Another key function of the original toy is the opening and closing head which I really wanted to have move as it talks.

To achieve this I chose to use a micro servo. I figured out a mounting point for the servo in the neck area on the underside of the head. To hold the servo in place I created a bracket on the laser cutter and fixed it to the head. To make the head actually move, I attached some paper clip wire from the servo horn through a small hole I made in the upper part of the head. Now when the servo moves it pushes and pulls the head open and closed.

One element I wanted to add was some kind of status LED to see what state the Pi was in. The AIY code already accommodates a status LED, so all I had to do was plumb it in. To keep it on theme, I thought I’d attached this to the head as a kind of antenna. To do this, I drilled a hole, then hot glued the LED in to place and ran wires down the next into the body compartment for wiring up later. To help limit the brightness of the LED a resistor was added in line with the LED.

Another element I liked from the original toy was the moving tongue, however I couldn’t find a way to incorporate this (did I mention space was tight?) so unfortunately I just had to cut it down and glue it in to place so I could at least keep the aesthetic.

The Speaker

As mentioned already, to allow the little guy to talk I decided to use the speaker pHat from Pimoroni. This does come with a speaker, however it isn’t the loudest so I decided to replace the speaker with another one I had. To be honest, the new speaker wasn’t much better spec’d, however I was able to wedge it against the base which made it reverberate much better when everything was closed up.

The Wiring

With all the components now in place it was just a case of wiring them up. To do this I used a Pico Hat Hacker, another Pimoroni special. So as not to interfere with the other components though I decided to mount it to the bottom of the Pi, rather than between the stacked pHat’s as is custom.

I wired the button and the servo as per the pinout used by the official Voicehat.

For the servo, I wanted to power this from the Pi itself so that I didn’t need an extra power supply. Given its only one micro servo this isn’t too much of a problem, but I wanted to put a precaution in place to try and prevent any current dips and spikes. For this I created a mini breakout board with a large capacitor bridging the power and ground lines so when the servo starts or stalls, it can pull or push a spike of current from the cap, rather than the Pi.

The Code

With all the hardware side complete, it was time to move on to the code side of things.

Basic Setup

The first thing to do is install the official AIY Project Voice Kit SD Image onto an SD card. I won’t go into detail on how to do this, but if you are unsure, you can find instructions on the official Raspberry Pi site. You’ll also want to configure a wifi connection.

Configure sound / mic

The standard AIY SD image is designed to work with the official voicehat hardware, however we are using the speaker pHat and a USB mic, so we’ll need to configure these.

First up, we’ll re-enable the default audio configuration by editing the boot config:

sudo nano /etc/boot.config

Scroll down to the bottom of the file and comment out 2 lines responsible for the google kit soundcard and enable the default driver:

dtparam=audio=on
#dtoverlay=i2s-mmap
#dtoverlay=googlevoicehat-soundcard

Next up, we’ll install the speaker pHat drivers by issuing the following command:

sudo curl -sS https://get.pimoroni.com/speakerphat | bash

Finally, we’ll make a few changes to the audio settings. The first being to disable the speaker pHats VU meter and secondly to combine the USB mic and speaker pHat driver into a single configuration. To do this, open up the audio settings config file in an editor:

sudo nano /etc/asound.conf

And then replace its contents with the following:

pcm.!default {
  type asym
  capture.pcm "mic"
  playback.pcm "speaker"
}

ctl.!default {
    type hw
    card 0
}

pcm.mic {
  type plug
  slave.pcm "hw:1,0"
}

pcm.speaker {
  type plug
  slave.pcm "softvol"
}

pcm.dmixer {
    type dmix
    ipc_key 1024
    ipc_perm 0666
    slave.pcm 'hw:0,0'
    slave {
        period_time 0
        period_size 1024
        buffer_size 8192
    }
    bindings {
        0 0
        1 1
    }
}

ctl.dmixer {
    type hw
    card 0
}

pcm.softvol {
    type softvol
    slave.pcm "dmixer"
    control {
        name "PCM"
        card 0
    }    
}

Configure AIY

Next up is to configure AIY. There quite a few steps to go through here, but thankfully Goole have done a really good job of documenting this step so rather than repeat this, I’ll just point you to the official docs and have you come back once you’re all set. Don’t worry, I’ll wait.

At this point you should have the AIY project working and responding to our commands, so now it’s time to add out little flourishes.

Configure Servo

The first of the changes is to have the head move. I decided on 3 states. The first was to open the head when you start a new question. Then it should move in a talking motion as it reads a response, and lastly it should close once again when it’s finished speaking.

To help with this, I created a small python class using RPi.GPIO to control the servo

import itertools
import logging
import threading
import time

import RPi.GPIO as GPIO

logger = logging.getLogger('mouth')

MIN_PWM_DC = 10
MAX_PWM_DC = 20

class Mouth:
    
    def __init__(self, channel):
        self.animator = threading.Thread(target=self._animate)
        self.channel = channel
        self.iterator = None
        self.running = False
        self.state = None
        self.sleep = 0

        GPIO.setup(channel, GPIO.OUT)

    def start(self):
        self.running = True
        self.animator.start()

    def stop(self):
        self.running = False
        self.animator.join()
        GPIO.output(self.channel, GPIO.LOW)

    def set_state(self, state):
        self.state = state

    def _start(self, dc):
        self.pwm = GPIO.PWM(self.channel, 100)
        self.pwm.start(dc)

    def _animate(self):
        while self.running:
            if self.state:
                if self.state == 'open':
                    self.iterator = None
                    self.sleep = 0.0
                    self._start(MAX_PWM_DC)
                    time.sleep(0.18)
                    self.pwm.stop()
                elif self.state == 'close':
                    self.iterator = None
                    self.sleep = 0.0
                    self._start(MIN_PWM_DC)
                    time.sleep(0.18)
                    self.pwm.stop()
                elif self.state == 'talk':
                    self.iterator = itertools.cycle([MIN_PWM_DC, MAX_PWM_DC])
                    self.sleep = 0.18
                    self._start(MIN_PWM_DC)
                else:
                    logger.warning("unsupported state: %s", self.state)
                self.state = None
            if self.iterator:
                self.pwm.ChangeDutyCycle(next(self.iterator))
                time.sleep(self.sleep)
            else:
                time.sleep(1)

def main():
    logging.basicConfig(
        level=logging.INFO,
        format="[%(asctime)s] %(levelname)s:%(name)s:%(message)s"
    )

    mouth = None
    try:
        GPIO.setmode(GPIO.BCM)

        mouth = Mouth(12)
        mouth.start()
        while True:
            try:
                state = input()
                if not state:
                    continue
                mouth.set_state(state)
            except EOFError:
                time.sleep(1)
    except KeyboardInterrupt:
        pass
    finally:
        mouth.stop()
        GPIO.cleanup()

if __name__ == '__main__':
    main()

There is quite a bit going on here, but mostly I just copied from the existing LED.py and adjusted it for my needs. One thing I did find during this, was that the servo would jitter quite a bit when holding a position, so to get around this, I just disengage the servo whenever it stops a motion. Thankfully the head is stiff enough that it holds its position, so this is not a problem.

I saved this code in a Mouth.py file in a folder ~/voice-recognizer-raspi/src/classes along with a blank file __init__.py which allows the class to be imported into other python code in the same folder.

With this saved, it was now a case of importing it in the Main.py file, and incorporating it into the main code base.

In the includes section at the top, add an include to our file and one for the RPi.GPIO class.

from classes.mouth import Mouth
import RPi.GPIO as GPIO

Then in the main function, setup an instance of the mouth class

GPIO.setmode(GPIO.BSM)
mouth = Mouth(12)
mouth.start()

Now, we need to get our mouth instance to the SyncMicRecognizer class so we need to pass it through the do_recognition method first. To do this, just add a mouth param to the method declaration and one to the constructor of SyncMicRecognizer and pass the mouth instance through when the method is called and when the class is instantiated.

Within the SyncMicRecognizer class, we’ll make a few changes to trigger our mouth actions. First off, update the _status method like so:

def _status(self, status):
    if self.led_fifo:
      with open(self.led_fifo, 'w') as led:
        led.write(status + '\n')
    logger.info('%s...', status)

    if status == 'listening':
      self.mouth.set_state('open')
    elif status == 'ready':
      self.mouth.set_state('close')

The start is the standard code, it’s just the bottom bit that we’ve add to trigger out mouth to open and close.

Next, we will trigger the talking action by editing the _handle_result method and setting the talk state whenever we start to play a sound

def _handle_result(self, result):
  if result.transcript and self.actor.handle(result.transcript):
    logger.info('handled local command: %s', result.transcript)
  elif result.response_audio:
    self.mouth.set_state('talk')
    self._play_assistant_response(result.response_audio)
  elif result.transcript:
    logger.warning('%r was not handled', result.transcript)
    self.mouth.set_state('talk')
    self.say(_("I don’t know how to answer that."))
  else:
    logger.warning('no command recognized')
    self.mouth.set_state('talk')
    self.say(_("Could you try that again?"))

With this, we should now have our head moving whenever we ask our little guy a question.

NOTE At this point, I started seeing a segmentation fault. To be honest, I don’t know what was causing this, but the following command seemed to fix it:

ulimit -s 32768

Change Voice Pitch

The last thing I wanted to do was make the voice fit our little robot. For me, the default Google voice wasn’t quite cute enough. To achieve this I decided to swap out the default player used by AIY for SOX, a robust sound processing program that supports a bunch of filters, including pitch shifting.

First up you’ll want to install sox

sudo apt-get install sox

Then we’ll modify the Player class inside the audio.py file to use the sox player rather than aplay. In this class, change the cmd array to the following:

cmd = [
  'play',
  '-q',
  '-t', 'raw',
  '-c', '1',
  '-e', 'signed',
  '-b', sample_width_to_sox_string(sample_width),
  '-r', str(sample_rate),
  '-',
  'pitch', '800'
]

We’ll also need to add a custom sample_width_to_sox_string helper method to the top of the file:

def sample_width_to_sox_string(sample_width):
  """Convert sample width (bytes) to SOX format string."""
  return {1: '8', 2: '16', 4: '32'}[sample_width]

And with that, we should have our little guy speaking in a much more suitable pitch for it’s size :)

Conclusion

This was actually meant to be a pretty quick build for me, but it ended up being quite a big mod, however I’m really happy with the result and I’m glad I persisted with the requirements of the moving head and pitch shifted voice.

Full disclosure I actually started this project a while ago, and got stumped with the code and only just finished it recently. Unfortunately the AIY code has changed a bit since I started so some of the steps might not be immediately copy and paste-able, but I hope it at least gives you a good starting point if you do end up trying it for yourself.

Tomy Turnin' Turbo Dashboard Outrun Arcade

If you’ve read RombusCT, Rombus3000 blog posts or follow me on twitter, you’ll probably know I love nothing more than hacking some retro tech, preferably from the 80s, and upgrading it with today’s technology to make something that might have existed if only the original designers/engineers had access to the same tech we do. Well, I’ve only gone and done it again, and this times it’s with the Tomy Turnin’ Turbo Dashboard, an old 80s desktop motorized driving game which I’ve converted into a suitably retro Outrun arcade.

Some key features are an integrated 3.5” TFT screen, fully usable steering wheel and gear shifter (dashboard turbo light comes on when in high gear), working ignition key for power, true MPH speed and rev counter displays, and a fuel gauge to represent the stage time remaining.

The project itself was quite a big one for me, filled with several moments of frustration, from burnt out potentiometers, to soldering LEDs backwards, multiple TFT screen purchases and more than one change in direction as approaches to problems were found to be inadequate.

What’s documented in this post then are the final approaches I took (or at least the best I can recall as some times I’m sure I was just trying anything :)).

Inputs

When hacking hardware, I usually follow a pretty simple rule, “keep it as stock looking as possible”, so the first constraint I set myself was I must use only the existing inputs, so I’d have to use the shifter, steering wheel, ignition and push button that came with the toy. Sounds simple, but these became a real challenge.

Gear Shifter

The first input I tackled was the gear shifter. Looking at the normal outrun arcades, these tend to have a 2 position shifter for high and low gear. Given the lack of an accelerator in the toy though, I decided to go with a 3 position setup, low, neutral and high for which I’ll later handle acceleration in code such that being in low or high gear will automatically apply the accelerator and being in neutral will apply the brakes.

Given this approach, I decided I’d use two switches to detect low / high gear and would also incorporate a self centering mechanism to automatically spring back to neutral if you let go of the shifter.

For the switches, I examined the areas around the shifters internals to see where I could mount them, and found I could fit some just to one side of the shifter. I also noticed that the shifter stick itself had a nice cutout which would be perfect to insert a 3D printed actuator, so this is exactly what I did. A bit of hot glue and JB weld later and the switches and actuator were mounted.

For the self centering mechanism, I kept a gear with a rod attachment from the original internals which sweeps side to side as the gear shifter is moved, and rigged up some rubber bands around some nearby internal structures to force it to stay centred, which in turn forces the shifter to stay centred. A bit Heath Robinson, but nobody is going to see it, so hey :)

Steering

The next tricky one to solve was the steering. Again reviewing the original mechanism, the end of the steering wheel already had an actuator that converts the rotary motion of the wheel into a linear, side to side motion. The first thought that came to mind then was to use a slide potentiometer with a custom head to match the original connector. Well, a custom PCB, a Digikey order of a few different sized slide pots, and some 3D printed tinkering and the approach worked :)

The PCB isn’t anything fancy, it just mounts to a plate that was already in the toy, and exposes the three pins of the potentiometer that get hooked up to the controller board later on.

Ignition (Power)

For the ignition, I really wanted this to be the power switch, so turning the ignition on turns on the Pi, and turning it off powers everything down. Any good Raspberry Pi developer knows you can’t just turn a Raspberry Pi off, but thankfully I’d recently purchased a few PowerBlock PCB’s which handled the powering up / down for you, so I simply used one of these and connected the wires that already came from the ignition key.

A couple of mods I did make to the PowerBlock though were to replace the upright pins with some right angled ones as I knew I was going to be stacking other components above it, so wanted to save some vertical space, and I also knew I was going to need access to the I2C pins which the PowerBlock connects to, as well as access to the 5/3v pins, so I modified a Pimoroni Pico HAT Hacker (making sure not to break any traces I’d need) and soldered it to the head of the pin tops on the PowerBlock PCB.

Another nice feature of the PowerBlock is the ability to attach an indicator LED, so for this I (carefully) drilled a hole in the chassis next to the ignition key and mounted a 3mm LED with hot glue.

Lastly, I needed to decide on an actual power source. I did consider battery power, but this was going to take up too much space, so I just went with an approach I’ve done in my other projects which is to use a panel mount barrel jack. This is really the only non original modification, however using panel mount components makes for a really clean solution, so I was happy to go with it. For the power source I use a 5V DC 2A power supply, so it should suffice for all my power needs and saves the need of any converters.

Start Button

The only really “push button” element from the original toy was a reset button for a counter, but again, this was all rather mechanical. From an arcade point of view, the only thing we’ll need a button for is to start the game (we’ll configure the game later to be freeplay so we don’t need a coin button) so this seemed a perfect candidate.

For this, I had some large tactile switches lying around already from another project so mounted one of these on some scrap prototyping board, cut it to size and mounted it roughly inline with the original hole. I 3D printed a block to act as a mounting wall, but really it was just a case of using something to keep it straight and provide something to glue against.

For the button, I used my dremel to cut it down to size and then JB welded it to a button cap that attaches perfectly to the tactile switch. It doesn’t really have much “in/out” movement, but it does the job. Wires were attached to the board and then linked up to the controller.

Volume Controls

I knew I was going to be adding a speaker, but I also knew I’d probably want to be able to control the volume of this, so volume controls were going to be needed. I really didn’t want to add any extra external controls for these to ruin the aesthetic, so instead I decided to mount them inside the old battery compartment out of the way. As they wouldn’t be seen, they didn’t need to beautiful, so I just soldered some small tactile switches to some spare perf board and hot glued them to the inside of the compartment.

Controller (Picade PCB)

The final element for the inputs was some kind of controller. As I’d used one before in both the Rombus3000 and the RombusCT, Rombus3000, a Picade PCB seemed the perfect candidate. Another positive for this was that it was already capable of handling analog joysticks, so with a bit of config, should just work with my steering wheel potentiometer no problem, as well has having an onboard amplifier for the speaker.

To configure the board, I downloaded the latest firmware update, and from the Pi, flashed it to the PCB (see the github repo for instructions). I kept the default keyboard configuration, but just changed the single “Up” connector to be a joystick input by issuing the serial command b 0 249 followed by an s command to save this to the EPROM.

The last thing to do was to wire everything up, which was pretty much standard. The only other thing I had to do was feed some 5v + GND wires to the steering wheel potentiometer. For this, I just pulled them off the ISP pins on top of the Picade board.

Outputs

With the inputs sorted, it was time to start thinking of how to actually display things. I knew I was going to need a screen for the actual game play, but I also really wanted to make the dashboard display interactive as this was such a key element of the original game.

Screen

In the end, I think I tried 3 or 4 different screen configurations, looking for the ideal setup. I was hoping to find something that would fit into the original bezel, but I ended up having to make a custom one instead as the screen was a little smaller than the cutout.

The screen I ended up going for was a KeDei 3.5” HDMI display (also sold under the brand KOOKYE). The HDMI element was really important, as I had tried a monitor that connected to the GPIO, but this just used up all the GPIO pins, which I knew I’d need, and on testing with the game later on, caused serious lag, so it had to be HDMI.

With the screen chosen, I then went about creating the mount and bezel. Starting with the bezel, I did a bunch of trial and error laser cuts out of black acrylic till I got something that fit snugly in the original space. The black acrylic ended up being a bit too shiny, so I sanded it down a bit to give it more of a matt look.

With the bezel mounted, then next tricky part was mounting the screen. To help with this, I 3D printed a thin surround to fit round the edge of the screen which I could glue into place without damaging the screen and then just use a few small dabs of hot glue on the back of the screen to hold it into place. It took some adjusting to get everything lined up perfectly, but it was really just patience and several attempts until it was spot on.

For the wiring, I purchased as low profile and flexible a HDMI cable as I could find, and for power, used a couple of jumper cables to take 5V and GND from the Pi’s GPIO header, and just hot glued those into place to make sure they wouldn’t fall out.

Dashboard

The dashboard was quite a tricky element. My initial hope was to reuse the original display and just mount some LEDs into the original cutouts. I designed and had manufactured a PCB for this, but on build, I realised it just wasn’t going to be good enough. There was also limitations in the speedo area as well as the original toy didn’t have cutouts for all the 7 seg segments of the speed display, so in the end, I decided to go with a full on custom display, but in the graphical style of the original.

The first PCB I had manufactured used SMD components, and during that test I found my SMD soldering skills weren’t great, so for this second attempt I knew I’d want to use through hole components. With that in mind, I did some DigiKey searching and found some rectangular LEDs and some right sized 7 Seg displays and went about updating the PCB design around those. The 7 Segs I got were actually a grey colour, but I wanted them black so I stuck some windscreen tinting film I’d purchased a sample of from ebay to the fronts and this worked out great.

For the LED controller, I already had an Adafruit IS31FL3731 charlieplexing LED driver board lying around, which was capable of driving more LEDs than I would need, so I went with that as the driver.

With the PCB designed and sent off to Dirty PCBs to be manufactured, I then focused on the dashboard decal. This was done in inkscape and I just transfered as much of the original design as I could making sure to line everything up with the PCB design being manufactured.

I printed the design out onto some vinyl sticker material I had purchased, cut out all the holes with a scalpel and then sandwiched it between 2 layers of clear acrylic, which also has cutouts for all the electrical components, which I’d cut out on my laser cutter.

When the PCB arrived, I soldered everything up, and did some testing with the Adafruit arduino driver, and it all worked just how I wanted it (well, maybe not first time, but this post is already getting pretty long :)).

To mount, I used the original dashboard mounting holes and screws, but then also hot glued the edges to make sure it wasn’t going to go anywhere.

Sound

The final output I would need would be a speaker. Outrun has some pretty nostalgic music so I knew I’d want to keep this element.

The speaker I used was one that I had pulled out of some other old toy a while back, and installation was just a case of finding a place it could mount easily. I ended up mounting it inside the old battery compartment, drilling a few holes to let the sound through.

Lastly, I wired the speaker up to the Picade PCBs speaker terminals, and that was that job done.

Construction

With all the inputs and outputs setup, the final hardware element to finish was the mounting of the Raspberry Pi itself, and any final wiring. There isn’t any rocket science here, I just chose the biggest clear space, and mounted everything in that spot stacked via some nylon standoffs, and being sure to leave enough room around the edge to make all the connections I would need.

Code

Now that all the hardware hacking was done, it was now time to move on to the code side of things.

Screen config

First up was getting the screen working. Being HDMI, I was hoping it would just be plug and play, which wasn’t the case, but thankfully it didn’t take much config to get going. All that was needed was to add the following to /boot/config.txt

disable_hdmi_overscan=1
hdmi_force_hotplug=1
hdmi_group=2
hdmi_mode=87
hdmi_cvt=480 320 60 6 0 0 0

There is a great review of this screen, including an explanation of this config over on the Raspberry Pi Forums, so if you want to know what all this means, be sure to check it out.

The screen is capable of supporting touch screen, but as this wasn’t really needed for this project, I just didn’t bother setting it up and moved on to the next item.

Sound config

For sound config I needed to do two things. Force analog audio out of the audio jack and merge the audio into a single mono track as I was only using a single speaker.

To force analog audio out, I issued the following commands at the terminal

sudo modprobe snd_bcm2835
sudo amixer cset numid=3 1 # Force analog

And then to merge the sound channels, I modified /etc/asound.conf with the following configuration

pcm.card0 {
  type hw
  card 0
}

ctl.card0 {
  type hw
  card 0
}

pcm.monocard {
  slave.pcm card0
  slave.channels 2
  type route
  ttable {
    # Copy both input channels to ouput channel 0 (left)
    0.0 0.5
    1.0 0.5
    # Send nothing to output channel 1 (right)
    0.1 0
    1.1 0
  }
}

ctl.monocard {
  type hw
  card 0
}

pcm.!default monocard

To make these changes take effect, you can either reboot, or just issue the command

sudo /etc/init.d/alsa-utils restart

Cannonball setup

Next up was the actual game itself. Given I knew I would want to read out some game variables such as speed, revs, turbo and time remaining etc, it was clear I was going to need something I could get pretty low level with. Thankfully I had already come across Cannonball, which is a C++ port of the original Outrun game and was capable of running on a Pi so I knew this would be my best option.

To get Cannonball running on the Pi, it boils down to the following commands

sudo apt-get update -y
sudo apt-get install -y cmake libboost-dev libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev
git clone https://github.com/djyt/cannonball.git
cd cannonball
mkdir build
cd build
cmake -G "Unix Makefiles" -DTARGET=sdl2_rpi ../cmake
make
ln -s ../roms roms

There is quite a bit going on here, but ultimately it’s just installing the needed libraries and setting up the cannonball build process. Cannonball makes use of the original MAME roms for the sprites so you’ll need to “acquire” these and drop them in the ROMs folder. With this setup, you can issue the command ./cannonball to start cannonball playing.

One thing you’ll probably want to do is enable OpenGL via raspi-config as without it the gameplay can be pretty laggy. I found the “Fake” option to be the best result.

With the game working it was now a case of exploring the code base and working out where certain things happen. This was quite time consuming and a lot to explain so I’ll just summarise here, but if you want to see all the changes I made, you can find them in my github repository here.

Basically though I hid all the graphic elements I was now going to be showing on the dashboard, and moved some other graphic elements around, such as the score and timer at the top of the screen.

Interfacing Cannonball with the Dashboard

With the game up and running, it was now time to get it talking to the dashboard.

For this I would use WiringPi and custom Dashboard class I wrote. Again, explaining all of the Dashboard code would be a bit too much for this post, but in summary I ported the Arduino code for the Adafruit IS31F3731 library to work on the Raspberry Pi by using WiringPi to do the I2C communications. Additional methods to interface with the individual dashboard elements were added, such as updateTacho, updateFuel, updateSpeed etc, and then the game code was updated to call these methods in place of the previously commented out code that would draw them to the game screen, making the dashboard update with the actual real time game values.

Note: Because cannonball is written in C++ this made this all a lot easier, but if you were using some other games engine, you could potentially inspect register values to pull out the different variables.

To incorporate our custom Dashboard class into the Cannonball codebase, I had to first install WiringPi (see instructions here, you’ll want to make sure you have it installed from src, so uninstall / reinstall if you don’t) then I had to update both the sdl2_rpi.cmake file to include the WiringPi dependency, as well as the CMakeList.txt file to include the new Dashboard C++ class files.

With those updated, you then need to re-generate your build files by navigating to ~/cannonball/build and re-issuing the commands

cmake -G "Unix Makefiles" -DTARGET=sdl2_rpi ../cmake

Now when you build the cannonball codebase using the make command, our custom Dashboard class and WiringPi will be fully compiled into the actual game executable and run as part of the game.

With all the code updates made, and our solution built, we can fire up the game to test everything by issuing the command

./cannonball

Now as we play the game, the revs, speed, time remaining (fuel) and turbo mode should all update our dashboard.

The last thing to do with Cannonball, was to make some configuration changes in config.xml file such as enabling fullscreen mode, enabling freeplay mode, setting the frame rate, disabling the menu system and enabling our analog steering wheel controller.

Autostart Cannonball

With cannonball working, we want to make it so that the game automatically starts when the system boots up. To do this I created a run.sh file in the ~/cannonball folder containing the following

#!/bin/bash
cd /home/pi/cannonball/build
./cannonball

Made it executable by issuing the command

chmod +x run.sh

Then added it to the desktop autostart file ~/.config/lxsession/LXDE-pi/autostart

@lxterminal -e “/home/pi/cannonball/run.sh”

Now whenever the Pi reboots, our game will automatically start.

PowerBlock config

Finally, the last thing to configure is the PowerBlock module so that our Pi safely shuts down when the ignition key is turned off. This is as simple as issuing the command

wget -O - https://raw.githubusercontent.com/petrockblog/PowerBlock/master/install.sh | sudo bash

Finishing Touches

With all the hardware and software done, the last things to do were just the finishing touches, which in this case was some custom decals. For these I designed them in inkscape again and printed them out on some printable sticker vinyl. Some careful scissor work later, and even more careful sticker placement and we were done!

Conclusion

If you actually read all of this post, then I salute you :) It was a pretty epic build, and a hard one to document so if I’ve skimmed over anything, be sure to leave a question in the comments. Overall though, it was a really challenging build, but I’m super happy with the result.

UPDATE: 2017-09-23

Thanks to feedback from a few people on twitter, I got reminded of a major feature that was present in the original Outrun arcades but that I had missed in my build, which was of course haptic feedback. Well, I couldn’t live knowing I was missing such an awesome feature, so I went ahead and added it in :)

For this I’m using a vibrating mini motor disc which I have attached to the underside of the steering wheel and routed the wires through the steering wheel shaft to the inside of the cabinet. There I attach them to an Adafruit DRV2605L Haptic Motor Controller which I have soldered directly on top of the IS31FL3731 boards I2C pins.

Cannonball already had an outputs class for haptic feedback, but I pretty much cleared that out and started fresh for my implementation. Similar to how I did the dashboard, I started by porting the Adafruit DRV2605L Arduino Driver to work on the Pi, then tweaked it to trigger different vibrations during the game (see my cannonball repo on GitHub for the full code). Currently I have it configured to vibrate when the car skids, goes off road or crashes.

All in all, I’m really glad I added this feature as it really does add an extra dimension and takes it to another level.

Rombus-CT - A Raspberry Pi powered mini cocktail arcade

If you follow my blog, you may recall my ROMBUS3000 project from a few months ago, which went down quite the storm. This was my attempt at fulfilling a long lived desire to create an arcade machine.

Well, when looking to create something to take to an event I am helping organise, CodeCabin, an arcade machine seemed the perfect fit. I could of course just take the ROMBUS3000, however I thought it would be much more fun to create a 2 player arcade so that multiple people can play together.

Looking around at case designs, there are many bar top options to choose from, but none of them really inspired me, until I came across an old video of a mini cocktail arcade.

When I had been looking to make an arcade machine many years ago, it was a cocktail arcade I was looking to make. I actually made a ton of progress including buying all the components, designing the case and cutting much of the wood, but I never actually put it all together, so this seemed like the perfect way to fulfill that dream, and thus ROMBUS-CT was born.

Design

Probably the longest running phase was the designing phase. This was all done in inkscape, and started by drawing out a few core components that I knew I wanted to use, such as the ZIPPYY joysticks (they have a nice short shaft, and are nice and cheap whilst still feeling “arcady”), the Sanwa 24mm diameter buttons (smaller than the standard arcade buttons) and the 8” monitor available from Pimoroni. With those in mind, the case design was built up around them.

A requirement of the design was that it must be able to be cut on my A3 laser cutter, so this pretty much defined the overall size of the top.

After a few nights work, I had a design I was happy with, and had broken it all out into flat panels to cut out on my laser cutter.

Prototype

With the design ready, I decided to go through a prototyping phase. I had a ton of laser ply in the garage, so this was perfect for experimenting with. I cut out all the panels, and dry fit everything together using masking tape to keep things together.

The prototyping phase was a really worthwhile process as it helped identify several little issues, allowing tweaks to be made to the design files before the real build began.

Build

With the design files ready for final production, the build began.

MDF was purchased from my local B&Q and cut down to A3 size, then the various panels were cut out and painted using a black satin wood paint to cover all visible faces and edges. A roller was used to give a much smoother finish.

Whilst the wood was coming out nice, reviewing the original video that inspired me, I really loved the wood effect finish they had, so at this point I started to look into wood effect vinyls, and came across some great options by d-c-fix (the guys at Pimoroni were suitably impressed too as they are now looking to stock this). I purchased a couple of metres of a few I liked the look of and proceeded to cut out a few sample panels on my plot cutter. The end result was nothing short of awesome, so I went ahead and cutout panels for all the external faces in a mix of light oak and black wood effect.

With all the panels ready, assembly began. M4 high tensile bolts were used (any bolts should work fine, but I liked the look of the black, high tensile ones) along with some 19mmx19mm metal brackets purchased from ebay to hold it all together. Care had to be taken not to tighten too much and ripple the vinyl, but it was usually a case of tighten them till it ripples and then do a quarter turn back.

The lid was attached via a couple of dolls house hinges, and all the buttons and joysticks were put into their associated locations.

Wiring

With the case built, the next step was to wire it up. Thankfully the guys at Pimoroni were kind enough to donate a couple of wiring looms from their Picade arcades (you can make your own really easily, they are just a bit time consuming so this saved me a bunch of time). I started by wiring all the buttons and joysticks, and then moved on to planning the internals and testing where components should sit.

Given how easy it was to use the Picade PCB in my ROMBUS3000 project, it was a no brainer I would used this again, however given that I now have 2 controllers this meant 2 would be needed (this requires a bit of fiddling code wise, but I’ll get onto that a little later). I also decided to upgrade the Raspberry Pi to a v3 with in built wifi and better processing speed. The only other piece I needed to fit inside was a little custom board I made with just some male PCB headers on to be used as a power distribution board so I could grab 5v/Gnd for various components, such as the monitor and some 5v LED’s in some of the buttons.

After a bit of jiggery pokery, I found a nice layout for everything and proceeded to drill some holes in the base so that I could screw all the components down. To save space I decided to stack the 2 Picade PCB’s together.

With everything in place, all the wires were attached to the various boards, and a power test was run. Of course it all worked first time :)

Programming

With the case built and wired, it was now the time to bring it to life.

The latest RetroPie was downloaded and burnt to the SD card and the Pi was booted up.

The first change I needed to make was to rotate the screen as it needs to be oriented in portrait mode (the top is actually designed so you can have it in either portrait or landscape mode, but I wanted to go with the classic cocktail arcade portrait mode). To do this I connected to the pi and updated the boot config file by running the command:

sudo nano /boot/config.txt

And then added/updated the display_rotate option as follows:

display_rotate=3

With that saved and the system rebooted, the display was now running in portrait mode. The next thing to configure was the Picade boards. By default, these come with a firmware that makes them act as a keyboard, which normally works fine, but when you are connecting 2 at the same time, RetroePie doesn’t differentiate them so there is no way to separate player 1 from player 2. Luckily, Phil at Pimoroni has been working on a new firmware that allows the boards to work as game controllers, which CAN be seen as separate controllers.

Before you can use the new firmware though, you’ll need to flash it to the boards. The easiest way to do this is from the pi itself.

Start by cloning the firmware repo:

git clone https://github.com/pimoroni/Picade-Sketch.git
cd Picade-Sketch/update

Now, with just 1 of the Picade boards attached, run the following command:

./update picade_2016.hex

Disconnect the Picade board, and do the same for the second board.

With the firmware flashed, we can now configure them as game controllers. To do this, you’ll need to connect to them over serial. I did this by connecting the board to my PC, and used Putty in serial mode, however you should be able to do this using Arduino’s serial monitor if you like. Just make sure you connect to the right COM port, and at baud rate 9600. With a connection made, configuring it as a game controller is as simple as typing the letter ‘g’. This will apply a default game controller config, however this will also replace the volume and esc/enter keys with alternative keys, but we want to keep these as they were with the keyboard setup. Luckily you can map these back by running the following commands:

b 12 176
b 13 177
b 14 250
b 15 251

With the controller configured, type ‘s’ to save the configuration to the Picade boards EPROM, and then repeat for the second one.

With the Picade boards configured as game controllers, you can now map them in RetroPie by running the gamepad mapping tool in the options menu. It’s best to connect the Player 1 controller first and configure the mapping, then connect the Player 2 controller. The Raspberry Pi seems to remember which USB port the controllers are connected to, so it should keep Player 1 as Player 1 and vica versa (though I’m not entirely sure how it does this). With the controllers configured, the only thing left is to load up some ROM’s. If you are using MAME, it’s worth going into the options menu with a game loaded (press tab), and go into the DIP Settings option and see if there is a “Cabinet” option. If there is, be sure to set it to “cocktail” and it’ll automatically flip the screen when it’s Player 2’s go. You’ll need to do this for each game individually. Another thing you can do if a game isn’t ordinarily cabinet friendly (this mainly works for top-down games such as Gauntlet or Bomberman) is in the options menu, tweak the controller settings for “this game” and invert player 2’s controls so that they can essentially play the game upside down.

And with that, the arcade is complete

Conclusion

All in all I think the cabinet came out awesome (I actually think it’s the best thing I’ve ever built). Some of the nice design touches I’m really happy with are using some large light up arcade buttons with a custom “coin slot” insert for the coin buttons, and the top decal printed onto acetate and cut out on the plot cutter.

Overall, it feels great to finally realize the project of building a cocktail arcade that I started so many years ago, and I can’t wait to see how well it goes down at the event.

PS. Be sure to checkout my youtube channel for some additional videos of the ROMBUS-CT in action.

UPDATE 2016-05-05

The guys at Pimoroni were kind enough to invite me onto their Bilge Tank show, so be sure to checkout episode 035 for an in depth look at the ROMBUS-CT :)