Go Down

Topic: Problems with Wire.requestFrom (Arduiono Uno v1.0.3) (Read 2674 times) previous topic - next topic

irethedo

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


Code: [Select]
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:
Quote

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


pylon

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

Code: [Select]
Wire.beginTransmission(0x22);

and

Code: [Select]
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.

irethedo

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...

pylon

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.

irethedo

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?


Code: [Select]
  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

Nick Gammon


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.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

irethedo

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.
Code: [Select]
  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):

Quote
ð---
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:
Quote
(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.

Code: [Select]
  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):

Quote
ð---
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):

Quote
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

pylon

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.

Nick Gammon

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

http://www.gammon.com.au/forum/?id=10896&reply=6#reply6
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

irethedo

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

Nick Gammon

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

There is another version of the Wire library that handles lack of response better. There is a link to it on my I2C page.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

irethedo

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

irethedo

Nick-

Please send a link to the Wire library on your site

thanks

Nick Gammon

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

http://dsscircuits.com/articles/arduino-i2c-master-library.html
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

irethedo

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

Go Up