Ignore what stevenvh says in his first paragraph. It's the wrong way to solve the problem. He is measuring cos(angle), which he rightly says is basically useless.
stevenvh has now fixed his first paragraph.
To measure inclination with an accelerometer, you must measure the horizontal acceleration, so that a positive inclination gives a positive acceleration reading, and a negative inclination gives a negative acceleration reading. Now your reading is proportional to sin(angle).
Taking this ADXL device as an example. When it's lying flat on the table, the Z axis reads 1g, while X and Y both read 0g. If you rotate it 0.5º about the Y axis, then the Z axis reading will hardly change, but the X axis reading will change noticeably.
Assume we have an accelerometer with sensitivity of ±1g, with a 12-bit output, giving a range of -2048..2047.
At 0º then, we measure 0g, and get an ADC output of 0. At 0.5º we measure sin(0.5)g = 0.0087g. Which will give us an ADC output of 0.0087*2047 = 17.
Therefore, you should be able to measure the first 0.5º from level with a ±1g accelerometer and a 12-bit ADC, as long as you calibrate it properly.
The problem is that your accuracy drops as you rotate away from level. This is where a second accelerometer comes in. To deal with a full 360º rotation, you must use two orthogonal accelerometers. (E.G. a 2-axis device).
Use the signal from each one to calculate the angle, then take the weighted average of those angles, each weighted by the amplitude of the signal of the other one.
float Angle_radians(float x, float y) const
{
float angle;
if (fabs(x)>fabs(y))
{
angle = atan(y/x);
if (x<0.0f) angle += PI;
}
else
{
angle = PI*0.5f - (float)atan(x/y);
if (y<0.0f) angle += PI;
}
if (angle < 0.0f) angle += PI*2;
if (angle > PI*2) angle -= PI*2;
return angle;
}
float x_acc = ADC_read(x_axis_channel) // read x axis (horizontal)
float y_acc = ADC_read(y_axis_channel) // read y axis (vertical)
x_acc *= 1.0 / 2047; // scale to range -1 .. +1
y_acc *= 1.0 / 2047;
angle = angle_radians(x_acc, y_acc);
Added: As markrages mentioned, there's usually also a function called atan2(), which does exactly this:
angle = atan2(x_acc, y_acc);
Added: Answering The Newbie's questions.
So, basically by using a dual/triple axis accelerometer there are better chances of getting the correct accuracy with averaging and filtering?
No, I'm saying that to get an accurate reading across the whole 360º range, you have to use two axes. One axis will go from maximum accuracy at 0º to zero accuracy at 90º. The other axis will do the opposite.
Could you please show me one example of an accuracy calculation for the datasheet attached?
Your part is the MMA8451Q, which contains a 14-bit ADC, is available in a 2g version, giving 4096 counts/g. This is twice the resolution of my example above. However, accuracy is not all about resolution. You also need to take into account the Zero-g offset.
When your device is flat on the table, one axis should read exactly zero, but it won't. There will be a slight offset. According to the datasheet, this can be as much as ±30mg. This is equivalent to an angle error of 1.7º! You will need to account for this offset error. You do this by calibration.
Take a thickish plate of glass or polished granite, and place a large ball bearing on it. Adjust the angle of the glass until the bearing doesn't roll any more. This is pretty level now.
Place your device flat on the glass, and take note of the reading from the horizontal sensors. They will give readings close to zero. You can now load these readings into the device, and it will subtract them from its own readings.
One last question is noise. The sensor readings won't be perfectly stable. With the device stationary, the readings will probably fluctuate very slightly. You can reduce the noise by taking multiple sensor readings (16 maybe), and averaging them. Of course, this reduces the your real sensor update rate.
See Guy NXT door for a good article about accelerometer calibration and sensor noise.
Best Answer
From a control system perspective it really does not matter where you place your sensors. The most important thing is that you know where they actually are!!! I mean this with regards to knowing where the sensor is relative to the centre of the rotary wings. As long as you know the offsets you can apply translations to calculate what your vehicle is doing.
From an electrical and performance perspective away from motor wiring and h bridges, away from vibrations sources and suitably mounted and damped. The dampening is important for the accelerometers to ensure that they do hit mechanical rails from high frequency vibration (do the math to work out the maximum displacement your accelerometer can with stand at various frequencies and you will understand this point). Similar for, but not as important for the gyros.