Monday, July 26, 2010

BalanceBot 2

I finally have communication between an Arduino and an ADXL345 accelerometer over SPI!

I used the SPI library from the Arduino playground but was still having trouble so in the end resorted to following the example source code provided by sparkfun for the ATmega328.

The following listing is copied straight from my Arduino environment.

#include <Spi.h>

/*
  BalanceBot
  Read from an accelerometer ADXL345.
  ADXL345 max clock speed is 5MHz, default arduino CLKi/o is 16MHz/64 (OK)
  ***SPI Pins***
  SCK    PB5    13
  MISO    PB4    12
  MOSI    PB3    11
  SS    Any    10
  Ben Caldwell
*/

byte tmp;
byte readData; //The byte that data read from SPI interface will be stored in
byte fifo[6]; //data read for x,y,z axis from the accelerometer's FIFO buffer
float x,y,z; //The ranged x,y,z data
float range; //The range of the x,y,z data returned

// The setup() method runs once, when the sketch starts

void setup()   {               
  Serial.begin(9600);
  Spi.mode((1<<SPE) | (1<<MSTR) | (1<<CPOL) | (1<<CPHA) | (1<<SPR1) | (1<<SPR0));

  Serial.println("Starting Setup");
  //Set SS high, slave disabled waiting to pull low for first exchange
  digitalWrite(SS_PIN, HIGH);
  delay(4000);
  //Wait for POWER_CTL register to go to correct state
  readData = 0x00;
  while (readData != 0x28)
  {   
    //POWER_CTL register: measure
    digitalWrite(SS_PIN, LOW);
    Spi.transfer(0x2D);
    Spi.transfer(0x28); //Measure
    digitalWrite(SS_PIN, HIGH);
    delay(5);
    digitalWrite(SS_PIN, LOW);
    Spi.transfer(1<<7 | 0x2D); //Set "read" MSb
    readData = Spi.transfer(0x00); //Send dummy byte to keep clock pulse going!
    digitalWrite(SS_PIN, HIGH);
    Serial.print("POWER_CTL: ");
    Serial.println(readData, HEX);
    delay(1000);
  }
  //Set FORMAT
  digitalWrite(SS_PIN, LOW);
  Spi.transfer(0x31);
  Spi.transfer(0x08);
  digitalWrite(SS_PIN, HIGH);
  delay(5);
  //Readback FORMAT
  digitalWrite(SS_PIN, LOW);
  Spi.transfer(1<<7 | 0x31);
  readData = Spi.transfer(0x00);
  digitalWrite(SS_PIN, HIGH);
  readData = readData & 0x03;
  switch (readData)
  {
    case 0:
      range = 2.0;
      break;
    case 1:
      range = 4.0;
      break;
    case 2:
      range = 8.0;
      break;
    case 3:
      range = 16.0;
      break;
  }
  Serial.print("FORMAT: ");
  Serial.println(readData, HEX);
  //Set FIFO
  digitalWrite(SS_PIN, LOW);
  Spi.transfer(0x38);
  Spi.transfer(0x00);
  digitalWrite(SS_PIN, HIGH);
  delay(5);
  //Readback FIFO
  digitalWrite(SS_PIN, LOW);
  Spi.transfer(1<<7 | 0x38);
  readData = Spi.transfer(0x00);
  digitalWrite(SS_PIN, HIGH);
  Serial.print("FIFO: ");
  Serial.println(readData, HEX);
  delay(4000);
}

// the loop() method runs over and over again,
// as long as the Arduino has power

void loop()                    
{
   //All x,y,z data must be read from FIFO in a multiread burst
  digitalWrite(SS_PIN, LOW);
  //Start reading at 0x32 and set "Read" and "Multi" bits
  Spi.transfer(1<<7 | 1<<6 | 0x32);
  for (int i=0; i<6; i++)
  {
    fifo[i] = Spi.transfer(0x00);
  }
  digitalWrite(SS_PIN, HIGH);
  delay(5);
  //The measurements in the FIFO 10bit 
  x = (float)((fifo[1]<<8) | fifo[0]) * range / 512.0;
  y = (float)((fifo[3]<<8) | fifo[2]) * range / 512.0;
  z = (float)((fifo[5]<<8) | fifo[4]) * range / 512.0;
  Serial.println("********************");
  Serial.print("[X,Y,Z](g): [");
  Serial.print(x);
  Serial.print(",");
  Serial.print(y);
  Serial.print(",");
  Serial.print(z);
  Serial.println("]");
  delay(1000);

}

 

References

  1. The SEN-09156 breakout board:
    http://www.sparkfun.com/commerce/product_info.php?products_id=9156
  2. Sparkfun example code:
    http://www.sparkfun.com/datasheets/Sensors/Accelerometer/ADXL345-talktest.zip
  3. Arduino SPI library:
    http://www.arduino.cc/playground/Code/Spi

1 comment:

  1. do your code work with Sparkfun ADXL345 evaluation board?

    link:
    http://www.sparkfun.com/products/9814

    ReplyDelete