0% found this document useful (0 votes)
2 views6 pages

Derivative Calculator for PID Control

Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views6 pages

Derivative Calculator for PID Control

Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

#include <Wire.

h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C address 0x27, 20 , 4

String command;
int n;
int trigPin = 9; // TRIG pin
int echoPin = 8; // ECHO pin
int fan = 11;// Main Graduated Cylinder Fan
int disturb = 10; // Disturbance Fan
float disturbanceFan;

float propBand=64;
float integralTime=2;
float derivativeTime=0.3;
float sampleTime=10;

bool enableDisturbance=false;

float Setpoint_Potentiometer();
float Ultrasonic_filterFunction(float timeConstant, float processGain,float
blockIn, float intervalTime);
float normalizesDistance();
float PID_output(float process, float setpoint, float Prop, float Integ, float
deriv, int Interval);
float DerivativefilterFunction(float timeConstant, float processGain,float blockIn,
float intervalTime);

void Disturbance_Potentiometer();
void printText();// Print static text to display

void setup()
{
[Link](); //initialize the lcd
[Link](); //open the backlight
// begin serial port
[Link] (19200);

// configure the trigger pin to output mode


pinMode(trigPin, OUTPUT);

// configure the echo pin to input mode


pinMode(echoPin, INPUT);
// power to fans
pinMode(fan, OUTPUT);
pinMode(disturb, OUTPUT);
printText();
}
//****************Start of Looping***********************************
void loop()
{
float controlledVariable;
float contOutNorm;
float setPoint;
if ([Link]())
{
command = [Link]('\n');
[Link]();
if ([Link]("PB+"))
{
propBand=propBand*2;
}

else if ([Link]("PB-"))
{
propBand=propBand/2;
if(propBand<=10)
propBand=10;
}

else if ([Link]("Ti+"))
{
integralTime=integralTime*2;
}
else if ([Link]("Ti-"))
{
integralTime=integralTime/2;
if (integralTime<=1)
integralTime=1;
}
else if ([Link]("Td+"))
{
derivativeTime=derivativeTime+0.1;
}
else if ([Link]("Td-"))
{
derivativeTime=derivativeTime-0.1;
if(derivativeTime<=0)
derivativeTime=0;
}
else if ([Link]("enDist"))
{
enableDisturbance=true;
}
else if ([Link]("disDist"))
{
enableDisturbance=false;
}
else
{
[Link]("bad command");
}
[Link]("Command: ");
[Link](command);
}

if(enableDisturbance==false)//enable/disble disturbace potentiometer


{
Disturbance_Potentiometer();

}
else if(enableDisturbance==true)//square wave disturbance
{
n++;

if(n<=500)
{
analogWrite(disturb,255);
disturbanceFan=10.0;
}
if(n>500)
{
analogWrite(disturb,0);
disturbanceFan=0.0;
}
if(n==1000)
n=0;
}

controlledVariable=normalizesDistance();
setPoint=-Setpoint_Potentiometer() + 1.0;// reveresing pot
contOutNorm=PID_output(controlledVariable, setPoint,propBand, integralTime,
derivativeTime, sampleTime);
analogWrite( fan,((float)contOutNorm)*255);
delay(sampleTime);
}
//************End of Looping***********************************************

float normalizesDistance()
{
float duration_us;
float distance_cm;
float filtered_distance;
// generate 10-microsecond pulse to TRIG pin
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);

// measure duration of pulse from ECHO pin


duration_us = pulseIn(echoPin, HIGH);

// calculate the distance


distance_cm = 0.017 * duration_us;
filtered_distance = Ultrasonic_filterFunction(0.5, 1.0,distance_cm, sampleTime);
if (filtered_distance>31)
filtered_distance=0;
return filtered_distance/31; // range 0 to 31 cm
//return distance_cm/31;
}

