Problems with Wire.requestFrom (Arduiono Uno v1.0.3)

I am using an Arduino Uno and experiencing some strange things with my code when
reading data from an I2C bus. I recently upgraded to Arduino IDE v1.0.3 but still have
this issue.

A snippet of my code is included below along with the serial monitor data when data is
available and when it is not.

I am seeing different results where a Wire.requestFrom does not seem to be processed
when data is not available and the code there after also seems to be ignored.

I am also intermittently seeing that when data is available the code locks up. I have been
trying to figure this one out and have been scratching my head.

//???????????? Suspect code here ?????????????

Wire.requestFrom(0x21, 1); // request 1 byte from 0x42h
timeout= Wire.available();

Serial.print(" Wire.available timeout= ");
Serial.print(timeout);

// ------------ turn on ext power ------------------
// Serial.print(" Wire.beginTransmission - ");
Wire.beginTransmission(0x22);
Wire.write(0xAF); // write command to turn on ext headbox power
Wire.endTransmission();

Serial.println(" turn on headbox ");

Wire.requestFrom(0x21, 1); // request 1 byte from 0x42h - revision
timeout= Wire.available();

while(Wire.available()) // slave may send less than requested
{
v44on = Wire.read(); // receive a byte as character
}
} // end of program loop

Any ideas what I am doing wrong and how to correct this?

Thanks

byte v44off;

   // ------------ turn on ext  power ------------------
  Wire.beginTransmission(0x22);
  Wire.write(0xAF);                //  write command to turn on ext power
  Wire.endTransmission();
  
   v44on = 0;
   Wire.requestFrom(0x21, 1);    // request 1 byte from 0x42h - revision
   timeout= Wire.available();
   
  while(Wire.available())    // slave may send less than requested
  { 
     v44on = Wire.read();    // receive a byte as character
  } 
  Serial.print("  ext hdbox read  ");

  Serial.print(" v44on= "); 
  Serial.print(v44on,HEX); 


 // ---------------- turn off ext power -----------------------

Wire.beginTransmission(0x22);
   Wire.write(0xFA);                //  write command to turn off ext power
   timeout = Wire.endTransmission();

    Serial.print(" timeout= ");
    Serial.print(timeout); 

    Serial.print("  Wire.endTransmission timeout= ");
    Serial.print(timeout);  
    Serial.println("   ****   ");

//???????????? Suspect code here ?????????????

    Wire.requestFrom(0x21, 1);    // request 1 byte from 0x42h
    timeout= Wire.available();

    Serial.print(" Wire.available timeout= ");
    Serial.print(timeout); 
  
  // ------------ turn on ext power ------------------

//  Serial.print(" Wire.beginTransmission - "); 
  Wire.beginTransmission(0x22);
  Wire.write(0xAF);                //  write command to turn on ext headbox power
 Wire.endTransmission();

  Serial.println(" turn on headbox "); 

  Wire.requestFrom(0x21, 1);    // request 1 byte from 0x42h - revision
  timeout= Wire.available();


  while(Wire.available())    // slave may send less than requested
  { 
     v44on = Wire.read();    // receive a byte as character
  } 

}  // end of program loop

Here is what the output looks like on the Serial monitor:

When data is available:
ext hdbox read v44on= 11 timeout= 0 Wire.endTransmission timeout= 0 ****
ext hdbox read v44on= 11 timeout= 0 Wire.endTransmission timeout= 0 ****
ext hdbox read v44on= 11 timeout= 0 Wire.endTransmission timeout= 0 ****

When no data is available:
ext hdbox read v44on= 0 timeout= 0 Wire.endTransmission timeout= 0 ****
Wire.available timeout= 0 turn on headbox
ext hdbox read v44on= 0 timeout= 0 Wire.endTransmission timeout= 0 ****
Wire.available timeout= 0 turn on headbox
ext hdbox read v44on= 0 timeout= 0 Wire.endTransmission timeout= 0 ****
Wire.available timeout= 0 turn on headbox

