AT24C256 EEPROM chip problem

I am using one of these modules with an Arduino Mega:

I am using this library:

And this example sketch:

/**
 * This sketch shows examples on how to use all the features of this library
 * 
 * It can also be used as a test  to verify that you have your eprom configured
 * propery to your Arduino as it prints out the results so you can see if everything works
 */

#include <at24c256.h>

// Create a eprom object configured at address 0
// Sketch assumes that there is an eprom present at this address
AT24C256 eprom(AT24C_ADDRESS_0);
// Create another eprom object configured att address 2
// Sketch assumes that there is NO eprom present at this address
AT24C256 badEprom(AT24C_ADDRESS_2);

void setup() {
  Serial.begin(115200);
  Serial.println("Starting up");

  // Initialize the i2c library
  Wire.begin();

  /** Write and read an integer */
  int foo = 42;
  // Write the integer foo to the eprom starting at address 0
  eprom.put(0, foo);
  int foo_in;
  // Read the integer foo_in from eprom starting at address 0
  eprom.get(0, foo_in);
  Serial.println(foo_in);

  /** Write and read a double */
  double pi = 3.141593;
  // Write the double pi to the eprom starting at address 0
  eprom.put(0, pi);
  double pi_in;
  // Read the double pi_in from eprom starting at address 0
  eprom.get(0, pi_in);
  // Create a buffer and convert pi_in to a string to be able to print it
  char buffer[10];
  dtostrf(pi_in, 9, 6, buffer); // Converts a double to a string
  Serial.println(buffer);

  /** Write and read a struct */
  // Declare the struct "Point"
  struct Point {
    int x;
    int y;
  };
  Point point = {17, 42};
  // Write the struct point to the eprom starting at address 0
  eprom.put(0, point);
  Point point_in;
  // Read the struct point_in from eprom starting at address 0
  eprom.get(0, point_in);
  Serial.println(point_in.x);
  Serial.println(point_in.y);

  /** Write and read a single byte */
  // Write the value 77 to the eprom byte at address 0
  eprom.write(0, 77);
  // Read the value of the byte at address 0
  int value = eprom.read(0);
  Serial.println(value);

  /** Write and read a byte buffer */
  uint8_t out[15] = "Test of buffer";
  // Write the 15 bytes long buffer "out" to eprom starting at address 0
  eprom.writeBuffer(0, out, 15);
  uint8_t in[15];
  // Read 15 bytes from eprom starting at address 0 into the buffer "in".
  eprom.readBuffer(0, in, 15);
  Serial.println((char*)in);

  /** Error handling on write, no error */
  // Read a byte from address 0, this should not result in an error
  eprom.write(0, 77);
  // Get the last error code, it should be 0 since there was no error
  int lastError = eprom.getLastError();
  Serial.print("last status on write: ");
  Serial.println(lastError);

  /** Error handling on write, using a eprom address without eprom */
  // Write the value 77 to an eprom that is not connected - this will fail
  badEprom.write(0, 77);
  // Get the last error code, it should not be zero, but 2 which means that there were no response from the eprom
  int lastError2 = badEprom.getLastError();
  Serial.print("last error on write: ");
  Serial.println(lastError2);  

  /** Error handling on read, using a eprom address without eprom */
  // Read the value from address 0 from an eprom that is not connected (and print it)
  badEprom.read(0);
  // Get the last error code, it should not be zero, but 2 which means that there were no response from the eprom
  int lastError3 = badEprom.getLastError();
  Serial.print("last error on read: ");
  Serial.println(lastError3);  

  // Read the size of the eprom and print it
  Serial.println(eprom.length());

  /** Write and read a long byte buffer, >32 which is TwoWire's internal buffer size and 
    * >64 which is the at24c256 page size) */
  uint8_t out2[80] = "Writing a really long message, testing some of several buffer limits on the way";
  // Write the long buffer to the eprom starting at address 0 and check how many bytes were actually written
  int written = eprom.writeBuffer(0, out2, 80);
  Serial.print(written);
  Serial.print(" bytes written, last error on write: ");
  // Get the last error and print it
  Serial.println(eprom.getLastError());
  uint8_t in2[80];
  // Read 80 bytes from eprom starting at address 0 and store it in the in2 buffer. Check how many bytes were actually read
  int readBytes = eprom.readBuffer(0, in2, 80);
  Serial.print(readBytes);
  Serial.print(" bytes read, last error on read: ");
  // Get the last error and print it
  Serial.println(eprom.getLastError()); 
  in2[79] = '\0';
  Serial.println((char*)in2);
}

