Overview
Devoted film fans will spend countless hours and hundreds of dollars (occasionally even thousands) to create flawless replica props for their personal collections. The iconic eye of HAL 9000 from 2001: a Space Odyssey is one such object of desire…popular enough that detailed (and pricey) licensed reproductions exist. This is cool stuff! But if we relax our criteria just a bit, you or I can turn out a pretty decent, recognizable facsimile in a weekend for just a small fraction of the cost. The 80/20 rule in action!
We’re not selling a prop or even a kit here…that would raise a big licensing stink, so please don’t ask. What follows are some ideas on creating one yourself. Much like our not-a-Back-to-the-Future-clock project, the concept came about when customers noted that a component already in our shop resembled an unrelated film item — in this case, our Massive Red Arcade Button and HAL’s distinctive lens.
Before you Begin…
This is not so much an electronics project as a craft project. The former would actually be easier to explain…a concrete matter of “connect wire A to point B,” period. The craft element though…what’s described here as “affordable” or “simple” might be contingent on a lot of techniques, tools and materials that I’ve amassed over the years (for example, getting access to a laser cutter may be a tall order). You’ll need to adapt the process to suit your skill set and the particular assortment of tools and materials at your disposal.As described here, this project involves among other things: laser cutting, spray painting, inkjet printing, sanding, soldering (if adding voice) as well as patience, a well-stocked junk drawer and a willingness to improvise. Before buying any materials, read through the guide, see how it matches up with what you have and know.
Page last edited April 22, 2013
Text editor powered by tinymce.
Doing a little homework to find actual HAL dimensions, I was surprised to see the button and bezel are within just a couple millimeters of the genuine prop — a Nikkor f/8 fisheye lens. We just need to dress it up a little, repainting the bezel from black to silver…
Squeeze these two tabs inward to release the button. It’s possible but a bit tricky to do with finger pressure alone, so you may want to use needle-nose pliers (gently!).
There may be a slight oily residue on the bezel (mold release from manufacturing, I suspect). This can be cleaned with dish soap and water, but be certain it’s absolutely dry before painting!
Paint Like a Pro:
The key to a good paint job is to use several light coats rather than one thick gloppy one. Allow 10-20 minutes between each coat to allow the paint to set up a bit. Make sure the paint is well-mixed prior to starting, and periodically give a few extra shakes while working.Hold the can about a foot away from the subject, and spray a light mist in three or four overlapping horizontal passes, starting just off one edge, working straight across and past the other edge. Yes, you’ll end up with more paint on your dropcloth than on the item, but it’s key to getting a flawless finish. Go fold laundry or something, then come back for another coat (perhaps turning the piece for a different angle). Repeat until there’s a few solid coats with no black showing through.
Allow the paint to dry for at least a couple hours (ideally overnight) before handling the piece. You can work ahead on other steps in the interim.
Model paint and a steady hand is an inexpensive approach. My craft stash happened to include some black vinyl contact paper (shelf liner) from a prior project. I used the clean, factory-cut straight edge toward the front of the lens, and trimmed at the back with a hobby knife.
This doesn’t include the extra materials for the optional black ring (sandpaper or masking tape, black model paint or contact paper) as I already had suitable items on-hand. Your tally may vary, depending on what steps you take and how you adapt this to your own supplies.
Page last edited April 22, 2013
Text editor powered by tinymce.
Crafting a Case
Working in Adobe Illustrator, I adapted the design to work with laser-cut acrylic and to fit our button. I chose to use common fasteners rather than glue…maybe not canon, but fast and easy. Acrylic cement has a way of seeping everywhere and ruining paint jobs. If you can’t get access to a laser cutter, you might still adapt this file (or Amadeus’ original) to your medium of choice.
YOU CAN DOWNLOAD THE GRAPHICS FILES HERE (ADOBE ILLUSTRATOR 10 FORMAT)
You’ll need to paint both sides of these pieces, and the edges as well. Spray at a 45° angle to reach both the face and edge. Allow to dry completely, then flip over and paint the other side.
In hindsight, I might cut these pieces out of clear acrylic; it seems less prone to this sort of warping, and it’s all getting painted anyway.
- Black acrylic is available with a matte finish on one side, if you don’t mind buying an extra bit of special material for this one part.
- Matte black spray paint can be used to kill the shine. Awful fingerprint magnet though.
- If you did the black contact paper thing around the eye, same material could be applied here.
- The front faceplate could be cut from 1/8" birch plywood and stained/painted black.
- We can rough up the acrylic to vaguely approximate a wood grain or brushed metal appearance…
The acrylic piece was dragged back and forth for a few minutes, being exceedingly careful never to move it perpendicular to the “grain.” Occasionally the piece was turned around or the sandpaper was repositioned so there wouldn’t be just one set of grooves.
When finished, the piece is quite pale and dusty, but washing it with dish soap and water restores most of the dark appearance. Be sure to let it dry completely before proceeding.
Or save a step and simply use inkjet sticker paper, if you have it.
I mentioned earlier the value in producing multiple copies of parts when the material allows; that’s why there’s four name tags here. The first two were trimmed a little off-center. The other two are usable, but the last I felt was the cleanest of the bunch and is what will go on the finished prop.
Page last edited April 22, 2013
Text editor powered by tinymce.
Assembly
Hey, wait a sec…if the center piece is symmetrical, it should be OK to flip either way. Why then is this face labeled “front”?
The trick is to examine the edge carefully…spot the bevel and arrange this piece so the frame parts want to lean “inward” — but will be held square by the front face. Done wrong, the frame pieces will splay outward and the corners won’t match up.
Not shown, the speaker grille can be similarly installed now, and the bottom edge of the frame with it.
The LED inside the button is already wired with a resistor for use up to 12 Volts. A 9 Volt battery (about $3) works fine. This connects to the two side terminals next to the switch.
LEDs have a specific polarity. You may need to switch battery terminals to get it to light.
So there you have it…a quick and inexpensive faux 9000-series computer. Not a perfect reproduction, but good enough to impress your geek friends, and it’s hard to argue at that cost.
You could bolt it to the front of your tower PC gaming rig and call it done. Or with a bit of extra effort and expense we can take this to the next level and add some sound effects…
Page last edited April 22, 2013
Text editor powered by tinymce.
Adding Sounds
For power you can either use the same 9 Volt battery as before…connecting to the Arduino using a 9V Battery Clip w/5.5mm Plug ($3)…or plug into the wall with a 9 Volt Switching Power Adapter ($7).
The WAV files are stored in the root directory of a FAT-formatted SD card. The card wasn’t factored into the cost above, figuring it’s likely that you (or someone you know) has spares around…the Wave Shield is a great way to reuse those feeble old 64 MB cards that are probably rattling around your camera bag.
- The + side of the LED (in the button) connects to VIN on the Wave Shield / Arduino.
- The – side of the LED connects to one of the GND connections (there are two right next to VIN).
- One terminal of the switch (either one) connects to the other GND.
- The other switch terminal connects to Analog Pin 0 (along the same edge of the board as VIN, on the next header over).
- The speaker (two wires) connects to the outputs on the Wave Shield board, just behind the headphone jack.
// Random HAL demo; adapted from PiSpeak sketch. When button
// on A0 is pressed, plays a random WAV file from a list.
#include <WaveHC.h>
#include <WaveUtil.h>
// REPLACE THESE WITH YOUR ACTUAL WAVE FILE NAMES:
// These should be at the root level, not in a folder.
static const char PROGMEM
file00[] = "0.wav",
file01[] = "1.wav",
file02[] = "2.wav",
file03[] = "3.wav",
file04[] = "4.wav",
file05[] = "5.wav",
file06[] = "6.wav",
file07[] = "7.wav",
file08[] = "8.wav",
file09[] = "9.wav";
// If adding files above, include corresponding items here:
static const char * const filename[] PROGMEM = {
file00, file01, file02, file03, file04,
file05, file06, file07, file08, file09 };
// Sorry for the sillyness, but this is how PROGMEM string
// arrays are handled.
#define error(msg) error_P(PSTR(msg))
SdReader card;
FatVolume vol;
FatReader root;
FatReader file;
WaveHC wave;
uint8_t debounce = 0, // Button debounce counter
prev = 255; // Index of last sound played
void setup() {
Serial.begin(9600);
if(!card.init()) error("Card init. failed!");
if(!vol.init(card)) error("No partition!");
if(!root.openRoot(vol)) error("Couldn't open dir");
// PgmPrintln("Files found:");
// root.ls();
digitalWrite(A0, HIGH); // Enable pullup on button
randomSeed(analogRead(A1)); // Randomize first sound
}
void loop() {
if(digitalRead(A0) == HIGH) { // Button not pressed
debounce = 0; // Reset debounce counter
return; // and nothing else
}
if(++debounce >= 20) { // Debounced button press
uint8_t n;
char name[20];
do { // Choose a random file...
n = random(sizeof(filename) / sizeof(filename[0]));
} while(n == prev); // ...but don't repeat last one
prev = n; // Save file #
debounce = 0; // Reset debounce counter
strcpy_P(name, (char *)pgm_read_word(&filename[n])); // PROGMEM->RAM
if(wave.isplaying) wave.stop(); // Stop WAV if playing
if(!file.open(root, name)) {
PgmPrint("Couldn't open file ");
Serial.print(name);
return;
}
if(!wave.create(file)) {
PgmPrintln("Not a valid WAV");
return;
}
wave.play(); // Start playing
while(wave.isplaying); // Wait for completion
sdErrorCheck(); // Check for error during play
while(digitalRead(A0) == LOW); // Wait for button release
}
}
void error_P(const char *str) {
PgmPrint("Error: ");
SerialPrint_P(str);
sdErrorCheck();
for(;;);
}
void sdErrorCheck(void) {
if(!card.errorCode()) return;
PgmPrint("\r\nSD I/O error: ");
Serial.print(card.errorCode(), HEX);
PgmPrint(", ");
Serial.println(card.errorData(), HEX);
for(;;);
}
Page last edited April 22, 2013
Text editor powered by tinymce.
Updating with CRICKIT
If you'd prefer to opt for a CRICKIT powered 9000 series rather than use the Wave Shield, this page will show you how!
If this is your first time using CRICKIT, follow this guide to get acquainted.
To get your CRICKIT and HAL talking, you will need some alligator clip to male jumper wire connectors, a screwdriver, and a micro USB cable (to upload code from your computer).
We will be taking advantage of CRICKIT's ability to multitask combined with the ease of CircuitPython.
The Signal port will be used to detect the button press, the Drive block to control the LED, and the Speaker block send audio signal to the speaker.
Attach the alligator clips to the button terminals as shown.
The two connections extending horizontally outwards detect a button press, while the two vertical terminals on the side are connected to the button's internal LED.
Connect button to CRICKIT
Now it's time to connect everything to your CRICKIT board.
Connect the red and black button wires to the Signal and GND ports.
Connect the LED+ wire to Drive 5V
Connect the LED– wire to Drive #1.
Use a screwdriver to tighten down the connections to the Drive terminal blocks.
Connect speaker to CRICKIT
Take the red and black wires coming from the speaker and insert them into the Speaker terminal block.
Tighten both connections with a small screwdriver.
A small square of double sided foam tape will hold your CRICKIT in place on the back of the speaker.
Once everything is connected you're ready for some code!
Getting Familiar with Mu
We will be using CircuitPython code, which is easiest to work with in the Mu Editor. If you haven't previously used Mu, this guide will get you started.
If you haven't used Circuit Playground Express with CRICKIT before, make sure you've updated it with the latest special 'seesaw' version of the CPX firmware. This guide will show you how.
Copy and paste the code below in your Mu editor window.
# SPDX-FileCopyrightText: 2018 Anne Barela for Adafruit Industries
#
# SPDX-License-Identifier: MIT
import os
import random
import time
import board
import audioio
import audiocore
from adafruit_crickit import crickit
# Hal button-and-voice example
# Button connected to Signal pin #1 & ground:
BUTTON = crickit.SIGNAL1
crickit.seesaw.pin_mode(BUTTON, crickit.seesaw.INPUT_PULLUP)
# LED connected to 5V & Drive pin #1:
LED = crickit.drive_1
LED.duty_cycle = 65535
# Find all Wave files in CIRCUITPY storage:
WAVEFILES = [file for file in os.listdir("/")
if (file.endswith(".wav") and not file.startswith("._"))]
print("Audio files found:", WAVEFILES)
# Audio playback object:
AUDIO = audioio.AudioOut(board.A0)
# Function to play a wave file in its entirety:
def play_file(wavfile):
print("Playing", wavfile)
with open(wavfile, "rb") as f:
wav = audiocore.WaveFile(f)
AUDIO.play(wav)
while AUDIO.playing:
LED.duty_cycle = random.randint(5000, 30000)
time.sleep(0.1)
LED.duty_cycle = 65535
while True:
if not crickit.seesaw.digital_read(BUTTON):
# Play a random wave file
play_file(random.choice(WAVEFILES))
# Then wait for button to be released
while not crickit.seesaw.digital_read(BUTTON):
continue
Use a micro USB cable to connect to the port on the Circuit Playground Express mounted on top of CRICKIT. You should see "CIRCUITPY" show up as a new device on your computer.
Save this code to CIRCUITPY as a file named "code.py".
Audio files for HAL 9000 are not included here, lest we run afoul of copyright issues, but with just a bit of Google searching you can find an ample supply already in WAV format.
Once you have WAV files you're happy with, you'll want to drag and drop them directly onto your CIRCUITPY drive.
When all is said and done your CIRCUITPY drive should look something like this.
It's OK if the file names for your .wav files are different from those in this image (the code is only looking for a specific file type, the names of the files themselves don't matter).
HAL speaks!
Connect CRICKIT to power and you should see the red button illuminate. Give the button a press and you'll be greeted with a random HAL 9000 quote.
Controlling volume
If you find HAL's voice is too loud or too quiet you can easily adjust this on the fly without the need for changing the code.
Use the small potentiometer on CRICKIT to adjust the speaker's volume up or down.
Page last edited April 22, 2013
Text editor powered by tinymce.