Constraining a value to work in radians (-Pi to Pi)

I have a gyroscope sensor that works in deg/s, I then integrate that value to get degrees. This works great, but I want the values to be constrained to -180 and 180 degrees (-Pi to Pi). When the value goes over 180 degrees, I want it to reset to -180 degrees, and when the value goes lower than -180 degrees, I want it to go back to 180.

Here is some sample code of what is happening right now.

axis_1 += gyro_data*gyro_time; //axis_1 is in degrees //gyro_data is in degrees per second

I thought about using an if statement:

if (axis_1 > 180) axis_1 = -180
if (axis_1 < -180) axis_1 = 180

But that would lose some of the information from the addition. If axis_1 = 179.8, and it adds 0.8, then axis_1 should be -179.6, not -180.

I also want the Arudino to calculate the error between the setpoint and the current state.

If axis_1 is at 10 degrees, and the setpoint is at 15. Then 15-10 = 5 degrees of error. But if axis_1 is at 175 degrees, and the setpoint is at 5 degrees. Then the error is 5-175 = -170, which is not true. It should be 10 degrees of error.

Any thoughts on how I would tackle this?

So you want the value to be whatever the number is greater than 180 degrees, so if the value is 184, you want it to be 4 (or 184-180 to state it mathematically). so just do that.

if (axis_1 > 180) axis_1 = axis_1 - 180

If your value can go past 360, then you basically want to keep subtracting 180 until it is in range, or:

while (axis_1 > 180) axis_1 = axis_1 - 180

You can also use shorthand notation by using the -= expression:

while (axis_1 > 180) axis_1 -= 180

and now do the same for the other side:

while (axis_1 > 180) axis_1 -= 180
while (axis_1 < -180) axis_1 += 180

You can also use the mod operator to prevent having to loop, but that only works for integers.
e.g. 184 % 180 = 4 and 364 % 180 = 4

TRex:
So you want the value to be whatever the number is greater than 180 degrees, so if the value is 184, you want it to be 4 (or 184-180 to state it mathematically). so just do that.

if (axis_1 > 180) axis_1 = axis_1 - 180

If your value can go past 360, then you basically want to keep subtracting 180 until it is in range, or:

while (axis_1 > 180) axis_1 = axis_1 - 180

You can also use shorthand notation by using the -= expression:

while (axis_1 > 180) axis_1 -= 180

and now do the same for the other side:

while (axis_1 > 180) axis_1 -= 180

while (axis_1 < -180) axis_1 += 180




You can also use the mod operator to prevent having to loop, but that only works for integers.
e.g. 184 % 180 = 4 and 364 % 180 = 4

for the range -180 to 180 degrees, I do not think that is entirely correct:

taking the value of 184 degress in @TRex example, the equivalent value for the range -180 to 180 degree would therefore be 184 -360 = -176 degree

so in effect, IMHO, the constraining rule should be

if (axis_1 > 180) axis_1 = axis_1 - 360;

and

if (axis_1 < -180) axis_1 = axis_1 + 360;

mschindl:
I also want the Arudino to calculate the error between the setpoint and the current state.

If axis_1 is at 10 degrees, and the setpoint is at 15. Then 15-10 = 5 degrees of error. But if axis_1 is at 175 degrees, and the setpoint is at 5 degrees. Then the error is 5-175 = -170, which is not true....

IMHO to be able to determing the error wrt to the setpoint you will also need to know the CURRENT direction of rotation (ie clockwise or counter-clockwise) in order to be able to evalute it correctly for the range -180 to 180 degrees.

hope that helps...