// This test program has no loop, it just runs once
void loop() 
{
}

This is the output in Serial monitor:

0
0

last status on write: 0
last error on write: 2
last error on read: 2
32768
80 bytes written, last error on write: 0
80 bytes read, last error on read: 0

I don't know if the write is failing. Or if the read is failing.
It doesn't matter what is written to the EEPROM, I just get back zeros.

Has anyone else had problems with these modules?
If so how does one fix it?Use code tags to format code for the forum

I tried the I2C scanner sketch and my device in found on the I2C bus.

A device at 0x50 and at 0x58

There are (at least) 4 possible things to check

  • EEPROM itself - never had problems with these
  • wiring - probably not the problem as I2C scanner worked
  • breakout board - have you checked it for bad soldering? (although I2C scanner worked)
  • library - not familiar with the one you used.

You might try my library to see if that works

Q: do you have pull up resistors on the SDA and SCL lines?

You have only one memory chip on the Breakout Board. Therefore, your scanner program should detect only one device at one address (0x50 or 0x51 or 0x52 or 0x53 depending on the jumper statuses of A0-A1 pins). Run the following scanner sketch and report the address (i2C slaveAddress) of the device.

#include <Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  Serial.println("I2C search");
  Serial.println("-------------------------");

  Wire.begin();
  int i2c = 0b0000000;
  for (int i = 0; i < 127; i++)
  {
    Serial.print("Search at [");
    Serial.print(i2c, HEX);
    Serial.print("]: ");
    Wire.beginTransmission(i2c);
    byte busStatus = Wire.endTransmission();
    if (busStatus == 0)
    {
      Serial.println("FOUND!");
      while(1);
    }
    else
    {
      Serial.println("not found");
    }
    i2c++;
  }
}

void loop() {}

Have a look at what position the WP jumper is in as that is the Write Protect signal.

I have what looks like the same module as in your photo and I'm pretty sure that with the jumpers set like yours, the device address is 0x50 and Write Protect is disabled.

Nup - that library does not work either.

I took the chip off and put it on a bread board. It still did not work.

I think I have 4 faulty chips!

None of them work.

You library gives me an error that it can't determine the EEPROM size.

Checked that. And with my multimeter - it is low.

Very possible. Appears to be a clone or fake. Not an Atmel or Microchip product.
Is this an Aliexpress or Alibaba special?

Search at [47]: not found
Search at [48]: not found
Search at [49]: not found
Search at [4A]: not found
Search at [4B]: not found
Search at [4C]: not found
Search at [4D]: not found
Search at [4E]: not found
Search at [4F]: not found
Search at [50]: FOUND!

Ebay - I have never had a problem until now.
Could get some replacement Microchip versions from Jaycar, $3.58 each.
Just replace the PDips on the modules.

I know Jaycar prices tend to be high but the DIP version is kind of rare now so even here in the US, I can find no cheaper then $2.90 (USD).

Ebay is very good with returns, I would send them back.

Ok1

Now, execute the following sketch. This sketch writes 0x53 at location 0x0100, reads it back and shows on Serial Minitor.

#include<Wire.h>

void setup()
{
  Serial.begin(9600);
  Wire.beginTransmission(0x50);
  Wire.write(0x01); //higher byte of location
  Wire.write(0x00); //lower byte of location
  Wire.write (0x53); //data for location: 0100
  Wire.endTransmission();
  delay(5);  //write-time delay
  //--read back and show on Serial Monitor
  Wire.beginTransmission(0x50);
  Wire.write(0x01); //higher byte og location
  Wire.write(0x00); //lower byte of location
  Wire.endTransmission();

  Wire.requestFrom(0x50, 1); //request to read 1 byte1
  Serial.println(Wire.read(), HEX); //should show: 53
  //--- if works, follow similar way to write multi byte data.
}

void loop(){}

This is ridiculous!

I purchased some of these chips from Jaycar and replaced the one that came with the module.

I have tried this sketch:

#include <Wire.h>

#define ADDR_Ax 0b000 //A2, A1, A0
#define ADDR 0x50

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Wire.begin();
  writeI2CByte(0, 11);
  Serial.println(readI2CByte(0));
}

void loop() {
  // put your main code here, to run repeatedly:
  
}

void writeI2CByte(uint16_t data_addr, byte data){
  Wire.beginTransmission(ADDR);
  Wire.write(data_addr);
  Wire.write(data);
  Wire.endTransmission();
}

