Update (April 2009): the PR-1000 is apparently being discontinued by Immersion, who posted this announcement:
[The PR-1000 is] not recommended for new designs. The PR-1000 module will soon be discontinued, and Immersion is not planning an off-the-shelf replacement. Current orders, and those accepted up to December 1, 2008, will be fulfilled using current delivery conditions. Orders received after September 3, 2008 will be priced at $49.99 per encoder, regardless of quantity. All orders will be shipped by June 30, 2009.
However, the PR-1000 is still being sold by mp3Car.com. A little bird tells me this:
"They [Immersion] are selling it [the PR-1000] under a different name through a different partner. I am not sure of the name. The technology is also still available in quantities directly from Immersion. We [mp3Car.com] had a call with immersion 2 weeks ago confirming this product is still live."
Meanwhile, a representative from Methode Electronics contacted me with this news:
I work for Methode Electronics, we are a licensee of Immersion. We are going to build a new more robust rotary haptic encoder to replace the PR-1000. We are currently in the final design phase of the project and will be in production in November 2009.
So, there you have it.
Dan Egnor (egnor -at- ofb -dot- net)
The PR-1000 is a programmable rotary encoder with haptic feedback. What this means is that, in theory, it's the world's most awesome knob control. It can be instantly switched in software to be a free-spinning knob, a knob with "detents" (like a car's volume control), a knob with snappier fixed positions (like an old-style TV channel changer), variable resistance to motion, "set points" that it falls into (like the center point of a balance knob), and so on.
As of this writing (June 2008), you can get one for $119.99 from mp3Car.com. It comes with a little USB interface board, the encoder itself, and a plastic knob that goes on the shaft (which you can replace with something sexier, if you like).
The catch is that, for some dumb reason, Immersion aren't publishing the protocol for interacting with their hardware. You can buy an SDK from them for thousands of dollars. That seems counterproductive to me, but maybe they're being distracted by a business model that has more to do with licensing IP than with selling hardware.
Anyway, the mp3Car guys have a Windows DLL that you can use to put it in one or two pre-programmed modes. That won't do! So, with a bunch of fooling around, I have reverse engineered the protocol used to talk to the knob.
The encoder itself has a little 4-pin connector. Looking at the connector with the key facing away, these are the pin assignments, from left to right:
The data lines use the RS-232 protocol but with 5V (TTL) logic levels. (Thanks to Cobey Smith for this info!)
If you're using the mp3Car kit, you don't need to worry about this; the mp3Car adapter board has a little FTDI USB/serial adapter chip, line level shifters and so on. For some reason this board is not a standard USB serial device, but you can get drivers:
For Windows, you can use mp3Car's official driver. It's apparently the same driver they use for some sort of XM radio interface, but don't worry about the name, it works fine, and the device shows up as COM5: or whatever.
For Mac, there are FTDI drivers you could probably adapt. You'll have to set the Vendor ID (0x6846) and Product ID (0x0001) somehow. You're on your own here.
I use Linux, which (as of 2.6) already includes a driver for the chip, but needs to be configured with the Vendor ID (0x6486) and Product ID (0x0001). Here's what I did (for Ubuntu Gutsy):
echo options ftdi_sio vendor=0x6846 product=0x0001 > /etc/modprobe.d/pr1000 echo ftdi_sio >> /etc/modules modprobe ftdi_sio
Once that's done, the device shows up as /dev/ttyUSB0. (If you have other USB serial devices, it might be assigned a different name. Check your dmesg logs, I guess.)
Anyway, after this is done, the knob should be on and you have a serial port device for talking to it. The knob uses 19200 baud, N/8/1, no flow control. You can use your favorite language and serial port library, I like Python and pySerial.
Since there's no flow control, make sure not to send too much data all at once, it might overwhelm the device.
The actual wire-level serial interface is really simple. The device has 60 byte-sized registers. Some of them are read-only, most are read-write. (Actually some of the registers are word-sized, but the high and low bytes are individually addressed.) Everything you do with the device is done by reading or writing these registers. Some of the registers reflect the current position of the knob, and when the user frobs it, you get updates.
Here's the message format used for both directions (host->device and device->host):
For example, to get all 60 device registers, you would send 5A 00 3C 66. The device would respond with 5A 00 3C .... XX, where .... is a dump of all 60 register bytes, and XX is the appropriate checksum. If you wanted to set registers 13 and 14 to 1 and 2 you would send 5A 8D 82 01 02 56.
When the user wiggles the knob, the device sends 5A 86 05 ?? ?? ?? ?? ?? XX. This is giving you an update on registers 6-11 (the ?? values), which are the registers that change when the knob is moved, followed by the appropriate checksum (XX).
Start/stop bits in the length byte are used during writes to update many registers atomically. When a write is received with 0x80 set in the length byte, writes are buffered until a write is received with 0x40 set in the length byte, at which point all buffered writes take effect. To ensure a write is processed immediately, always add 0x40 to the length byte. (Thanks to Cobey Smith and Reed Martin for help figuring these out.)
Simple enough, right? The trick is knowing what all the registers do. Read on...
The PR-1000 is a rotary encoder coupled with an electromagnetic brake and a little microcontroller. The rotary encoder reports the precise position of the shaft at all times. The electromagnetic brake can be configured to provide varying amounts of "drag", which makes it easier or harder to turn the shaft. There's a limit to the amount of braking, which means that there's no such thing as a total hard stop on shaft rotation. If you configure it for a hard stop, you can always push past it with a little bit of force. (Don't worry, this doesn't hurt anything.) This also means that the device can only resist motion, it can't actually rotate the shaft under its own power, for example it can't "spring back" into a set position when the user lets go.
What you're defining is a resistance profile which tells the device how much resistance to apply for which position of the knob. The microcontroller adjusts the brake as the user turns the knob to give the illusion of going over hills and valleys. One slightly fancy bit is that the resistance profile can be longer than one full turn of the knob, meaning it takes several turns to wind your way through it. (Think about a tuner control, where you rotate the knob many times to work your way from one end of the dial to another, but there are hard stops at the ends and perhaps notches along the way for stations.)
You don't get to define a totally arbitrary resistance profile. The profile has a beginning, and an ending, and in between a specific number of sections (the term is mine, probably Immersion calls them something else). You get to define two types of sections, default sections and alternate sections. Every section of each type is identical, so you have a series of identical bumps or notches or whatever. Normally all sections are default sections, but you can specify that a certain subrange of sections are alternate sections, or that every Nth section is an alternate section. So, for a balance control, you could have 11 notches, but make the center one deeper or wider or whatever.
For each type of section, you can choose the basic shape, which can either be flat (constant resistance), one of two stock shapes (a hill and a notch), or a custom shape defined by a series of control points. You can also set the width and maximum resistance and various other attributes separately for each section type.
For the endpoints, you can either make them hard stops (again, there's no true hard stop, the user can push through with some force), or a gentle hill, or no barrier at all (the wheel just keeps spinning).
Okay, now you've got the basic idea, let's see the actual settings.
Unless specified, read/write registers default to 0.
These registers are always fixed on my device, to 0x01, 0x07, 0x03, and 0x40 respectively. I'm guessing they're some sort of version or capability code.
This two byte value gives the resolution of the encoder, in counts per revolution. On my device this is 0x880 (2176) and apparently can't be changed. That means the smallest movement it can detect is 0.17 degrees, which isn't bad.
This is 0 normally, 1 when the knob is pressed in. You will automatically get an update when the knob is pushed or released.
This value starts at 0 and increments by one any time you program one of the registers. You will automatically get an update when you set a register. You can use this value to know that the device has processed your update.
Which section the knob is currently positioned within. This can be from 1 to the number of sections defined (see register 11), -1 (0xFF) if the knob is before the first section, or -2 (0xFE) if the knob is after the last section. You will automatically get an update when the knob moves. You can set this value; the knob doesn't physically rotate, but it acts as if it had.
The exact position within this section, in encoder counts (see registers 4,5). The range of values depends on the width of the section (see registers 16,17 and 30,31), but is negative on the left side, 0 in the center of the section, and positive on the right side. You will automatically get an update when the knob moves. You can set this value; the knob doesn't physically rotate, but it acts as if it had.
The number of sections (both default and alternate) from the beginning to the end. Note that there are two "half sections" added before and after the defined number of sections, which seem to be put there by Immersion to merge better with the end points, and also to make things confusing. So really you will end up with N+1 sections.
The high nybble controls the left endpoint, the low nybble controls the right endpoint. Each nybble can be one of these values:
For "hill" endpoints, the width of the hill in encoder counts (see registers 4,5).
For "hill" endpoints, the strength of maximum resistance (0 to 100?).
The width in encoder counts (see registers 4,5) of default sections. Does not include inter-section spacing, if any (see registers 28,29).
Normally set to the same as the section width (registers 16,17), this controls the size of the actual section shape in encoder counts (see registers 4,5). Smaller values make for "quicker" hills and valleys.
Set the maximum resistance used in the section (0 to 100?). Higher values make for "harder" hills and "deeper" valleys.
These registers (along with registers 24,25) control some sort of "snap" effect I don't fully understand. They seem to set the position within the section where the "snap" is triggered.
(???)
(???)
Set the base resistance (0-100?) that will always apply within the section, which is also the resistance used in inter-section spacing (see registers 28,29).
Unknown/unused? Padding?
Create a blank spot between each section, with the specified width in encoder counts (see registers 4,5). The blank spot has the minimum resistance (see register 26).
These registers are the same as registers 16-26, but they define the alternate section type instead of the default section type. See registers 42-45 for which sections are alternate sections. Note that the inter-section spacing does not apply to alternate sections.
Unknown/unused? Padding?
Sections starting with this section use the alternate section settings (registers 30-40) instead of the default section settings (registers 16-26). This can be from 1 to the number of sections defined (see register 11).
The number of sections in a row which use alternate settings instead of default settings. (See register 42.)
Make every Nth section (see register 45 for the value of N) use alternate settings instead of default settings, starting with this section. This can be from 1 to the number of sections defined (see register 11).
Define the repeat interval for settings which use the alternate section settings. For example, if set to 2, every other section will use the alternate settings. (Register 44 would control whether it is the even or odd sections.)
When the custom section shape is set (see register 21, or register 35 for alternate settings), these control points are used to define the shape. Each control point is a two-byte offset in encoder counts (see registers 4,5) from the center of the shape (positive or negative). See registers 54-59 for the actual resistance values at these points.
For custom shape profiles, define the resistance values (0-100?) for the far left side of the shape, then for each of the custom control point positions (see registers 46-53), then for the far right side of the shape. Resistance values at other points are interpolated between the nearest control points.
To set up a simple volume knob with detents and endpoints (this one goes to 11), send these bytes:
5A 8B 82 0A 22 7B # 10 sections, hard-stop endpoints 5A 90 46 00 80 00 80 32 01 BF # 128 counts wide, 50 resistance, hill bumps
To set up a balance knob with a fixed range and a notch in the center, send these bytes:
5A 8B 82 09 22 78 # 9 sections, hard-stop endpoints 5A 90 06 00 80 00 80 32 00 FE # default section settings: constant resistance 5A 9E 06 00 80 00 80 32 02 F2 # alternate settings: a notch in the center 5A AA 42 05 01 B6 # use alternate settings for the center section
Let me know if these don't work for you. Also please send me corrections or things you've figured out, in general this is all my best guess because I don't have any real docs.