BMA180 + ITG3205 + HMC5883l Erratic i2c readings

Hi. First of all thanks a lot and sorry for my horrible english.
Second, I am trying make sensor fusions of the sensors in the subject, but I’m having problems reading them.
I am having weird peaks in the lectures, ie: the accelerometer is still, and the z axis read in the 15000-16500 range, and suddenly, a value drops to 300.
I make a peak filter for that, but now I’m experiencing the same problem with the magnetometer.
Can you please check my code?

#include <Wire.h> 
#define BMA180 0x40  //address of the accelerometer
#define RESET 0x10   
#define PWR 0x0D
#define BW 0X20
#define RANGE 0X35
#define DATA 0x02

double accX, accY, accZ = 0;

void AccelerometerInit() 
//
{ 
 byte temp;

  //
  i2cWrite(BMA180,RESET,0xB6);
  //wake up mode
  i2cWrite(BMA180,PWR,0x10);
  // low pass filter,
  temp = i2cReadByte(BMA180, BW);
  temp=temp&0x0F;
  i2cWrite(BMA180, BW, temp);   
  // range +/- 2g 
  temp = i2cReadByte(BMA180, RANGE);  
  temp=(temp&0xF1) | 0x04;
  i2cWrite(BMA180,RANGE,temp);
}

void updateAcc(){
  uint8_t* data = i2cRead(BMA180, DATA, 6);
  accX = (data[0] | (data[1] << 8));
  accY = (data[2] | (data[3] << 8));
  accZ = (data[4] | (data[5] << 8));
} 

void setup(){
  Serial.begin(115200);
  Wire.begin();
  AccelerometerInit();
}

void loop(){
  updateAcc();
  Serial.println(accZ);
  delay(20);
}

And my I2C library:

#include <Wire.h>



void i2cWrite(uint8_t address, uint8_t registerAddress, uint8_t data) {
  Wire.beginTransmission(address);
  Wire.write(registerAddress);
  Wire.write(data);
  Wire.endTransmission();
}


uint8_t* i2cRead(uint8_t address, uint8_t registerAddress, uint8_t nbytes) {
  
  byte data[nbytes];
  for (uint8_t i=0;i<nbytes;i++){
    Wire.beginTransmission(address);
    Wire.write(registerAddress+i);
    Wire.endTransmission();
    Wire.beginTransmission(address);
    Wire.requestFrom(address,uint8_t(1));
    if(Wire.available()){
    data[i] = Wire.read();
    Wire.endTransmission();
    }
  }
  return data;
}


byte i2cReadByte(char address, char registerAddress)
{
  //This variable will hold the contents read from the i2c device.
  byte data=0;
  
  //Send the register address to be read.
  Wire.beginTransmission(address);
  //Send the Register Address
  Wire.write(registerAddress);
  //End the communication sequence.
  Wire.endTransmission();
  
  //Ask the I2C device for data
  Wire.beginTransmission(address);
  Wire.requestFrom(address, 1);
  
  //Wait for a response from the I2C device
  if(Wire.available()){
    //Save the data sent from the I2C device
    data = Wire.read();
  }
  
  //End the communication sequence.
  Wire.endTransmission();
  
  //Return the data read during the operation
  return data;
}

Thanks a lot!!

The BMA180 is a barometric sensor, isn't it ?

For some reason, the Bosch website does not list at BMA180, although it does have BMA150, BMA220 etc etc.

Anyway, it looks like you are putting the MSB and LSB of the data together the wrong way around. That can certainly cause the behaviour that you are seeing.

Be aware that the acceleration reading can be positive or negative, and learn how 2's complement integer representations work.

I am also dubious about your I2c reading function.

You are declaring the data array inside your i2c read function. This data array wil go out of scope when the function returns, and the pointer to it will be technically invalid. This will probably work on the arduino anyway, if you are not using interrupts, but it is not correct coding.

Thanks a lot for the fast repply michinyon!
I didn’t know that my code was so bad =( Anyway, is best to know the problem source than being struggling with it.
Im actually using interrupts for new gyro data.
Can you please tell me which is the right way to make the two’s complement? And how should I read the I2C and returning an array?
Thanks for your time!

PS: Here is a caption of the Z axis data for the BMA180(accelerometer), after the two’s complement, when the sensor is still:
16945.00
16925.00
16837.00
16977.00
16877.00
16869.00
16909.00
16933.00
17041.00
17053.00
16925.00
0.00 <-------------------------- This is the problem
16957.00
17005.00
16889.00
16965.00
17049.00
16965.00
16965.00
16989.00
16869.00
16957.00
16921.00
17077.00

Well, I have changed the i2cRead function to this:

void i2cReadAcc(uint8_t address, uint8_t registerAddress, uint8_t nbytes) {
  
  
  for (uint8_t i=0;i<6;i++){
    Wire.beginTransmission(address);
    Wire.write(registerAddress+i);
    Wire.endTransmission();
    Wire.beginTransmission(address); 
    Wire.requestFrom(address,uint8_t(1));
    if(Wire.available()){
      data[i] = Wire.read();
      Wire.endTransmission();
    }
  }

}

Works like a charm! That was the problem, obviously! Thanks a lot!