Arduino with i2c eeprom

hi guys!
I recently bought a new arduino duemilanove and I need Your help for some easy stuffs.
I have one
-20X2 display
-One external eeprom (24c16, 24c256 in the future)
I would like to realize a device where pushing a botton I could see, on the display, some sentences written on the eeprom

First, I tested the display thanks to LiquidCrystal.h lybrary: it was good
Then, to test the eeprom I follow the instuction written Here: http://www.ghettohax.com/2009/02/i2c-eeprom-for-arduino.html

Something is wrong because when I try to store one byte in the first eeprom block, and to read this data to show it on the display.

Result: the display always appears to me a black square with inside a white p.

How can I test if it is a problem in writing or reading on the external EEPROM?
What do you think is wrong?
How can I fix it?

You could begin by showing your code.

Then, you could isolate the problem by disconnecting the LCD, and using the serial monitor instead.

A likely source of the problem, although this is strictly a guess since I don't know your code, is that you wrote a byte to the LCD, not a char,and the LCD interpreted it as a char.

Thank you PaulS for your help. As you said I post the code:

 // include the library code:
 #include <LiquidCrystal.h>

 // initialize the library with the numbers of the interface pins
 LiquidCrystal lcd(12, 11, 5, 4, 3, 2);


//gestione eeprom esterna
   #include <Wire.h>

void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
  int rdata = data;
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8)); // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.send(rdata);
  Wire.endTransmission();
}

// WARNING: address is a page address, 6-bit end will wrap around
// also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddresspage >> 8)); // MSB
  Wire.send((int)(eeaddresspage & 0xFF)); // LSB
  byte c;
  for ( c = 0; c < length; c++)
    Wire.send(data[c]);
  Wire.endTransmission();
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8)); // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}

// maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8)); // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,length);
  int c = 0;
  for ( c = 0; c < length; c++ )
    if (Wire.available()) buffer[c] = Wire.receive();
}
 void setup() {
i2c_eeprom_write_byte( 0x50, 1, 'C' );

   // set up the LCD's number of rows and columns: 
   lcd.begin(20, 2);
   //lcd.setCursor(0,7);
   // Print a message to the LCD.
   char test;
   test = i2c_eeprom_read_byte( 0x50, 1 );

   lcd.print(test);
   delay(1000);
  }

 void loop() {
   
   }

The problem persist, in both cases :

  • using lcd the result is the P
  • using serial monitor the result is a strange y.

please help me...is there some errors on code?

using serial monitor the result is a strange y.

When you do your "Serial.print", you should use the DEC or HEX qualifier to find the actual value of the char value, not the ASCII representation of it if you're in doubt about what it will print.

Another thing is that some EEPROMs require a delay or a wait-on-write-cycle-complete after a write operation, before you can read back the value.
However, I don't know if that's the problem here.

I executed the following tests:
I tried to disconnect the display, I put the delay after write operation, I used the serial monitor.
The code that I used is this:

   #include <Wire.h>

void i2c_eeprom_write_byte( int deviceaddress, unsigned int eeaddress, byte data ) {
  int rdata = data;
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8)); // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.send(rdata);
  Wire.endTransmission();
}

// WARNING: address is a page address, 6-bit end will wrap around
// also, data can be maximum of about 30 bytes, because the Wire library has a buffer of 32 bytes
void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddresspage >> 8)); // MSB
  Wire.send((int)(eeaddresspage & 0xFF)); // LSB
  byte c;
  for ( c = 0; c < length; c++)
    Wire.send(data[c]);
  Wire.endTransmission();
}

byte i2c_eeprom_read_byte( int deviceaddress, unsigned int eeaddress ) {
  byte rdata = 0xFF;
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8)); // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  if (Wire.available()) rdata = Wire.receive();
  return rdata;
}