What kind of device are you communicating with? You're writing to another address than you're reading from:

Wire.beginTransmission(0x22);

and

Wire.requestFrom(0x21, 1);    // request 1 byte from 0x42h - revision

I first thought you might emulate the read/write bit in the address byte (not necessary with the Wire library because the library expects a 7-bit address and handles the r/w bit itself) but with the comment it seems that you already did the conversion from 8 to 7 bit for the address.

Thanks for the response...
The primary device that I am communicating to is a medical amplifier.
The I2C is configured so that I need to offset the lower address bit. This is working just fine
as I am setting other I2C registers without any problems.

In the WirebeginTransmission(0x22); statement I am sending a command to my primary device to set the power on/off to a secondary I2C device that is connected it.

In the WireRequestFrom(0x21, 1); // request 1 byte from 0x42h - revision
statement I am reading an I2C device on the secondary device which is why the address is different
as I want to verify that the power did switch on/off on the secondary device.

It is when the secondary device is connected is when I notice certain lines of code not being executed by evidence of the output and the serial print statements to the serial monitor. Also, I sometimes get what seems like a stack overflow or something that stops the sketch in its tracks.

When the secondary device is not connected it seems that all the lines in my code are being executed...

Not sure what is causing this...

I guess I don't understand your problem. Are connecting and disconnecting devices from the I2C bus? If this is the case, you have to write some bytes to the device and use the return value of Wire.endTransmission() to determine if the device is connected or not. Only if it is connected you can do a call to Wire.requestFrom() with that device's address.

Thanks for the reply-

I came up with the following to test the condition of Wire.endTransmission()
but it is coming up with "2" whether the device is there or not...

Am i doing this right?

  Wire.beginTransmission(0x22);
  Wire.write(0xAF);                	//  write command to turn on power
  Wire.endTransmission();
  
   digitalWrite(D8, HIGH);
   digitalWrite(D7, LOW);
   delay(200);

  v44on = 0;

  Wire.beginTransmission(0x21);
  Wire.write(0x00);                		//  write command to test if I2c device is there
  timeout = Wire.endTransmission();  

  Serial.print(" AMP IS ON- timeout= ");
  Serial.print(timeout); 
  if (timeout == 2)
  {
     Wire.requestFrom(0x21, 1);    // request 1 byte from 0x42h - revision
     Wire.available();

     while(Wire.available())    // slave may send less than requested
     { 
        v44on = Wire.read();    // receive a byte as character
     } 

     Serial.print(" v44on= "); 
     Serial.print(v44on,HEX); 


 // ---------------- turn off ext  power -----------------------

   Wire.beginTransmission(0x22);
   delay(200);

   Wire.write(0xFA);                //  write command to turn off ext headbox power
   Wire.endTransmission();

  Wire.beginTransmission(0x21);
  Wire.write(0x00);                //  write command to turn on ext headbox power
  timeout = Wire.endTransmission();  
   
Serial.print(" AMP IS OFF- timeout= ");
Serial.print(timeout);  

        while(Wire.available())    // slave may send less than requested
        { 
          v44off = Wire.read();    // receive a byte as character
        } 
delay(200);
Serial.print(" v44off= "); 
Serial.println(v44off,HEX);

===============================
Serial monitor output:
AMP IS ON- timeout= 2 v44on= 0 AMP IS OFF- timeout= 2 v44off= 0

irethedo:
In the WireRequestFrom(0x21, 1); // request 1 byte from 0x42h - revision
statement I am reading an I2C device on the secondary device which is why the address is different
as I want to verify that the power did switch on/off on the secondary device.

You don't modify the device address to read from it. The library does that. You are reading a different device that way (which probably doesn't exist).

Fix that first.

Thanks for the reply...
I tried your suggestion and have posted the code and results for two different scenarios.

  1. Reading from the I2C with the address offsets.
  2. Reading from the I2C per your suggestion.
    I had to leave the writing to set the power up as I had it otherwise the power would not switch on and off as I intend for it to do...

