EEPROM I2C problem [SOLVED]

Hi everyone! This is my second topic on this forum and I am new to electronics so any detailed help is appreciated!
I bought a 8 pin temperature sensor (datasheet: https://www1.elfa.se/data1/wwwroot/assets/datasheets/AT30TSE752_54_58_eng_tds.pdf) that I finally got to work. The problem I have now is with the included EEPROM, I get a permanent Wire.available() equal to zero (=no incoming byte) and as a consequence I cannot read/write from the EEPROM (maybe I wrote on the EEPROM but I cannot check it by reading the written value...).
Here is my commented code I would be grateful if someone can help me because I've been trying to solve this for over 7 hours now and it's driving me MAD :0 :0 :0!!!

#include <Wire.h>
#define rom 84    // my EEPROM address according to table 5.1 in the datasheet (I have A2=1, A1=0, A0=0 and I don't count the R/W byte + the I2C Scanner does detect this address)

void setup(){
 Serial.begin(9600);
 Wire.begin();   
 delay(15);
 unsigned int address = 0;  // the address where the data should be written
 writeEEPROM(rom, address, 65);  // write to device number "rom" at byte register "address" the number 65 (function definition below)
 delay(15);
 readEEPROM(rom, address); // read from device number "rom" at byte register "address" (function definition below)
 delay(300);}


void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) 
{
  Wire.beginTransmission(rom);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
  delay(5);
}
 
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) 
{
  byte rdata = 128;                      // some random value to check that rdata is updated with the new value (65)
  Wire.beginTransmission(rom);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Serial.print("Wire end: ");
  Serial.println(Wire.endTransmission());    // prints "Wire.end: 0" which means the transmission was successful
  Wire.endTransmission();
  Wire.requestFrom(rom,1);
  while(!Wire.available()){}                     // since Wire.available() equals zero this loop is infinite and my program gets stuck here 
Serial.println("Read************"); 
rdata = Wire.read(); 
Serial.println(rdata);  //not executed since the code gets stuck in previous while loop...
  
  return rdata;
}

