Raspberry Pi and I2C

Update: 2018;

Working with the RPi Zero W board.

There are two problems with the I2C bus as far as I know, one is to do with timeout and the other is a quirk that may only be apparent when using I2C with the PIC16F series.

Timing and Clock Stretch

As far as I can tell clock stretching has now been implemented, however there is a timeout of about 0.8mS by which time if the slave has not released the clock results in a timeout error. This is fine for most devices such as an RTC however in real work applications that have to operate say relays or LCD's, this time out can be too short.

I don't at the moment know of any way of easily changing this without resorting to running programs before hand. There is a good description of the problem here:

https://raspihats.com/i2c-hat/2016/02/16/raspberry-pi-i2c-clock-stretch-timeout.html

This is very similar but much better developed to the work I did in 2012

So far I have managed to keep the firmware, hardware under the time out limit but if this changes I may well have to resort to I2C buffering which has its own problems.

Bit 7 Set to 1 When Reading

Now this really is a puzzler and seems only to relate to PIC16F hardware I2C but could occur elsewhere I suppose.

Above is a read from a device that returns 0, there is nothing wrong with the read and indeed the Saleae logic analyser correctly shows 0, however the RPi interprets this as 128 or 0x80. In other words it has set the MSB to 1. In detail the clock width is between 5 and 6 uS, however at the NAK of read the clock is only 4uS and it is this that seems to cause the problem.

For I2C to read it sends a read address and then clocks the data out. From the slave point of view when a read address is received, the buffer needs to be loaded so that it can later be clocked out. The slave can hold the clock low after a read address is received for about 5uS and this works.

With this waveform the RPi correctly interprets the value as 0.

smBUS

The smBUS is for smBUS devices so lets leave it at that, not much use (but can be used) for none smBUS devices.

Python and I2C

Because of lists only one function is needed to read and write any I2C device.

i2c(address,[list to send],bytes to receive,optional general call)

Some examples:

i2c(34,[1,2,3],0)  # send 1,2,3 to device with I2C address 34

i2c(34,[1,2],3) # send 1,2 to device with address 34 and read 3 bytes from that device

i2c(34,[],2) # read 2 bytes from device with i2c address 34

General Call

This is a special address 0 that will address ALL of the devices on the i2c bus, suppose there are several devices on the bus and each will respond to a general call, if follows by say 5, with instruct the device to reset so:

i2c(nn,[5],0,1)

nn may still be needed see later, 5 is sent to all of the devices and all of the devices will receive it (assuming that respond to a general call). The last parameter is set to 1 to indicate that it is a general call. In this way all of the devices can be reset at once.

i2c(72,[17,25],1,1)

Some devices can respond to a general call as above but may have special commands taht are accessed by a secondary address. In this case the secondary address is 17. So what will happen here is that a general call will be output and so all devices will listen for the next byte, the 17 will only apply to one device so that device will listen out for the next byte (25). This is a command that will send back a byte, hence the need for the devices proper I2C address of 72.

The code for this is just a few lines:

How to use:

import i2c_p
i = i2c.IIC(1) # the 1 is for the I2C bus number

i.i2c(32,[1,2,3],1)