Hello Everyone,
I purchased two BMA180 Accelerometers without double checking all of the specs (big mistake!) and now I have been working to understand I2C and the Wire Library. After the past three days of working I have finally achieved a consistent and correct output. I thought I would share my findings since there is very little information about using this accelerometer with an Arduino.
I am using an Arduino Mini 04 and have soldered extra pins to Analog 3 and 4 to allow me the use of the Wire library. It is important to note that the BMA180 is not a 5v device, it operates in many different ranges but all are below the 5v that the Arduino uses. It is ok to power the BMA180 with the 3.3v rail of an Arduino Duemilanove but the Wire library needs the signal at 5v.
For my setup, it was necessary to purchase a Logic Level Converter (Sparkfun sku: BOB-08745). Because communication with I2C is bidirectional, I had to wire both the clock and signal line to the TX path on the logic level converter. This means that I need one converter for one Accelerometer. No big deal, these guys only cost 2 bucks.
An I2C setup needs to have pullup resistors on both lines, on an Arduino Duemilanove the Wire library enables pullups by default, with the Arduino Mini, the information on this subject is ambiguous. One source includes the pullup resistors, another source has you change part of the Wire library code and recompile... thus enabling the pullups on the Mini. I have selected two 10k resistors and used them on the I2C wires on the 5V side of the logic level converter.
If everything is wired correctly, it will respond to its address and it will always return the value 3 when asked for its ID. Checking the ID is a good way to confirm that the chip is up and running. The C example code on the Sparkfun website is very helpful in understanding how to access and change the register values on the chip.
One thing that I can recommend is to thoroughly read the BMA180 datasheet. Page 21 of the PDF gives you all of the register values and the breakdown of the bits contained in each value. Look to the individual register descriptions to see the binary values they accept.
For a beginner like me, communicating in binary and hex looked impossible at first. I spent many hours trying to break down the example code for the BMA180 on the Sparkfun site and it has started to click. The BitwiseAnd section of the Arduino reference should help de-mystify some of the binary arithmetic concepts used in the example code.
I hope this information helps someone, below is the code that I have used to setup the BMA180 and then read a constant stream of the x acceleration value.
Here is the code for my main file.
#include <Wire.h>
#define address 0x40
void setup()
{
Wire.begin();
Serial.begin(9600);
initBMA180();
delay(2000);
}
void loop()
{
readAccel();
delay(10);
}
In my Arduino IDE I keep the BMA functions in a separate tab.
int x;
void readAccel()
{
int temp, result;
temp = 0;
while(temp != 1)
{
Wire.beginTransmission(address);
Wire.send(0x03);
Wire.requestFrom(address, 1);
while(Wire.available())
{
temp = Wire.receive() & 0x01;
}
}
Wire.beginTransmission(address);
Wire.send(0x02);
Wire.requestFrom(address, 1);
while(Wire.available())
{
temp |= Wire.receive();
temp = temp >> 2;
}
Serial.print("X = ");
Serial.println(temp);
result = Wire.endTransmission();
}
void initBMA180()
{
int temp, result, error;
Wire.beginTransmission(address);
Wire.send(0x00);
Wire.requestFrom(address, 1);
while(Wire.available())
{
temp = Wire.receive();
}
Serial.print("Id = ");
Serial.println(temp);
result = Wire.endTransmission();
checkResult(result);
if(result > 0)
{
error = 1;
}
delay(10);
if(temp == 3)
{
// Connect to the ctrl_reg1 register and set the ee_w bit to enable writing.
Wire.beginTransmission(address);
Wire.send(0x0D);
Wire.send(B0001);
result = Wire.endTransmission();
checkResult(result);
if(result > 0)
{
error = 1;
}
delay(10);
// Connect to the bw_tcs register and set the filtering level to 10hz.
Wire.beginTransmission(address);
Wire.send(0x20);
Wire.send(B00001000);
result = Wire.endTransmission();
checkResult(result);
if(result > 0)
{
error = 1;
}
delay(10);
// Connect to the offset_lsb1 register and set the range to +- 2.
Wire.beginTransmission(address);
Wire.send(0x35);
Wire.send(B0100);
result = Wire.endTransmission();
checkResult(result);
if(result > 0)
{
error = 1;
}
delay(10);
}
if(error == 0)
{
Serial.print("BMA180 Init Successful");
}
}
void checkResult(int result)
{
if(result >= 1)
{
Serial.print("PROBLEM..... Result code is ");
Serial.println(result);
}
else
{
Serial.println("Read/Write success");
}
}
void readId()
{
int temp, result;
Wire.beginTransmission(address);
Wire.send(0x00);
Wire.requestFrom(address, 1);
while(Wire.available())
{
temp = Wire.receive();
}
Serial.print("Id = ");
Serial.println(temp);
result = Wire.endTransmission();
checkResult(result);
delay(10);
}