As I told you I am a newbie in electronics (but I have some experience in programming).
I was wondering if there was something with the wiring of the sensor that could make the temperature sensor work but not the EEPROM? So far wiring the SDA, SCL (both with 4.7kOhm pull up resistors), Vcc from the arduino uno to A2 on the sensor and the ground from the arduino to the sensor was enough to get the temperature reading (which uses another address than the 4kbit EEPROM included in the sensor).
I tried to wire the Vcc pin on the sensor to the arduino's 5V but it didn't change anything.
I tried several tutorials but some seemed to be outdated so I don't know if:

  • my code has a problem
  • the EEPROM of my sensor is faulty (but not the temperature sensor)
  • my wiring is wrong (or something is missing)
  • I should change pull up resistor values (I don't think so since the temperature sensor also uses I2C to communicate and does it without any problem, but maybe EEPROM does need more voltage/current)
  • something else is going on....
    If someone can test my code on an EEPROM by changing the address ("rom") and let me know if it works it would be nice too!
    It is also possible that this particular sensor needs a particular code but I did all I could with the datasheet and now I'm stuck...

Could you modify your previous post ? Please place the sketch between [code] ... [/code] tags.

The i2c_scanner shows the 7-bit hexadecimal address. That is the address that used by Wire.begin().
http://playground.arduino.cc/Main/I2cScanner
You use a decimal 8-bit addres which you shift.
Please tell me what the output is of the i2c_scanner.

Could you make your code look better ?
For example the function "Wire.endTransmission()" is called twice.
Don't try to write three code statements in a single line.
Use return values and variables.

  int n = Wire.available();
  Serial.print("Wire available: ");
  Serial.println( n);

That makes the sketch larger, but it is a lot better to read and understand.

I don't know if your code will work. I took a quick glance at the data sheet, and it has limit registers and a busy flag. Is there example code for the Arduino somewhere ?

 readEEPROM(rom, address);

should be something like

byteValue = readEEPROM(rom, address);

Hi! I'll try to make my code more readable next time sorry.
I called Wire.available twice because I wanted to know what its value was while debugging (that's why I printed it) and it is 0, while it shouldn't be (I'll edit the code above to remove it).
I stillhave my problem when I call it once.
Here is my I2C Scanner output as you requested:

I2C Scanner
Scanning...
I2C device found at address 0x4C  !
I2C device found at address 0x54  !
I2C device found at address 0x55  !
done

I did not find any code for arduino matching exactly this sensor.
You are right Jack WP, this function indeed returns a byte. Thank you, I copied different parts from different tutorials and I did not see that this function wasn't "void". But this does not solve my problem unfortunately...

You have 3 other devices on the I2C line? this one being the 4th?

Try taking all the other devices off line, and scan again just with this new EEPROM I2C.

The only device I have on this I2C bus is my temperature captor / EEPROM (they are combined in the same chip).
I know that 76 (0x4C) is the temp sensor, 0x54 should be the EEPROM according to the datasheet but I don't know what the third one is. It is strange because my A0 pin is not connected so this value shouldn't exist...

0x54 should be the EEPROM according to the datasheet

I don't see in your sketch that you use this address (or have you converted it?)

Yes I converted it in decimal (it makes 84).

Ok.
In looking at your code, I don't see any loop() function.
Have you fixed the call to byteValue =  readEEPROM(rom, address); yet? Are you trying to display byteValue somewhere?
Once your code is updated, please upload it again?

You can use Wire.available as many times as you like, but you use Wire.endTransmission twice in readEEPROM.

Never use this: while(!Wire.available()){}
You can check Wire.available() to see how many are available. It returns the number of bytes that are available in the internal buffer in the Wire library.

Hi again!
I forgot to put a loop function it's true (I did not upload the entire code, I am making an automatic watering system for my garden and would like to store some temperature values to decide if the plants should be watered or not, and what quantity of water). Thanks for the tip Erdin, I copied that from a tutorial apparently it's a "no-no" :wink: . I do get a value now (255) but it doesn't match the value I wrote previously (65). Does anyone one know how to solve this?
So here is the code with loop function:

#include <Wire.h>
#define rom 84    // my EEPROM address according to table 5.1 in the datasheet (I have A2=1, A1=0, A0=0 and I don't count the R/W byte + the I2C Scanner does detect this address)

void setup(){
 Serial.begin(9600);
 Wire.begin();   
 delay(15);
 unsigned int address = 0;  // the address where the data should be written
 writeEEPROM(rom, address, 65);  // write to device number "rom" at byte register "address" the number 65 (function definition below)
 delay(15);
 byte byteValue = readEEPROM(rom, address); // read from device number "rom" at byte register "address" (function definition below, it gets stuck in a while loop so the value c is not printed below)
 delay(300);
 Serial.print(byteValue);}

void loop(){}

void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) 
{
  Wire.beginTransmission(rom);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.write(data);
  Wire.endTransmission();
  delay(5);
}
 
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) 
{
  byte rdata = 128;                      // some random value to check that rdata is updated with the new value (65)
  Wire.beginTransmission(rom);
  Wire.write((int)(eeaddress >> 8));   // MSB
  Wire.write((int)(eeaddress & 0xFF)); // LSB
  Wire.endTransmission();
  Wire.requestFrom(rom,1);
  Serial.print("Wire.available() value = ");
  Serial.println(Wire.available());                     
  Serial.println("Read************");  
  rdata = Wire.read(); 

  
  return rdata;
}

Here is the output on the serial monitor for this code:

Wire.available() value = 0
Read************
255

That device requires only one address byte. Replace your write and read functions with this:

void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) 
{
  Wire.beginTransmission(rom);
  Wire.write((int)(eeaddress & 0xFF));
  Wire.write(data);
  Wire.endTransmission();
  delay(5);
}
 
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) 
{
  byte rdata = 128;                      // some random value to check that rdata is updated with the new value (65)
  Wire.beginTransmission(rom);
  Wire.write((int)(eeaddress & 0xFF));
  Serial.print("Wire end: ");
  Serial.println(Wire.endTransmission());    // prints "Wire.end: 0" which means the transmission was successful
  Wire.endTransmission();
  Wire.requestFrom(rom,1);
  while(!Wire.available()){}                     // since Wire.available() equals zero this loop is infinite and my program gets stuck here 
Serial.println("Read************"); 
rdata = Wire.read(); 
Serial.println(rdata);  //not executed since the code gets stuck in previous while loop...
  
  return rdata;
}

