RetroPie Outlet

Synopsis

This is yet another RetroPie project to add to the internet's list. I wanted something that was going to be out of the way since my television is mounted on the wall without any furniture beneath it. Sure, I could have just tossed the Raspberry Pi behind the television and been done with it, but that's no fun.

This project nicely combined three of my favorite interests. It took some electronics fiddling, coding and a dose of 3D printing. Oh and I guess retro gaming. So four. Yeah, four.

Video Demonstration

Let's face it; this is why you are here. So let's just get this out of the way, now.

Photo Album

You can see a Google Photos photo album of everything related to this project here:

Special Features

Reed Switch Reset

I placed a reed switch (magnetic contact sensor) electrically in line with the RUN pin on the Raspberry Pi. When the switch is activated by a magnet from the front of the plate, the pin is tied to ground which resets the Pi. This keeps anyone (kids) from "accidentally" resetting the system. A reset switch is necessary because I don't want to remove the whole plate every time I need to shutdown the system to make an SD card backup.

Hidden Indicators

My first prototypes had the OLED display and Bluetooth LED's poking out of the plate, but the OLED display was hard to mount that way because the board it is mounted to is flush with the display portion. I did some tests with different layer heights in white and brown and decided that the brown hid the board nicely while allowing the light to shine through enough to be read, especially in dim room lighting.

I liked the way that worked out and then decided to mount the two LED's that way as well. This also keeps the LED's from piercing the room with their directional light beams. A script monitors the Pi's Bluetooth connections and lights one LED for each controller when they connect.

The OLED display shows the current CPU temperature only when the average of the last five temperature readings is above 46.5°C. When that temperature drops below 46.5°C again and the display is cleared, the script waits 5 seconds before watching the rolling temperature again. This keeps the display from flickering off and on when the temperature is close to the threshold.

Details

3D Printing

I went through about three or four iterations of the plate itself. It would have been a lot more, but I was a little smarter this time around. I knew that it was going to take some trial and error to get sizing right for the LED's, display, etc. even after measuring them with calipers, so I first printed out some small test prints of just those parts.

To get the translucency right, I printed out a few rectangles at different layer heights to see how well the display could shine through.

The main plate was started from a customizer tool found on Thingiverse. The tool allowed adding keystone jacks which were nearly perfect for the USB connectors I found. I couldn't generate exactly what I wanted, but some cutting and tweaking with Tinkercad and I had it. All that was left was to design the other bits for the LED's, reed switch, micro-SD reader, potentiometer and OLED display.

As you can see in some of the photos here, I used a healthy amount of hot glue to keep things in place in cases where the printed part alone wasn't quite enough. This also made it relatively painless to remove everything in the first few print iterations.

Electronics Circuitry

I couldn't be bothered to spend the few minutes it would take to build a nice digital version of the circuit diagram to the left here, but if you embiggen the image, you can probably make most of it out. There's certainly nothing groundbreaking going on here.

The only mildly tricky part was getting the resistor values dialed in for the Bluetooth connection indicators. The blue LED's and the potentiometer I added to adjust the brightness, were all parts I had in my bins. This meant that I had to work with what I had. The potentiometer had a wiper that measured from 23Ω to 88kΩ. Of course the 23Ω was too small and would have allowed the Pi to source too much, so I added 1kΩ resistors in front to keep the current in check.

A two pin header was soldered into the Pi at the PEN and RUN pins. The RUN pin was tied to a ground pin through the reed switch to allow me to easily issue a reset from the front of the plate with any magnet.

The green activity LED for showing drive accesses was tied to GPIO 19 through a 100Ω resistor. The following line was added to the config.txt file in the boot partition to make the pin follow disk activity.

dtoverlay=pi3-act-led,gpio=19

Python Scripting

This was my first real (if you can call it that) delve into Python. I come from a background in mostly C++ and C#, so I really missed my semicolons and curly brackets. And it just seems really strange that text indentations are what determine code blocks. At any rate, I fought my way through it enough to get it to do what I needed and then let it be. The code can really use some clean-up, but I'm leaving it as it is for now.

The one ray of sunshine was the Adafruit webIDE. At first, I was editing my Python scripts in a nano session, but quickly missed my syntax highlighting. Some quick searches for Python IDE's led me to the Adafruit webIDE. After installing that, editing scripts became much less painful.

There are two Python scripts that are started when the Pi boots up. One of the scripts shows the CPU temperature on the OLED display and the other controls the Bluetooth connection LED's.

The TemperatureStatus.py script started out (as is usually the case) with a sample script provided by Adafruit for the OLED display. The original script showed some interesting data on the OLED display but not the CPU temperature. After some digging I found the easiest way to get that value:

import subprocess
...
cmd = "/opt/vc/bin/vcgencmd measure_temp"
Temperature = subprocess.check_output(cmd, shell = True)

Once I had that figured out, I then added a very simple loop to check the temperature and average out the last five readings before printing the value to the OLED display. I didn't want it to be ON all the time, so there is a threshold of a hard-coded (don't judge me) 46.5°C that must be passed before anything is displayed.

The BluetoothStatus.py script was way more annoying to get working. The trouble was in determining when particular devices were connected. I found an old (likely abandoned) library on GitHub that worked for a short period of time, but would eventually crash, taking my script with it. I tried for several days to figure out why that was happening, but gave up in favor of a more direct method.

Similarly to how I retrieve the CPU temperature, I elected to use a subprocess call to the OS; this time to get the output of the hcitool. This returns all of the current connections as a string of text which I then check to see if it contains one or both of the hard-coded (again, stop judging) Bluetooth MAC addresses for the two game controllers that I have.

import subprocess as sp
...
stdoutdata = sp.check_output(["hcitool", "con"])
if "E4:17:D8:XX:XX:XX" in stdoutdata.split():
  bt1Connected = True

If one or both of the controllers are connected, then it's just a simple GPIO call to light the respective blue LED.

Parts and Downloads


Thanks for checking this out!

My sincerest apologies for the dorkiness expressed in this document. It's hard to hold back sometimes.