The sampling speed is too low

Hello, I'm using Arduino Mega 2560 with I2C sensor ADXL345. And I'm using delay(1) to control the sampling interval at 1 millisecond, neamly I should have 1000 sampling points per second. However, the output is far less than 1000, it is only around 80 points per second. The output data rate of the sensor is 800 Hz and the excitation frequency is 1000 Hz. I also tried millis() to control the sampling rate, no developing.

#include <Wire.h>
#include <ADXL345.h>


ADXL345 adxl; //variable adxl is an instance of the ADXL345 library

void setup() {
    Serial.begin(9600);
    adxl.powerOn();

    //set activity/ inactivity thresholds (0-255)
    adxl.setActivityThreshold(75); //62.5mg per increment
    adxl.setInactivityThreshold(75); //62.5mg per increment
    adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?

    //look of activity movement on this axes - 1 == on; 0 == off
    adxl.setActivityX(1);
    adxl.setActivityY(1);
    adxl.setActivityZ(1);

    //look of inactivity movement on this axes - 1 == on; 0 == off
    adxl.setInactivityX(1);
    adxl.setInactivityY(1);
    adxl.setInactivityZ(1);

    //look of tap movement on this axes - 1 == on; 0 == off
    adxl.setTapDetectionOnX(0);
    adxl.setTapDetectionOnY(0);
    adxl.setTapDetectionOnZ(1);

    //set values for what is a tap, and what is a double tap (0-255)
    adxl.setTapThreshold(50); //62.5mg per increment
    adxl.setTapDuration(15); //625us per increment
    adxl.setDoubleTapLatency(80); //1.25ms per increment
    adxl.setDoubleTapWindow(200); //1.25ms per increment

    //set values for what is considered freefall (0-255)
    adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
    adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment

    //setting all interrupts to take place on int pin 1
    //I had issues with int pin 2, was unable to reset it
    adxl.setInterruptMapping(ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN);
    adxl.setInterruptMapping(ADXL345_INT_DOUBLE_TAP_BIT,   ADXL345_INT1_PIN);
    adxl.setInterruptMapping(ADXL345_INT_FREE_FALL_BIT,    ADXL345_INT1_PIN);
    adxl.setInterruptMapping(ADXL345_INT_ACTIVITY_BIT,     ADXL345_INT1_PIN);
    adxl.setInterruptMapping(ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN);

    //register interrupt actions - 1 == on; 0 == off
    adxl.setInterrupt(ADXL345_INT_SINGLE_TAP_BIT, 1);
    adxl.setInterrupt(ADXL345_INT_DOUBLE_TAP_BIT, 1);
    adxl.setInterrupt(ADXL345_INT_FREE_FALL_BIT,  1);
    adxl.setInterrupt(ADXL345_INT_ACTIVITY_BIT,   1);
    adxl.setInterrupt(ADXL345_INT_INACTIVITY_BIT, 1);
}

void loop() {

    //Boring accelerometer stuff
    int x, y, z;
    adxl.readXYZ(&x, &y, &z); //read the accelerometer values and store them in variables  x,y,z
    // Output x,y,z values
    Serial.print("values of X , Y , Z: ");
    Serial.print(x);
    Serial.print(" , ");
    Serial.print(y);
    Serial.print(" , ");
    Serial.println(z);

    double xyz[3];
    double ax, ay, az;
    adxl.getAcceleration(xyz);
    ax = xyz[0];
    ay = xyz[1];
    az = xyz[2];
    Serial.print("X=");
    Serial.print(ax);
    Serial.println(" g");
    Serial.print("Y=");
    Serial.print(ay);
    Serial.println(" g");
    Serial.print("Z=");
    Serial.print(az);
    Serial.println(" g");
    Serial.println("**********************");
    delay(1);

}

Welcome to the forum

Start by increasing the baud rate of the Serial printing. 9600 baud is really pathetic

3 Likes

modern standard baudrate is 115200.

I have tested arduino Unos and Megas they work up to abudrate of 250000 reliably
Depending on how much samples you want to collect it might be an option to store the samples in an array and after dampling do the printing.

best regards Stefan

9600 baud will only let you print 960 characters/second, and the loop time is going to vary depending on the value of the numbers you are printing (larger numbers that take more characters will take longer to print).

