How to Readout 3 BMA020 Acceleration Sensors on Mega2560 via SPI ?

Hey,
i am trying to readout a couple of Acceleration Sensors via SPI.

Rewriting the example code of the SCP1000-Pressuresensor resulted in partial success. The readings (Attachement 3) claim a value of 255 ( Maximum measurable Value of the BMA020) or 127 when moved. My coding is not yet final i.e. readout changes are only visible on the Y-Axis but i hope to fix this later.

The more important questions now are What do i have to change to prevent the readout from beeing overranged? and Why does an 8MHz readout result show only zeroes?- the datasheet (Page25) claims SPI to be possible up to 10MHz

Hardware:

  • Mega2560

-BMA 020
http://www.elv-downloads.de/Assets/Produkte/9/915/91521/Downloads/91521_bma020_data.pdf

/*

Reworked "SCP1000 Barometric Pressure Sensor Display by Tom Igoe" to fit the BMA020 Acceleration Sensor
 
 
 
 Current State: OVERRANGE Sensorvalues are shown as 255 (= Maxcapability of BMA020)
 
 
 
 */

// the sensor communicates using SPI, so include the library:
#include <SPI.h>

#define SS   53  //each SPI device needs an own pin! 
#define MOSI 51  
#define MISO 50  
#define SCK  52  

//Sensor's memory register addresses:
const int ACC_X1 = 0x02;      // 2 LSBbits BMA020
const int ACC_X2 = 0x03;      // 8 MSBbits BMA020 
const int ACC_Y1 = 0x04;      // 2 LSBbits BMA020
const int ACC_Y2 = 0x05;      // 8 MSBbits BMA020 
const int ACC_Z1 = 0x06;      // 2 LSBbits BMA020
const int ACC_Z2 = 0x07;      // 8 MSBbits BMA020 

const int Bandwidth = 0x14;   //16 bit acceleration reading
const int READ = 0b10000010;     //  BMA020 Ctrlbyte (P25) Reg02h read command
                                                                     //Addresses are automatically incremented as long as CSB stays active low
const int WRITE = 0b00001011;   //// BMA020 Ctrlbyte Reg0Bh write command



void setup() {
  Serial.begin(19200);

  // start the SPI library:
  SPI.begin();

  // initalize the  data ready and chip select pins:
  pinMode(SS,OUTPUT);    // Slave Select, Sensor gets Data from Arduino active low 
                         // If PIN53 is not labelled as OUTPUT Board will act as SLAVE
  digitalWrite(SS,HIGH); // The 'HIGH'-command turns it off by connecting it to VCC
  pinMode (MOSI,OUTPUT); // Master Output Slave Input active high
  pinMode(MISO,INPUT);   // Master Input Slave Output active high
  pinMode(SCK,OUTPUT);   // Serial Clock active high

  //SPI.setClockDivider(2);    // 16MHZ/2 = 8 Mhz SPI Standard is 4 MHZ
                              //Max for BMA020 are 10 MHZ (Page 25) but 8MHZ ARE TOO FAST resulting in "0"-Output 
  SPI.setBitOrder(LSBFIRST);  //Readoutorder	
  SPI.setDataMode(SPI_MODE3); //// CPOL=1 CPHA=1 Data captured on rising edge, propagated on falling edge
  

  // give the sensor time to set up:
  delay(100);
}

void loop() {
  //Select High Resolution Mode, which is determined by bandwidth
  writeRegister(0x14, 0x06); // Set bandwidth to  1.5kHz Bin 110 Hex 0x06

  // don't do anything until the MISO is high:
  if (digitalRead(MISO) == HIGH) {
    //Read the acceleration data LSB on new_data_bit 
    int accDataX = readRegister(0x02, 0);
    int accDataY = readRegister(0x04, 0);  
    int accDataZ = readRegister(0x06, 0);

   Serial.print("X=");
    Serial.print(accDataX);
  
    Serial.print("\t Y=");
    Serial.print(accDataY);  
    
    Serial.print("\t Z=");
    Serial.print(accDataZ);
    
    Serial.print("\n");
  }
}

//Read from or write to register from the BMA020:
unsigned int readRegister(byte thisRegister, int bytesToRead ) {
  byte inByte = 0;           // incoming byte from the SPI
  unsigned int result = 0;   // result to return
 /* Serial.print(thisRegister, BIN); NO SENSE in Printing This
  Serial.print("\t"); */
  // BMA020 expects the register name in the upper 7 bits (Figure 5 P25)
  // of the byte. So shift the bits left by one bit:
  thisRegister = thisRegister << 1;
  // now combine the address and the command into one byte
  byte dataToSend = thisRegister & READ;
  // Serial.println(thisRegister, BIN); NO SENSE in Printing This
  // take the chip select low to select the device:
  digitalWrite(SS, LOW);
  // send the device the register you want to read:
  SPI.transfer(dataToSend);
  // send a value of 0 to read the first byte returned:
  result = SPI.transfer(0x00);
  // decrement the number of bytes left to read:
  bytesToRead--;
  // if you still have another byte to read:
  if (bytesToRead > 0) {
    // shift the first byte left, then get the second byte:
    result = result << 8;
    inByte = SPI.transfer(0x00);
    // combine the byte you just got with the previous one:
    result = result | inByte;
    // decrement the number of bytes left to read:
    bytesToRead--;
  }
  // take the chip select high to de-select:
  digitalWrite(SS, HIGH);
  // return the result:
  return(result);
}


//Sends a write command to BMA020

void writeRegister(byte thisRegister, byte thisValue) {

  // BMA020 expects the register address in the upper 7 bits
  // of the byte. So shift the bits left by one bits
  thisRegister = thisRegister << 1;
  // now combine the register address and the command into one byte:
  byte dataToSend = thisRegister | WRITE;

  // take the chip select low to select the device:
  digitalWrite(SS, LOW);

  SPI.transfer(dataToSend); //Send register location
  SPI.transfer(thisValue);  //Send value to record into register

  // take the chip select high to de-select:
  digitalWrite(SS, HIGH);
}

Additional Information:

  • As far as I can tell the sensors don’t have a manufacturer imprinted ID making an I2C connection without an additional multiplexer impossible

  • The Sensors are fine, I got nice readouts using I2C on a single one

-If you find any stupid mistakes-Mention them, i just started using arduino at the beginning of the month so its highly plausible that i overlooked something :wink:

Thanks in advance,
Chris

Edit:
04.06. modified the READ and WRITE commands according to the Datatsheet (Page 26)