How to Make a Jog-dial Style Volume Control

DISCLAIMER: the following represents my first venture into the fascinating field of things that need soldering. I'm a hacker, not an electronics wiz. When I was starting this, I didn't even know how to solder properly (I do now... having learned the hard way). Consequently, I will make no representations about the following circuits, apart from the fact that they do indeed work in my car, as advertised, and haven't blown up yet. They may be poorly designed (I did have some input from a real electronics engineer. But I  never showed him the final product.) They may blow up your serial port, your motherboard, or even your car, and I will not feel any responsibility whatsoever! Proceed at your own risk. If you happen to know something of electronics, and see anything grossly wrong with all this, I'd appreciate if you let me know by e-mail.

You probably know how a jog-dial works. A lot of nice head units come with them. It's basically a volume knob which makes little clicks when you rotate it. The rotation is not limited in any direction. On my MP3 player, you push the knob to switch between volume - bass - mid - treble - balance, and rotate to adjust. This is a helluva lot more convenient than pushing little buttons on the remote control (not to mention the coolness factor). Makes for safer driving, too (I enjoy my car and my music enormously. If you know what it's like to redline a Golf GTI in 5th while keeping an eye on the radar detector, with your favourite track playing at full blast, you will understand that I don't want any extra user interface issues.) The push-knob has some additional functions. If the system is off, the push-knob powers it on. Plus the push-knob can be held down to access a simple menu (shutdown, sleep, play, pause) - handly for when the remote's battery runs down.

If you want to build something similar, this page ought to help. Some low-level programming is required - you have to know how to read the serial port status lines under your OS of choice. You have to know which pin on the serial port is which. You have to know how to program the sound card's mixer. You'll use up a lot of solder, and you need the tools. The only thing this is easy on is your wallet - I spent under $25 on the components.

Some day soon I'll borrow a digital camera and post some pictures of my setup. Meanwhile ...

A jog-dial is just three switches

The jog-dial itself is a little thingy called a  rotary encoder. I purchased mine from Conrad Electronics here in the Netherlands (part no. 705594). Here's a link to its datasheet (way ugly.) I'm sure places like Digi-Key or Mouser carry similar devices. When selecting an encoder, pay attention to its number of pulses per rotation - more is better. (Mine is rated at 30 ppr.) And make sure it includes a push-button function - some will only rotate, but won't let you push on the knob. Here's a link to another encoder I found on the web.

The encoder is, basically, three switches. One switch is activated when you push on the knob. The other two are activated during rotation. It's quite easy to wire the switches to a serial port, and have a little program keep track of their status. The RS-232 port has has four modem status pins (RI, DCD, RTS, DSR) which can be used for this. Unfortunately, keeping track of the rotation switches is not trivial at all. The diagram on the left shows what happens when you rotate the knob. In the detend position (between clicks) switches A-C and B-C are either both open or both closed. As you turn the knob one click to the next detend position, both switches close or open, but not simultaneously. When rotating clockwise, A-C changes status ahead of B-C. Rotating counter-clockwise, it's the other way around. Trying to catch who changes first is hopeless if you try to do it purely in software (believe me, I've tried). It's all a matter of timing (unless you have a true real-time operating system - QNX-based MP3 players, anyone?)

Adding some logic

The solution is to add some logic ICs. Here is my circuit in Postscript or JPEG format. (NB: there's a typo in the diagram - two pin 13's on every chip. The topmost one is actually pin 14). Here's an explanation of how it works.

I used two ICs: a latch (Texas Instruments SN5477: see datasheet) and an inverter (TI SN5404). The latch IC is the real key here. It has a Data (D) input signal, an Enable (C) signal, and an output (Q). When Enable is high, Q is Data. When Enable goes from high to low, Q effectively "remembers" the state of Data at the time of the transition, and will stay fixed in this state until Enable goes high again.

So what I do is connect +5V to the C pin of the rotary encoder. The A pin connects to the latch Enable input, and the B pin to the latch Data input. Let's assume switches A-C and B-C are both closed. The latch sees +5V (high state) at both Enable and Data, so Q is high. As you rotate the knob one click, either A-C or B-C opens first, depending on the direction. After the click, Q will be high if A-C opened first (i.e. Enable went low while Data was still high), or the other way around. Now Q you can wire into the serial port, watch it in software, and not worry about timing anymore.

There's one more wrinkle here. The next click will open A-C and B-C, and the input signals will go from low to high. Since the latch ignores low-to-high transitions, it would "miss" every second click. Hence the inverter IC. The inverter, ahem, inverts its input signal. So I use it to invert A-C and connect that to the Enable of a second latch. The second latch will "remember" the state of B-C when A-C went from low-to-high. Fortunately, the SN5477 IC contains four separate latches, so I can easily use two of them. As you can see in the diagram, the A pin is wired into the serial port and into into 1C/2C (this is the common Enable signal for latches 1 and 2), the inverted A is wired into 3C/4C, and the B pin is wired into both 1D and 3D. The outputs - 1Q and 3Q - go straight to RS-232 status lines.

Now, by watching the serial port, you can reliably detect the encoder's rotation. Note that three status lines are used (1Q, 3Q and A), which is somewhat wasteful. By adding more IC logic, you can probably reduce this to just two status lines. I didn't bother - I'd rather write extra code than do any more soldering, any day of the week.

The power-on circuit

The push-knob is a simple switch, quite easy in comparison. In my setup it sees dual use: both to select functions, and to power on the system. You can see this in another diagram (this part of the circuit is placed in the system box itself). It uses a single DPDT (double pole, double throw) 6V relay. The two terminals of the push-knob switch (SW1 and SW2) connect to the relay's switched inputs. The normally-closed pins of the relay are wired to the ATX power-on jumper. The relay coil is wired to the standard +5V and Ground of the power supply. When the system is off, the relay is closed, and the push-knob switch is effectively connected straight through to the ATX power-on posts. Push the knob, the system starts up, +5V appears at the coils. Now the relay opens, and the push-knob becomes connected to +5V and the serial port.
If you don't need this circuit (or maybe you don't use an ATX mobo), you can skip the relays, and wire the push-knob switch directly to +5V and a serial status line.

The software

Your software has to watch the serial status lines for changes. Note that by reading straight from the port registers, you can get both the current state, and the "changed since last read" flags. I don't remember the details.  If you use Windoze, you're on your own here. It's quite simple in theory: you only have four status bits to keep track of. One status bit is the push-knob switch. The other three (with eight possible combinations) give you the direction of rotation. Then you set the sound card's mixer accordingly. Here's a little C program I wrote under Linux. It watches the serial port and prints jog-dial events, which my main Perl program then handles. It also uses a timer to generate auto-repeat events when the push-knob is held down.

I had a lot of fun building this. I have even more fun using it. Enjoy!