Pages: [1]   Go Down
Author Topic: How to Read Data from BMA180, but always in the positive range?  (Read 992 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Jr. Member
**
Karma: 0
Posts: 72
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, i try to read data from BMA180 accelerometer. So far, i did it using code from:  http://www.electrodragon.com/?p=3660
This is the complete code:

Code:
#include <Wire.h>
 
void setup()
{
  Serial.begin(115200);
  Wire.begin();
 
  Serial.println("Demo started, initializing sensors");
 
  AccelerometerInit();
 
  Serial.println("Sensors have been initialized");
}
 
void AccelerometerInit()
{
  Wire.beginTransmission(0x40); // address of the accelerometer
  // reset the accelerometer
  Wire.write(0x10);
  Wire.write(0xB6);
  Wire.endTransmission();
  delay(10);
 
  Wire.beginTransmission(0x40); // address of the accelerometer
  // low pass filter, range settings
  Wire.write(0x0D);
  Wire.write(0x10);
  Wire.endTransmission();
 
  Wire.beginTransmission(0x40); // address of the accelerometer
  Wire.write(0x20); // read from here
  Wire.endTransmission();
  Wire.requestFrom(0x40, 1);
  byte data = Wire.read();
  Wire.beginTransmission(0x40); // address of the accelerometer
  Wire.write(0x20);
  Wire.write(data & 0x0F); // low pass filter to 10 Hz
  Wire.endTransmission();
 
  Wire.beginTransmission(0x40); // address of the accelerometer
  Wire.write(0x35); // read from here
  Wire.endTransmission();
  Wire.requestFrom(0x40, 1);
  data = Wire.read();
  Wire.beginTransmission(0x40); // address of the accelerometer
  Wire.write(0x35);
  Wire.write((data & 0xF1) | 0x04); // range +/- 2g
  Wire.endTransmission();
}
 
void AccelerometerRead()
{
  Wire.beginTransmission(0x40); // start transmission to device, address of the accelerometer
  Wire.write(0x02); // send register address, set read pointer to data
  Wire.endTransmission();
  Wire.requestFrom(0x40, 6);
 
  // read in the 3 axis data, each one is 16 bits
  // print the data to terminal
  Serial.print("Accelerometer: X = ");
  short data = Wire.read();
  data += Wire.read() << 8;
  Serial.print(data);
  Serial.print(" , Y = ");
  data = Wire.read();
  data += Wire.read() << 8;
  Serial.print(data);
  Serial.print(" , Z = ");
  data = Wire.read();
  data += Wire.read() << 8;
  Serial.print(data);
  Serial.println();
}
 
void loop()
{
  AccelerometerRead();
 
  delay(500); // slow down output
}

The problem is, the data range for X, Y and Z axis from the sensor is always in the range -17000 to 17000. I want to get data only in positive range, how i can do that?

Thank You..
Logged

Switzerland
Offline Offline
Faraday Member
**
Karma: 108
Posts: 5144
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Change the type of the variable:

Code:
  uint16_t data = Wire.read();
  data += Wire.read() << 8;
  Serial.print(data);

Although the correct value is:

Code:
  uint16_t data = Wire.read();
  data += Wire.read() << 8;
  data >>= 2;
  Serial.print(data);

because bit 0 and 1 of the LSB are "new_data" flag and 0.
Logged

Offline Offline
Faraday Member
**
Karma: 61
Posts: 2841
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The acceleration value is inherently negative and positive.

You need to be clear,  why you think you want only positive values.  What are you
trying to achieve ?

If you just want to know the magnitude,  take the absolute value.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 72
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@pylon:
Thanks, i will try it..

@michinyon:
i want to make 3 axis gimbal for my project. I use 3 servo motors and this Multiwii board:
https://www.hobbyking.com/hobbyking/store/__27033__MultiWii_328P_Flight_Controller_w_FTDI_DSM2_Port.html

Those board is Arduino based. There are 4 sensors, but i just use BMA180 accelerometer and ITG3205 Gyroscope for my 3 axis gimbal. The Multiwii board is coming with the program, but the gimbal program is only for 2 Axis. Besides that, I want to make a program by my self from the beginning.

So i learn all from beginning, including reading data from BMA180..

can you help me in making 3 axis gimbal? is there anything that can be a reference for me?

Thank You..
« Last Edit: January 30, 2013, 09:33:32 pm by mamette » Logged

Offline Offline
Faraday Member
**
Karma: 61
Posts: 2841
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

acceleration can occur in two directions.    So for three axes,  there are six directions.
It can be accelerating forwards or backward,  up or down,  left or right.  Thats six.
Thats why you get three numbers which may be positive or negative.

It's unclear why you only want positive numbers.   If the sensor tells you -2000,  what do you want ?    0  or  +2000 ?

If you want the total magnitude of the acceleration,  you would calculate the length of the apparent acceleration vector,
which would be something like

a_magnitude =  sqrt (( a_x * a_x ) + ( a_y * a_y ) + ( a_z * a_z ))

which will always be a positive number.
Logged

Offline Offline
Jr. Member
**
Karma: 0
Posts: 72
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So far, i found 3 different example to read data from BMA180. Each of them have different output value.

The First Code is in first Post on this thread..

And this is the Second Code:
Code:
/**********************************************************
 * BMA180_I2C_Example.pde ----- Sample sketch for BMA180 Accelerometer using I2C
 *
 * A sample sketch that shows the basic functions of the BMA180 acclerometer.
 *
 *
 * 2011, DSS Circuits, Inc.  http://www.dsscircuits.com
 *
 **********************************************************/
#include <Wire.h>

#define BMA180              0x40
#define ee_w_MASK           0x10
#define mode_config_MASK    0x03
#define bw_MASK             0xF0
#define range_MASK          0x0E
#define lat_int_MASK        0x01
#define lat_int             0x01

int x,y,z,temp;

void setup()
{
  Wire.begin();
  Serial.begin(9600);
  initializeBMA180();
}

void loop()
{
  Serial.write(0x0D);
  readAccel();
  printAccel();
  Serial.write(0x20);
  delay(200);
}

byte readAccel()
{
  Wire.beginTransmission(BMA180);
  Wire.write(0x02);
  if(Wire.endTransmission()){return(1);}
  if(Wire.requestFrom(BMA180,7) != 7){return(2);}
  x = Wire.read();
  x |= Wire.read() << 8;
  x >>= 2;
  y = Wire.read();
  y |= Wire.read() << 8;
  y >>= 2;
  z = Wire.read();
  z |= Wire.read() << 8;
  z >>= 2;
  temp = Wire.read();
}

void printAccel()
{

  Serial.print("X = ");
  Serial.print(x);
  Serial.print("  ");
  Serial.print("Y = ");
  Serial.print(y);
  Serial.print("  ");
  Serial.print("Z = ");
  Serial.print(z);
  Serial.print("  Temperature(C) = ");
  Serial.println(map((int8_t)temp,-128,127,-400,875)/10.0,1);
}

byte initializeBMA180()
{
  /*Set EEPROM image to write mode so we can change configuration*/
  delay(20);
  Wire.beginTransmission(BMA180);
  Wire.write(0x0D);
  if(Wire.endTransmission()){return(1);}
  if(Wire.requestFrom(BMA180,1) != 1){return(2);}
  byte ee_w = Wire.read();
  ee_w |= ee_w_MASK;
  Wire.beginTransmission(BMA180);
  Wire.write(0x0D);
  Wire.write(ee_w);
  if(Wire.endTransmission()){return(1);}
  delay(20);
  /*Set mode configuration register to Mode 00*/
  Wire.beginTransmission(BMA180);
  Wire.write(0x30);
  if(Wire.endTransmission()){return(1);}
  if(Wire.requestFrom(BMA180,1) != 1){return(2);}
  byte mode_config = Wire.read();
  mode_config &= ~(mode_config_MASK);
  Wire.beginTransmission(BMA180);
  Wire.write(0x30);
  Wire.write(mode_config);
  if(Wire.endTransmission()){return(1);}
  delay(20);
  /*Set bandwidth to 10Hz*/
  Wire.beginTransmission(BMA180);
  Wire.write(0x20);
  if(Wire.endTransmission()){return(1);}
  if(Wire.requestFrom(BMA180,1) != 1){return(2);}
  byte bw = Wire.read();
  bw &= ~(bw_MASK);
  bw |= 0x00 << 4;
  Wire.beginTransmission(BMA180);
  Wire.write(0x20);
  Wire.write(bw);
  if(Wire.endTransmission()){return(1);}
  delay(20);
  /*Set acceleration range to 2g*/
  Wire.beginTransmission(BMA180);
  Wire.write(0x35);
  if(Wire.endTransmission()){return(1);}
  if(Wire.requestFrom(BMA180,1) != 1){return(2);}
  byte range = Wire.read();
  range &= ~(range_MASK);
  range |= 0x02 << 1 ;
  Wire.beginTransmission(BMA180);
  Wire.write(0x35);
  Wire.write(range);
  if(Wire.endTransmission()){return(1);}
  delay(20);
  /*Set interrupt latch state to non latching*/
  Wire.beginTransmission(BMA180);
  Wire.write(0x21);
  if(Wire.endTransmission()){return(1);}
  if(Wire.requestFrom(BMA180,1) != 1){return(2);}
  byte latch_int = Wire.read();
  latch_int &= ~(0x01);
  Wire.beginTransmission(BMA180);
  Wire.write(0x21);
  Wire.write(latch_int);
  if(Wire.endTransmission()){return(1);}
  delay(20);
  /*Set interrupt type to new data*/
  Wire.beginTransmission(BMA180);
  Wire.write(0x21);
  if(Wire.endTransmission()){return(1);}
  if(Wire.requestFrom(BMA180,1) != 1){return(2);}
  byte int_type = Wire.read();
  int_type |= 0x02;
  Wire.beginTransmission(BMA180);
  Wire.write(0x21);
  Wire.write(int_type);
  if(Wire.endTransmission()){return(1);}
  delay(20);
  return(0);
}

Third Code:
Code:
//BMA 180 demo, from: http://www.electrodragon.com/?p=3660
#include <Wire.h>
 
void setup()
{
  Serial.begin(115200);
  Wire.begin();
 
  Serial.println("Demo started, initializing sensors");
 
  AccelerometerInit();
 
  Serial.println("Sensors have been initialized");
}
 
void AccelerometerInit()
{
  Wire.beginTransmission(0x40); // address of the accelerometer
  // reset the accelerometer
  Wire.write(0x10);
  Wire.write(0xB6);
  Wire.endTransmission();
  delay(10);
 
  Wire.beginTransmission(0x40); // address of the accelerometer
  // low pass filter, range settings
  Wire.write(0x0D);
  Wire.write(0x10);
  Wire.endTransmission();
 
  Wire.beginTransmission(0x40); // address of the accelerometer
  Wire.write(0x20); // read from here
  Wire.endTransmission();
  Wire.requestFrom(0x40, 1);
  byte data = Wire.read();
  Wire.beginTransmission(0x40); // address of the accelerometer
  Wire.write(0x20);
  Wire.write(data & 0x0F); // low pass filter to 10 Hz
  Wire.endTransmission();
 
  Wire.beginTransmission(0x40); // address of the accelerometer
  Wire.write(0x35); // read from here
  Wire.endTransmission();
  Wire.requestFrom(0x40, 1);
  data = Wire.read();
  Wire.beginTransmission(0x40); // address of the accelerometer
  Wire.write(0x35);
  Wire.write((data & 0xF1) | 0x04); // range +/- 2g
  Wire.endTransmission();
}
 
void AccelerometerRead()
{
  Wire.beginTransmission(0x40); // start transmission to device, address of the accelerometer
  Wire.write(0x02); // send register address, set read pointer to data
  Wire.endTransmission();
  Wire.requestFrom(0x40, 6);
 
  // read in the 3 axis data, each one is 16 bits
  // print the data to terminal
  Serial.print("Accelerometer: X = ");
  unsigned int data = Wire.read();
  data += Wire.read() << 8;
  Serial.print(data);
  Serial.print(" , Y = ");
  data = Wire.read();
  data += Wire.read() << 8;
  Serial.print(data);
  Serial.print(" , Z = ");
  data = Wire.read();
  data += Wire.read() << 8;
  Serial.print(data);
  Serial.println();
}
 
void loop()
{
  AccelerometerRead();
 
  delay(500); // slow down output
}

The Question is, what the different of those code? Why they have different output value, and which is the most correct method to read data from BMA180?
Logged

Offline Offline
Faraday Member
**
Karma: 61
Posts: 2841
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Try all of them,  and see what they do.   You can scale the numbers however you like.
Logged

Pages: [1]   Go Up
Jump to: