Make a sensor interface for your computer for under a buck!
Update 6/9/08: After exploring several avenues I've concluded there is no practical manner of implementing this technique in Microsoft Windows. This is not petty OS bashing, I've really busted a nut trying! Sorry! Windows users needing I2C capabilities are best served by existing USB-based solutions.
Update 5/24/08: Linux support has been added, as well as sample code for the Nintendo Wii Nunchuk controller and the BlinkM "smart LED." See the README.txt file included with the source code for directions on compiling and setup on Linux.
I2C (short for Inter-Integrated Circuit) is a two-wire serial bus typically used in computers for low-level communication between internal components. I2C is also popular in robotics. All manner of sensors and actuators are available in an I2C-compatible form: ultrasonic rangefinders, sensors for acceleration, tilt, temperature and pressure, servo controllers, and bus expanders that provide additional general-purpose (GPIO) lines.
Most modern microcontrollers (Atmel, Microchip PIC, etc.) have support for I2C built right in. But the processing power available on microcontrollers is limited, and software development - with specialized cross-compilers and programming environments - can sometimes be a chore. With laptops and single-board computers becoming ever smaller and more affordable, it's increasingly common to see these systems used directly in robotics and electronics projects. This provides ample power for new capabilities such as vision processing and more sophisticated A.I., and it greatly expands the scope of available development tools and languages...but it also presents a new problem: interfacing these "regular" systems to peripherals is typically done through mainstream consumer-grade ports such as USB; there's no externally-available "I2C port" we can just tap into to make use of our sensors...or is there?
Step 1: Existing Options
One way of connecting I2C devices to an ordinary desktop or laptop computer is through a USB-to-I2C adapter. There are at least a dozen such options out there, ranging from do-it-yourself kits with open source software, to sophisticated commercial units with every bell and whistle.
One downside to the USB-to-I2C approach is cost. A full-featured commercial model can cost $250 or more. Even the "free" homebrew alternatives assume a collection of parts and a prior investment in a microcontroller programmer and the related knowledge to make use of it. Another downside is the relative scarcity of driver support outside the popular Windows fold. Few of these devices work natively on Macintosh or Linux computers.
Step 2: DDC Is I2C
When I said in the introduction that there's no external I2C port on most computers, I lied. Turns out there is, and it's been there all along for nearly a decade now, mostly sitting dormant.
Most modern graphics cards and monitors have support for something called Display Data Channel (DDC), a communication link within a video cable that allows the computer and display to negotiate mutually compatible resolutions and permit software control of monitor functions normally accessed with physical buttons on the display.
DDC is, in fact, simply an implementation of an I2C bus with a few established rules. By tapping into this connection between the computer and monitor (or making use of the DDC lines on an spare unused video port, such as the external monitor connection on a laptop), one can interface with some I2C devices at virtually no expense, bypassing the usual need for an adapter device entirely.
All we need to physically access this I2C bus is a hacked-up video cable...
Step 3: Dissecting the Cable
Four wires are needed for our I2C interface: +5V power, ground, serial data and serial clock. Pinouts for the various types of video ports can be found on Wikipedia or Pinouts.ru. Remember if using a VGA cable to find one with the full complement of pins; some only include a subset.
Cutting back the insulation and shielding from the outside of the cable, you'll likely find two groups of wires within. Thicker wires, or bundles of wires wrapped in additional shielding, usually carry the video signal. We're not interested in these and they can be trimmed back. Thinner, unshielded wires usually carry the DDC (I2C) signals among others. A multimeter or continuity tester can help in finding the correct four wires for your cable. Using a bare connector can be advantageous here, as you just need to solder four wires to the pins of interest.
A note on the +5V power: available current is very limited; about 50 mA according to the DDC specification. Most I2C devices sip just a tiny bit of current, so it should be possible to run several at once...but if using more than one or two LEDs (or other comparatively high-current devices), external power should be provided.
Step 4: The Completed Adapter
Here's the finished adapter. That's all there is to it! I made mine extra stubby so it could fit easily in my laptop bag, and added a four-pin plug that connects directly to an I2C servo controller that I have.
Step 5: Software and Projects
Mac OS X and Linux source code for working with the adapter can be downloaded from my web site (download link is at bottom of page). It's written in C, and you'll need to have gcc installed (Linux usually includes this by default, while Mac users will need to install the developer tools that are an optional installer on your original OS disc, or downloadable free from Apple). Example code is included for reading a temperature sensor, flashing a BlinkM "smart LED," writing and verifying a serial EEPROM, reading a Nintento Wii Nunchuk controller (Linux only), and communicating with a servo controller board.
Unfortunately this adapter scheme is not compatible with all systems. Support for DDC is not mandated, so not all video cards support this capability. I've had good luck thus far with Mac systems that have ATI or Intel graphics chips, but NVIDIA-based systems are out of luck. On the Linux side I've only successfully tested an IBM ThinkPad A31p (ATI graphics), but it would not work with an Asus EeePC (Intel).
The images here show a test rig that demonstrates various I2C devices in action. The computer continually reads the ambient temperature from an I2C temperature sensor, periodically logs this data to an I2C serial EEPROM chip (yes, it could just print to a file, but this was to further demonstrate I2C applications), and then a servo (through an I2C controller) serves as a makeshift indicator dial. With the library and sample code for these devices already in place, it only took a few minutes to put together this demo (and most of that was in making the indicator dial).