i2c is kickin' my ...

I'm trying to interface the arduino with a microchip 24LC00, and I'm getting screwy results.
Here is an example of my code (I have everything in the setup() method because I only need the info once):

#include Wire.h
#define CHIP B1010000

void setup()
{
  Wire.begin();
  Serial.begin(115200);

  Wire.beginTransmission(CHIP);
  Wire.send(0);      // moving to memory pointer to address 00
  Wire.endTransmission();
  Wire.requestFrom(CHIP, 16);
  while(Wire.available())
  {
     char c = Wire.receive();
     Serial.print(c, DEC);
     Serial.print(", ");
  }
  Serial.println();
  }
}

This is all well and good, and I get the following output in my Serial window:

0, 0, 0, 5, 5, 5, 10, 10, 10, 15, 15, 15, 20, 20, 20, 25

Which is also all well and good.

The problem raises its ugly head when I try to write AND read the chip. When I add the following code after the Serial.begin(115200); line:

   Wire.beginTransmission(CHIP);
   Wire.send(0);  // moving the pointer to 00
   Wire.send(2);
   Wire.send(2);
   Wire.send(2);
   Wire.endTransmission();

I get the following gibberish on my Serial window:

0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

Stranger still - if I remove the code that writes to the device, and only read from it I now get:

0, 0, 0, 2, 2, 2, 10, 10, 10, 15, 15, 15, 20, 20, 20, 25

It is as though the write operation succeeded but somehow corrupted the subsequent read operation, but I have no idea how.

Any and all assistance would be appreciated.

Hi,
I had a look at the datasheet, and it seems the device supports only single byte writes? (section 6)
Also it does not automatically increment the address-pointer as it does in "serial read".
If you intended to set the first 3 bytes of the eeprom to 0x02 you should use:

   Wire.beginTransmission(CHIP);
   Wire.send(0);  // moving the pointer to 00
   Wire.send(2);
   Wire.endTransmission();
   delay(4);
   Wire.beginTransmission(CHIP);
   Wire.send(0x01);  // moving the pointer to 1
   Wire.send(2);
   Wire.endTransmission();
   delay(4);
   Wire.beginTransmission(CHIP);
   Wire.send(0x02);  // moving the pointer to 2
   Wire.send(2);
   Wire.endTransmission();
   delay(4);

I also added a 4ms delay, because that it the maximum time the device needs to store the data.
Eberhard

Sorry to take so long with the reply - but thanks. It never even occurred to me that the chip might not auto-increment the counter for writing as it does for reading. I'll give it a try and let you know.

Thanks again.

I also tried out to read and write i2c eeprom device, but in my case this is a PCA9501 8bit IO with 2kbit eeprom. Unfortunately I don't get it to work. Below you can see my actual code for write and read. Can anyone help me?

Is it correct that TwoWire library from arduino add the "0" for write and the "1" for read at the end of address?

void PhilipsPCA9501::writeByteEeprom(uint8_t address, uint8_t eeaddress, uint8_t data ) {
  // transmit to deviceAdr (lib add one 0 at the end for "Write")
  Wire.beginTransmission(address|B01000000); //force set bit for eeprom
  Wire.send(eeaddress);
  Wire.send(data);
  Wire.endTransmission();
  delay(5);
}
uint8_t PhilipsPCA9501::readByteEeprom(uint8_t address, uint8_t eeaddress) {
  uint8_t rdata = 0xFF;
  Wire.beginTransmission(address|B01000000); //force set bit for eeprom
  Wire.send(eeaddress);
  Wire.endTransmission();
  delay(5);
  Wire.requestFrom((int)address,1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}

At the moment I write a byte to eeprom read it back from the same address. But the comparison went wrong. :cry:

I have made a big step forward now. Two things are importend:

1.) I had forgotten to force the eeprom bit at read:

//old: Wire.requestFrom((int)address,1);
Wire.requestFrom((address|B01000000),1); //new

2.) After a write of eeprom address the chip increment the pointer of eeaddress. This is also true for write eeaddress without data (set eeaddress before read). :o
Therefore I set the eeprom address decremented by 1 (see the complete code for read):

uint8_t PhilipsPCA9501::readByteEeprom(uint8_t address, uint8_t eeaddress) {
  uint8_t rdata = 0xFF;
  Wire.beginTransmission(address|B01000000); //force set bit for eeprom
  Wire.send(eeaddress-1); //decrement because AI after set address
  Wire.endTransmission();
  delay(10);
  Wire.requestFrom((address|B01000000),1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}

This work well for most addresses, but for each 16th address this will generate a wrong read (or has bad influence to the write after it) - very strange.

I have solved all issues. The main problem was the write control input (wc pin 17 at PCA9501). Only at eeprom write this input must be set to low.

Now you can write address by address or use the page write. This means that you can write 16 bits with one preset of address. The auto increment (for page write) affect only the 4 least significant bits then this 4 bits will roll over.

At read (wc to high or open) the auto increment will roll over at address 255, that means the complete memory can be read without set the address more than one time.

Set the wc-pin to Low at read will cause the "16th address -Problem" caused from 4bit roll over during set of address!

This code for reading now works perfect when pin wc is high at reading.

uint8_t PhilipsPCA9501::readByteEeprom(uint8_t address, uint8_t eeaddress) {
  uint8_t rdata = 0xFF;
  Wire.beginTransmission(address|B01000000); //force set bit for eeprom
  Wire.send(eeaddress);
  Wire.endTransmission();
  //delay(4) //delay only if necessary
  Wire.requestFrom((address|B01000000),1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}