You will probably be familiar with I²C, a serial bus typically used for not-very-fast communication with microcontroller peripherals. It’s likely though that unless you are an I²C wizard you won’t be intimately familiar with the intricacies of its operation, and each new device will bring a lengthy spell of studying data sheets and head-scratching.
If the previous paragraph describes you, read on. [Clint Stevenson] wrote a library for interfacing I²C EEPROMs to Arduino platforms, and when a user found a bug when using it on an ATtiny85, he wrote up his solution. The resulting piece is a clear explanation of how I²C EEPROMs talk to the bus, the various operations you can perform on them, and the overhead each places on the bus. He then goes on to explain EEPROM timing, and how since it takes the device a while to perform each task, the microcontroller must be sure it has completed before moving to the next one.
In the case of [Clint]’s library, the problem turned out to be a minor incompatibility with the Arduino Wire library over handling I²C start conditions. I²C has a clock and a data line, both of which are high when no tasks are being performed. A start condition indicates to the devices on the bus that something is about to happen, and is indicated by the data line going low while the clock line stays high for a while before the clock line starts up and the data line carries the I²C command. He’s posted samples of code on the page linked above, and you can find his library in his GitHub repository.
If you want to know more about I²C, take a look at Hackaday Editor [Elliot Williams’] masterclasses on the subject: What could go wrong, I²C edition, and Embed With Elliot, I²C bus scanning.
Serial EEPROM die picture, By Epop (Own work) [CC0], via Wikimedia Commons.
It appears often i2c driver implementers take shortcuts because they’re not aways of some obscure situations that can happen. I am not completely suprised there are some bugs in de Arduino i2c lib in that respect. Writing an reading to/from an serial EEPROM is really no rocket science (compared to e.g. the BMP180 environmental sensor).
When dealing with I2C thou shall never forget the clock stretching….
Actually, not that many moderne devices use clock stretching.
It’s making a comeback now as I2C sensors bake in a little 8051 or Cortex-M0 to implement both the sensor stuff (temp comp, sensor fusion) and host comms. Had a heck of a time with a design that used two BNO055 IMUs while trying to do lots of other things; those things clock-stretch like crazy.
I’ve hooked up many i2c devices to Arduinos such as 3rd party NXT sensors etc… and normally can get them to work just fine. Sometimes though… there is a demon on the bus and logic analyzers be damned if I can solve it.
Latest issue is a VexIQ smart motor that has been working flawlessly all week then suddenly stops working. The logic analyzer shows the motor is holding the clock line low (at least it jumps back up when I unplug it). Spent part of a week just figuring out what commands are being sent over the bus (when it was working perfectly).
Ugh…sorry for the rant.
I’ve been burned by resetting my MCU while the i2c slave (accelerometer) is being read and the slave is putting data on SDA. The i2c slave was holding the data line low and its statemachine though it was in a read.state. My MCU couldnt get control of the bus.
I found an I2C slave reset sequence in this app note that fixed it.
http://ww1.microchip.com/downloads/en/AppNotes/01028B.pdf
It forces a slave into an idle state and its cleared up my problems. Only thing is you have to bit bang it during initialization
“The following sequence can be sent in order to
ensure that the serial EEPROM device is properly
reset:
• Start bit
• Clock in nine bits of ‘1’
• Start bit
• Stop bit”
I am a computer eng student – what protocol would be best to learn/ experiment with first?
RS232/UART, No addressing to deal with, point-to-point only, full duplex. Get on top of the serial data slow, parsing messages etc.
It’s all fun and games until you encounter a 24RFXX device :)