UPDATED 3/27/2012 @ 1:50pm EDT
Hey everyone!
I've just begun working on a consistent, documented, centralized library of different I2C device classes, built on top of a basic but simple I2Cdev class which provides a uniform single-bit, multi-bit, single-byte, and multi-byte reads and writes. I also recently added 16-bit register support in the form of word-based read/write methods in addition to the original byte-based ones.
http://www.i2cdevlib.com (fledgling project website)
GitHub - jrowberg/i2cdevlib: I2C device library collection for AVR/Arduino or other C++-based MCUs (source repository)
My goal is to have it continue to grow through my own code contributions as well as those of anyone else who wants to contribute, though that part is up to you all.
Current device classes:
- ADS1115 - Texas Instruments ADS1115 16-bit A/D converter
- ADXL345 - Analog Devices ADXL345 3-axis accelerometer
- AK8975 - AKM AK8975 3-axis magnetometer
- BMA150 - Bosch Sensortec BMA150 3-axis magnetometer
- DS1307 - Maxim DS1307 real-time clock
- HMC5843 - Honeywell HMC5843 3-axis magnetometer
- HMC5883L - Honeywell HMC5883L 3-axis magnetometer
- ITG3200 - InvenSense ITG-3200 3-axis gyroscope
- MPR121 - Freescale MPR121 12-bit capacitive touch sensor (thanks to Andrew Schamp)
- MPU6050 - InvenSense MPU-6050 6-axis accelerometer/gyroscope combo (compatible with MPU-6000)
- SSD1308 - Solomon Systech SSD1308 128x64 OLED/PLED driver
- TCA6424A - Texas Instruments TCA6424A 24-bit I/O expander
Some public code already exists for some of these, but nothing is really consistent. I want libraries that are well-documented, predictable, and feature-complete according to the manufacturer datasheets. I am also concerned with the lack of a centralized place to search, which I think can easily be overcome by using a repository like GitHub (and, eventually, creating a website for it, which I haven't got around to yet). Additionally, all of my code here is released under the MIT license, because I want people to be very free to do whatever they want with it. Some of the existing libraries out there are under the GPL, which is great but not always ideal depending on your project.
The I2Cdevlib project also aims to include detailed register information for every device in its database, which allows for rich interactive register maps like this:
(This particular image shows data for the MPU-6050, visible here)
This dynamic register info will shortly be able to be used to automatically create device class code, not just for Arduinos, but ultimately for other platforms like PIC, ARM, MSP430, etc.
Each device class is written with these ideas in mind:
-
Helpful and thorough documentation in Doxygen comments right in the source code.
That way you don't have to go looking for it, but it's also easy to convert into well-organized HTML or PDFs. -
Abstracted I2C hardware communication into a separate, static class.
This means (1) less memory usage for multiple devices, and (2) easy modification if you need to switch everything from the Arduino "Wire" library over to, say, a software bit-banging implementation or something like Fastwire. -
Uniform constant definitions.
This is done so you know that ADXL345_RA_[anything] is a register address, and you know that ADXL345_[function]_BIT is a bit position, no matter what it's called. This convention is kept across all devices. -
Uniform convenience methods.
All devices have an "void initialize()" method and a "bool testConnection()" method, which can be used in your setup() function to verify connectivity easily. The TCA6424A's "initialize()" has no code in it because it requires no initialization (this is documented in a Doxygen comment also), but it's there anyway for consistency. The rest of the methods of each class are generally "get*" and "set*" except for very specific action methods, like "reset()", "readPin()" or "writePin()". You'll still want to look through the header files or docs, but functions are all named obviously according to their behavior as defined in the datasheet. Other than these few convenience functions, other "helper" functions like data conversion, application-specific calibration, etc. are not included in the classes in order to keep everything clear and modular from a design standpoint.
So far, so good, at least as far as my needs go, but I'd love to hear from you all about whether (1) you think this is a good idea, (2) you have specific devices you want to see in the library, (3) you are using (or will use) this code anywhere, or (4) you want to contribute code. Although I can't promise particularly speediness, I can write libraries for devices upon request (though if you want to send me a breakout board to test it with, that would be much appreciated also). Code contributions are welcome and easy using GitHub's fork and pull request features, though I will likely make a few small tweaks to contributed code just to make sure it fits well with the library's conventions. I want to keep all the code under the MIT license as well.
So...thoughts?
Jeff (the Keyglove guy)