PID help

Hello all,

I' m working on a university project and i encountered a problem i can't apparently solve by myself. The project consist in a 2D helicopter shape hanging from the ceiling which only has tail blade rotor driven by a DC motor, a motor shield to control it (HW-095) and a GY-251 board which mount an MPU6050. The objective is to bring back the shape to the starting position after a disturb (me pushing it). To do it i' m using this PID controller library: https://playground.arduino.cc/Code/PIDLibrary/

As input of the controller i have the yaw value from the MPU6050 and i write the output to the enable PIN of the motor shield as PWM signal to modulate the response.

I tried many methods to set the constant parameters Kp, Kd, Ki but it seems like whatever constants i use the system always diverges from the setpoint and permanently oscillate. Can anybody give some hints on how to set those?

What i tried: Method 1: Setting Kd, Ki to 0 and increasing Kp untill steady oscillation occur, calculate period of the oscillation to set Ki, Kd via Zieger Nichols tabulated guide. Setting Kd, Ki to 0. Increasing Kp untill steady oscillation, set it to 0 again and set Kd to a value where it kept the helicopter in the position i put it(I couldn't make it), set Ki to eliminate the steady error.

Setting Kd, Ki to 0. Increasing Kp untill steady oscillation, set it to 0 again and set Kd to a value where it kept the helicopter in the position i put it(I couldn't make it), set Ki to eliminate the steady error.

I'm quite sure you're supposed to leave the Kp setting at the oscillation point, then start increasing the value of Ki.

https://en.wikipedia.org/wiki/PID_controller

Have you tried a faster sample time ... the default is 100ms. Maybe a faster sample time of 20ms would make an improvement.

Can you post your code?

I did not try to decrease sample time, that’ s actually a good hint.
I attach the code below.
I also forgot to mention that i changed the PID library to this one:

Thank you for your help

Progetto_elicottero_uni.ino (6.55 KB)

Oh, so your critical period Tu = 12.12 ... I guess this is milliseconds? Then I would change the sample time to much lower, maybe 1 to 4 ms.

dlloyd: I'm quite sure you're supposed to leave the Kp setting at the oscillation point, then start increasing the value of Ki.

https://en.wikipedia.org/wiki/PID_controller

Thanks for the great animation! I'm likely corroded thinking that Kp is turned up, like You show, but then Kd is adjusted and finally Ki.

dlloyd: Oh, so your critical period Tu = 12.12 ... I guess this is milliseconds? Then I would change the sample time to much lower, maybe 1 to 4 ms.

Oh no don 't look at those! Those are old datas that i wrongly measured in the past and never deleted. Tu in this case rappresent the time taken by the helicopter to complete an oscillation with the very first Kp i set.. Tu was 12.12 seconds in that case

Oh no don 't look at those!

Whoops! Uhm, too late! Did a quicker sample time make a difference?

@Railroader - Yeah, that's pretty neat ... its from the lower down the page at the Wikipedia link.

Finetuning 8 ton forklift trucks running automatically following a buried signal kabel, having a margin of 10 cm, at speeds up 9 km/h, PID trimming was at the edge. You bet I was close to the servo stearing guys when they trimmed the inverter. Then I was the testpilot that made the over all main logic in the computer.

dlloyd: Whoops! Uhm, too late! Did a quicker sample time make a difference?

@Railroader - Yeah, that's pretty neat ... its from the lower down the page at the Wikipedia link.

I reevaluated the parameters and changed the sample time but the issue persists.. I' ve read something about the library i' m using and found out that in some cases it presents wind-up, a phenomena similar to what happens to my model. Could it be the case?

Fisrt idea, it is is not an easy system to control. Fisrt question, have you got the mathematical model?
Rethink the procedure you did:
Increase Kp until it oscilates permanently: Kp0
Decrease Kp half Kp0: 0,5*Kp0
Increase slowly Ki until error disapears but oscilation is not permanent
Increase slowly Kd until oscillation disapears,
That’s the procedure.

Certainly Wind-up can affect the stability. Do you know how tot stop its effect?
If you era using a library and don’t know how to change the code it is difficult. The idea is to stop integration when you detect that DAC output is over the maximum value other under minimum value and activate again the integration when it can return between the limits. Perhaps it is better to use your own PID code (is extremelly easy to do)

Would you like I give you code for PID with against-windup ?
And please, answer me the first question I did.

As you said the system is not easy to control at all given the big Inertia it has and the fact it presents almost no friction to help in dampening the oscillations make the situation worst.

triado:
Increase slowly Ki until error disapears but oscilation is not permanent

What you mean by that?

Would you like I give you code for PID with against-windup ?

That would be really kind, it would be helpful for sure

Fisrt question, have you got the mathematical model?

I haven’ t, unluckily. I could have used matlab to calculate the paramaters in that case.

Thank you for your answer!

A possible solution to reduce the wind-up using the library could be:

  if (Input > rangePID || Input < rangePIDmin) {
    myPID.SetMode(MANUAL);
    analogWrite(En, 255);
  }
  else {
    myPID.SetMode(AUTOMATIC);
    Output = myPID.Run(Input);
    potmot = map(abs(Output), 0, PIDMax, MinPower, 255);
    analogWrite(En, potmot);
  }

Where you disable PID computing when the input is too big and would cause problems to PID calculations.
Also, setting the mode to MANUAL should reset P, I and D terms (Not the costants!).

You can not disable de PID computing, you must disable only the integration part. Tomorrow I will give you a code because I am at work now. Can you wait until tomorrow ? (for me it's now 4:30 PM)

Yeah for sure! No hurry

First of all, I will explain it step by step what we wanna do; and, as I told you, in a next post (tomorrow) I will send the code, since I want to try it beforehand because I don’t remember exactly the sintax of Arduino codification.

Important: The following lines are not the code but an introductory explanation about what must be done:

Integration (trapezoidal rule ):
integ(k)=integ(k-1)+ (e(k)+e(k-1))*Ts/2; //Ts means sample Time, e(k) ís the error variable (or deviation)

Integration (trapezoidal rule ) with against-windup (alternative):
if u(k) >=minimum_output and u(k)<= maximum_output
integ(k)=integ(k-1)+ (e(k)+e(k-1))*Ts/2; //integrate normally
else
integ(k)=integ(k-1); //freeze the value of integ(k)
end

Derivative:
der(k)=(e(k)-e(k-1))*Ts

So, the whole controller is:
u(k)=Kpe(k)+Kiinteg(k)+Kd*der(k)

... and before we continue, can you answer me some questions? and depend on your answers your main problem could be another problem

  • Do you work with Arduino Due, don't you?
  • How many bits has your ADC? (ADC: Analog to digital converter)
  • Are you aware that the input from ADC is always positive? For example, if you use 12 bits the input goes from 0 to 4095 In that case, you can do 2 diferent things: you should change to bipolar your signal substracting the half of the range (in our example of 12 bits, 2048), or you should put the reference as a value into the range.
  • And also; are you aware that the output to DAC should be also in the range of 0 to 4095 (in our example of 12 bits)? The solution, is that you add 2048 bits (in our example of 12 bits) before you write the output to DAC.

All in all, if you "feed" a PID allways with positives values it is impossible that it runs properly. Do you know what I mean?

triado:

  • Do you work with Arduino Due, don’t you?

No, i’ m currently using Arduino Uno r3 board

  • How many bits has your ADC?

I don’ t really know how to asnwer this question, if you mean the MPU6050 it should communciate via 8bit signals but i don’ t really know much about it, i’ m literally new to Arduino and electronics world.

  • Are you aware that the input from ADC is always positive? For example, if you use 12 bits the input goes from 0 to 4095
    In that case, you can do 2 diferent things: you should change to bipolar your signal substracting the half of the range (in our example of 12 bits, 2048), or you should put the reference as a value into the range.
  • And also; are you aware that the output to DAC should be also in the range of 0 to 4095 (in our example of 12 bits)? The solution, is that you add 2048 bits (in our example of 12 bits) before you write the output to DAC.

I’ m really not, sorry. I will study some more material about that for sure.

All in all, if you “feed” a PID allways with positives values it is impossible that it runs properly. Do you know what I mean?

What i’ m giving to the PID controller as input is the yaw angle given by the MPU-6050 converted from radiants to degrees, hence i’ m “feeding” both positive and negative values to the controller.
Did you mean that?
Also, i constrained PID outputs to the range (-255,255) since the PWM modulation maximum is 255.

I attached the script i’ m currently using.

Progetto_elicottero_uni.ino (6.55 KB)

I thougth you worked with Arduino Due.
So, I will study your script and I will say you something in a few days, if I get the problem.

Joan Triadó

I've been studying the code you used. Fisrt of all, I can't find any setting of Sample time. If it is, please tell me in which line. It is very difficult to control a system without being aware of and controlling your sample time.

But I reconsidered your first message (in the very begining). You try to control a position system very close to the inestability adding an integrator to it. In theory, if your system is a type 1 system (a system with "one" integrator itself in the plant) it is very dangerous (and usually impossible to control) to add another integrator. All position systems are type 1 systems. Type 1 systems do not need integration for positioning with a constant reference because its steady state deviation is zero.

My proposal: did you try not to use any integrator? Just Kp? Other Kp and Kd? You will solve, also, the problem of windup, wich is only possible with integration. Ki is allways a source of approching to inestability. Necessary when system is type zero for constant references, but not necessary to use if not needed.

I will try and post the results here.

You are very very kind sir. Thanks for all the time and help you are giving me!