Introduction: Sonic Screwdriver Style Computer Interface

These instructions will document the creation of a HCI device in the style of a sonic screwdriver.
The main components are two RFD21733 transceivers and a Teensy 3.0.

A demonstration video of the working device can be found here: http://youtu.be/rfqSQ8AdxLw
The video shows how the device can be used to open web pages, select files and play music.

A binary coded rotary switch will be used as an input to an RFD21733 transmitter. The transmitter will then send the commands to an RFD21733 receiver, which will pass the command to the Teensy. The Teensy will be emulating a keyboard, it will interpret the command and send a sequence of keyboard shortcuts to the computer to perform the required task.
The main design will be powered by two AAA batteries and will have an eight bar LED display. It will be housed in a sonic screwdriver style casing with a large LED on top, which will light up when the device is transmitting.
The second RFD21733 module and the Teensy will be sepparate and connected to the computer.
Using this setup, the Teensy can be programmed to control multiple applications and the device can be used as a full computer interface.

The rest of this introduction lists the required components, then in the first step the Teensy will be set up. In step two the wireless transceivers will be tested on a breadboard, then step three will connect the RFD21733 modules with the Teensy to get some basic functionality. Step four describes the details of the LED display and testing it on a  breadboard. In step five the power supply is constructed and in step six the chassis is prepared. Step seven then details how the display section should be arranged to fit in the chassis. Step eight puts all of the sections together and step nine takes the receiver circuit off of the breadboard to complete the hardware side. In step ten a simple application is described and code is given, then in step eleven a more complex application is suggested with example code.


Component List:

