# Compute yaw from magnetometer and accelerometer

I use an Arduino and a 9 DOF sensor (gyroscope, accelerometer and magnetometer) and I'm trying to use the pitch, roll and yaw that the sensor gives me to rotate an object in unity.

I managed to correctly compute pitch and roll (the z and x axis in unity) from the accelerometer but it seems that I can't get the Yaw right. By that I mean that when I rotate my sensor pitch or roll it rotates my yaw too, in a weird way.

Code in the arduino to get the heading

``````void getHeading(void)
{
}

{
//float pitch = asin(-Axyz);
//float roll = asin(Axyz/cos(pitch));
float pitch = atan( Axyz / sqrt( Axyz * Axyz + Axyz * Axyz ) );
float roll = atan( Axyz / sqrt(Axyz * Axyz + Axyz * Axyz));

float xh = Mxyz * cos(pitch) + Mxyz * sin(pitch);
float yh = Mxyz * sin(roll) * sin(pitch) + Mxyz * cos(roll) - Mxyz * sin(roll) * cos(pitch);
float zh = -Mxyz * cos(roll) * sin(pitch) + Mxyz * sin(roll) + Mxyz * cos(roll) * cos(pitch);
tiltheading = 180 * atan2(yh, xh)/PI;
}
``````

Pitch and roll

``````    float _Pitch  = (float)(180 / Math.PI * Math.Atan( m_ResultX / Math.Sqrt( m_ResultY * m_ResultY + m_ResultZ * m_ResultZ ) ) );
float _Roll = (float)(180 / Math.PI * Math.Atan(m_ResultY / Math.Sqrt(m_ResultX * m_ResultX + m_ResultZ * m_ResultZ)));
``````

Don't hesitate to ask for details.

• did u figure out why your yaw changes if you pitch/roll the sensor? and how was it addressed? any information would help me too.
– ems
Oct 29 '18 at 20:43

I don't know how all your sensor's axis are lined up, but it looks like you should level the magnetometer readings by rotating them by `-pitch` and `-roll` to get back to the global reference frame, instead of rotating the magnetometer readings by the positive angles.
However, The pitch and roll angles in the code are both relative the horizon, not a set of euler angles that define a rotation between two states; because of this, they do not compose to rotate the magnetometer back into the global xy frame like I assume the equations are trying to do. The code is also only using `atan` for pitch and roll instead of `atan2`, so their range is only 180 degrees.