I'm missing something re I2C EEPROM

Hi all,

Been fiddling with I2C today. I have an adafruit i2c oled display working correctly, and the playground i2c scanner shows I have the 3 devices I expect, to wit the oled display at address 3c and eeprom chips at address 50 and 51. The eeproms have pin 7 to ground to write enable, although the datasheet says floating is ok too.

Problem is I can't seem to write (edit: write a byte, that is) to the EEPROM using the example code function (by the mysterious "hkhijhe") from the playground. (I'm using this sketch as a (I hoped) easier to understand than (say) Rob Tillaart's library approach. I'll get to that next, once I understand this sketch.)

Seems to me that to write the value 42 to device 50's internal address 0, I should go:

i2c_eeprom_write_byte(0x50, 0, 42);

.... and to read back:

  byte b=i2c_eeprom_read_byte(0x50, 0);

Alas, with various combos of data value and internall address, and on both eeprom chips at 50 and 51, my serial prints show that it always reads back 255.

Here's the full sketch, basically a simplification of the playground code:

/* 
 *  Use the I2C bus with EEPROM 24LC64 
 *       ok well mine is a 24LC256
 *  Sketch:    eeprom.pde
 *  
 *  Author: hkhijhe
 *  Date: 01/10/2010
 * 
 *  jimboza trying to use this to write byte then read it back
 */

#include <Wire.h> //I2C library

// i have eeproms at 0x50 and 0x51

// in setup I will try to write one byte and then read it back
// so have removed playground functions except write_byte and read_byte

// below is the write function, untouched from playground
void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
  int rdata = data;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(rdata);
  Wire.endTransmission();
}


// below is the read function, untouched from playground
byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.write((int)(eeaddress >> 8)); // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  if (Wire.available()) rdata = Wire.read();
  return rdata;
}

void setup() 
{

  Wire.begin(); // initialise the connection
  Serial.begin(9600);

  //usage of write:
  //void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data )
  Serial.println("About to write");
  i2c_eeprom_write_byte(0x50, 0, 42);
  Serial.println("Wrote");

  //usage of read:
  //byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress )
  Serial.println("About to read");
  byte b=i2c_eeprom_read_byte(0x50, 0);
  Serial.print("Read ");
  Serial.println(b);

}

void loop() 
{
  // nothing for now

}

Here's the debug print. It always shows 255:

About to write
Wrote
About to read
Read 255

I'm pretty sure I've missed a trick here. Any help please?

EDIT.... forgot to say, the compile fell over originally, warning me that Wire.send and .receive should be changed to .write and .read. As you can see, I did that.

EDIT2.... Sorry, should also say the whole original playground sketch also works, dutifully reading back and displaying:

Memory written
this is data from the eeprom 
this is data from the eeprom 
this is data from the eeprom

Hi JimboZA

I added a 5 millisecond delay at the end of the i2c_eeprom_write_byte function and your posted code worked for me on an Uno R3 with a 24cXX eeprom of undetermined origin. The posted coded did not return the written value when I ran it unmodified.

Wire.beginTransmission(device);
  Wire.write((int)(add >> 8)); // left-part of pointer address
  Wire.write((int)(add & 0xFF)); // and the right
  Wire.write(data);
  Wire.endTransmission();
  delay(5);

In my web searching on the topic of external eeproms I have seen reference to a delay requirement on write of 5,7, or 10 millis. I don't know if it is hardware dependent upon the eeprom or the Arduino.

cattledog:
Hi JimboZA

I added a 5 millisecond delay at the end of the i2c_eeprom_write_byte function and your posted code worked for me

Well that was a simple fix! Works for me now, too:

About to write
Wrote
About to read
Read 42

Thanks c-dog.

Note:
Wire.endtransmission is the workhorse, it does the actual transmission.
It returns a value indicating errors/ok. Checking that value is good practice.