loop input to a PID controller

hi there,

I built my own quadrocopter based on an arduino mega. Everything works fine so far. 8)
Now I added a compass module (cmps10) to get and set the current bearing of the quadrocopter.
The bearing gets controlled by a PID controller (Arduino Playground - PIDLibrary).
The PID input is the bearing from the compass and the PID setpoint is a value between 0 and 359. With these two values, the PID controller controls the rotors to turn the quadrocopter to the desired bearing (setpoint).
This algorithm works but it has a problem:
Let's say that the bearing setpoint is 350 deg and the quadrocopter's current bearing is 10 deg. The quadrocopter now turns right till its bearing is about 350 deg. That's not really wrong, but for this example it would have been easier to just turn left 20 degs.
The problem is that the PID controller doesn't know that the bearing values build a loop, so that after 359 degs comes 0 degs.

My question is, is it somehow possible to tell the PID controller that the input values form a loop??

You could fudge the "current heading" (Input to the PID) to be a value within 180 degrees of the Setpoint. Just tell the PID that the current heading is 370° and it will give you an Output to turn left. Likewise if the Setpoint is 10° and the heading is 350° just tell the PID that the current heading is -10° and it will give an Output to turn right.

   // Normalize the heading to be within 180° of Setpoint (desired heading: 0-359°)
    if (heading - Setpoint < -180)  // Setpoint = 350, heading = 10...
         heading += 360;                    // change heading to 370
   if (heading - Setpoint > 180)   // Setpoint = 10, heading = 350...
         heading -= 360;                  // change heading to -10

Yes, make the set point zero, pass the angle error as the control input. You can ensure the
angle error is in the range -180 to +180 before its passed to the PID and allow it to turn the
most direct way.

In other words do this sort of thing before the PID

  angle_error = actual_angle - setpoint_angle ;
  if (angle_error < -180) angle_error += 360 ;
  if (angle_error > 180) angle_error -= 360 ;