Raspberry Pi I2C experiments

eeprom-bugAfter soldering so many 0602 packages and 0.65mm pitch circuits, it is really nice to do some soldering on 1.25mm pitch ICs. You can even solder cables to these ICs. Why should one do this? I have to do some tests with I2C communication on the Raspberry Pi. The Raspberry should program an I2C EEPROM.

That does not look like an audio project, but it is. This is the first step for our DSP project (the DSP will run standalone and has an integrated EEPROM for its program).

The default Raspian distribution does not come with the necessary tools installed. Therefore we first had to install them:

sudo apt-get install python-smbus
sudo apt-get install i2c-tools

Then, the I2C modules have to be added to /etc/modules:

i2c-bcm2708
i2c-dev

An they also have to be removed from the /etc/modprobe.d/raspi-blacklist.conf file (just comment them out).

After a reboot I2C communication should work:

[email protected] ~ $ sudo i2cdetect -y 1
...
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
...

The EEPROM has the I2C address 0x50 – correct.

Now we have to write data to it and read it. There is a Python library SMBus, that has a very simple API. Unfortunately there are two issues:

  • there is almost no documentation
  • it is optimized for command-based I2C devices, where all command are single-byte command

With the 16kB EEPROM used here, this does not work very well, because addresses use 2 bytes. Therefore we need an additional abstraction layer to read and write data. Note, that the following program code is not final and only shown as an example.

# Simple I2C EEPROM routines
# works with 16-bit addressable EEPROMs (up to 64kB)

from smbus import SMBus

smb=SMBus(1);
slaveaddr=0x50;

def eeprom_set_current_address(addr):
  a1=addr/256;
  a0=addr%256;
  smb.write_i2c_block_data(slaveaddr,a1,[a0]);

def eeprom_write_block(addr,data):
  a1=addr/256;
  a0=addr%256;
  data.insert(0,a0);
  smb.write_i2c_block_data(slaveaddr,a1,data);

def eeprom_read_byte(addr):
  eeprom_set_current_address(addr);
  return smb.read_byte(slaveaddr);

eeprom_set_current_address(0);
#eeprom_write_block(1024,[3,1,4,1,5])

for x in range(0,10):
  print eeprom_read_byte(x);

for x in range(1024,1030):
  print eeprom_read_byte(x);

Leave a Reply