Bosh BMA180, Accelerometer

I purchased a Bosh BMA180 tri axis accelerometer from Sparkfun to play with.  It has been one of the most frustrating devices I have ever used.  I connected it up with SPI instead of the optional i2c interface because it can't handle 5 volts.  SPI is unidirectional and simple voltage dividers allow me to connect it to my breadboard Arduino.  The SDO/MISO and INT/INT0 connections are ok to direct connect because my processor sees the 3.3 volt output as a high signal.


Purchased from sparkfun.com
Datasheet



My code is chalk full of bugs but it's a start:

///////////////////////////////////////////////////////////////////////////////////////////////////////
// Tri Axis Accelerometer, BMA180 connected with SPI

//function prototypes
void solid(int r, int g, int b, int t);

//Pin declarations
#define PIN_INTERUPT 0
#define PIN_LEDR     3
#define PIN_LEDG     5
#define PIN_LEDB     6
#define DATAOUT     11   //MOSI
#define DATAIN      12   //MISO - not used, but part of builtin SPI
#define SPICLOCK    13   //SCK
#define SLAVESELECT 10   //SS


int r=0, g=0, b=0;


///////////////////////////////////////////////////////////////////////////////////////////////////////
void setup()
{
  delay(2000);
  Serial.begin(57600);
  Serial.println("BMA180 Test");

  byte clr;
  pinMode(DATAOUT, OUTPUT);
  pinMode(DATAIN, INPUT);
  pinMode(SPICLOCK, OUTPUT);
  pinMode(SLAVESELECT, OUTPUT);
  digitalWrite(SLAVESELECT, HIGH);    //disable device
  pinMode(PIN_INTERUPT, INPUT);

  SPCR = (1<
  //SPCR = (1<
  // The SPI control register (SPCR) has 8 bits, each of which control a particular SPI setting.
  // SPCR
  // | 7    | 6    | 5    | 4    | 3    | 2    | 1    | 0    |
  // | SPIE | SPE  | DORD | MSTR | CPOL | CPHA | SPR1 | SPR0 |

  // SPIE - Enables the SPI interrupt when 1
  // SPE - Enables the SPI when 1
  // DORD - Sends data least Significant Bit First when 1, most Significant Bit first when 0
  // MSTR - Sets the Arduino in master mode when 1, slave mode when 0
  // CPOL - Sets the data clock to be idle when high if set to 1, idle when low if set to 0
  // CPHA - Samples data on the falling edge of the data clock when 1, rising edge when 0
  // SPR1 and SPR0 - Sets the SPI speed, 00 is fastest (4MHz) 11 is slowest (250KHz)

  clr=SPSR;
  clr=SPDR;
 
  // if connected correctly, ID register should be 3
  while (read(0x00) != 3) {
    Serial.println("Error connecting to BMA180");
    delay(1000);
  }
  Serial.println("Successfully connected to BMA180");

  for (int j=0x20; j<0x40; j++) {
    //read_bits (j, 7, 0);
  }

  // You must turn this on to change anything from 0x20 to 0x3F
  write_bits(0x0D, 4, 4, 1);      // ee-w, Allow updates from 0x20 to 0x50
  write_bits(0x26, 0, 0, 1);      // dis_i2c, Turn off I2C
  write_bits(0x35, 3, 1, 2);      // range, Set the range, 2g
  write_bits(0x20, 7, 4, 4);      // bw, Set the bandwidth, 150hz
  
  //write_bits(0x22, 2, 0, 3);      // offset_finetuning, Turn on full calibration
  //write_bits(0x0E, 7, 7, 1);      // en_offset_x, Start calibration on X axis
  //write_bits(0x0E, 6, 6, 1);      // en_offset_y, Start calibration on Y axis
  //write_bits(0x0E, 5, 5, 1);      // en_offset_z, Start calibration on Z axis

  write_bits(0x21, 6, 6, 0);      // slope_int,    Turn on/off interupt
  write_bits(0x21, 5, 5, 0);      // high_int,     Turn on/off interupt
  write_bits(0x21, 4, 4, 0);      // low_int,      Turn on/off interupt
  write_bits(0x21, 3, 3, 0);      // tapsens_int,  Turn on/off interupt
  write_bits(0x21, 2, 2, 0);      // adv_int,      Turn on/off interupt
  write_bits(0x21, 1, 1, 0);      // new_data_int, Turn on/off interupt
  write_bits(0x21, 0, 0, 0);      // lat_int,      Turn on/off interupt

  write_bits(0x24, 0, 0, 1);      // tapsens_filt,  Tap sensor will use filtered data

  write_bits(0x0D, 4, 4, 0);      // ee_w, disable updates

  attachInterrupt(0, bma180_interupt, CHANGE);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
char read(uint8_t address) {
  //returns the contents of any 1 byte register from any address
  //sets the MSB for every address byte (READ mode)

  char byte;

  address |= 0x80;

  digitalWrite(SLAVESELECT, LOW);     //enable device by setting CSB to 0
  txdata(address);
  byte = rxdata();
  digitalWrite(SLAVESELECT, HIGH);    //disable device by setting CSB to 1

  return byte;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
void write(uint8_t address, char data) {
  //write any data byte to any single address
  //adds a 0 to the MSB of the address byte (WRITE mode)

  address &= 0x7F;  // Set the RW bit to 0 (write)     

  digitalWrite(SLAVESELECT, LOW);     //enable device
  txdata(address);
  txdata(data);
  digitalWrite(SLAVESELECT, HIGH);    //disable device
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
char rxdata(void) {
  SPDR = 0x00;
  while (!(SPSR & (1<
  //while((SPSR&0x80) == 0x00);
  return SPDR;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
void txdata(char data) {
  SPDR = data;
  while (!(SPSR & (1<
  //while((SPSR&0x80) == 0x00);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
int read_bits(uint8_t address, int first, int last) {
  byte temp = 0;

  temp = read(address);
  
  temp = (temp<<(7-first));        // Get rid of the un-wanted right most bits
  temp = (temp>>(7-first+last));   // Get rid of the un-wanted left most bits
  Serial.print("Reading Register: 0");
  Serial.print(address, HEX);
  Serial.print("h, bits ");
  Serial.print(first);
  Serial.print("-");
  Serial.print(last);
  Serial.print(": 0");
  Serial.print(temp, HEX);
  Serial.print("h ");
  Serial.print(temp, BIN);
  Serial.print(" binary");
  Serial.println();

  return temp;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
void write_bits(uint8_t address, int first, int last, int value) {
  byte temp = 0;
  byte save_left = 0;
  byte save_right = 0;
  
  temp = read(address);
  
  save_left = (temp>>first+1);        // Get rid of the un-wanted right most bits
  save_left = (save_left<
  save_right = (temp<<8-last);        // Get rid of the un-wanted right most bits
  save_right = (save_right>>8-last);        // Get rid of the un-wanted right most bits
  temp = (save_left | save_right | (value<

  Serial.print("Writing Register: 0");
  Serial.print(address, HEX);
  Serial.print("h, bits ");
  Serial.print(first);
  Serial.print("-");
  Serial.print(last);
  Serial.print(", new value: ");
  Serial.print(value, HEX);
  Serial.print(": 0");
  Serial.print(temp, HEX);
  Serial.print("h ");
  Serial.print(temp, BIN);
  Serial.print(" binary");
  Serial.println();

  write(address, temp);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
void bma180_interupt() {
  read_bits (0x0B, 7, 0);
  //Serial.println("Something happened");
}

///////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  delay(10);

  long total;
  signed short temp = 0;
  signed short x = 0;
  signed short y = 0;
  signed short z = 0;
  byte x_msb_byte = 0;
  byte x_lsb_byte = 0;
  byte y_msb_byte = 0;
  byte y_lsb_byte = 0;
  byte z_msb_byte = 0;
  byte z_lsb_byte = 0;

  digitalWrite(SLAVESELECT, LOW);     //enable device by setting CSB to 0
  txdata(0x02 | 0x80);
  x_lsb_byte = rxdata();
  x_msb_byte = rxdata();
  y_lsb_byte = rxdata();
  y_msb_byte = rxdata();
  z_lsb_byte = rxdata();
  z_msb_byte = rxdata();
  digitalWrite(SLAVESELECT, HIGH);    //disable device by setting CSB to 1

  temp = x_msb_byte;
  temp = (unsigned int)temp << 8;
  temp |= x_lsb_byte;
  temp = (unsigned int)temp >> 2;    // Get rid of two non-value bits in LSB
  temp = (unsigned int)temp << 2;    // Put it back
  x = temp / 4;                      

  temp = y_msb_byte;
  temp = (unsigned int)temp << 8;
  temp |= y_lsb_byte;
  temp = (unsigned int)temp >> 2;    // Get rid of two non-value bits in LSB
  temp = (unsigned int)temp << 2;    // Put it back
  y = temp / 4;                      

  temp = z_msb_byte;
  temp = (unsigned int)temp << 8;
  temp |= z_lsb_byte;
  temp = (unsigned int)temp >> 2;    // Get rid of two non-value bits in LSB
  temp = (unsigned int)temp << 2;    // Put it back
  z = temp / 4;                      
   
  if (x > 0) {
    r = map(x, 0, 4500, 0, 255);
    //r = 0;
    g = 0;
    b = 0;
  } 
  else {
    r = 0;
    g = 0;
    //b = 0;
    b = map(x, 0, -4500, 0, 255);
  }
  
  //g = map(y, -5000, -5500, 0, 255);
  
  Serial.print(x);
  Serial.print("   ");
  Serial.print(y);
  Serial.print("   ");
  Serial.print(z);

  total = abs(x) + abs(y) + abs(z);
  Serial.print("   ");
  Serial.print(total);
  Serial.println();
  
  // PWM output to LED
  analogWrite(PIN_LEDR, r);
  analogWrite(PIN_LEDG, g);
  analogWrite(PIN_LEDB, b);
}

///////////////////////////////////////////////////////////////////////////////////////////////////////




created: Dec. 1, 2013, 1:01 a.m.
modified: April 14, 2019, 12:42 a.m.

Dullbits.com