// maybe let's not read more than 30 or 32 bytes at a time!
void i2c_eeprom_read_buffer( int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) {
  Wire.beginTransmission(deviceaddress);
  Wire.send((int)(eeaddress >> 8)); // MSB
  Wire.send((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,length);
  int c = 0;
  for ( c = 0; c < length; c++ )
    if (Wire.available()) buffer[c] = Wire.receive();
}
 void setup() {
   
   Serial.begin(9600);
byte vdm=(byte)'C';
i2c_eeprom_write_byte( 0x50, 1, vdm );
delay (2000);

   char test;

   test = char(i2c_eeprom_read_byte( 0x50, 1 ));

Serial.println("Begin TEST");
Serial.println(vdm);
Serial.println(test);
Serial.println("End TEST");

  }

 void loop() {
   
   }

I got this result:

B
C
ÿ
End TEST

There are errors in the code?
Where is the error?

I'm a little surprised not to see "Begin" - the I2C must've interrupted the Serial print (?).

Did you try:

Serial.println(test, DEC);

as suggested?

I tried those tutorials with my EEPROM (AT24C02) and they didn't work.

Here's some code I'm using for mine, make sure the whole left side of the chip, pins 1 2 3 and 4 are all grounded. That gives you address 0x51

Here's a little table that shows how the bits are setup:

A2  A1  A0
| 0 | 0 | 0 | = 0x50
| 0 | 0 | 1 | = 0x51
| 0 | 1 | 0 | = 0x52
| 0 | 1 | 1 | = 0x53
| 1 | 0 | 0 | = 0x54
| 1 | 0 | 1 | = 0x55
| 1 | 1 | 0 | = 0x56
| 1 | 1 | 1 | = 0x57

Now here's the code I'm using. There's no need to shift anything anywhere. This is actually using 5 chips, tested and works on them all, fairly easy to edit to get just one:

#include <Wire.h> // specify use of Wire.h library.

// address in 24ATC02 values from 0 to 255. 

int BEGIN = 0;
int ADDR[] = {
  0x50, 0x51, 0x52, 0x53, 0x54};
char* TEST[] = {
  "Chip0", "Chip1", "Chip2", "Chip3", "Chip4"};


void setup() 
{ 
  Wire.begin(); // join i2c bus (address optional for master) 
  Serial.begin(9600);  // setup serial for output 
  // send test message "Arduino"
  for(int x = 0; x < 6; x++){
    Wire.beginTransmission(ADDR[x]); // connect to 24LC08 device address 
    Wire.send(BEGIN); // beginning address within EEPROM
    Wire.send(TEST[x]);
    Wire.endTransmission(); 
    delay(10);
  }

} 

void loop() 
{ 

  for(byte x = 0; x < 6; x++)
  {
    Wire.beginTransmission(ADDR[x]); // link to 24LC08
    Wire.send(BEGIN); // must act as a position pointer
    Wire.endTransmission();
    delay(10);
    Wire.requestFrom(ADDR[x], 5); // request 7 bytes from slave device 24LC08
    delay(10);
    // below will loop until 7 bytes are received. 

    while(Wire.available()) // slave may send less than requested 
    { 
      char c = Wire.receive(); // receive a byte as character 
      Serial.print(c); // print the character 
    } 
    Serial.print("\n"); // next line
  }


  delay(10000); // wait one second. 
}

This was obviously just for testing, but it took me a while to realize there is no reason to bit shift.. or change anything really, just using the library as it is works fine.

Thanks, CaptainObvious the EEPROM with your code is written and read, but there is a problem. I can write only the first 16 bytes for each page. For example, if I insert a sentence of 20 characters, it is truncated.

How could I fix this?

Well if you read the data sheet, some will allow 8-byte page writes, while others will allow 16-byte page writes, sounds like you have a 16-byte.

Basically, you need to send a stop bit at the end of every 16 bytes, then send again.

This is just an example:

Wire.beginTransmission(0x50);
Wire.send(0); // start at location 0 inside eeprom
Wire.send("1234567890123456"); // sends 16 bytes
Wire.endTransmission(); // this is what you need to call after 16 bytes, the "stop byte"

Wire.beginTransmission(0x50);
Wire.send(16); // start where we left off
Wire.send("7890");//
Wire.endTransmission();

You can use the eeprom examples from the website, for write page, but edit it to work with the EEPROM settings. For example, don't shift out, edit it to 16-byte page write, etc.

You can always call two 8-byte page writes, just to keep better track.

This sounds a lot like what I have going on with my LCD and my DS1307 RTC. There seems to be a conflict between the LCD library and the Wire library... (See my thread here.) I have yet to find the cause.

This may very well be.

I've got 5 arduino's, and 5 external eeprom all sharing the same i2c line. One of the Arduino's is running an LCD and reading data and storing it from the other Arduinos, then prints it to the screen.

BUT, I'm not using the LiquidCrystal library, I'm using the LCD-4bit library, a modded version to work with LCD-Smartie.

So I suggest trying a different library if you're getting conflicts, if you don't mind switching of course. lol

Pardon the newbish question, but is that library on the playground? Also is it a one-for-one swap with the liquid crystal library? How difficult is the change over?

I'm not 100% sure it's on the playground, I know they have one very close which uses the same commands but I haven't tried it.

Well, it's a little bit different from liquidcrystal library, the commands are fairly similar. I know that LiquidCrystal offers some stuff that this library doesn't, so I guess it depends what you need exactly.

Here's the playground version:
http://www.arduino.cc/playground/Code/LCD4BitLibrary

Here's the modded version (not sure what's modded, just know it works for LCD-smartie:)):
http://www.nuelectronics.com/download/projects/LCD4Bit_mod.zip

Be sure to check out the link above for instructions on how to use it. The biggest change is instead of using just lcd.print, it's lcd.printin.

Sorry again for another newb question... What's LCD-Smartie? Is that something other than the standard Hitatchi 44780 interfaced parallel LCD modules?

On another note... Spokane huh? I'm just south of you in Oregon.

LCD-smartie is a program that basically runs on your computer and talks to your LCD through your Arduino. There are alot of plugins out there that people have made, and you can make your own.
For example, there's a WinAmp plugin that displays the song name/title/etc on your LCD, there's uhh, programs to do bar-graphs, you can display text from a file, display your hard drive space, or used/free hard drive space.

There's a LOT of plugins.. I used to use the Yahoo weather plug-in.. but I guess Yahoo took that ability away. It would tell me the temperature, if it's sunny/rainy, could check the weekly forecast.. all on an LCD on the Arduino. :stuck_out_tongue: Pretty snazzy.

Of course the library can't do it by itself, you need a sketch (provided on the Nuelectronics website) that'll run the LCD-smartie.

The website hasn't been updated in years.. you can find more information/plugins and such in the forums. People are still very active on the forums.

You can also check some videos to see examples, google Arduino LCD Smartie and you should get a good amount of hits. :slight_smile: And oh yeah, got to love Spokane! :slight_smile: There's quite a few people here in Washington I was surprised.

This is a bit of an outdated thread, but looking at your post, CaptainObvious, I don't get where it's sending the text "Arduino"....

Here's some code I'm using for mine, make sure the whole left side of the chip, pins 1 2 3 and 4 are all grounded. That gives you address 0x51

Here's a little table that shows how the bits are setup:

Also, if you grounded A0-A2, wouldn't that be address 0x50?...

I'm really confused haha..