Loading...
Pages: [1]   Go Down
Author Topic: Multiple bytes read of I2C  (Read 376 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello everyone

I want to make arduino read read 3 bytes(values of 3-axis) from the accelerometer (i2c bus) :
device address: 0x1D
3 register addresses:
X----0x06    Y----0x07   Z----0x08

And here is my code:
Code:
#include <Wire.h>
 
int address = 0x1D >> 1;
 int reading;
void setup()
{
  Serial.begin(9600);
  Wire.begin(); // join i2c bus (address optional for master)
 }
 
void loop() {
 
  Wire.beginTransmission(address);
  Wire.send(0x06);
  Wire.endTransmission();
  
  Wire.requestFrom(address, 3);
 
   if(3 <= Wire.available())    // if 3 bytes were received
  {
    reading = Wire.receive();  // receive high byte (overwrites previous reading)
    reading = reading << 8;    // shift high byte to be high 8 bits
    reading += Wire.receive(); // receive low byte as lower 8 bits
    reading = reading << 8;
    reading = reading << 8;
    reading /= 10;
    Serial.println(reading);   // print the reading
  }
 delay(100);

}

But nothing appeared on the serial monitor.......
Could anyone help me..... smiley-cry

Regards.
« Last Edit: April 02, 2011, 05:15:39 pm by zzczznn » Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 96
Posts: 6331
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You request three bytes, wait for three to arrive, and only read two?!?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks man.
I have modified the code.
But it's just a clerical error....
Logged

Massachusetts, USA
Offline Offline
Tesla Member
***
Karma: 96
Posts: 6331
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The computer tries to do exactly what you say, clerical error or not.

Your code is written such that if the reply does not arrive win the few milliseconds after you make the request, the request is just repeated.  Perhaps you should allow some time for the data to arrive before you give up.

Instead of:  if(Wire.available() >= 3) you could put in a while((Wire.avaialble() < 3) loop.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 5
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tried with your suggestion.
All zeros flash without delay...............
Anyhow, much better than nothing.

in my opinion, each data has an ack/nack.
So, if shifting them by 9 bits would be better?

I really dont want to give up........
Logged

Seattle, WA
Offline Offline
God Member
*****
Karma: 4
Posts: 673
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

First off, you have to make sure your device will SEND you three bytes when you ask for register 0x06.  The data sheet will have this answer.  Perhaps it wants you to make three calls, one to each address.

So, here is an example of something I've written that has been bulletproof for shuttling volumes of data around via I2C.

Code:
uint16_t M24LC256::ReadChunk(uint16_t location, uint16_t length, uint8_t* data)
{
    uint16_t bytes_received = 0;
    uint16_t bytes_requested = min(length,16);

    Wire.beginTransmission(i2c_address);
    Wire.send((uint8_t)(location >> 8));
    Wire.send((uint8_t)(location & 0xff));

    Wire.endTransmission();

    Wire.requestFrom(i2c_address,bytes_requested);
    uint16_t remaining = bytes_requested;
    uint8_t* next = data;

    while (Wire.available() && remaining--)
    {
        *next++ = Wire.receive();
        ++bytes_received;
    }

    return bytes_received;
}

It's a little more complex than your situation, but hopefully illustrative.  This assumes that Wire.available() turns true immediately, and stays true the entire length of the receive() calls.  I think the Wire.requestFrom() call blocks until all of the data is in the buffer, so available() is just giving you the state of internal buffers.
Logged


Pages: [1]   Go Up
Print
 
Jump to: