In the last page we’ve seen a way to read analog outputs from the accelerometer calling analogRead in the main loop function. The sampling rate was around 20Hz, which is not the speed you expect from this kind of sensor. A few specifications are reported in Figure 1. From the ‘Bandwidth response’ lines, we see that specified frequency, -3dB, is 350Hz for the x and y axis and 150 for the Z axis. This means that if our x-axis sampling rate is greater than 350Hz, the value measured won’t be accurate and you are actually acquiring a 30% attenuated amplitude.


Specification mma7260q

Figure 1

As our first attempt, let’s try to minimize the time interval between successive readings and track the sampling rate.

If we call the analogRead function in a for loop and store the readings in an array of floats, this operation will be faster than the previous one. This approach could be useful for data acquisition purposes in which you just need to store a finite number of samples and send them via serial. If you want to plot the results, you can create a second array to store time value. Try the following sketch

Warning

Memory is a finite resource on these boards. The microcontrollers used on Arduino boards have a small amount of RAM. Running out of RAM due to the complexity of the sketch or a memory leak may be the cause of bugs.
const float RESOLUTION=800;
const float VOLTAGE=3.3;

const float ZOUT_1G = 850;

const int N  = 50;   

// Connect the X,Y and Z pin to A0,A1 and A2 respectively
const int xaxis = 0;
const int yaxis = 1;
const int zaxis = 2;

float zeroX,zeroY,zeroZ;
int x,y,z;
float aax,aay,aaz;

// Array to store data
int lenBuff = 100;
float values
[100]; double time[100]; int contSamples = 0; // Serial byte received byte mode; // Acc Timers unsigned long accTimer; unsigned long lastAccTimer; unsigned long startRead; unsigned long stopRead; int rate; float zeroPoint(int axis) { float acc = 0; for (int j=0;j<N;j++) { acc = acc + (((float) analogRead(axis)*5000)/1023.0); delay(20); } return acc/N; } void setup() { Serial.begin(9600); // 9600 bps pinMode(xaxis,INPUT); pinMode(yaxis,INPUT); pinMode(zaxis,INPUT); zeroX = zeroPoint(xaxis); zeroY = zeroPoint(yaxis); zeroZ = zeroPoint(zaxis); zeroZ = zeroZ - ZOUT_1G; Serial.println("Ready"); } void loop() { serialRoutine(); } void serialRoutine() { if (Serial.available()>1) { mode = Serial.read(); if (mode == 83) { startRead = micros(); Serial.println("Acquiring 1000 samples."); for (int i=0; i <= lenBuff ; i++) { lastAccTimer = micros(); x=analogRead(xaxis); aax = (((x*5000.0)/1023.0)-zeroX)/RESOLUTION; values[i] = aax; accTimer = micros() - lastAccTimer; time[i] = accTimer; } stopRead = micros() - startRead; Serial.println("Printing acceleration values"); for (int i=0;i<=lenBuff;i++) { Serial.println(values[i]); Serial.print("@"); Serial.println(time[i]); } int avgRate = stopRead/lenBuff; Serial.print("Avg Sampling Rate: "); Serial.print(avgRate); Serial.println(" us"); Serial.print("Total acquisition time "); Serial.print(stopRead); Serial.println(" us"); contSamples = 0; } } }


In this code, the approach has changed. Now, we do not call the analogRead and Serial.print in the same main loop. AnalogRead has been placed in a for loop to isolate the acquisition. The operation has not been slowed down by the serial routine.
The programs runs only the serialRoutine function in each loop, it just waits for the serial input to be ‘S’ (value 83 according to the ASCII table).
Open the serial monitor, wait for the message Ready to be displayed and press ‘S’ to start the acquisition.

Ready
  Press 'S'
Acquiring 1000 samples.
Printing acceleration values
200.00 @ 200.00
0.01 @ 200.00
0.00 @ 200.00
-0.00 @ 212.00
-0.01 @ 200.00
-0.00 @ 204.00
[...]
0.00 @ 200.00
Avg Sampling Rate: 214 us
Total acquisition time 21408 us

As we can see the time interval between readings is now around 214 micros sec. Not bad.
We have obtained 5000 acceleration values every second on the x and y axis. I’m sure we get increase this rate. Check the next page to see how.