float Ultrasonic_filterFunction(float timeConstant, float processGain,float


blockIn, float intervalTime)
{
float static blockOut;
blockOut=blockOut+(intervalTime/1000/(timeConstant+intervalTime/
1000))*(processGain*blockIn-blockOut);
return blockOut;
}

float Setpoint_Potentiometer()
{
int potA3;
potA3=analogRead(A3);
return (float)potA3/1023;
}

void Disturbance_Potentiometer()
{
int potA1;
potA1=analogRead(A1);
analogWrite(disturb,(float)potA1/1023*255);// temporary for test
disturbanceFan=(float)potA1/1023*10;
}

float PID_output(float process, float setpoint, float Prop, float Integ, float
deriv, int Interval)
{
float Er;
static float Olderror, Cont;
static int Limiter_Switch;
static float Integral=0.82;
float derivative;
float proportional;
float deltaT;
float filteredDerivative;
deltaT=float(Interval)/1000;
Limiter_Switch = 1;
//delay(Interval); // Interval in msec is delta t in the integral and derivative
calculations
Er=(process-setpoint); //forward acting
//Limiter switch turns integration OFF if controller is already at 100% output or
0% output
//Prevents integral windup, where controller keeps integrating when controller
output can no longer
//affect the process.

if ((Cont >= 1 && Er > 0) || (Cont <= 0 && Er < 0) || (Integ >= 3600))
Limiter_Switch = 0;
else
Limiter_Switch = 1;

Integral = Integral + 100 / Prop / Integ * Er *deltaT * Limiter_Switch;// Integral


calculator
derivative = 100 / Prop * deriv * (Er - Olderror) / deltaT;// Derivative calculator
//filteredDerivative=DerivativefilterFunction(0.1, 1.0,derivative, sampleTime);
proportional = 100 / Prop * Er;// Proportional calculator

Cont = proportional + Integral + derivative;


Olderror = Er;// remember previous error for deriative calculator

if (Cont > 1) // limit controller output between 0.0 and 1.0 a normalized value
Cont = 1;

if (Cont < 0)
Cont = 0;
// Serial Plotter Variables
[Link](-31*process+31);
[Link](" = Process");
[Link](",");
[Link](-31*setpoint+31);
[Link](" = Set Point");
[Link](",");
[Link](disturbanceFan);
[Link](" = disturbance Fan");
[Link](",");
// LCD Display Variables
[Link](9 , 1);
[Link](" ");
[Link](9 , 1);
[Link]((int)(Cont*100.0));

[Link](15 , 0);
[Link](" ");
[Link](15 , 0);
[Link]((int)(proportional*100.0));

[Link](15 , 1);
[Link](" ");
[Link](15 , 1);
[Link]((int)(Integral*100.0));

[Link](15 , 2);
[Link](" ");
[Link](15 , 2);
[Link]((int)(derivative*100.0));

[Link](9 , 2);
[Link](" ");
[Link](9 , 2);
[Link]((int)(-31*setpoint+31));

[Link](9, 0);
[Link](" ");
[Link](9, 0);
[Link]((int)(-31*process+31));

//PID Parameters
[Link](3 , 3);
[Link](" ");
[Link](3 , 3);
[Link]((int)Prop);
[Link](11 , 3);
[Link](" ");
[Link](11 , 3);
[Link]((int)Integ);
[Link](17 , 3);
[Link](" ");
[Link](17 , 3);
[Link](deriv);
[Link](0, 0);
[Link]("P");

return Cont;
}

void printText()// Print Static Text


