Hello,
I am trying to measure vibrations on a machine using a Nano + an ADXL345 accelerometer. I will be sending the data to a Raspberry Pi where I will be doing a FFT.
The thing is that I am still having issues programming the Nano to achieve a constant sampling rate. No matter what I have tried, my code is printing a few values (~10-20) under/above the wanted sampling rate (e.g. 600 Hz). Is there something I am missing or that I could improve to reach a constant sampling rate?
#include<Wire.h> // Wire library, used for I2C communication
/*------------CONSTANTS---------------------------*/
const int SENSITIVITY_DIVISOR_2G = 256;
const int SENSITIVITY_DIVISOR_4G = 128;
const int SENSITIVITY_DIVISOR_8G = 64;
const int SENSITIVITY_DIVISOR_16G = 32;
const int DATARATE_25_HZ = 8;
const int DATARATE_50_HZ = 9;
const int DATARATE_100_HZ = 10;
const int DATARATE_200_HZ = 11;
const int DATARATE_400_HZ = 12;
const int DATARATE_800_HZ = 13;
const int ADXL345 = 0x53; // I2C address of the ADXL345
/*------------CONSTANTS---------------------------*/
/*------------PROGRAM VARIABLES-------------------*/
float AccX, AccY, AccZ; // outputs
float gravity = 9.81;
unsigned long previousMicros = 0L;
/*------------PROGRAM VARIABLES-------------------*/
/*------------SETTINGS----------------------------*/
uint8_t sensitivityRange= 2; //Must be equal to 2,4,8 or 16
int sensitivityDivisor = SENSITIVITY_DIVISOR_2G; // change this to change sensitivity_divisor
int dataRate = DATARATE_800_HZ; //
int arduinoSamplingRate = 600; // MUST BE LESSER THAN dataRate (in Hz)
/*------------SETTINGS----------------------------*/
float samplingIntervalfloat= (1000000/arduinoSamplingRate); //float variable for intermediate calculation
int samplingInterval = (int)samplingIntervalfloat;
void setup() {
Serial.begin(250000); // Initiate serial communication for printing the results on the Serial monitor
Serial.println(samplingInterval);
delay(2000);
Wire.begin(); // Initialize communication
Wire.setClock(400000L); // Set Clock Speed
// Set ADXL345 in measuring mode
Wire.beginTransmission(ADXL345); // Start communication with the ADXL345
Wire.write(0x2D); // Talk to the register 0x2D (POWER_CTL register)
Wire.write(8); // (8dec -> 0000 1000 binary) Bit D3 High for measuring enable
Wire.endTransmission();
// Set ADXL345 data rate
Wire.beginTransmission(ADXL345); // Start communication with the ADXL345
Wire.write(0x2C); // Talk to the register 0x2C (BW_RATE register)
Wire.write(dataRate); // (13 -> 800 Hz, 12 -> 400 Hz, 11 -> 200 Hz, 10 -> 100 Hz)
Wire.endTransmission();
//Set ADXL345 Sensitivity Range
setRangeSetting(sensitivityRange);
}
void loop() {
unsigned long currentMicros = micros();
if (currentMicros - previousMicros >= samplingInterval) {
// save the last time you blinked the LED
previousMicros = currentMicros;
// === Read accelerometer data === //
Wire.beginTransmission(ADXL345);
Wire.write(0x32); // Start with register 0x32 (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(ADXL345, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
AccX = ( Wire.read()| Wire.read() << 8); // X-axis value
AccX = (AccX / sensitivityDivisor) * gravity; //For a range of +-2g, we need to divide the raw values by 256, according to the datasheet
AccY = ( Wire.read()| Wire.read() << 8); // Y-axis value
AccY = (AccY / sensitivityDivisor) * gravity;
AccZ = ( Wire.read()| Wire.read() << 8); // Z-axis value
AccZ = (AccZ / sensitivityDivisor) * gravity;
Serial.print(AccX);
Serial.print(", ");
Serial.print(AccY);
Serial.print(", ");
Serial.println(AccZ);
} //if
}
/* ---------------------------------HELPER FUNCTIONS---------------------------------------*/
void setRangeSetting(int val) {
byte _s;
byte _b;
switch (val) {
case 2:
_s = B00000000;
break;
case 4:
_s = B00000001;
break;
case 8:
_s = B00000010;
break;
case 16:
_s = B00000011;
break;
default:
_s = B00000000;
}
readFromI2C(0x31, 1, &_b);
_s |= (_b & B11101100);
Wire.beginTransmission(ADXL345);
Wire.write(0x31);
Wire.write(_s);
Wire.endTransmission();
}
void readFromI2C(byte address, int num, byte _buff[]) {
Wire.beginTransmission(ADXL345);
Wire.write(address);
Wire.endTransmission();
// Wire.beginTransmission(ADXL345_DEVICE);
// Wire.reqeustFrom contains the beginTransmission and endTransmission in it.
Wire.requestFrom(ADXL345, num); // Request 6 Bytes
int i = 0;
while(Wire.available())
{
_buff[i] = Wire.read(); // Receive Byte
i++;
}
if(i != num){
Serial.println("Error");
}
}
/* ---------------------------------HELPER FUNCTIONS---------------------------------------*/