Hello, I increased the baud rate to 115200 and 500000, but still ended up with the same sampling rate.

Hello, thanks for your advice. Because the Arduino IDE can't store and save the data, so I use Python to save the data. Besides, I don't print out the data in the terminal, this part should not intervene in the speed. I tried 115200, it increased the sampling rate to 200 points per second. However, then it can't be optimized anymore. Even with 2000000, it is still 200 Hz.

Which ADXL library are you using? There are 6 or 7 available in the manager...

Take a moment, try replacing your loop with this, and show us what it prints, please:

void loop() {

  //Boring accelerometer stuff
  int x, y, z;
  adxl.readXYZ(&x, &y, &z); //read the accelerometer values and store them in variables  x,y,z
  Serial.print(millis());
  Serial.print(" --- ");
  double xyz[3];
  double ax, ay, az;
  adxl.getAcceleration(xyz);
  ax = xyz[0];
  ay = xyz[1];
  az = xyz[2];
  Serial.println(millis());
}

Hello, this is the output from the your code:
16:09:17.387 -> 20746 --- 20757

16:09:17.420 -> 20764 --- 20774

16:09:17.420 -> 20782 --- 20792

16:09:17.453 -> 20799 --- 20809

16:09:17.453 -> 20817 --- 20828

16:09:17.485 -> 20835 --- 20845

16:09:17.518 -> 20852 --- 20862

16:09:17.518 -> 20870 --- 20881

16:09:17.551 -> 20888 --- 20898

16:09:17.551 -> 20905 --- 20916

16:09:17.584 -> 20923 --- 20933

16:09:17.584 -> 20940 --- 20952

16:09:17.616 -> 20959 --- 20969

16:09:17.616 -> 20976 --- 20986

16:09:17.649 -> 20994 --- 21004

16:09:17.649 -> 21011 --- 21022

16:09:17.689 -> 21029 --- 21040

16:09:17.689 -> 21047 --- 21057

16:09:17.723 -> 21064 --- 21074

16:09:17.748 -> 21083 --- 21093

I'm using ADXL345.h, what do you mean there are other choices? I did not find others online, would you mind sharing a link?

You don't need a link, just search for ADXL in the Library Manager of the IDE

I find I might misunderstand something. The word 'print' means printing the data in a terminal or save them in a file? I've increased the baud rate, the maximal sampling rate is around 200 Hz, and can't be optimized anymore no matter how big the baud rate is. Do we have other methods to develop it?

Thanks :grinning:, I'm still not familiar with Arduino.

It means send data out through the default Arduino serial port. The serial monitor acts as a terminal and displays the data, but you can use any terminal program to both display the data and log the data to a file.

I use TeraTerm and PuTTY for this on Windows, GTKterm on linux.

To solve the sampling rate problem, you need to tell us which ADXL library you are using, where you downloaded it, and/or how you installed it.

I'm using the ADXL345.h which comes form the example on the website of the Seeed Studio, https://github.com/Seeed-Studio/Accelerometer_ADXL345. I find a same-name one from the IDE library, they might be the same.

Above all, I'm using Python to save the data.

Your code from post # 1 sets these values

these values seem to be about timing.
1.25 ms sounds like 1.25 milliseconds.
Another reason might be the speed of I2C.
At what clock-frequency does the I2C-bus run?
I guess you don't know. You will have to look up the datasheet what the maximum-bus-frequency is

I was googling for ADXL345 andfound this product

It meantions SPI

The SPI-bus is much faster than I2C.
So this might be an option too.

You should post exactly that ADXL345 Sensor or ADXL345-board that you are using.

As you can see now:
The microcontroller-world is not superstandardised like USB-devices
You have to take care about more details than just
"does the plug fit into the socket?"

The datasheet has a table that shows different sampling rates


Which mentions a Rate Code.
So I guess you will have to adjust this Rate Code

best regards Stefan

My code demonstrates two details for you and us.

  • Your loop, with only minimal serial output, still executes at roughly 10ms +/-, per sample. So no amount of serial tuning will help. What I was trying to expose was whether your verbose serial output per per loop was in fact impacting your loop rate; inconclusive, but unlikely.
  • The verbose output, though, will cause grief sooner or later, as your output buffer isn't large, so you'll eventually end up with a full output buffer, at which point the code proceeds only as quickly as the buffer empties. You might not see an effect at 200 Hz, but this is going to get WORSE as you improve the loop speed. Beware.