{

[Link](0, 0);
[Link]("Posit cm ");
[Link](0, 1);
[Link]("C Out % ");
[Link](0, 2);
[Link]("SetPt cm ");

[Link](13, 0);
[Link]("P ");
[Link](13, 1);
[Link]("I ");
[Link](13, 2);
[Link]("D ");

[Link](0, 3);
[Link]("PB= ");
[Link](8, 3);
[Link]("Ti= ");
[Link](14, 3);
[Link]("Td= ");

Common questions

Powered by AI

The PID_output function maintains the stability of the control process and prevents integral windup by using a limiter switch. This switch deactivates integration when the controller output is already at maximum (Cont >= 1) or minimum (Cont <= 0) levels or if the integration time exceeds a threshold (Integ >= 3600). These conditions ensure that further integration does not occur when it cannot affect the process, effectively preventing integral windup .

The implemented PID control strategy effectively maintains system stability through dynamic adjustments of proportional, integral, and derivative components. A key strength is the prevention of integral windup via the limiter switch. However, limitations include the potential for overshoot if parameters are not properly tuned, and delay or instability in rapidly changing environments. These might be addressed by optimizing sampling time, incorporating adaptive control techniques, or implementing additional filtering to handle noise and prevent excessive response to disturbances .

The proportional component reduces the error by applying a correction proportional to the current error value, implemented via the proportional variable. The integral component addresses accumulated past errors to eliminate steady-state offsets by summing previous errors, managed through the Integral variable and its limiter switch. The derivative component predicts future error trends based on its rate of change, calculated using the derivative variable. By combining these, the PID controller achieves precision in dynamic control systems, addressing not only immediate errors but also trends and past accumulations .

The Ultrasonic_filterFunction serves to smooth out the distance measurements obtained from the ultrasonic sensor. It is implemented using a block out calculation, which incrementally updates the blockOut variable by considering the time constant, process gain, input value (blockIn), and the interval time. This approach helps to eliminate short-term fluctuations from the distance readings, providing a more stable signal .

Sample time, defined as 10 milliseconds in the code, dictates the frequency at which the control loop is executed. It influences the speed and responsiveness of the PID control; shorter sample times result in faster system response but may increase the computational load, whereas longer times reduce resource usage but may slow down the response to changes. Optimizing this parameter is crucial for balancing control loop performance and computational efficiency .

The LCD display provides real-time feedback by showing key control variables, such as the controlled process (position in cm), control output percentage, set point, current PID parameters (proportional, integral, derivative values), and the disturbance fan state. These variables are updated in real-time by adjusting the cursor position on the display and printing the new values as they change. This visualization helps the user understand the current state of the system, facilitating monitoring and adjustments for optimal control .

The code handles user input from the Serial monitor by reading strings until a newline character is detected. It recognizes commands to adjust the proportional band ("PB+", "PB-"), integral time ("Ti+", "Ti-"), derivative time ("Td+", "Td-"), and enable or disable disturbance ("enDist", "disDist"). These commands allow users to finetune the PID parameters and control the disturbance mechanism, and any unrecognized commands prompt a "bad command" response .

The disturbance management strategy in the code addresses typical control system challenges like oscillation and external noise by offering both manual and automated disturbance control options. The manual disturbance potentiometer and automated square wave disturbance allow testing under diverse conditions, helping calibrate the system's resilience to external perturbations. While effective in demonstrating control adaptability, real-world applications might require more sophisticated noise filtering and adaptive control strategies to tackle unpredictable disturbances. The code showcases these challenges but doesn’t fully implement comprehensive solutions typically needed in complex dynamic systems .

The Setpoint_Potentiometer function reads the analog input from a potentiometer connected to pin A3, normalizing this value between 0 and 1. This value is used as the setpoint in the PID control process, setting the target for the controlled variable. The difference between this setpoint and the actual process variable informs the PID calculation, driving the control output accordingly to minimize error. By allowing manual adjustment of the setpoint, it gives users a flexible way to dictate control objectives .

The code uses the disturbance potentiometer and a square wave disturbance to control system disturbances. The disturbance potentiometer is activated when enableDisturbance is false, allowing manual control via analog readings from a potentiometer (A1). When enableDisturbance is true, a square wave disturbance is generated by alternating the disturbance fan's power between high and low signals every 500 cycles, using the variable n to track cycles. These mechanisms are toggled by receiving specific commands via the Serial interface .

You might also like