NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Project Help and Ideas » Accelerometer - ADXL345 ... Please help

March 26, 2012
by ashag
ashag's Avatar

Hi,

I am trying to make a device to detect falls and I am using the ADXL345 accelerometer for this. The datasheet for the accelerometer is - http://www.analog.com/static/imported-files/data_sheets/ADXL345.pdf

Here's the problem that I'm having - When I initialize the accelerometer using the following line

ADXL345_Write(_DATA_FORMAT, 0x0B);

the values it displays on the terminal are 0,0,1 in the X,Y,Z axis when lying on a table but when I shake the accelerometer, the values don't change.

When I initialize the accelerometer using -

ADXL345_Write(_DATA_FORMAT, 0x0F);

the values it displays in the X,Y and Z axes when lying flat are 0,0,9. The values however change when I shake the device.

The only difference between the two lines I have posted is that the justify bit is turned on in the 2nd line. The description of Justify bit in the datasheet is - A setting of 1 in the justify bit selects left-justified (MSB) mode, and a setting of 0 selects right-justified mode with sign extension.

I do not understand what it means though.

The code to initialize the accelerometer is -

char ADXL345_Init(void) {
  char id = 0x00;

  // Go into standby mode to configure the device.
  ADXL345_Write(0x2D, 0x00);

  id = ADXL345_Read(0x00);
  if (id != 0xE5) {
    return _ACCEL_ERROR;
  }
  else {

    ADXL345_Write(_POWER_CTL, 0x00);         // Go into standby mode to configure the device
    ADXL345_Write(_DATA_FORMAT, 0x0F);       // Full resolution, +/-2g, 4mg/LSB, right justified
    ADXL345_Write(_BW_RATE, 0x0F);           // Set 100 Hz data rate
    ADXL345_Write(_FIFO_CTL, 0x80);          // stream mode
    ADXL345_Write(_POWER_CTL, 0x08);         // POWER_CTL reg: measurement mode*/
    //ADXL345_Write(_OFSZ, 0x01);

    //ADXL345_Write(_OFSX, 0x08);

    return 0x00;
  }
}

The code to read the X,Y and Z-axes
// Read Z Axis (// ---------- Please note that the code to calculate the x and y axis is exactly the same so I didn't post it)

short Accel_ReadZ(void) {
  unsigned short high_byte, low_byte;
  short Z;

  high_byte = ADXL345_Read(_DATAZ1);
  low_byte  = ADXL345_Read(_DATAZ0);

  Z = (high_byte & 0x1F) << 8;
  Z = Z | low_byte;
  if (Z > 4095) Z = Z - 8192;

  return Z;
}

The code to calculate the average value of G in each direction. The formula I'm currently using to calculate g is - (Raw data) * (G-range) / (2^13). I'm using +/- 16g so I believe the G range should be 32.

// Calculate the average values of the X, Y and Z axis reads
void Accel_Average(void) {
 signed int sx, sy, sz;
 float fsx,fsy,fsz;

  char i;

  // sum
  sx = sy = sz = 0;
   fsx,fsy,fsz=0;

  // average accelerometer reading over last 16 samples
  for (i=0; i<10; i++) {
    sx += Accel_ReadX();
    sy += Accel_ReadY();
    sz += Accel_ReadZ();
  }
  // average
  sx = (sx/10);
  fsx=(signed short)sx*0.00390625;
  //sx = sx*0.00390625;
  readings[0] = (int16_t)fsx;

  sy = (sy/10);
   fsy=((signed short)sy*0.00390625);
  //sy = sy*0.00390625;
  readings[1] = (int16_t)fsy;

  sz = (sz/10);

     fsz=(signed short)sz*0.00390625;
  //sz = sz*0.00390625;
  readings[2] = (int16_t)fsz;
  //ADXL345_Write(_OFSZ, 0xFF);
}

I will really appreciate if someone is able to help me out.

Thanks Ashish

March 26, 2012
by pcbolt
pcbolt's Avatar

Hi Ashish -

I would try to print out the raw values (both high and low bytes separately) you get when you execute "Accel_ReadZ()". Then go back and try setting/clearing the justify bit to see how your results change. Maybe the conversion to a 10-bit number needs tweaking depending on how the device outputs its values.

March 27, 2012
by pcbolt
pcbolt's Avatar

Ashish -

I'm not sure this line is right:

if (Z > 4095) Z = Z - 8192;

Since you declared Z as a short (int16_t), it shouldn't need to be converted, since it is already twos-complemented. If it does need to be converted, for 16-bit numbers the range is 0 to 65,536 (unsigned) and -32,768 to +32,767 (signed) so I don't think 4095 and 8192 will work.

Post a Reply

Please log in to post a reply.

Did you know that a motor's no-load current at a given voltage is much less than it's resistance would suggest? Learn more...