# Quadcopter PID tuning

In continuation of the question I asked here: Quadcopter instability with simple takeoff in autonomous mode ...I'd like to ask a few questions about implementing a basic PID for a quadrotor controlled by an APM 2.6 module. (I'm using a frame from 3DRobotics)

I've stripped down the entire control system to just two PID blocks, one for controlling roll and another for controlling pitch (yaw and everything else... I'd think about them later).

I'm testing this setup on a rig which consists of a freely rotating beam, wherein I've tied down two of the arms of the quadrotor. The other two are free to move. So, I'm actually testing one degree of freedom (roll or pitch) at a time.

Check the image below: here A, B marks the freely rotating beam on which the setup is mounted.

With careful tuning of P and D parameters, I've managed to attain a sustained flight of about 30 seconds.

But by 'sustained', I simple mean a test where the drone ain't toppling over to one side. Rock steady flight is still no where in sight, and more than 30 secs of flight also looks quite difficult. It wobbles from the beginning. By the time it reaches 20 - 25 seconds, it starts tilting to one side. Within 30 secs, it has tilted to one side by an unacceptable margin. Soon enough, I find it resting upside down

As for the PID code itself, I'm calculating the proportional error from a 'complimentary filter' of gyro + accelerometer data. The integral term is set to zero. The P term comes to about 0.39 and the D term is at 0.0012. (I'm not using the Arduino PID library on purpose, just want to get one of my own PIDs implemented here.)

Check this video, if you want to see how it works.

http://www.youtube.com/watch?v=LpsNBL8ydBA&feature=youtu.be [Yeh, the setup is pretty ancient! I agree. :)]

Please let me know what could I possibly do to improve stability at this stage.

@Ian: Of the many tests I did with my setup, I did plot graphs for some of the tests using the reading from the serial monitor. Here is a sample reading of Roll vs 'Motor1 & Motor2 - PWM input' (the two motors controlling the roll):

As for the input/output:

Input: Roll and pitch values (in degrees), as obtained by a combination of accelerometer + gyro

Output: PWM values for the motors, delivered using the Servo library's motor.write() function

Resolution

I resolved the problem. Here's how:

1. The crux of the issue lied in the way I implemented the Arduino program. I was using the write() function to update the servo angles, which happens to accept only integer steps in the argument (or somehow responds only to integer input, 100 and 100.2 produces the same result). I changed it to writeMicroseconds() and that made the copter considerably steadier.

2. I was adding up RPM on one motor while keeping the other at a steady value. I changed this to increase RPM in one motor while decreasing the opposing motor. That kinda keeps the total horizontal thrust unchanged, which might help me when I'm trying to get vertical altitude hold on this thing.

3. I was pushing up the RPM to the max limit, which is why the quadcopter kept losing control at full throttle. There was no room for the RPM to increase when it sensed a tilt.

4. I observed that one of the motor was inherently weaker than the other one, I do not know why. I hardcoded an offset into that motors PWM input.

Thanks for all the support.

Source Code:

If you're interested, here's the source code of my bare-bones PID implementation: PID Source Code

Please feel free to test it in your hardware. Any contributions to the project would be welcome.

• What is the input and what is the output of the loop? Jan 15, 2014 at 3:43
• @GuySirton: Updated my question Jan 15, 2014 at 10:52
• What are those flat sections in your motor commands? Looks like something is saturating. You roll changes like a continuous function but your commands look very abrupt. Also why are both motor PWM commands drifting up while your roll input stays in what looks like the same range? What is the approx timescale by the way? Jan 15, 2014 at 22:57
• The reason you're losing control after 30 seconds is probably related to both your commands drifting up. I think you are trying to control the difference between the commands but you can't allow those to keep drifting up. Jan 15, 2014 at 23:03
• @GuySirton: They're not drifting up, I'm incrementing it upwards from zero, so that it reaches a particular steady state within 3/4 secs. However, I think you're right when you say "reason you're losing control after 30 seconds is probably related to both your commands drifting up". If I don't use this gradual increment, if I fix my PWM input at a certain level (lower than the max input shown above), the problem of losing control after 30secs goes away. Jan 16, 2014 at 5:00