byte readI2CByte(uint16_t data_addr){
  byte data = NULL;
  Wire.beginTransmission(ADDR);
  Wire.write(data_addr);
  Wire.endTransmission();
  Wire.requestFrom(ADDR, 1); //retrieve 1 returned byte
  delay(1);
  if(Wire.available()){
    data = Wire.read();
  }
  return data;
}

It DOES NOT WORK!

I tried changing the code to this:

#include <Wire.h>

#define ADDR_Ax 0b000 //A2, A1, A0
#define ADDR 0x50

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Wire.begin();
  writeI2CByte(0, 11);
  Serial.println(readI2CByte(0));
}

void loop() {
  // put your main code here, to run repeatedly:
  
}

void writeI2CByte(uint16_t data_addr, byte data){
  Wire.beginTransmission(ADDR);
  Wire.write(highByte(data_addr));
  Wire.write(lowByte(data_addr));
  Wire.write(data);
  Wire.endTransmission();
}

byte readI2CByte(uint16_t data_addr){
  byte data = NULL;
  Wire.beginTransmission(ADDR);
  Wire.write(highByte(data_addr));
  Wire.write(lowByte(data_addr));
  Wire.endTransmission();
  Wire.requestFrom(ADDR, 1); //retrieve 1 returned byte
  delay(1);
  if(Wire.available()){
    data = Wire.read();
  }
  return data;
}

But it still does not work!

But no matter what value I write to the EEPROM I get back 0 when I read it back!!!!

I tried swapping Arduino Mega MCUs in case there was something wrong with the I2C bus.

But I get the same result!
WTF???? How do you use these BLOODY chips with Arduino???

Sorry, haven't read upthread. Have you tried any of the available libraries in Library Manager?

Time to include some "real" debug statements.

void writeI2CByte(uint16_t data_addr, byte data){
  Wire.beginTransmission(ADDR);
  Wire.write(data_addr);
  Wire.write(data);
  int x = Wire.endTransmission();
  Serial.print("W:\t");
  Serial.println(x);
}

byte readI2CByte(uint16_t data_addr){
  byte data = 0;
  Wire.beginTransmission(ADDR);
  Wire.write(highByte(data_addr));
  Wire.write(lowByte(data_addr));
  int x = Wire.endTransmission();
  Serial.print("R1:\t");
  Serial.println(x);

  x = Wire.requestFrom(ADDR, 1);   //retrieve 1 returned byte
  Serial.print("R2:\t");
  Serial.println(x);
  if (x == 1) {
    data = Wire.read();
  }
  else
  {
    Serial.println("no data fetched");
  }
  return data;
}

please give it a try

I ran your latest code on a Nano writing to a 24C32. Your second version, with the high and low data address bytes sent separately, works if I add delay(2) after the write function. With no delay, or with delay(1), I get zero just as you did.

Using your first version, which expects Wire to automatically send two bytes when you give it a uint16_t address, doesn't work. With the delay added, I get "255" back. So I assume Wire is only sending one data address byte.

Edit: The max write cycle time is 5ms per the data sheet:

it's wrong
The number of I2c devices depends on EEPROM size. On AT24C02 - AT24c16 chips every 2Mbits page detects as separate I2c device on the scanner.
Therefore, the single AT24C04 chip detects on two i2c devices.

What this from post #9?

I meant your suggestion "One chip - one I2c address" is not true.
For example, a single AT24C04 chip has a two i2c addresses.

Sometimes it's just better to do than talk.

Using the original sketch from post #1, and the same version of the library, with a 24LC256 from DigiKey wired up as shown below (4.7K pullups on SDA and SCL, A0-A2 and WP grounded, and a 0.1uF bypass cap):

these are the results of running the sketch. Everything worked as expected.

Connecting to /dev/ttyACM0. Press CTRL-C to exit.
Starting up
42
 3.141593
17
42
77
Test of buffer
last status on write: 0
last error on write: 2
last error on read: 2
32768
80 bytes written, last error on write: 0
80 bytes read, last error on read: 0
Writing a really long message, testing some of several buffer limits on the way

Compiling with all warnings turned on, there were a few "initialized out of order" and one "unsigned vs signed" comparison warnings from the library, but nothing I'd consider serious. I did shuffle the initialization order and change one loop counter from int to size_t just because I like a nice clean compile with no warnings. I don't imagine it had any impact on the results.

Edit: oh, and the results of running the I2C scanner sketch were as I'd expected as well: the EEPROM only showed up at address 0x50.

2 Likes