Pete

BTW - I think the reason that the I2C found addresses 0x54 and 0x55 is because your device has 4K bits = 1kbyte.

Pete

Hi Pete! In the begining of the 38th page of the datasheet it is written "AT30TSE754 (=my sensor which is the 4Kbit version) requires a 9-bit address field" so I think the byte adress must be on two bytes (since it's 4Kbits = 512bytes so one adress byte wouldn't be enough. Also 4kbits=512bytes=0.5Kbytes watch out bits and bytes :wink: you have to divide by 8 not 4 to get bytes from bits ). I tried your code just in case but it return 0 as value.
I saw that the I2C scanner goes only until 127 so I modified it to go until 255 and got some new "hits", here's the output:

I2C device found at address 0x4C ! // =76 which is the temp sensor that works (my setting is A2=1, A1=0, A0=0)
I2C device found at address 0x54 ! // =84=B1010100 which is the EEPROM adress without the R/W bit according to table 10-2
I2C device found at address 0x55 ! // =85=B1010101 ?? which is strange because A0=0 and the format is 1010A2A1A0 for the EEPROM
I2C device found at address 0x80 ! // =128=B10000000 ??? No reports of this value in the datasheet (that I could find...)
I2C device found at address 0xCC ! // =204=11001100 ???
I2C device found at address 0xD4 ! // =B11010100 it's the EEPROM adress without the R/W bit but with "1" before to indicate that the memory page address is 1 (page 38)
I2C device found at address 0xD5 ! // =B11010101 ?? also strange because A0=0 and the format is 11010A2A1A0 for the EEPROM at this memory page.
I2C device found at address 0x00 ! // ???
I2C device found at address 0x4C !
I2C device found at address 0x54 ! //then it repeats itself endlessly
I2C device found at address 0x55 !
I2C device found at address 0x80 !
I2C device found at address 0xCC !
etc ...