My comment about libraries, points you to installable libraries in the IDE. You've identified, now, that Seeed is involved, so that's likely the library, though GOK which version you have vs which version is installed by the Library Manager.

Probably not, as there are many with the same or very similar name.

Use an ADXL library that is well documented, and start with the example code from that particular library.

Hello StefanL38, this is my sensor https://wiki.seeedstudio.com/Grove-3-Axis_Digital_Accelerometer-16g/, and it works with * Grove Base Shield V2.0 for Arduino https://www.seeedstudio.com/Base-Shield-V2.html.
I've found the same table about my apparatus. Do you know how to set the power mode and Rate Code in Arduino IDE? And because I use several sensors at the same time. So I'm also using the Multiplexer https://www.seeedstudio.com/Grove-8-Channel-I2C-Hub-TCA9548A-p-4398.html. Under this circumstance, how do I set the different power mode and Rate code?
I used the Rate Code 0b1101 so that the ODR should be 800Hz and changed the power mode to 0x2C, the output sampling rate is still around 200 Hz.

#include <Wire.h>
#include <ADXL345.h>
#define SENSOR_ADDRESS 0x53  // Replace with your sensor's I2C address

ADXL345 adxl; //variable adxl is an instance of the ADXL345 library

void setup(){
  Serial.begin(115200);
  
  adxl.powerOn();

  //set activity/ inactivity thresholds (0-255)
  adxl.setActivityThreshold(75); //62.5mg per increment
  adxl.setInactivityThreshold(75); //62.5mg per increment
  adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?
 
  //look of activity movement on this axes - 1 == on; 0 == off 
  adxl.setActivityX(1);
  adxl.setActivityY(1);
  adxl.setActivityZ(1);
 
  //look of inactivity movement on this axes - 1 == on; 0 == off
  adxl.setInactivityX(1);
  adxl.setInactivityY(1);
  adxl.setInactivityZ(1);
 
  //look of tap movement on this axes - 1 == on; 0 == off
  adxl.setTapDetectionOnX(0);
  adxl.setTapDetectionOnY(0);
  adxl.setTapDetectionOnZ(1);
 
  //set values for what is a tap, and what is a double tap (0-255)
  adxl.setTapThreshold(50); //62.5mg per increment
  adxl.setTapDuration(15); //625us per increment
  adxl.setDoubleTapLatency(80); //1.25ms per increment
  adxl.setDoubleTapWindow(200); //1.25ms per increment
 
  //set values for what is considered freefall (0-255)
  adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment
 
  //setting all interrupts to take place on int pin 1
  //I had issues with int pin 2, was unable to reset it
  adxl.setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_DOUBLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_FREE_FALL_BIT,    ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_ACTIVITY_BIT,     ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN );
 
  //register interrupt actions - 1 == on; 0 == off  
  adxl.setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_DOUBLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_FREE_FALL_BIT,  1);
  adxl.setInterrupt( ADXL345_INT_ACTIVITY_BIT,   1);
  adxl.setInterrupt( ADXL345_INT_INACTIVITY_BIT, 1);
  // Configure the sensor for an Output Data Rate of 800 Hz and enable all axes
  configureSensor();
}
void configureSensor() {
  // Set the Output Data Rate (ODR) to 800 Hz and enable all axes
  byte newDataRateConfig = 0b1101;  // Assuming 800 Hz, adjust based on your sensor's specifics
  byte newDataFormatConfig = 0b00000000;  // Assuming no special data format, adjust based on your needs

  // Write the updated configuration to the sensor
  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.write(0x2C);  // Address of the BW_RATE register
  Wire.write(newDataRateConfig);
  Wire.endTransmission(true);

  Wire.beginTransmission(SENSOR_ADDRESS);
  Wire.write(0x31);  // Address of the DATA_FORMAT register
  Wire.write(newDataFormatConfig);
  Wire.endTransmission(true);

  // Serial.println("Sensor configured for 800 Hz Output Data Rate and all axes enabled.");
}