read slave device registers with I2C

hello everyone I have a I2C device connected to my arduino, I can write data to its registers doing this:

  Wire.begin();
  Wire.beginTransmission(DEVICE_ADDR);  
  Wire.write(REGISTER_NUMBER);
  Wire.write(VALUE);              
  Wire.endTransmission();

but what should I do if I want to read that value back or the value of some other register?

see - http://arduino.cc/en/Reference/WireRequestFrom -

http://gammon.com.au/i2c

thanks, but using Wire.requestFrom() I can only specify the device I want to read, how can I specify the register I want to read of that device?

thanks, but using Wire.requestFrom() I can only specify the device I want to read, how can I specify the register I want to read of that device?

That decision is made based on the data that you sent to the device, earlier. This request is simply announcing that it is time for the other device to make it's reply.

ok, I tried to write to the slave the value of the register I need to read. It doesn't reply with the right data. According to the datasheet of the device, I need a repeated start routine in order to obtain the data I want..but the Wire library doesn't seem to allow that, is that true?

Please post a link to the datasheet.

from an RTC-lib

DateTime RTC_DS1307::now() {
  Wire.beginTransmission(DS1307_ADDRESS);
  Wire.send(0);	 <<<<<<<<<<<<<<<<<<<<< select register 0
  Wire.endTransmission();
  
  Wire.requestFrom(DS1307_ADDRESS, 7);  <<<<<<<<<<<< request 7 bytes
  uint8_t ss = bcd2bin(Wire.receive() & 0x7F);
  uint8_t mm = bcd2bin(Wire.receive());
  uint8_t hh = bcd2bin(Wire.receive());
  Wire.receive();
  uint8_t d = bcd2bin(Wire.receive());
  uint8_t m = bcd2bin(Wire.receive());
  uint16_t y = bcd2bin(Wire.receive()) + 2000;
  
  return DateTime (y, m, d, hh, mm, ss);
}

http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=MPR121&tab=Documentation_Tab&pspll=1&SelectedAsset=Documentation&ProdMetaId=PID/DC/MPR121&fromPSP=true&assetLockedForNavigation=true&componentId=2&leftNavCode=1&pageSize=25&Documentation=Documentation/00610Ksd1nd%60%60Data%20Sheets&fpsp=1&linkline=Data%20Sheets

Dimitree: ok, I tried to write to the slave the value of the register I need to read. It doesn't reply with the right data. According to the datasheet of the device, I need a repeated start routine in order to obtain the data I want..but the Wire library doesn't seem to allow that, is that true?

According to the datasheet, which you linked to after asking this question, you may use a repeated start condition if you want to avoid confusion. It doesn't say you must use it:

When operating with multiple masters, bus confusion between I2C masters is sometimes a problem. One way to prevent this is to avoid using repeated starts to the MPR121. On a I2C bus, once a master issues a start/repeated start condition, that master owns the bus until a stop condition occurs.

The diagram on page 22 is pretty clear. You send the device address, the register address, and then read back the result. Exactly as in the examples on the page I linked to:

http://www.gammon.com.au/i2c

I tried this:

  Wire.beginTransmission(MPR_1);
  Wire.write(0x5E);
  byte r = Wire.read();
  Wire.endTransmission();
  Serial.println(r, HEX);

I also tried to add a Wire.write(MPR_1) after begin.Transmission, I tried to remove begin.Transmission, I tried to add another beginTransmission after and endTransmission and then write the register address, and a couple of other tries. Every time the results is FF, but I write the register at the start using:

  Wire.begin();
  Wire.beginTransmission(MPR_1);  
  Wire.write(0x5E);
  Wire.write(0x0C);
  int a =  Wire.endTransmission();
  Serial.println(a);

the result is 0 (Success).

I read the whole page on gammon/i2c, but I couldn't find a similar example

It should be like this:

  Wire.beginTransmission(MPR_1);
  Wire.write(0x5E);
  if (Wire.endTransmission() != 0)
    {
    // error, could not send
    } 
  else
    {
    // read response
    if (Wire.requestFrom (MPR_1, 1) != 1)
      {
      // error, no data
      } 
    else
      {
      byte r = Wire.read();
      Serial.println(r, HEX);
      }
    }  // end of transmission OK

thanks, I tried it but unfortunately I can’t get any “correct” value.

this is the whole code to test this thing

#include <Wire.h>

#define IRQ_PIN  2
#define MPR_1  0x5A

void setup() {
  Serial.begin(115220);
  
  pinMode(IRQ_PIN, INPUT);      
  digitalWrite(IRQ_PIN, HIGH);   
 
  Wire.begin();                  
 Wire.beginTransmission(MPR_1);  
 Wire.write(0x5E);              
  Wire.write(0x0C);             
  Wire.endTransmission();
}

void loop() {

  Wire.beginTransmission(MPR_1);
  Wire.write(0x5E);
  if (Wire.endTransmission() != 0)
      Serial.println("error #1");
  else
    if (Wire.requestFrom (MPR_1, 1) != 1)
          Serial.println("error #2");
    else {
      byte r = Wire.read();
      Serial.println(r, HEX);
    }
  Wire.endTransmission();
  
  delay(1000);
  
}

I did this loop because everytime I reset the arduino, the value read is different…so I tried to read every second, and this is an example of what I get by doing so:

20
4
0
A
2
0
20
14
2
6
80
8

What’s the extra endTransmission doing there?

void loop() {

  Wire.beginTransmission(MPR_1);
  Wire.write(0x5E);
  if (Wire.endTransmission() != 0)
      Serial.println("error #1");
  else
    if (Wire.requestFrom (MPR_1, 1) != 1)
          Serial.println("error #2");
    else {
      byte r = Wire.read();
      Serial.println(r, HEX);
    }
  Wire.endTransmission();  // <----------- this one!
  
  delay(1000);
  
}

Here is a simpler version of loop, without the nested "if"s.

void loop() 
{
  delay(1000);

  // send
  Wire.beginTransmission(MPR_1);
  Wire.write(0x5E);
  if (Wire.endTransmission() != 0)
  {
    Serial.println("error #1");
    return;
  }
  
  // request result
  if (Wire.requestFrom (MPR_1, 1) != 1)
  {
    Serial.println("error #2");
    return;
  }

  // receive result
  byte r = Wire.read();
  Serial.println(r, HEX);

}

thanks, I tried this code too, but I still get random values. I also tried with other registers too, not always the same