I only have this temp sensor which has an EEPROM included (at a different address) but no other devices connected.
I couldn't figure out more, the60 pages of technical information of the datasheet are quite hard to digest for me.
I am not sure if I should consider including the R/W byte but as far as I understood in Arduino language the Wire.beginTransmission(address) and Wire.requestFrom(address,number of bytes) indicate that the following operations will be W and R respectively so there's no need to use the R/W bit while addressing the device right?
Maybe the answer to my problem lies in the paragraph 10.4.2 of the datasheet called "Random Read" to read a byte at a given address but I don't know how to translate the steps into Arduino language (at least I tried a lot of different ways without success).
Or maybe my sensor is faulty (although it seems weird that the temp sensor works fine while I can't get the EEPROM to work), any ideas/suggestions?

In the begining of the 38th page of the datasheet it is written "AT30TSE754 (=my sensor which is the 4Kbit version) requires a 9-bit address field" so I think the byte adress must be on two bytes

No. See table 10-2 on page 38. The bottom eight bits of the address are sent as one byte after the address byte. The high order address bits are encoded in the address byte as shown in that table.

I saw that the I2C scanner goes only until 127 so I modified it to go until 255

There are only 127 addresses.

Pete

Also look at Figure 10-1 on page 39 which shows how to write one byte. There's a "device address" byte followed by a "word address" byte followeed by the data byte.

Pete

Hi guys I finally solved this!!!
I changed my temperature sensor / EEPROM with another one (same model Atmel AT30TSE754) and the code below works (thanks Pete you were right, only one byte for the byte adress apparently).
The strange thing is that for this sensor the EEPROM works but not the temperature sensor :astonished:. I must say that these are not new, I experimented with them with my old fat soldering iron before buying a thinner soldering iron so I suspect that some components were fried in the process: one got the EEPROM burnt the other the temperature sensor. At least I got the answer to my problem. I'll try to put them both on the same I2C bus (one for temperature the other for EEPROM) before I order some new ones (they're about 3 dollars/piece here in Switzerland). Do I just have to wire the second device to the first (with SCL, SDA and GND from the first device connected to the second and assign another address with the A2A1A0 wiring to do that? I tried doing that but only the first gets detected by I2C scanner... Shall I change the pull up resistors (4.7kOhms) to a lower value now that I want to use 2 devices?
Anyway, thanks for the help guys, I hope this may help someone having the same or a similar problem...

#include <Wire.h>
#define rom 84    // my EEPROM address according to table 5.1 in the datasheet (I have A2=1, A1=0, A0=0 and I don't count the R/W byte + the I2C Scanner does detect this address)

void setup(){
 Serial.begin(9600);
 Wire.begin();   
 unsigned int address = 6;  // the address where the data is written
 writeEEPROM(rom, address, 99);  // write to device number "rom" at byte register "address" the number 99 (function definition below)
 delay(15);
 byte byteValue = readEEPROM(rom, address); // read from device number "rom" at byte register "address" (function definition below)
 delay(20);
 Serial.print("byteValue=");
 Serial.println(byteValue);
 Serial.print("address=");
 Serial.println(address);

 }
void loop(){}

void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data ) 
{
  Wire.beginTransmission(deviceaddress);
  Wire.write(eeaddress);
  Serial.print("data=");
  Serial.println(data);
  Wire.write(data);
  Wire.endTransmission();
  delay(5);
}
 
byte readEEPROM(int deviceaddress, unsigned int eeaddress ) 
{
  byte rdata = 128;                      // some random value to check that rdata is updated with the new value (99)
  Wire.beginTransmission(deviceaddress);
  Wire.write(eeaddress);
  Wire.endTransmission();
  Wire.requestFrom(deviceaddress,1);
  Serial.print("Wire.available()=");
  Serial.println(Wire.available());
  rdata = Wire.read(); 

  
  return rdata;
}

This is the corresponding serial monitor output:

data=99
Wire.available()=1
byteValue=99
address=6

It does change when I modify the value to be written or the address were to write it. :slight_smile:

with SCL, SDA and GND from the first device connected to the second and assign another address with the A2A1A0 wiring to do that?

Yes. The lower bits of the address of both the temperature sensor and the EEPROM are set by the A2A1A0 bits.

Shall I change the pull up resistors (4.7kOhms) to a lower value

If you can't get the second device recognized by the scanner try a 2.2k resistor.

Pete

Well only the first one is recognized, I tried with 4.7K, 2K and 1K pull up resistors but it does not get detected (I have set different adresses with the A2A1A0 pins).
I will not spend too much time trying to solve this since these sensors are faulty, I'll try again once I'll receive the new ones to be sure something else is wrong.
My last question is: to set the A2A1A0 adresses shall I use the 3.3V or is 5V ok?
Thanks for sharing your knowledge again!

Use the same voltage as what you are using to power the device - usually 5V from the Arduino. It can use 5V or 3V3.

You could try putting the devices on the bus one at a time to find out which ones are responding. If you find two good ones you can put them both on the bus and try the scanner again. If it doesn't see them together you'll know something other than the device itself is wrong.

Pete