How to interpret results from an accelerometer

Hi,
I am trying to connect an Arduino to a digital accelerometer. The Arduino receives commands from a mobile app and transmits over Bluetooth through hardware serial.

Code:

#include <SPI.h>

const int X8 = 0x06;
const int Y8 = 0x07;
const int Z8 = 0x08;

/*
bits
1 0  mode 00: standby, 01: measurement
5     1: spi 3 wire, 0: 4 wire
4      self test
3     2 glevel: 01 2g
1 0  mode, 00 standby, 01 measurement 
*/
const int MODE = 0x16;

const int STATUS = 0x09;

//7 digital filter band width, 0 62.5 Hz, 1 125 Hz
const int CONTROL = 0x18;

bool isTesting = false;

const int chipSelectPin = 7;

 
 void setup()  
 {  
  Serial.begin(9600);  
    SPI.begin();
    pinMode(chipSelectPin, OUTPUT);

    //set up standby, spi 4 wire, 2g range, 
    writeRegister(MODE, 0x04);

    //set up speed
    writeRegister(CONTROL, 0x00);

        delay(100);
 }  
 void loop()  
 {  
  if(getSerial() ==  't')  
  {  
       isTesting = true;
       writeRegister(MODE, 0x05); // 0000 0101- 0001 0101 0x15
       testing();

  }  

 } 
 void testing(){
    while (isTesting ){
        if ((readRegister (STATUS) & 1) == 1 ){
            Serial.print((char)readRegister (X8),DEC);
            Serial.print("x");
            Serial.print((char)readRegister (Y8),DEC);
            Serial.print("y");
            Serial.print((char)readRegisterChar (Z8),DEC);
            Serial.print("z");
        }

        if (getSerial() == 'u'){
            isTesting = false;  
            writeRegister(MODE, 0x04);
        }
    }    
 }
 char getSerial(){
    if (Serial.available()){
        char c = Serial.read();
        return c;
    }
    return 'x';
 }
 byte readRegister (byte thisRegister){
    byte inByte = 0 ;
    SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); // 500khz clock
    digitalWrite(chipSelectPin, LOW);
    SPI.transfer(thisRegister << 1);
    inByte = SPI.transfer(0x00);
    digitalWrite(chipSelectPin, HIGH);
    return inByte;
} 
 char readRegisterChar (byte thisRegister){
    char inChar = 0 ;
    SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); // 500khz clock
    digitalWrite(chipSelectPin, LOW);
    SPI.transfer(thisRegister << 1);
    inChar = SPI.transfer(0x00);
    digitalWrite(chipSelectPin, HIGH);
    return inChar;
} 
void writeRegister (byte thisRegister, byte value){
    SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); // 500khz clock
    digitalWrite(chipSelectPin, LOW);
    SPI.transfer(128 | thisRegister << 1);
    SPI.transfer(value);
    digitalWrite(chipSelectPin, HIGH);
}

The sensor allows for data values of 10 bits but for simplicity I am getting only the 8 bit data. The data received when the sensor is on a flat surface is:

  • x y z
  • 5 -11 74
  • 4 -19 74
  • 2 -9 69
  • 0 -8 68
  • 7 -16 68
  • 7 -11 73

When the self test is run, the results are:

  • -5 -20 122
  • -4 -22 122
  • -1 -20 123
  • -4 -20 123
  • -5 -21 121
  • -3 -18 123
  • -8 -22 127

From the data sheet: "When the self-test function is initiated through the mode control register ($16),
accessing the “self-test” bit, an electrostatic force is applied to each axis to cause it to deflect. The Z-axis is trimmed to deflect
1g."

Is the data correct? How is it interpreted? If the z data during self test is 1g, shouldn't it have the same magnitude as when it is on a flat surface?

Thank you.

It does not simplify anything to throw away data bits.

For best results, accelerometers should be individually calibrated. Overview here. In going through this process, you will learn how to interpret the data.

Thank you for the guidance. The link to download FreeIMU for Windows (source) is down. Building an app from binaries is beyond my ability.

I changed the Arduino so that it gets the 10 bits of data:

const int X10_LSB = 0x00;
const int X10_MSB = 0x01;
const int Y10_LSB = 0x02;
const int Y10_MSB = 0x03;
const int Z10_LSB = 0x04;
const int Z10_MSB = 0x05;

//[...]

void testing(){
    while (isTesting ){
        if ((readRegister (STATUS) & 1) == 1 ){

            int xData = (readRegister (X10_MSB)<<8) | readRegister (X10_LSB);
            
            // checks if bit 9 is 1 and sign extends
            if ((xData & 512) == 512)
                xData = (0b1111110000000000 | xData);
            int yData = (readRegister (Y10_MSB)<<8) | readRegister (Y10_LSB);
            if ((yData & 512) == 512)
                yData = (0b1111110000000000 | yData);
            int zData = (readRegister (Z10_MSB)<<8) | readRegister (Z10_LSB);
            if ((zData & 512) == 512)
                zData = (0b1111110000000000 | zData);

            Serial.print(xData);
            Serial.print("x");
            Serial.print(yData);
            Serial.print("y");
            Serial.print(zData);
            Serial.print("z");


        }

The outputs for 2g measurement is:

  • 4 246 -183
  • 5 245 -183
  • 5 245 -182
  • 6 245 -181

For the self test:

  • 252 -20 -134
  • 253 -21 -133
  • 253 -21 -135
  • 253 -20 -135

if you are interested this was answered here: arduino uno - How to get and interpret digital accelerometer data? - Arduino Stack Exchange

I'm most familiar with the ADXL345 but that chip looks to be very similar.

The self-test is useless. It adds to the acceleration sensed. It looks like your chip is functional. You could flip it upside-down and get a reading close to zero when self-test is activated.

So is there another problem?

How do I Mark as [Solved]

Edit your first post to change the title.