1. It looks like your proportional gain is too high.
2. You seem to be constantly increasing RPM on one motor while locking in the other one to make the system rotate. This isn't a good control strategy as eventually those are going to both saturate and you will lose control. Also as time increases your ability to command the system decreases. So you need a better model of the system.
3. If you deal with #1, and #2 you'll have a more stable system but you may not be happy with the control bandwidth. To deal with that you need to make your system stiffer which includes getting rid of any lag on the sensor side of things and on the control side of things.

I'd start by reading over this question: What are good strategies for tuning PID loops?

If I had to guess, I'd say you have a problem in the way your complimentary filter is constructed. With the quadcopter motors off, you should tilt the frame back and forth and see if the roll / pitch values that are reported are actually accurate.

To me, it looks like there is a delay between the input from the accelerometer and the output of your filter -- the oscillation could be explained by late reactions to the input data. The eventual turning over looks like a possible integration error that accumulates over time -- in other words, while your quadcopter is on its side it actually thinks it's hovering levelly.

(Update) Regarding your graph, the fact that your motor speeds continue to increase (instead of staying balanced) means you have an error somewhere. Perhaps your Integral term is growing unbounded, and you should specify a reasonable maximum for it.

• I updated my question with the roll values, when tilting back and forth. I solved the eventual turning over by lowering my max PWM input. It seems like the correction values do not work at very high RPM. I can easily turn the rig with my hand when working at high RPM. At lower RPM, I feel considerable resistance and the quadcopter seems to oscillate back to its original position (which is good, I guess). So, 'turning over' problem is probably solved by lowering the RPM (don't know if the drone will take off at all or not, hope it does). Oscillation problem still remains. Jan 15, 2014 at 10:51
• If I'm reading this graph correctly, your roll sensor thinks that it starts at $-3^{\circ}$, oscillates, and ends up around $-5^{\circ}$. But in the video, the quadcopter is on its side at $\pm90^{\circ}$. Where does this discrepancy come from?
– Ian
Jan 15, 2014 at 14:31
• Well, the graph isn't exactly for the test shown in the video. As mentioned above, the graph is from one of the many tests I did with this setup and I do not recall exactly how this particular case looked like. The graph is just to give you an idea how the input vs output response behaves, and I also wanted to establish that there ain't much of a lag between input and output (given that the loop is running at 150+ Hz). Matching the video with the graph may not make much sense. I do not have the exact data set for the test in the video. Jan 15, 2014 at 17:04
• I realized the graph is kinda misleading, sorry for that. I'll try and update the graph with a more accurate one. Actually, since I was plotting data from the serial port, when I created this graph, the Arduino board was tethered with the laptop. After a certain bit of oscillation, I had to intervene and slow down the oscillation manually. That's why you see it settling down at - 5 deg, while in reality its around 90 deg. I'll try to update a more accurate graph later. Jan 15, 2014 at 17:41
• One other thing I see from the graph is that your combined thrust is always increasing. That seems wrong.
– Ian
Jan 16, 2014 at 14:36

Well there could be a number of things going on here...

1) Are your reported angles correct? noisy? You can easily check that by manually tilting your quad and monitoring the values coming out.

2) your own PID implementation has a bug. You could use the trusted implementation out there to check your code.

3) Props, motors mounted the wrong way round.

4) ...

• 1) I've tilted and checked the reported angles, almost correct, but definitely noisy. 2) very likely... in fact, I think that summarizes it entirely :P 3) not very likely, two clockwise, two anti-clockwise... I've checked the props multiple times + I guess this type of error would have resulted in wild errors, way beyond control. 4) .... Jan 15, 2014 at 16:50
• 4)... a wrong PID tuning can makes things worst than if you didn't have a PID at all!
– dm76
Jan 15, 2014 at 17:01
• Yeh, I see that now. I'll get working on it tomorrow. My first plan is to use the trusted PID library and second is to change the output of the PID from PWM signals to roll.pitch correction. Jan 15, 2014 at 17:10