Botched
16Apr/1210

PID success!!

After many days ironing out a ridiculous amount of careless bugs plus a major break in the frame I have finally managed to get the PID algorithm keeping the quad level 😀 At this point I *think* it would hover if released from its supports, but for now I would rather improve the code further to get it more responsive still.

The main change I am about to make is switching the output compare modules from PWM mode to single shot. This is because at the moment it takes a full PWM cycle before a new duty cycle can be loaded, adding a 2.5ms delay between the motors and the sensors. By locking the update rate to 400Hz, I should be able to trigger a new pulse as soon as the new duty cycle is calculated, completely removing this delay.

Comments (10) Trackbacks (0)
  1. Nice! I’ve prepared a “similar” testing bench but I’ve got some doubts about PID settings. Which values did you use for the constants? I was thinking by starting with 5, 0.2 & 0.2 but I’m not sure if I’m way too far from useful values and I don’t want to chop my head off 🙂

    Thanks!!

    • I’m currently using P=35, I=85, and D=30. I think I might drop KD down to around 25 to improve the command tracking a bit, and it’s important to note I calculate the integral term as I+=I*dt instead of just summing the error, meaning if you are just summing like most quads seem to you would need to use KI=85/400=0.21 (400Hz is my update rate). I also use a pretty tight wind up limit, meaning the integral term doesn’t really have a massive effect on the output, it’s just there to correct the small steady state error.

      However as for tuning, I would say the best method would be to disregard any values I or anyone else has used, as they seem to vary a lot depending on the quad dimensions and the code behind it. I obtained mine by starting every constant at 0 and the throttle at 1/3, then used the serial connection to increment them individually until I achieved a response I liked, starting with P D then I.
      Just make sure you have a kill switch, especially when first implementing the integral term 😛

      • Thanks for the explanation. I’ll give it a try as you mention. This PID tuning seems to be the most obscure process for quads as almost everybody skips explaining it. I understand PID tuning is some “magic” process but I think it is actually the most interesting!

  2. Hi!, I’m traying to take the mathematic model of my quadcopter, but I have some problems with it. ¿How did you do to obtain the values of PID terms? ¿Had you used a Ziegler-Nichols method or something like that?

    • I tuned it by hand by increasing KD and KP until I achieved a response I liked, then slightly increased KI to eliminate the steady state error. However, on the next version I’ll be redesigning the loop, as at the moment the command tracking is very poor. I’ll probably do this by adding some sort of feed forward control, but I haven’t had the time to research this properly yet.

  3. Hi,

    I was looking at you code and it looks very nice and simple to understand. I am interested in the PID control part, and there is one thing that I don’t finish to understand though. How did you jump from here:
    PID_XOUTPUT = XERROR*KP + XDIFFERENTIAL*KD + XINTEGRAL*KI;
    PID_YOUTPUT = YERROR*KP + YDIFFERENTIAL*KD + YINTEGRAL*KI;
    PID_ZOUTPUT = ZERROR*ZKP; + ZDIFFERENTIAL*ZKD;

    to here:
    OC1_output = 0.7071*PID_XOUTPUT + -0.7071*PID_YOUTPUT + PID_ZOUTPUT + MOTOR_MIN + MOTOR_RANGE*throttle;
    OC2_output = 0.7071*PID_XOUTPUT + 0.7071*PID_YOUTPUT – PID_ZOUTPUT + MOTOR_MIN + MOTOR_RANGE*throttle;
    OC3_output = -0.7071*PID_XOUTPUT + 0.7071*PID_YOUTPUT + PID_ZOUTPUT + MOTOR_MIN + MOTOR_RANGE*throttle;
    OC4_output = -0.7071*PID_XOUTPUT + -0.7071*PID_YOUTPUT – PID_ZOUTPUT + MOTOR_MIN + MOTOR_RANGE*throttle;

    I hope you can help me here a little bit. Where did you find, or how did you know this PID stratige to use. I mean I understande the PID, but from the PID result to the motor ouputs I don’t get it.

    • The PID values represent the change required in each axis. In reality, this quad is in an X configuration, so each motor is affected by both the x and y PID outputs, meaning they must be ‘mixed’. This is what you see here. This mixed value is then added on top of the minimum motor speed along with the base throttle required.

      • wow, thanks for the fast answer :). yeah I unterstend the logic, I actually tought that it was a X configuration. But I don’t get why 1/sqrt(2)Pid_X -1/sqrt(2)Pid_Y + 1*Pid_Z … etc. Are you kind of normalizing the ouput? like a vector? How did you get to that mixed configuration.

        I am programming a + configuration. So if I understand your logic, for me it whould be something like
        Motor1 = Pid_xOuput + Pid_zOuput + Motor_Min + MotorRange*Throttle
        Motor2 = Pid_yOuput + Pid_zOuput + Motor_Min + MotorRange*Throttle
        Motor3 = -Pid_xOuput – Pid_zOuput + Motor_Min + MotorRange*Throttle
        Motor4 = -Pid_yOuput – Pid_zOuput + Motor_Min + MotorRange*Throttle

        • I think the zOutput is wrong, it should be like this right?
          Motor1 = Pid_xOuput + Pid_zOuput + Motor_Min + MotorRange*Throttle
          Motor2 = Pid_yOuput – Pid_zOuput + Motor_Min + MotorRange*Throttle
          Motor3 = -Pid_xOuput + Pid_zOuput + Motor_Min + MotorRange*Throttle
          Motor4 = -Pid_yOuput – Pid_zOuput + Motor_Min + MotorRange*Throttle

  4. Where can I find the code for this?


Leave a comment

No trackbacks yet.