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.