# Calibrating an accelerometer

I would like to calibrate an accelerometer so that I can get the output in meters per second. The math works when I stick my own numbers in there, but when I tell it to calibrate, it gets stuck in a loop. This is the piece of code that gets stuck in a loop:

``````void Calibrate(){
Calibrating = true;

while(Calibrating){                         //Flash LED while Calibrating
previousMillis = millis();
digitalWrite(CalLED, HIGH);
}
else{
digitalWrite(CalLED, LOW);
}
}
}

for(Level = false; Level == true;){
if(yAverage == xAverage){
Level = true;
}
kAccel = (zAverage - yAverage);
zeroAccel = yAverage;
}
delay(500);
timeSeconds = 0;
Calibrating = false;
}
``````

The bottom half after the led flash is supposed to check of it’s level, and if it is, take those values to calculate the acceleration. It seems to be getting stuck in that for loop, even though there are plenty of occasions where x and y are equal. It is possible for x and y to be equal if it’s tilted 45 degrees between x and y, so if there’s a better way to calibrate it I’d like to see it. Also it seems that the z axis has a different zero point than the x and y axis, but that’s another issue. The main point is that I want to fix this for loop.

Here’s the full code:

``````/*
* Pins used:
*    Analog: 0, 1, 2
*    Digital: 0, 1, 5, 6, 7, 8, 10, 11, 12, 13
* Pins available:
*    Analog: 3, 4, 5, 6, 7
*    Digital: 2, 3, 4, 9
*/

#include <SD.h>                               //SD card library
#include <SPI.h>

boolean Calibrating = false;                  //Check if it's calibrating
boolean Level;                                //Chech if it's level

const int xAxis = A0;                         //Define axis inputs
const int yAxis = A1;
const int zAxis = A2;
const int CS_pin = 10;                              //Chip select for SD module
const int reCal = 9;                          //Button pin to recalibrate
const int CalLED = 8;                         //Pin to indicate calibratrion
const int samples = 100;                      //Define sampe size
const float G = 9.81;

long xTotal;                                  //Store total values
long yTotal;
long zTotal;
int xAverage;                                 //Store average values
int yAverage;
int zAverage;
int zeroAccel = 492;                          //Zero acceleration default
float xAccel;                                 //Acceleration
float yAccel;
float zAccel;
float kAccel = 118;                           //Constant for calculating acceleration default

String dataString;                            //String to be stored on the SD card
String values;                                //Data string for serial output
unsigned long dataID = 1;                     //DataID to keep track of the data
unsigned long previousMillis = 0;             //Timer mark
float timeSeconds;                            //Time elapsed since calibration
float fractional = 1000;                      //Divide milliseconds to seconds

//******************************************************************************************************//
//******************************************************************************************************//

void setup() {
SD.begin();                                 //Initialize SD library
Serial.begin(9600);                         //Initialize serial monitor
Serial.println("Initializing");

//******************************************************************************************************//

pinMode(xAxis, INPUT);                      //Set inputs
pinMode(yAxis, INPUT);
pinMode(zAxis, INPUT);
pinMode(reCal, INPUT);                      //Recalibrate button
pinMode(CalLED, OUTPUT);                    //Indicates Calibrating
digitalWrite(CalLED, LOW);                  //Not calibrating
analogReference(EXTERNAL);                  //3.3v ref for accelerometer output

//******************************************************************************************************//

for(int i = 0; i < samples; i++){           //Allow input to stablalize
}

//******************************************************************************************************//

if(!SD.begin(CS_pin)) {                     //SD card stuff
Serial.println("Card Error");
return;                                 //Comment out to test without the SD card
}

File Data = SD.open("Data.csv", FILE_WRITE);
if(Data) {
Data.println(", , , , , , , , , , , , ");
String header = "Data ID, Seconds, X Axis, Y Axis, Z Axis";
Data.close();
}
else {
Serial.println("Couln't Open Data File");
return;
}
Serial.println("Calibrating Axis");         //Initial Calibration
Calibrate();

}

//******************************************************************************************************//
//******************************************************************************************************//

void loop() {

Calibrate();
Serial.println("Calibrating Axis");
}

//******************************************************************************************************//

timeSeconds = millis()/fractional;

//******************************************************************************************************//
//Organize averages into a string, save, and println
values = String(dataID) + ", " + String(timeSeconds) + ", " + String(xAverage) + ", " + String(yAverage) + ", " + String(zAverage) + ", " + String(xAccel) + ", " + String(yAccel) + ", " + String(zAccel);
Serial.println(values);
dataString = String(dataID)+ String(timeSeconds) + ", " + String(xAccel) + ", " + String(yAccel) + ", " + String(zAccel);
File Data = SD.open("Data.csv", FILE_WRITE);
Data.println(dataString);
Data.close();
dataID++;
}

//******************************************************************************************************//
//******************************************************************************************************//

void Calibrate(){
Calibrating = true;

while(Calibrating){                         //Flash LED while Calibrating
previousMillis = millis();
digitalWrite(CalLED, HIGH);
}
else{
digitalWrite(CalLED, LOW);
}
}
}

for(Level = false; Level == true;){
if(yAverage == xAverage){
Level = true;
}
kAccel = (zAverage - yAverage);
zeroAccel = yAverage;
}
delay(500);
timeSeconds = 0;
Calibrating = false;
}

//******************************************************************************************************//
//******************************************************************************************************//

for(int i = 0; i < samples; i++){           //Loop 10x
}

xAverage = xTotal / samples;                //Calculate averages
yAverage = yTotal / samples;
zAverage = zTotal / samples;

xTotal = 0;                                 //Reset totals
yTotal = 0;
zTotal = 0;

xAccel = G * (xAverage - zeroAccel)/kAccel;
yAccel = G * (yAverage - zeroAccel)/kAccel;
zAccel = G * (zAverage - zeroAccel)/kAccel;
}
``````

Found the issue! It was focused on the blinking and not moving on to the actual calibration. I also changed the “for(Level = false; Level == true;)” to a “while(Level == false)”
To make it blink at the same time i merged the while loops:

``````void Calibrate(){
digitalWrite(CalLED, HIGH);
Calibrating = true;
Serial.println("Calibrating");

while(Level == false){
previousMillis = millis();
digitalWrite(CalLED, HIGH);
}
else{
digitalWrite(CalLED, LOW);
}
}
if(yAverage == xAverage){
Level = true;
}