ADXL345 Data Rate

Hi,

I’m using ADXL345 Accelerometer to capture measured data and problem occurs when I’m trying to set up the data rate frequency. Regardless of the data rate I enter, sampling frequency amounts to 900Hz. What I’m trying to achive is sampling frequency of 1600Hz or higher. I’m using I2C communication and Arduino Due, the code is pasted below. Any help?

Thanks.

#include <SparkFun_ADXL345.h>         // SparkFun ADXL345 Library
int z;
long cas;

ADXL345 adxl = ADXL345();             // USE FOR I2C COMMUNICATION

void setup() {
  // put your setup code here, to run once:
  Serial.begin(250000);             

  adxl.powerOn();                     

  adxl.set_bw(800);                  
  adxl.setRate(1600);                 

  adxl.setRangeSetting(16);
}

void loop() {
  // put your main code here, to run repeatedly:

  int z;  
  adxl.readAccel(&z); 

  long cas = micros();

  Serial.print(z); 
  Serial.print(" , ");
  Serial.println(cas);
}

Since I didn’t save my first (overly long) reply, I’ll keep this one short. The major issue(s) with your sketch not achieving the data rates are as follows:

  1. The loop() call to read the sensor is not synchronised with the sensor. You may be having to wait for the sensor to be ready to send data.

  2. As I am not familiar with the Sparkfun ADXL library, I do not know what assumptions the calls make/do not make. I do not see your I2C bus speed listed.

You need data collection at 1.6kHz or 625 microseconds/cycle. I already had a sketch that reads data from a GY-85 IMU (ADXL345, gyro, and compass) where it queried the chips at separate rates. I clipped out the unneeded portions and tweaked to get it running stably at the 1.6kHz sampling rate (verified on scope, see the attachment) The top trace is the ADXL345 DATA_READY interrupt, the bottom trace is the ISR cycle time (by setting and clearing flag bits).

// GY-85 board - ITG-3205/HMC5388L/ADXL345B
// Adapted fron GetGY85RawData
// This program collects unfiltered raw data from just accelerometer
// Interrupt to take store data in arrays
// Modify integer math to use 16-bit signed as needed
// Added control through multiple interrupts (modified WInterrupts.c to release PIOA,PIOC,PIOD IRQ handlers)
// Added device presence checks
// Accelerometer interupt - PIOC
//
// Xuthus 24 Apr 17
//
// Arduino Pin Assignments
// D36 - (PIO C.4) Accelerometer interrupt input (GY_85 A_INT1)
// D20 - I2C Data (GY-85 SDA)
// D21 - I2C Clock (Gy-85 SCL)
// D13 - (PIO B.27)(internal connection) Accelerometer interrupt flag
// GND - Breadboard 3.3 GND Rail
//
#include <Wire.h>
#define ACC 0x53                             // ADXL345 ACC address
#define AccRegAddr 0x32                      // First data register address on the ADXL345

// Add calibration factors measured 22 Apr 17

#define AA11  3.941662
#define AA12  0.033395
#define AA13  0.085917
#define AA21  0.033395
#define AA22  4.007295
#define AA23  0.037694
#define AA31  0.085917
#define AA32  0.037694
#define AA33  4.018319
#define AB1   5.702705
#define AB2  -7.150334
#define AB3 -10.167222
#define ARadius 1000
#define G_MS_MG  .00980665

volatile float acc[3];                           // Accelerometer data array

