How to address a BMA180 Accelerometer

Hello

I was able to program my Arduino to read the values of a BMA180 accelerometer, but I want to read more than one. I think you can give them I2C addresses, and the default is 0x40 (correct me if I'm wrong). I wasn't able to find how to actually do that (for example, change the address of a BMA180 from 0x40 to let's say 0x42). Any help will be much appreciated.

Thanks in advance!

Page 54 of this datasheet says the address can be selected as either 0x40 or 0x41 depending if SDO pin is pulled to VCC or GND. All the pins are only 4.25V tolerant according to the datasheet so don't connect directly to 5V arduino pins.

If you want more than two BMA180's, you are in trouble.

There are ways to use more than two.

  • Use another type of accelerometer with other I2C addresses. Like the ADXL345. The ADXL345 can have also two on the I2C bus
  • Use SPI mode, that way the amount of accelerometers can easily be extended to 10 (or even 100 with little extra hardware). The ADXL345 can be used in SPI mode.
  • Using an I2C expander, that creates a few new I2C busses. Like the PCA9544A.
  • Creating a I2C switch with a logic chips, like this, http://arduino.cc/forum/index.php?topic=15749.0

Thank you both for your information. I think I'll go with the multiplexer solution; seems like a really good choice. One last thing, I wasn't able to find an example code of SPI mode use? Because I've never used it in the past.

Take a look at the first basic code, https://www.sparkfun.com/tutorials/240 It uses the SPI library, http://arduino.cc/en/Reference/SPI

Added: I don't know what went wrong, but this is the link to BMA180, https://www.sparkfun.com/products/9723

Thank you once again for your assistance; given these, I was able to understand a lot of things. So, I decided to communicate using SPI for now. I found out how to connect the pins, and an example code for SPI coummunication, so I was able to communicate with the BMA180. The code is this:

/**********************************************************
 * BMA180_SPI_Example.pde ----- Sample sketch for BMA180 Accelerometer using SPI Mode 3
 * 
 * A sample sketch that shows the basic functions of the BMA180 acclerometer.
 *
 *
 * 2011, DSS Circuits, Inc.  http://www.dsscircuits.com
 * 
 **********************************************************/
#include <SPI.h>

#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
#define START               PORTB &= ~0x04
#define STOP                PORTB |= 0x04
#define READ                0x80
#define CSB                 10     //slave select pin

int x,y,z,temp;

void setup() {
  Serial.begin(115200);
  pinMode (CSB, OUTPUT); // set the slaveSelectPin as an output
  SPI.begin();
  SPI.setDataMode(SPI_MODE3);
  initializeBMA180();
}

void loop()
{
  readAccel();
  printAccel();
  delay(200);
}

void readAccel()
{
  START;
  SPI.transfer(0x02|READ);
  x = SPI.transfer(0xFF);
  x |= SPI.transfer(0xFF) << 8;
  x >>= 2;
  y = SPI.transfer(0xFF);
  y |= SPI.transfer(0xFF) << 8;
  y >>= 2;
  z = SPI.transfer(0xFF);
  z |= SPI.transfer(0xFF) << 8;
  z >>= 2;
  temp = SPI.transfer(0xFF);
  STOP;
}

void printAccel()
{
  Serial.print("X = ");
  Serial.print((int)x,DEC);
  Serial.print("  Y = ");
  Serial.print((int)y,DEC);
  Serial.print("  Z = ");
  Serial.print((int)z,DEC);
  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);
  START;
  SPI.transfer(0x0D|READ);
  byte ee_w = SPI.transfer(0xFF);
  STOP;
  delay(1);
  START;
  ee_w |= ee_w_MASK;
  SPI.transfer(0x0D);
  SPI.transfer(ee_w);
  STOP;
  delay(20);
  //disable I2C as per the datasheet
  START;
  SPI.transfer(0x27|READ);
  byte dis_I2C = SPI.transfer(0xFF);
  dis_I2C |= 0x01;
  STOP;
  delay(1);
  START;
  SPI.transfer(0x27);
  SPI.transfer(dis_I2C);
  STOP;
  delay(20);
  /*Set mode configuration register to Mode 00*/
  START;
  SPI.transfer(0x30|READ);
  byte mode_config = SPI.transfer(0xFF);
  mode_config &= ~(mode_config_MASK);
  STOP;
  delay(1);
  START;
  SPI.transfer(0x30);
  SPI.transfer(mode_config);
  STOP;
  delay(20);
  /*Set bandwidth to 10Hz*/
  START;
  SPI.transfer(0x20|READ);
  byte bw = SPI.transfer(0xFF);
  bw &= ~(bw_MASK);
  bw |= 0x00 << 4;  
  STOP;
  delay(1);
  START;
  SPI.transfer(0x20);
  SPI.transfer(bw);
  STOP;
  delay(20);
  /*Set acceleration range to 2g*/
  START;
  SPI.transfer(0x35|READ);
  byte range = SPI.transfer(0xFF);
  range &= ~(range_MASK);
  range |= (0x02 << 1) ;  
  STOP;
  delay(1);
  START;
  SPI.transfer(0x35);
  SPI.transfer(range);
  STOP;
  delay(20);
  /*Set interrupt latch state to non latching*/
  START;
  SPI.transfer(0x21|READ);
  byte latch_int = SPI.transfer(0xFF);
  latch_int &= ~(0x01);
  STOP;
  delay(1);
  START;
  SPI.transfer(0x21);
  SPI.transfer(latch_int);
  STOP;
  delay(20); 
  /*Set interrupt type to new data*/
  START;
  SPI.transfer(0x21|READ);
  byte int_type = SPI.transfer(0xFF);
  int_type |= 0x02;
  STOP;
  delay(1);
  START;
  SPI.transfer(0x21);
  SPI.transfer(int_type);
  STOP;
  delay(20); 
  return(0);
}

I got values back but they weren’t correct. For instance, whilst steady, the device returned a 4000 acceleration on the x-axis, and -35 degrees temperature, then all zeros, then something else irregural etc
I searched through the whole code and I couldn’t find what’s wrong. I just tried changing SPI_MODE3 to SPI_MODE2 because I think it works in that mode (if I correctly recall, CPOL=1 and CPHA=0 on this device), but the result was the same. Can you assist me further?

Just a note, I already accomplished I2C communication with this very certain BMA180 with successful communication and valid values.

I don't have a BMA180 myself, so I can't assist as much as I would like.

Do you use this page, http://www.dsscircuits.com/accelerometer-bma180.html ? Do you have a Arduino Uno ? I think the example is for the Uno, not the Mega. How do you interface the 5V signals from the Arduino to the 3.3V BMA180 ? The datasheet of the BMA180 shows how to connect it with a low voltage (1.2V ... 3.6V) microcontroller. If you let a digital output of a 5V Arduino connect to the BMA180, it might be damaged. That could explain the wrong readings. If you use the USB port as power supply, it might still work.

According to the comments here, https://www.sparkfun.com/products/9723 , someone is using mode 0. I checked these pages: http://arduino.cc/en/Reference/SPI http://en.wikipedia.org/wiki/Serial_Peripheral_Interface_Bus Clock active low : CPOL = 1 Data on rising clock : CPHA = 1 So I am pretty sure it is mode 3

If SPI causes problems, always lower the clock with SPI.setClockDivider(). http://arduino.cc/en/Reference/SPISetClockDivider

The code from dsscircuits use direct pin changes of PORTB for the Chip Select (called CSB). The START makes CSB low = active. The STOP makes CSB high = not active. You could change that code into normal Arduino code, it will be slower, but that makes it easier to use more than one.

// Old code, fast, but not very friendly.
//    #define START               PORTB &= ~0x04
//    #define STOP                PORTB |= 0x04
// New code, with Arduino function call.
#define START        digitalWrite( CSB, LOW)
#define STOP          digitalWrite( CSB, HIGH)

I'll look into the info you provided, once again thank you very much!

Sadly, no good news yet. I use an Arduino mega, and I have already switched to the right DSI,DSO,SS and SCK pins. Before that, I was getting nothing but zeros (obviously). Now I get the "crazy" numbers.

You were right about the VDDIO, so I soldered voltage dividers and I lowered the voltage to be in range. Still no luck. Of course the VDD was already in the 3.3V pin.

Then I tried all the SPI.modes. No luck either.

And then I tried all possible clock dividers. Again, no luck. Still weird numbers.

And last, I tried the declaration you provided for START and STOP. Same results.

Of course, I also tried combinations of the above solutions. Am I missing something? I think I tried everything.

Is there an other library to try ? Can you compare with another BMA180 ? Perhaps this one is not okay anymore.

Oh my bad, I forgot to mention that I plugged another device. I think I should try another code but I can’t find any. Maybe I’ll start building my own. But I must be missing something.

You can start by comparing the readAccel() and initializeBMA180() with other code. I found these:

If other code has the same result, you should be looking at the wiring once more. Perhaps you can upload a photo of it. Is the power supply decoupled ? Are you using a breadboard ? (those have sometimes bad connections).

Thank you so much for your assistance, I've managed to get it to work today.

I replaced the code you provided for START and STOP, and added a clock divider by 2 (10 MHz was the maximum CLK frequency as stated in the datasheet), and rechecked the wiring. Some of it or all of it was causing trouble. Thanks again!