Auto 0 calibrate an accelerometer

I am designing a ballistocardiogram (measures the ballistic forces of the heart) using a tri-axial accelerometer. The accelerometer rests on a person’s sternum and measures the low frequency vibrations of the sternum caused by the heart.

I’m having a tough time calibrating the accelerometer (setting the x, y, and z values to 0). The accelerometer is wired to an Arduino Uno and I attempted to set the x, y, and z axes to 0 by adding or subtracting small values but it seems every time I turn on the Arduino to start taking measurement it’s reading something different than before.

So my question is, does anyone know of a way I can auto 0 calibrate the accelerometer? My current idea is to write some code that takes the last 10 measurements, averages them, and adds/subtracts that value to make the accelerometer axes read 0, but I’m not that great at coding so I don’t know how to go about doing that.

My current code to read the accelerometer values using the Arduino is shown below. Note that it is an LIS3DH accelerometer chip which is soldered to a STEVAL-MKI105V1 LIS3DH adapter board for standard DIL 24 socket.

#include <Wire.h> //I2C Arduino Library

   #define address 0x19 //I2C 7bit address


   void setup(){ 
   //Initialize Serial and I2C communications
   Serial.begin(9600);
   Wire.begin();

   //Put into the correct operating mode
   Wire.beginTransmission(address); //open communication with
   Wire.write(0x20);  
   Wire.write(0x27);  
   Wire.endTransmission(); 
   }     

   void loop(){ 

   int x,y,z,a,b,c; //triple axis data 


   Wire.beginTransmission(address); 
   Wire.write(0xA8); 
   Wire.endTransmission(); 
   //Read data from each axis 
   Wire.requestFrom(address, 6); 
   if(6<=Wire.available()){ 
   x = (int)Wire.read();  
   x |= (int)Wire.read()<<8;  
   y = (int)Wire.read(); // Note change in operator on this and next three statements
   y |= (int)Wire.read()<<8;     
   z = (int)Wire.read(); 
   z |= (int)Wire.read()<<8;
   } 

   //Print out values of each axis 
   Serial.print(" "); 
   Serial.print(x); 
   Serial.print(" "); 
   Serial.print(y); 
   Serial.print(" "); 
   Serial.println(z); 

   delay(450);
   }

The accelerometer is reading the acceleration due to gravity in addition to the accelerations relative to a fixed position. Perhaps if you keep a running average of a few seconds you can use that as a baseline from which to evaluate motion due to the heartbeat.

The accelerometer is reading the acceleration due to gravity in addition to the accelerations relative to a fixed position. Perhaps if you keep a running average of a few seconds you can use that as a baseline from which to evaluate motion due to the heartbeat.

I appreciate the quick reply John. Are you familiar with Arduino code? I’m a bit new to it, and I’m not sure how I would go about receiving the last few measurements of data. Would it be possible to set up some sort of ‘if’ statement, for the z-axis I could have something like:

i = 0
if i < 10
(Serial.print(z(i)) + Serial.print(z(i-1))/2

But again, I’m horrible at coding, I’m positive what I posted above wouldn’t work. Do you know how exactly I could alter what I have above to work on the Arduino?

The reading depends on the orientation of the accelerometer, which presuably is different every time.

You clearly don't care about the DC signals, so high-pass filter your accelerometer data and all will be well - there is no "calibration" needed.

https://en.wikipedia.org/wiki/High-pass_filter#Algorithmic_implementation

MarkT: The reading depends on the orientation of the accelerometer, which presuably is different every time.

You clearly don't care about the DC signals, so high-pass filter your accelerometer data and all will be well - there is no "calibration" needed.

https://en.wikipedia.org/wiki/High-pass_filter#Algorithmic_implementation

I'll give that a try, thanks for taking the time to reply.