1. Reading from the I2C with the address offsets.

  Serial.flush();  // flush the serial buffer
   delay (300);
   Serial.println("---"); 
     // ------------ turn on ext power ------------------
   Wire.beginTransmission(0x22);        // write to I2c Address 44h to set power condition
//   Wire.beginTransmission(0x44);      // writing to I2c Address 44h to set power condition - DOES NOT WORK
   Wire.write(0xAF);                    //  write command to turn off ext headbox power
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?
   delay(4500); 
   Serial.print(" Power IS ON- timeout= ");    // Check status of data sent- did it get there?
   Serial.print(timeout);  

   Wire.beginTransmission(0x21);        // write to I2c Address 42h to check if ext device is available
    Wire.write(0x00);                   //  write command to test to see if device exists 
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?  
   
   Serial.print(" check power on- timeout= ");
   Serial.print(timeout);  
   
   v44on= 0;                    // initialize v44off to zero
   Wire.requestFrom(0x21, 1);    // request 1 byte from 0x42h - revision
   
   while(Wire.available())    // slave may send less than requested
   { 
        v44on = Wire.read();    // receive a byte as character
   } 
   Serial.print(" v44onf= ");
   Serial.println(v44on); 
   
     // ------------ turn off ext power ------------------
   Wire.beginTransmission(0x22);        // write to I2c Address 44h to set power condition
//   Wire.beginTransmission(0x44);      // writing to I2c Address 44h to set power condition - DOES NOT WORK
   Wire.write(0xFA);                    //  write command to turn off power
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?
   delay(4500);    
   Serial.print(" Power IS OFF- timeout= ");
   Serial.print(timeout); 

   Wire.beginTransmission(0x21);        // write to I2c Address 42h to check if ext device is available
   Wire.write(0x00);                    //  write command to test to see if device exists 
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?
   
   Serial.print(" check power off- timeout= ");
   Serial.print(timeout); 

   v44off= 0;                    // initialize v44off to zero
   Wire.requestFrom(0x21, 1);    // request 1 byte from 0x42h - revision
   
   while(Wire.available())    // slave may send less than requested
   { 
        v44off = Wire.read();    // receive a byte as character
   } 
   Serial.print(" v44on= ");
   Serial.println(v44on); 
   
     // ------------ turn on ext power ------------------
   Wire.beginTransmission(0x22);        // write to I2c Address 44h to set power condition
//   Wire.beginTransmission(0x44);      // writing to I2c Address 44h to set power condition - DOES NOT WORK
   Wire.write(0xAF);                    //  write command to turn off ext headbox power
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?
   delay(4500); 
   Serial.print(" Power IS Turned Back ON- timeout= ");    // Check status of data sent- did it get there?
   Serial.println(timeout);

===============================================================================

With the device connected:
(I2C addr 42h = 1 when power is on
No data is displayed when power is off)
When testing to see if the device is there, Wire.endTransmission returned "0"

I tried writing to 0x44 instead of 0x22 but then my power would not switch on and off.
(the library does not accomodate how the I2C parts are wired on the device that I am communcating with...)

Here is a sample of the output seen (device connected):

ð---
Power IS ON- timeout= 0 check power on- timeout= 0 v44onf= 1
ø---
Power IS ON- timeout= 0 check power on- timeout= 0 v44onf= 1

With the device disconnected:

