ADXL335 with Arduino Fio

Hello,

I am working with the ADXL 335 accelerometer from Sparkfun and trying to output a tilt measurement using the Arduino Fio. I have tried a variety of different codes, and have verified the sensitivity (0.3) with the datasheet. However, the angle measurements are still incorrect. When I tilt and rotate the accelerometer, the angle measurements are changing, but they never go completely to zero. They are only showing relatively small changes in angle despite drastic tilting on my part. I have an accurate ADC conversion, so I know that is not the problem. Is there any way I can verify my offset value? Or is something else wrong in my code? My code is given below. Does anyone already have a successful code I can use for reference? Any input would be greatly appreciated!

Here is my code:

// A0: self test, A1: z-axis, A2: y-axis, A3: x-axis, A4: ground, A5: vcc
const int groundpin = 18; // analog input pin 4 -- ground
const int powerpin = 19; // analog input pin 5 -- voltage
const int xpin = A3; // x-axis of the accelerometer
const int ypin = A2; // y-axis
const int zpin = A1; // z-axis (only on 3-axis models)
const float pi = 3.14;

//const int Voffset = 1.65;
const float Sensitivity = 0.3;

void setup()
{
Serial.begin(57600);
//Serial.print(127);

pinMode(groundpin, OUTPUT); // Provide ground and power by using the analog inputs as normal
pinMode(powerpin, OUTPUT); // digital pins. This makes it possible to directly connect the
digitalWrite(groundpin, LOW); // breakout board to the Arduino. If you use the normal 5V and
digitalWrite(powerpin, HIGH); // GND pins on the Arduino, you can remove these lines
}

void loop()
{
float Vout_x = analogRead(xpin); // x axis /do we need the step value here?/
float Vout_y = analogRead(ypin); // y axis
float Vout_z = analogRead(zpin); // z axis

float Vm_x = Vout_x * .003223; // Vmeasured for x axis
float Vm_y = Vout_y * .003223; // Vmeasured for y axis
float Vm_z = Vout_z * .003223; // Vmeasured for z axis

float x= Vm_x - 1.64;
float y= Vm_y - 1.62;
float z= Vm_z - 1.98;

Serial.print("X-axis ");
Serial.print(analogRead(xpin), DEC); // print the sensor values
Serial.print("\t");
Serial.print("Y-axis ");
Serial.print(analogRead(ypin), DEC);
Serial.print("\t");
Serial.print("Z-axis ");
Serial.println(analogRead(zpin), DEC);

//delay(500); // delay before next reading

float R_x = (x/(Sensitivity)); //radians
float R_y = (y/(Sensitivity));
float R_z = (z/(Sensitivity));

Serial.print("x = ");
Serial.println(x, DEC);
Serial.print("y = ");
Serial.println(y, DEC);
Serial.print("z = ");
Serial.println(z, DEC);

float Angle_x = acos(R_x);
float Angle_y = acos(R_y);
float Angle_z = acos(R_z);

float degree_x = (180/pi)*Angle_x;
float degree_y = (180/pi)*Angle_y;
float degree_z = (180/pi)*Angle_z;

Serial.print("Angle_x = "); //Angle x in degrees
Serial.println(degree_x, DEC);
Serial.print("Angle_y = "); //Angle y in degrees
Serial.println(degree_y, DEC);
Serial.print("Angle_z = "); //Angle z in degrees
Serial.println(degree_z, DEC);

delay(500);
}

Why don't you look at the data sheet? It tells you what range the offset voltages may lie in and what the sensitivity is.

The values 1.64, 1.62 and 1.98 in the code look to me as if they were chosen for a particular instance of that sensor.

That's a nominal 3 volt device, with limits defined in the datasheet of 1.8 to 3.6 volts. You shouldn't be powering it with 5 volts.

I am working with the ADXL 335 accelerometer

Perhaps some research into what an accelerometer measures, and what it does not measure, is in your future, too.

An accelerometer measure instantaneous acceleration (rate of change of velocity). You seem to expect to be able to use a measure of "rate of change of velocity" to directly give you angular position. That won't happen.

The reason that what he is trying to do is possible is that gravity and acceleration are indistinguishable (General Relativity). So a 3-axis accelerometer will also sense the component of gravitational field along each axis. Hence it can be used to measure tilt.

Hence it can be used to measure tilt.

Only if turned very, very slowly. Any jerkiness, and the value no longer corresponds to angle. Turning by hand, it is not possible to turn it smoothly enough to measure angle alone.

Don't smartphones and games console controllers (and other stuff) use mems accelerometers to do motion sensing? They seem quite responsive.

Don't smartphones and games console controllers (and other stuff) use mems accelerometers to do motion sensing? They seem quite responsive.

Yes, but responsive and accurate (as in your phone is rotated 32 degrees about the X axis, 27 degrees about the Y axis, and 8 degrees about the Z axis) are not the same thing. The actual position of the accelerometer requires an understanding of the history of acceleration that the device went through, over time, to get where it is now. That history is not maintained by the accelerometer. The microcontroller is expected to maintain and use that data to determine the current position (angular or spatial) of the device (phone with accelerometer or Arduino with accelerometer).

PaulS:
The actual position of the accelerometer requires an understanding of the history of acceleration that the device went through, over time, to get where it is now. That history is not maintained by the accelerometer.

You can determine the tilt in 2 axes without knowing the history, all you need is a calibrated starting position with gravity in a known direction relative to the sensor. That's how spirit level apps on iPhone and Android work.