# Help in finding correct PID values in PID library ??

I have seen many posts on the theory of PID. I do understand the theory. but when it comes to tuning the arduino PID library i could not find any good examples. please correct me where I’m wrong. As i understand in the arduino libraryPIDLibrary

I am using the LED brightness control example. the brightness of a LED is measured by a photoresistor according to that the output to the LED is controlled through analogWright to keep the LED in set brightness.
Set point is the value we want the system to stay (brightness), Input is the photoresistor sensor input. the Output is the value given to the LED pin. So for the system to be perfectly stable the Setpoint = Input and the Output =0, right ?? that cant be wright, If the output is 0 the LED turns OFF.

In tuning I’m trying to follow these rules
1.Set all gains to zero.
2.Increase the Kp until the response to a disturbance is steady oscillation.
3.Increase the Td until the oscillations stop (i.e. it’s critically damped).
4.Repeat steps 2 and 3 until increasing the Td does not stop the oscillations.
5.Set Kp and Td to the last stable values.
6.Increase Ti gain until the convergence to the set point occurs with or without overshoot at an acceptable rate.
first of all how to identify steady oscillation ?
In the attached picture the set point is 30 and the kp=2,Ki=0,Kd=0. red colore is Input, Blue is Set pint and Green is Output.
these outputs are confusing. can some one please explain what is going on hear. these responses are without changing the set point.

``````// From https://github.com/bcomnes/315-lab-microcontroller/blob/master/code/pid_led_set_serial/pid_led_set_serial.ino
#include <PID_v1.h>
const int photores = A0; // Photo resistor input
const int pot = A1; // Potentiometer input
const int led = 9; // LED output
double lightLevel; //variable that stores the incoming light level

// Tuning parameters
float Kp=2; //Initial Proportional Gain
float Ki=0; //Initial Integral Gain
float Kd=0;  //Initial Differential Gain

double Setpoint =30; // fixed setpoint

double Input, Output;  //These are just variables for storing values
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, REVERSE); // This sets up our PDID Loop
//Input is our PV
//Output is our u(t)
//Setpoint is our SP
const int sampleRate = 1; // Variable that determines how fast our PID loop runs

// Communication setup
const long serialPing = 500; //This determines how often we ping our loop
// Serial pingback interval in milliseconds
unsigned long now = 0; //This variable is used to keep track of time
// placehodler for current timestamp
unsigned long lastMessage = 0; //This keeps track of when our loop last spoke to serial
// last message timestamp.

void setup(){
lightLevel = analogRead(photores); //Read in light level
Input = map(lightLevel, 0, 1024, 0, 255); //Change read scale to analog out scale
//Setpoint = map(analogRead(pot), 0, 1024, 0, 255);  //get our setpoint from our pot
Serial.begin(9600); //Start a serial session
myPID.SetMode(AUTOMATIC);  //Turn on the PID loop
myPID.SetSampleTime(sampleRate); //Sets the sample rate
myPID.SetOutputLimits(0,255);
Serial.println("Begin"); // Hello World!
lastMessage = millis(); // timestamp
}

void loop(){
//Setpoint = map(analogRead(pot), 0, 1024, 0, 255); //Read our setpoint
lightLevel = analogRead(photores); //Get the light level
Input = map(lightLevel, 0, 1024, 0, 255); //Map it to the right scale
myPID.Compute();  //Run the PID loop
analogWrite(led, Output);  //Write out the output from the PID loop to our LED pin

now = millis(); //Keep track of time
if(now - lastMessage > serialPing) {  //If its been long enough give us some info on serial
// this should execute less frequently
// send a message back to the mother ship
Serial.print("Setpoint = ");
Serial.print(Setpoint);
Serial.print(" Input = ");
Serial.print(Input);
Serial.print(" Output = ");
Serial.print(Output);
Serial.print("\n");
if (Serial.available() > 0) { //If we sent the program a command deal with it
for (int x = 0; x < 4; x++) {
switch (x) {
case 0:
Kp = Serial.parseFloat();
break;
case 1:
Ki = Serial.parseFloat();
break;
case 2:
Kd = Serial.parseFloat();
break;
case 3:
for (int y = Serial.available(); y == 0; y--) {
Serial.read();  //Clear out any residual junk
}
break;
}
}
Serial.print(" Kp,Ki,Kd = ");
Serial.print(Kp);
Serial.print(",");
Serial.print(Ki);
Serial.print(",");
Serial.println(Kd);  //Let us know what we just received
myPID.SetTunings(Kp, Ki, Kd); //Set the PID gain constants and start running
}

lastMessage = now;
//update the time stamp.
}

}
``````

The code was modified not to take pot input as setpoint.

Try measuring the LED brightness first. PWM will rapidly turn the LED on and off, and if the photo resistor does not flatten this blinking sufficiently, a low pass filter must be added in hardware or software.

DrDiettrich:
...if the photo resistor does not flatten this blinking sufficiently...

Photoresistors tend to have a significant lag (10 ms to 1 s according to Wikipedia though I've not crossed paths with any that are as slow as 1 s).

...a low pass filter must be added in hardware or software...

Or increase the PWM frequency well beyond the response time of the photoresistor.

Another option is the PIDAutotuneLibrary: Arduino Playground - PIDAutotuneLibrary

tuning PID is like fixing someone’s diet.

the vast array of things that can be controlled is amost unimaginable.

if I needed a ‘circuit’ you should be able to offer one ? I will not tell you if it is to light an LED or control the output of the power from the Hoover Dam !

There is a really good 20 page procedure written for/by duPont some many years ago. still on the net,

but, the simplictiy is
you remove I and D from the cirucit and only adjst P
you adjust P until the process is on the boarder of stable and un-stable.
then you adjust I to get the unit to work in the control range you want.

D is almost short for Don’t bother.
low speed processes like temperature or water level have no need for D and often no need for I either.
high speed processed cannot use D as it will cause more instability, and I/D (inverse Derivative) is the proper function.

so the small range of projects that benefit from D make it so it is not needed frequently.

so, remove I and D, adjust P until the system is at the unstable point
then adjust I so it becomes stable.

as a note, P is really like guard rails. if you get too far from center, you need to take drastic action.
P is the guard rails.

I is the tweaking of the output so that is does small but frequent adjustments.

P will cause a process to overshoot
I will make small, but frequent adjustmenets to try to get the process closer to the desired point.

as a note, if you turn on your blast furnice, and measure temperatre accross the room, by the time the senosr sees an increase, you could shut off the process and the temperature will increase well beyond your desired point.
it is too late to use D anyway.

if you hear a sound, it is already of magnitude and you need an inverse derivative to control something that fast.

so, the reason you cannot find anything easy, is because this knowledge is hard to come by and those that know it, have not bothered to write one group of settings for an oil furnace and a gas furnace and a hot air furnace and a hydronic furnace and an electric heater and an electric oil bath heater… that is the tip of heaters… there are a ba-zillioin variations of control so there no simple set of numbers.

I know you can buy a PID in a DIN enclosure on E-bay for a few dollars and it has an auto-tune function.
I have pressed that button on too many occasions and it responded, “cannot set parameters.”

but your best option is to find a forum where others are doing the same thing as you, a still or quad-copter, and get some ball-park numbers to start with.