void setup() {

  Serial.begin(921600);

  Wire.begin();
  Wire.setClock(3500000);

  // Initialize ACC

  Serial.println("Initialize ADXL345B");
  Wire.beginTransmission (ACC);
  if (Wire.endTransmission ())
  {
    Serial.println("Could not find a valid ADXL345B sensor, check wiring!");
    while (1) {};
  }

  // Setup accelerometer

  writeTo(ACC, 0x2D, 0x08);                  // p.25 Power-saving features control
  writeTo(ACC, 0x31, 0x00);                  // p.26 Put device into standby
  // Interrupt will be set for active low (DUE input trigger) after DUE PIO interrupt vector set
  // otherwise you get a lockup condition.
  writeTo(ACC, 0x2C, 0x0E);                  // p.25 1600Hz data rate and reg power mode control
  writeTo(ACC, 0x1E, 0x00);                  // p.24 X-Axis offset
  writeTo(ACC, 0x1F, 0x00);                  // p.24 Y-Axis offset
  writeTo(ACC, 0x20, 0x00);                  // p.24 Z-Axis offset
  writeTo(ACC, 0x38, 0x00);                  // p.27 Bypass FIFO, Send trigger output to INT2
  writeTo(ACC, 0x2F, 0x00);                  // p.26 Send all interrupts to INT1
  writeTo(ACC, 0x2E, 0x00);                  // p.26 Disable DATA_READY interrupt

  // Initialize PIO for output and input triggered interrupt

  // Setup blinky lights for each of the interrupts PIOC:B.27/L

  REG_PIOB_WPMR = 0x50494F00;                // p.674 PIO Write Protect Mode (RW) 32 bit - enable write to PIOB register
  REG_PIOB_PER = REG_PIOB_PSR | 1 << 27;     // p.633 Enable PIO control / disable peripheral control on port B.27 'L' LED
  REG_PIOB_OER = REG_PIOB_OSR | 1 << 27;     // p.636 Enable output on port B.27
  REG_PIOB_PUDR = REG_PIOB_PUSR | 1 << 27;   // p.653 Disable pullup resistor on port B.27
  REG_PIOB_CODR = 1 << 27;                   // Turn off B.27

  // Setup interrupt inputs: C.4

  REG_PMC_PCER0 = REG_PMC_PCSR0 | 0x2000;    // p.542 Turn on PIOC clock, necessary for reading input
  REG_PIOC_WPMR = 0x50494F00;                // p.674 PIO Write Protect Mode (RW) 32 bit - enable write to PIOC register
  REG_PIOC_PER = REG_PIOC_PSR | 1 << 4;      // p.633 Enable PIO control / disable peripheral control on port C.4 - Arduino D36
  REG_PIOC_ODR = !REG_PIOC_OSR | 1 << 4;     // p.637 Enable input on port C.4
  REG_PIOC_PUER = !REG_PIOC_PUSR | 1 << 4;   // p.654 Enable pullup resistor on port C.4
  REG_PIOC_IFDR = !REG_PIOC_IFSR | 1 << 4;   // p.640 Disable glitch filter on PIO C.4
  REG_PIOC_ESR = !REG_PIOC_ELSR | 1 << 4;    // p.668 interrupt source is edge detection on PIO C.4
  REG_PIOC_FELLSR = !REG_PIOC_FRLHSR | 1 << 4; // p.671 interrupt source is falling edge detection on PIO C.4
  REG_PIOC_AIMER = REG_PIOC_AIMMR | 1 << 4;  // p.664 additional interrupt modes enable on PIO C.4
  REG_PIOC_IER = REG_PIOC_IMR | 1 << 4;      // p.646 enable input change interrupt on PIO C.4

  NVIC_EnableIRQ(PIOC_IRQn);                 // Enable PIOC interrupts
  writeTo(ACC, 0x31, 0x2B);                  // p.26 Full resolution, interrupt high, RJ data format, +/-16G
  writeTo(ACC, 0x2E, 0x80);                  // p.26 Enable DATA_READY interrupt

}

void loop() {

  REG_PIOB_CODR = 1 << 27;                   // Turn off B.27
}

void PIOC_Handler() {
  boolean dummy = (REG_PIOC_ISR >> 4);       //  p. 649 Read PIOC interrupt status, clear register
  REG_PIOB_SODR = 1 << 27;                   //  Turn on PIO B.27

  byte buff[6];
  int16_t temp[3];

  //read data from accelerometer into buffer array

  readFrom(ACC, AccRegAddr, 6, buff);

  // Accelerometer data is Little-endian 16-bit

  temp[0] = (int16_t(buff[1]) << 8) | buff[0];
  temp[1] = (int16_t(buff[3]) << 8) | buff[2];
  temp[2] = (int16_t(buff[5]) << 8) | buff[4];

  // Uncomment for raw data
  //acc[0] = temp[0];
  //acc[1] = temp[1];
  //acc[2] = temp[2];

  // Uncomment for scaled data
  acc[0] = (AA11 * (float(temp[0])-AB1) + AA12 * (float(temp[1])-AB2) + AA13 * (float(temp[2])-AB3)) * G_MS_MG;
  acc[1] = (AA21 * (float(temp[0])-AB1) + AA22 * (float(temp[1])-AB2) + AA23 * (float(temp[2])-AB3)) * G_MS_MG;
  acc[2] = (AA31 * (float(temp[0])-AB1) + AA32 * (float(temp[1])-AB2) + AA33 * (float(temp[2])-AB3)) * G_MS_MG;

  Serial.print(acc[0], 3); Serial.print("\t"); Serial.print(acc[1], 3); Serial.print("\t"); Serial.println(acc[2], 3);

}


void writeTo(int DEVICE, uint8_t address, uint8_t val) {
  Wire.beginTransmission(DEVICE);         // Start transmit queue to device
  Wire.write(address);                    // Buffer register address
  Wire.write(val);                        // Buffer value to write
  Wire.endTransmission();                 // Send transmission
}

void readFrom(int DEVICE, uint8_t address, int num, uint8_t buff[]) {
  Wire.beginTransmission(DEVICE);         // Start transmission to MAG
  Wire.write(address);                    // Sends address to read from
  Wire.endTransmission();                 // Send transmission
  Wire.beginTransmission(DEVICE);         // Start transmission to MAG
  Wire.requestFrom(DEVICE, num);          // Request 6 bytes from MAG
  int l = 0;
  while (Wire.available())                // ACC may send less than requested (abnormal)
  {
    buff[l] = Wire.read();                // Receive a byte from buffer
    l++;
  }
  Wire.endTransmission();                 // End transmission
}

I’m viewing the output on Teraterm set at 921K 7-N-1 Xon/Xoff. Yes, the Serial rate and I2C are jacked way up, but that was needed to get it to run stably. The code actually outputs scaled values of all three axes. At 1.6 kHz, the cycle time is 320 microseconds, so you would NOT be able to run at 3.2 kHz without losing something