Hello! I want to do tilt sensing using a single 3 axis accelerometer. I want to develop a similar algorithm like in smart phones for tilt sensing to change the orientation of the screen. I have developed a few algorithms which do not work as well, so was wondering if anyone has done this sort of a thing. Thanks

The accelerometer is sensing the pull of gravity. If the accelerometer is flat the X and Y accelerations are 0 and the Z acceleration is -1g. As the accelerometer tilts the Z acceleration gets closer to 0 and the X and/or Y accelerations go up or down. Using some trig you can determine the pitch and roll angles.

First thing to do is to calibrate the accelerometer so you can subtract the zero offset and calculate acceleration in g.

johnwasser: The accelerometer is sensing the pull of gravity. If the accelerometer is flat the X and Y accelerations are 0 and the Z acceleration is -1g. As the accelerometer tilts the Z acceleration gets closer to 0 and the X and/or Y accelerations go up or down. Using some trig you can determine the pitch and roll angles.

First thing to do is to calibrate the accelerometer so you can subtract the zero offset and calculate acceleration in g.

Right, I have done that. I have used the atan2 function to get the pitch and roll. The problem is that when I get the pitch, i get strange values for roll, and when I get roll I get strange values for pitch. *xrot = atan2(-yforce,-zforce)*57.2957795+180; *yrot = atan2(-xforce,-zforce)*57.2957795+180; *zrot = atan2(-yforce,-xforce)*57.2957795+180; This is what I use, 180/PI = 57.2957795 xrot is the rotation about x axis. I want to understand how is it done in smartphones?

You really need to post code and a definition of what "strange" means.

Well, by strange I mean that I am unable to get 2 rotations together at the same time. The third rotation, which is in the direction of g will never be obtainable, I understand that. However the other 2 roatations should be obtainable. Here is how it happens. I hold the accelerometer on my palm facing up. The x axis is aligned along the fingers and y axis is perpendicular to it If i rotate about the x axis, I get a proper 0-360 degree value, but while this is happening I do not get any change in y, and then i suddenly jump by 90 degrees in y. while i do the rotation about y axis, i get a similar thing going along the x axis, but the jump is of 180 degrees. and the code is just what i posted above, xforce - it is just the value of the force vector along x, force being gravity. I have already done the calibration, subtracted the zero g values etc. I was just curious if someone has tried it here the way smart phones have used the accelerometer. I might be able to figure out a way... Thanks

When you tilt the X axis up past 90 degrees, the Z axis goes through zero and then starts going positive. Since yrot is based on the X and Z measurements, when Z goes from negative to positive you get a different answer, even though Y is staying near zero.

To get pitch and roll, try:

```
pitch=atan2(ax,sqrt((ay*ay)+(az*az)))
roll=atan2(ay,sqrt((ax*ax)+(az*az)))
```

Note that the result is in Radians so if you want degrees you still have to convert. You shouldn't get a problem with both arguments to atan2() being zero unless your accelerometer is in free-fall. :)

johnwasser: When you tilt the X axis up past 90 degrees, the Z axis goes through zero and then starts going positive. Since yrot is based on the X and Z measurements, when Z goes from negative to positive you get a different answer, even though Y is staying near zero.

To get pitch and roll, try:

`pitch=atan2(ax,sqrt((ay*ay)+(az*az))) roll=atan2(ay,sqrt((ax*ax)+(az*az)))`

Note that the result is in Radians so if you want degrees you still have to convert. You shouldn't get a problem with both arguments to atan2() being zero unless your accelerometer is in free-fall. :)

Great, thank you. I think I understand the point, in case of pitch,you need to take the projection of the y and z vectors in the y-z plane so that you get the angle b/w the x vector and this projected vector. I have not been able to try this, I am out of town for now. I just would like to ask for 1 last favour, can you please explain how atan2 works. I have the basic understanding, but as you saw that wasn't good enough. I have never found a good answer to this question. This would be a great help to a lot of people starting out in robotics, I've noticed even the pros do not have a clear understanding of the concept. I wish to share that understanding in my small local robotics group. Thanks a lot

atan2() just saves you the trouble of dividing the Opposite side by the Adjacent side. It also preserves quadrant information that would be lost in the division.

Tangent = Opposite over Adjacent

johnwasser: When you tilt the X axis up past 90 degrees, the Z axis goes through zero and then starts going positive. Since yrot is based on the X and Z measurements, when Z goes from negative to positive you get a different answer, even though Y is staying near zero.

To get pitch and roll, try:

`pitch=atan2(ax,sqrt((ay*ay)+(az*az))) roll=atan2(ay,sqrt((ax*ax)+(az*az)))`

Note that the result is in Radians so if you want degrees you still have to convert. You shouldn't get a problem with both arguments to atan2() being zero unless your accelerometer is in free-fall. :)

Hi john. Can you please explain the logic of the above code. Lets say for instance roll, here we will get the angle between which quantities? I tried this, it does not give me right results. Roll goes from 0-45 when it should go upto 90, and then it should continue and go to 180 but it goes back to 0 from 45.

sqrt((x*x)+(y*y)) calculates the length of the hypotenuse of a right triangle with sides X and Y (Pythagorean Theorem)

Unfortunately it gives the absolute magnitude and destroys information about quadrant. I guess you need the sign information for the various forces to determine pitch and roll correctly.

johnwasser: sqrt((x*x)+(y*y)) calculates the length of the hypotenuse of a right triangle with sides X and Y (Pythagorean Theorem)

Unfortunately it gives the absolute magnitude and destroys information about quadrant. I guess you need the sign information for the various forces to determine pitch and roll correctly.

Yes John. I am gonna try and use the signs, but even the magnitude does not make sense because we get 45 degrees instead of 90. I figured out the problem with my earlier code, the first one 1 posted. What happens there is this For xrot(roll) i use the y-z plane to get the angle, and for yrot(pitch) i use the x-z plane to get the angle. This is perfectly fine if i just want to calculate either the roll alone or the pitch alone. I hold the device on my palm with my palm facing upwards, such that z points upwards and the x along my fingers. Now if i do roll then I am right in measuring the angle in the y-z plane. And if I do pitch, then I am right in measuring the angle in the x-z plane. Which works fine for both. But now if i do a roll by +90 degrees, (counterclockwise), then and now if I want to do a pitch, then the pitching plane has changed, it has now become x-y plane instead of the x-z plane. So i cannot get pitch and roll simultaneously.

I am stuck!!

Here's a link that might give you some insight into how it's done in smart phones: http://www.freescale.com/files/sensors/doc/app_note/AN3461.pdf.

It appears to be a bit more complex than what's been described so far, but maybe not a whole lot more complex. In particular, for any particular orientation of the accelerometer, there are two different values of pitch and roll that could describe the device's orientation, depending on whether you treat it as pitch followed by roll, or as roll followed by pitch. You'll find some general formulas. You'll also find a discussion of how a phone selects between portrait and landscape modes, which seems to be what you wanted in the first place. It looks to be a lot simpler than determining precise values for pitch and roll.