Main Functionality:
2x RFD21733 [I would recommend the transceivers already soldered into breakout boards - http://www.coolcomponents.co.uk/rfd21733-2-4gz-transceiver-breakout-board.html]
1x Teensy 3.0 [http://www.coolcomponents.co.uk/teensy-3-2.html]
1x 3PDT Switch [http://uk.farnell.com/jsp/search/productdetail.jsp?SKU=1813634]

Input
1x Binary Coded Rotary Switch [http://uk.farnell.com/jsp/search/productdetail.jsp?SKU=807590]
3x 1M pull down resistors
1x Knob [http://www.rapidonline.com/Mechanical-Fastenings-Fixings/OKW-Tuning-Knob-Thermoplastic-Body-With-Aluminium-Cap-12-x-4-x-7-2-x-5-5mm-51-9458]

Display:
1x LED Array [http://uk.farnell.com/jsp/search/productdetail.jsp?SKU=2290323]
1x Resistor Network [http://uk.farnell.com/jsp/search/productdetail.jsp?SKU=9355936]
1x Quad OR gate IC [The DIP package was chosen so that it could be put in to a breadboard for testing - http://uk.farnell.com/jsp/search/productdetail.jsp?SKU=1739939]
1x Quad AND gate IC [http://uk.farnell.com/jsp/search/productdetail.jsp?SKU=1739924]

Top LED:
1x Large LED [any large LED is fine but make sure that the forward voltage drop is somewhat less than 3v - http://www.maplin.co.uk/10mm-super-bright-leds-587417]
1x LED Clip [http://www.maplin.co.uk/led-clips-covers-2071]
1x 1k resistor

Power:
1x Battery box for two AAA batteries [http://www.maplin.co.uk/aaa-size-battery-holders-31426]
1x SPDT slide switch [http://www.maplin.co.uk/single-polesub-miniature-2476]

Casing:
2x Drinking yogurt bottles [would recommend strawberry - http://www.sainsburys.co.uk/groceries/index.jsp?bmUID=1381997198629]


Misc:
Wire
Header pins
USB Cable (for programming Teensy)
Tactile switch (optional)
Copper strip board
Paint
Glue gun
Soldering iron with solder
Power supply and breadboards for testing
Batteries

Step 1: Teensy Testing

So in this step we will just get the Teensy connecting to the computer.

Essentially, follow the instructions here: [http://www.pjrc.com/teensy/first_use.html]
Use the Teensyduino style of programming your device, for which there are further details here: [http://www.pjrc.com/teensy/teensyduino.html] (This will require the Arduino software [http://www.arduino.cc/en/Main/Software])

If successful you should now know how to open a sketch in the Arduino editor, compile it, download it to the Teensy and then run it.
If this is not the case then you should review the documentation in the links above.

Step 2: Going Wireless

In this step we will attempt to get the RFD21733 modules talking to each other.

So the RFD21733 modules are designed to be easy to get up and running, with 8 different preset modes, built in antenna and a wide supply voltage range.

We will be using modes 1 & 6:

Mode 1 - Input Logic Transmitter
In this mode the module will simply transmit any 3 bit input it's given.

Mode 6 - Receiver with Logic Output (20ms hang-time)
In this mode the module will listen for any transmissions and then output any 3 bit messages it receives.

Firstly, solder header pins to the break out board so they can be put into a breadboard.
Secondly attach a 3v power supply and connect the pins as follows:

Transmitter: (pins going from top left anticlockwise; IE. down the left side then up the right side)
Pin 1 - MS2 - Ground
Pin 2 - LED - Resistor -> LED -> Ground
Pin 3 - IN1 - Input
Pin 4 - IN2 - Input
Pin 5 - IN3 - Input
Pin 6 - X
Pin 7 - X
Pin 8 - GND - Ground
Pin 9 - Vd - 3v
Pin 10 - X
Pin 11 - MS0 - 3v
Pin 12 - MS1 - Ground

Attaching the mode select (MS) pins in this way puts the module into mode 1.
The LED will light up when the module is transmitting.
The inputs (IN) can be attached to the rotary switch when testing, or you can simply connect a wire to ground or 3v to get the desired input. The attached picture shows the use of three tactile switches for the inputs.
The rotary switch takes a 3v input from the single pin at the back, then the outputs at the front can be connected, via pull down resistors, directly to the transmitter inputs.

Receiver:
Pin 1 - MS2 - 3v
Pin 2 - X
Pin 3 - IN1 - Output
Pin 4 - IN2 - Output
Pin 5 - IN3 - Output
Pin 6 - X
Pin 7 - X
Pin 8 - GND - Ground
Pin 9 - Vd - 3v
Pin 10 - X
Pin 11 - MS0 - Ground
Pin 12 - MS1 - 3v

Attaching the MS pins in this way puts the module into mode 6.
The outputs can be attached to LEDs via resistors when testing to show the output.

If the modules have been connected correctly, then sending any of the input pins high should firstly turn on the LED on the transmitter to show that it's transmitting and then the corresponding outputs should be driven high on the receiver.
If this isn't the case then check the power is turned on and then check your connections.

Step 3: Basic Functionality

In this step we will connect the wireless modules up to the Teensy and use them to send an input to the computer.

Firstly, solder some header pins on to the Teensy so that it can be used in a breadboard.

The transmitter can stay as it was in the previous step.

Adjust the receiver to the following:

Receiver -> Teensy:
Pin 1 - MS2 - Teensy pin labelled "3.3V (100 mA max)"
Pin 2 - X
Pin 3 - IN1 - Teensy pin 0
Pin 4 - IN2 - Teensy pin 1
Pin 5 - IN3 - Teensy pin 2
Pin 6 - X
Pin 7 - X
Pin 8 - GND - First Teensy pin labelled "GND"
Pin 9 - Vd - Teensy pin labelled "3.3V (100 mA max)"
Pin 10 - X
Pin 11 - MS0 - First Teensy pin labelled "GND"
Pin 12 - MS1 - Teensy pin labelled "3.3V (100 mA max)"

The Teensy pin numbers and names are taken from [http://www.pjrc.com/teensy/card5a.pdf]
The receiver will be powered from the computer USB port via the Teensy, so there should now be nothing connecting the two transceivers.
The input pins on the Teensy are changeable, just make sure they are set correctly in the code.


Next the attached code should be loaded on to the Teensy and run. It can be copied as it is, to a sketch and then should run fine on the Teensy 3.0.

The code firstly defines the pins that are in use and their functions.
Then it declares a few variables for storing values, such as the input from the module.
There is also a timer set for debouncing.
The interrupt handler is called when an interrupt is triggered and then disables the interrupts, gets the input values and then enables the interrupts again.
The interrupt enable and disable functions attach and detach rising edge interrupts to the three input pins respectively.
The get input function simply reads in the three input pins and an optional button, then, after some debouncing, converts the binary input into a decimal integer. Lastly it uses the serial connection to output the result to the computer.
The setup function (unusual order I know!) sets the function of the pins (IE. Input/output), enables the interrupts and then flashes the Teensy LED to show that it's ready for use.

Overall, the code tells the Teensy to wait for an input. When it receives an input an interrupt is triggered - an interrupt is an event that causes the current program to pause whilst some other code is run. So in this case the program is doing nothing, then this nothing is interrupted and the interrupt service routine (ISR) is called, once this function has finished then the program will go back to doing nothing exactly as before.
Our ISR first disables the interrupts, this is so the Teensy doesn't try to run the ISR whist already running the ISR as this can get seriously messy with variable access and generally undefined behaviour... :-/
Additionally the debouncing thing... Debouncing is the mitigation of mechanical bounce. Mechanical bounce is the small amount of oscillation experienced by a switch. So when you turn a switch on it isn't just a simple off -> on swap, sometimes it happens that the two connectors actually hit each other and then bounce up and down before becoming stable, this is called mechanical bounce. In our design the switch connecting the rotary switch and the transmitter may suffer from mechanical bounce causing the input to be transmitted more than once, so a timer is put in the code so that if more than one input is received within 100 microseconds only the first will be accepted.
So essentially, the code will wait for an input, read the input and output it via the serial connection.

To view the serial output, when the program is running click the magnifying glass button in the top right hand corner of the Arduino code editor. This should display "RFD21733 Interface:" after the LED has flashed.

If this has all been done correctly then the serial display should print the decimal version of the binary input given to the transmitter.
If you are unable to open the serial display or the LED doesn't flash then the teensy code isn't running, try resetting the Teensy.
If the "RFD21733 Interface:" message doesn't appear then the input test code hasn't been downloaded correctly, try downloading it again.
If there is no output after the initial message then check the pins have been set correctly in code to correspond to the connections made with the hardware. {This should be set in the "Constants" section, directly after the "Define pin numbers" comment}
Alternatively, check the connections from the receiver to the Teensy, the power to the receiver, that the transmitter is turned on and is transmitting (the LED turns on).
If the numbers are showing up but the order doesn't seem to correspond to the binary input, check that least significant bit connects to input 0 and the most significant bit connects to input 2.

Step 4: Display

In this section I will describe how to make the display.
However, as the device will still function without it, the rotary switch outputs can simply be connected to the LED array via the resistor array to give a basic display option. This will also save space and make it easier to fit into the chassis.

The aim here is to provide a way of converting the binary output from the rotary switch to a "level meter".
So selecting one would light up the first LED, selecting two would light up the first two LEDs, selecting three would light up the first three LEDs....
In this design the first LED is used as a power indicator, then the input level is displayed on top of this.

This can be done using digital logic, with only four OR gates and four AND gates. Labelling the binary inputs A, B and C and the LED outputs as a, b, c, d, e, f, g and h, the logic for each output will be as follows:

h = A & B & C
g = B & C
f = (A & C) | (B & C)
e = C
d = (A & B) | C
c = B | C
b = A | B | C
a = 1


The pins should therefore be connected as follows:

AND Gate:
1 - Input A and OR Gate pin 1
2 - AND Gate pin 13
3 - OR Gate pin 4
4 - Input A
5 - AND Gate pin 10
6 - AND Gate pin 12
7 - Ground and OR Gate pin 7
8 - Resistor Network pin 10 and OR Gate pin 13
9 - Input B
10 - Input C and OR Gate pin 10 and AND Gate pin 5
11 - Resistor Network pin 9
12 - AND Gate pin 6 and OR Gate pin 12
13 - Input B and AND Gate pin 2
14 - 3v and OR Gate pin 14

OR Gate:
1 - AND Gate pin 1
2 - OR Gate pin 8
3 - Resistor Network pin 15
4 - AND Gate pin 3
5 - OR Gate pin 10
6 - Resistor Network pin 13
7 - AND Gate pin 7
8 - Resistor Network pin 14 and OR Gate pin 2
9 - AND Gate pin 9
10 - AND Gate pin 10 and OR Gate pin 5
11 - Resistor Network pin 11
12 - AND Gate pin 12
13 - AND Gate pin 8
14 - AND Gate pin 14 and Resistor Network pin 16

Resistor Network:
1 - LED Array pin18
2 - LED Array pin 17
3 - LED Array pin 16
4 - LED Array pin 15
5 - LED Array pin 14
6 - LED Array pin 13
7 - LED Array pin 12
8 - LED Array pin 11
9 - AND Gate pin 11
10 - AND Gate pin 8
11 - OR Gate pin 11
12 - OR Gate pin 10
13 - OR Gate pin 6
14 - OR Gate pin 8
15 - OR Gate pin 3
16 - OR Gate pin 14

LED Array:
1 - X
2 - X
3 - AND Gate pin 7
4 - AND Gate pin 7
5 - AND Gate pin 7
6 - AND Gate pin 7
7 - AND Gate pin 7
8 - AND Gate pin 7
9 - AND Gate pin 7
10 - AND Gate pin 7
11 - Resistor Network pin 8
12 - Resistor Network pin 7
13 - Resistor Network pin 6
14 - Resistor Network pin 5
15 - Resistor Network pin 4
16 - Resistor Network pin 3
17 - Resistor Network pin 2
18 - Resistor Network pin 1
19 - X
20 - X

This particular arrangement has been designed to make it easier to stack the ICs and give the circuit a smaller footprint so it can fit in the chassis.

If these connections have been made correctly then the LED should light up in response to the inputs as described above.
If they don't then check all the connections are going to the right places.

Step 5: Power Supply

In this short step we will assemble the power supply.

The power supply is simply the battery box with the sliding switch attached.
The switch can be soldered on to on of the terminals on the battery box.
Then two wires can be run down the length of the box and attached to two header pins.
One wire should connect directly to the battery box terminal, the other should connect to the switch. Such that, when the switch is open the wire doesn't connect to the battery box terminal, but when the switch is closed the wire will connect to the batteries.

The header pins are designed to slot into a connector within the chassis, to make it removable so that the batteries can be replaced.

If this step is successful, when the switch is closed there should be some voltage potential between the header pins.
If not, then check there are batteries in the box, check the connections, check the batteries still work.

Step 6: The Chassis

In this step we will prepare the chassis.

Firstly, drink the contents of the two bottles and wash them out.
Cut away the bottoms and make holes for the 3PDT switch, the LED array, the rotary switch, the sliding power switch and the top LED.

The aim for the power is to have it removable, so the sliding switch should be near the bottom, preferably where the lid is.

In my design I used the entire bottom bottle just for the power, put the switch in the middle and squeezed everything else into the top bottle.

As the power supply is intended to be removable, a small copper strip board platform was inserted at the top end of the bottom bottle (when it's upside down). This platform only has two header connectors, which link the power supply to the rest of the device. In this way all of the components can draw power from this platform and the power supply can be removed and replaced. The top view of this platform is shown in the photo.

The top LED and its clip can be glued to the top bottles lid, with the anode and cathode protruding through as shown in the photo.

I would recommend painting the chassis after everything has been assembled, so messy glue joints can be painted over.

Step 7: Preparing the Display

In this step I will describe how the digital logic for the display can be condensed to a size small enough to fit in the chassis.

The basic method here is stacking the ICs on top of each other as closely as possible, as shown in the photo.
The AND gate should go on top, with the OR gate tucked directly underneath it. Then the resistor network in the same way.
The LED array should come next but facing the other way, so the bottom of the resistor network is facing the bottom of the LED array.

In order to put this together, the first thing that needs to be done is the self-connections; those that connect two pins on the same IC.
Of which there are 5:
-Pins 2 and 13, 5 and 10, 6 and 12 on the AND gate.
-Pins 2 and 8, 5 and 10 on the OR gate.

Once these are in place the ICs can be glued to each other (only use a small amount of glue to begin with, incase of mistakes).

Then the connections between ICs can be soldered.

And finally the LED array can be soldered in and glued in place.

If this step has been done correctly you should be left with a small cuboid shaped thing. If a voltage can be applied and the inputs still produce the expected outputs then this step has been a success.
If not then check your connections.

Once this step was complete I smothered the components in glue to stop them moving and coming apart.

Step 8: Putting It All Together

In this step we will squeeze all of the components into the chassis.

I would recommend placing everything inside so you know where things should go before trying to fix things in place.
I would also use fairly long wires for connecting up parts, so you can fix in a section then solder it to the next section and fix that in.

The largest part is the display so I'd solder that to the rotary switch and leave long wires from the rotary switch for the inputs and also for the power connections. Then glue these sections in place within the chassis, but making sure there's enough room for the wires from the transmitter to pass by.

Then I'd attach the top LED to the transmitter and put this above the display, with long wires going down to the power and 3PDT switch.

Once this is in place the top lid can be glued down.

Next I'd solder the 3PDT switch using long wires to the power supply and the input wires from the transmitter and the rotary switch.
The switch should be soldered such that the transmitter inputs are normally connected to ground, then when the switch is pressed they're connected to the output of the rotary switch.
This should connect up the top and bottom bottles, so the two halves can be glued together.

I would also recommend testing the device at each stage to be sure that no wires have come detached in the assembly.

Once it's together and working, I flooded the device with glue so that nothing could move.

Next you can paint it and make it look more like sonic screwdriver.

Finally, the control knob can be attached to the rotary switch.

If this step was successful you should now have a complete device, which can send 3 bit inputs to a computer.

Step 9: The Receiver Board

In this step we will construct the receiver board.

This is a simple design for a bit of copper strip board to connect the receiver and the Teensy, so we can take them off of the breadboard. The connections can be seen in the attached photo.

Firstly, the wires need to be soldered into place.
Then the connections that aren't required should be routed out.
Finally, the receiver and the Teensy can be soldered in.

If successful the components should behave exactly as before, but now be mounted on a piece of copper strip board.

Step 10: Simple Software

In this step we will look at a simple bit of code to control a single application.

In order to control the computer with the Teensy, we will instruct the Teensy to mimic a keyboard. In this way we can use our device to trigger any keyboard shortcut we like.

Since there are only 7 possible commands to send (0 is a send nothing command), the easiest thing to do is to assign each command a task.

In the simple example code, the commands are used to control the VLC media player on a MAC.
The commands are assigned as follows:
1 - Play/Pause - Space bar
2 - Next Track - cmd + Right arrow
3 - Previous Track - cmd + Left arrow
4 - Volume Up - cmd + Up arrow
5 - Volume Down - cmd + Down arrow
6 - X
7 - X

The code itself works in the same way as before, but a new data flag (ndf) is used to indicate a task should be performed.
In the main loop this flag is polled to check for new commands.
When a new command is sent a switch case is used to select the corresponding task.
The task functions then simply send the appropriate shortcut to the computer and the program returns to checking the ndf.

These tasks can be changed for your own application, more information on using the Teensy to emulate a keyboard can be found here: [http://www.pjrc.com/teensy/td_keyboard.html]

If this step is successful you should be able to control a single application remotely using the device.

Step 11: Advanced Software

In this step we will look at how the device can be used to create a fully functional computer interface.

Since there are only 7 possible commands controlling more than one program is a little more complex.

In the HCI advanced code I have implemented a finite state machine to control multiple programs through the device.
Essentially, this means that once you send a command, the set of commands available to you changes.
For example, here is the first set of commands available:

1 - VLC
2 - Internet
3 - Calculator
4 - Finder
5 - X
6 - X
7 - X


If option 2 for the internet is selected, the Teensy will open an internet browser, then the next set of commands available will be:

1 - Email
2 - Facebook
3 - Google
4 - TV Guide
5 - News
6 - Weather
7 - Exit the browser


If option 5 for the weather is selected, the Teensy will then open a webpage showing the weather forecast and the next set of available commands will be:

1 - X
2 - X
3 - X
4 - X
5 - X
6 - X
7 - Exit webpage


Since 7 is the only option we select exit and the Teensy will close the webpage. The previous set of commands are then available again, namely:

1 - Email
2 - Facebook
3 - Google
4 - TV Guide
5 - News
6 - Weather
7 - Exit the browser

If the browser is no longer required we can select option 7, the Teensy will close the browser and we will be presented wit the original set of commands to choose another application.


In this way multiple programs can be controlled and a full computer interface can be realised using only the seven inputs available through the device.

The commands and shortcuts are there to be personalised to your own preferences so I've only included the basic framework with some examples.

Essentially, each of the command sets are numbered states, of which the current state is stored globally.
Then when a command is received, the Teensy can check which state it's in and run the corresponding switch case of tasks.
After each task the current state can be changed, if required, to switch to the next set of commands.

If this step has been completed correctly then you should have a fully functioning sonic screwdriver style device, which can be used as a computer control interface... well done :-)