(all data is seen- power doesn't matter as device is not connected)

Power IS ON- timeout= 0 check power on- timeout= 2 v44onf= 0
Power IS OFF- timeout= 0 check power off- timeout= 2 v44on= 0
Power IS Turned Back ON- timeout= 0

2. Reading from the I2C per your suggestion.

  Serial.flush();  // flush the serial buffer
   delay (300);
   Serial.println("---"); 
     // ------------ turn on ext power ------------------
   Wire.beginTransmission(0x22);        // write to I2c Address 44h to set power condition
//   Wire.beginTransmission(0x44);      // writing to I2c Address 44h to set power condition - DOES NOT WORK
   Wire.write(0xAF);                    //  write command to turn off ext headbox power
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?
   delay(4500); 
   Serial.print(" Power IS ON- timeout= ");    // Check status of data sent- did it get there?
   Serial.print(timeout);  

    Wire.beginTransmission(0x42);       // write to I2c Address 42h to check if ext device is available
    Wire.write(0x00);                   //  write command to test to see if device exists 
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?  
   
   Serial.print(" check power on- timeout= ");
   Serial.print(timeout);  
   
   v44on= 0;                    // initialize v44off to zero
     Wire.requestFrom(0x42, 1);    // request 1 byte from 0x42h - revision
   
   while(Wire.available())    // slave may send less than requested
   { 
        v44on = Wire.read();    // receive a byte as character
   } 
   Serial.print(" v44onf= ");
   Serial.println(v44on); 
   
     // ------------ turn off ext power ------------------
   Wire.beginTransmission(0x22);        // write to I2c Address 44h to set power condition
//   Wire.beginTransmission(0x44);      // writing to I2c Address 44h to set power condition - DOES NOT WORK
   Wire.write(0xFA);                    //  write command to turn off power
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?
   delay(4500);    
   Serial.print(" Power IS OFF- timeout= ");
   Serial.print(timeout); 

   Wire.beginTransmission(0x42);        // write to I2c Address 42h to check if ext device is available
   Wire.write(0x00);                    //  write command to test to see if device exists 
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?
   
   Serial.print(" check power off- timeout= ");
   Serial.print(timeout); 

   v44off= 0;                    // initialize v44off to zero
    Wire.requestFrom(0x42, 1);    // request 1 byte from 0x42h - revision
   
   while(Wire.available())    // slave may send less than requested
   { 
        v44off = Wire.read();    // receive a byte as character
   } 
   Serial.print(" v44on= ");
   Serial.println(v44on); 
   
     // ------------ turn on ext power ------------------
   Wire.beginTransmission(0x22);        // write to I2c Address 44h to set power condition
//   Wire.beginTransmission(0x44);      // writing to I2c Address 44h to set power condition - DOES NOT WORK
   Wire.write(0xAF);                    //  write command to turn off ext headbox power
   timeout = Wire.endTransmission();    // Check status of data sent- did it get there?
   delay(4500); 
   Serial.print(" Power IS Turned Back ON- timeout= ");    // Check status of data sent- did it get there?
   Serial.println(timeout);

Per your suggestion, I wrote to and read from 0x42 instead of 0x21-
I tried writing to 0x44 instead of 0x22 but then my power would not switch on and off.
(the library does not accomodate how the I2C parts are wired on the device that I am communcating with...)

With the device connected:
(I2C addr 42h = 0
When testing to see if the device is there, Wire.endTransmission returned "4"
When power is on and no data is displayed when power is off)

Here is a sample of the output seen (device connected):

ð---
Power IS ON- timeout= 0 check power on- timeout= 4 v44onf= 0
ð---
Power IS ON- timeout= 0 check power on- timeout= 4 v44onf= 0

With the device disconnected: (timeout is now 2 but data did not change).
Here is a sample of the output seen (device not connected):

Power IS ON- timeout= 0 check power on- timeout= 2 v44onf= 0
Power IS OFF- timeout= 0 check power off- timeout= 2 v44on= 0
Power IS Turned Back ON- timeout= 0

In a post before you told that you're accessing two different devices. I think it's time to tell exactly what devices these are and post links to their datasheets. Everythings let us guess and not help you. And try to draw how you wired everything together.

I'm getting confused now. Can you please run the I2C scanner and post what it returns?

There are no links to datasheets for these items as these devices are custom and company
confidential information.

Can someone send me a link to the Wire commands in v1.0.3?

If I could ask the same question in an easier way, it might go like this:

The problem seems to be when I try to write to I2C address 44h with the following code
which shuts the power off to the device that i am attempting to communicate or get a
status if whether it is connected or not and the data returned from Wire.endTransmission()
(and all the code from that point to the end of my loop closing bracket) is ignored...

Is there some sort of error handling going on behind the scenes that is causing a break
statement (of sorts) in my loop?

I need more information on the v 1.0.3 Wire library I think.

Please see comments in the code below

// ------------ turn off ext power ------------------
Wire.beginTransmission(0x22); // write to I2c Address 44h to set power condition
// Wire.beginTransmission(0x44); // (Use address in line above) because this one DOES NOT WORK
Wire.write(0xFA); // write command to turn off power
// ***** power does turn off here with the command in the line above as expected ***********
timeout = Wire.endTransmission(); // Check status of data sent- did it get there?
delay(4500);
Serial.print(" Power IS OFF- timeout= "); // This time out is not being displayed in Serial monitor .. Why is that?
Serial.print(timeout); // and all the code through the end of my loop end bracket is also ignored

Hmmm - you are turning the device's power off? No wonder it doesn't respond. :slight_smile:

There is another version of the Wire library that handles lack of response better. There is a link to it on my I2C page.

Thanks Nic-

I just saw your scanner and here is my output

I2C scanner. Scanning ...
Found address: 33 (0x21)
Found address: 34 (0x22)
Found address: 35 (0x23)
Done.
Found 3 device(s).

I will take a llok at your I2C page

thanks

Nick-

Please send a link to the Wire library on your site

thanks

It's not mine, but here is the link:

Thanks for the link.

I am attempting to switch my code over to use this I2c.h library but I keep getting an error with the following:

I2c.begin(); gives me this error: 'I2c' was not declared in this scope

in my code I have included the file included:
#include <I2C.h> and in both the v1.0.3 IDE and v1.0.1 IDE
I have also tried adding I2c.h & I2c.cpp but still I get this error.

This was done after I placed I2C folders (which contain I2c.h & I2c.cpp) into \my documents\Aduino-1.0.1\libraries
and \my documents\Aduino-1.0.3\libraries folders.

I see an import library option in the sketch pull down menu but the I2c library does not exist in the list nad there does not appear to be a way to browse for it either...

Any ideas what i am missing or doing wrong?

thanks

Just a guess but:

I2C.h and I2c.begin(); seem to be using mixed case characters and C/C++ is case sensitive?

Try I2C.begin();
Lefty

Thanks...
I tried changing the case the I2c.begin() to I2C.begin() and the error for the same line of code
changes to request for member 'begin' in 'I2C', which is of non-class 'int'

What gives?

I copied the sample code that was on the library link page and it does the same thing:
/*******************************************
Sample sketch that configures an HMC5883L 3 axis
magnetometer to continuous mode and reads back
the three axis of data.
Code compiles to a size of 1500 bytes
Equivalent Wire Library code compiles to 2032 bytes
*******************************************/

#include <I2C.h>

#define HMC5883L  0x1E 

int x = 0;
int y = 0;
int z = 0;


void setup()
{
  I2c.begin();
  I2c.write(HMC5883L,0x02,0x00); //configure device for continuous mode
}

void loop()
{
  I2c.read(HMC5883L,0x03,6); //read 6 bytes (x,y,z) from the device
  x = I2c.receive() << 8;
  x |= I2c.receive();
  y = I2c.receive() << 8;
  y |= I2c.receive();
  z = I2c.receive() << 8;
  z |= I2c.receive(); 
}

I can't really help you. All my sketches that use I2C stuff use the #include <Wire.h> I2C library that comes standard with the Arduino distribution.

Lefty

I would still be using Wire.h also if it wasn't locking up my sketch...

Did you restart the IDE after installing the library? Did you install the library?