0% found this document useful (0 votes)
0 views

PID Position 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)
0 views

PID Position 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
You are on page 1/ 6

#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()
{
lcd.init(); //initialize the lcd
lcd.backlight(); //open the backlight
// begin serial port
Serial.begin (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 (Serial.available())
{
command = Serial.readStringUntil('\n');
command.trim();
if (command.equals("PB+"))
{
propBand=propBand*2;
}

else if (command.equals("PB-"))
{
propBand=propBand/2;
if(propBand<=10)
propBand=10;
}

else if (command.equals("Ti+"))
{
integralTime=integralTime*2;
}
else if (command.equals("Ti-"))
{
integralTime=integralTime/2;
if (integralTime<=1)
integralTime=1;
}
else if (command.equals("Td+"))
{
derivativeTime=derivativeTime+0.1;
}
else if (command.equals("Td-"))
{
derivativeTime=derivativeTime-0.1;
if(derivativeTime<=0)
derivativeTime=0;
}
else if (command.equals("enDist"))
{
enableDisturbance=true;
}
else if (command.equals("disDist"))
{
enableDisturbance=false;
}
else
{
Serial.println("bad command");
}
Serial.print("Command: ");
Serial.println(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
Serial.print(-31*process+31);
Serial.print(" = Process");
Serial.print(",");
Serial.print(-31*setpoint+31);
Serial.print(" = Set Point");
Serial.print(",");
Serial.print(disturbanceFan);
Serial.println(" = disturbance Fan");
Serial.print(",");
// LCD Display Variables
lcd.setCursor(9 , 1);
lcd.print(" ");
lcd.setCursor(9 , 1);
lcd.print((int)(Cont*100.0));

lcd.setCursor(15 , 0);
lcd.print(" ");
lcd.setCursor(15 , 0);
lcd.print((int)(proportional*100.0));

lcd.setCursor(15 , 1);
lcd.print(" ");
lcd.setCursor(15 , 1);
lcd.print((int)(Integral*100.0));

lcd.setCursor(15 , 2);
lcd.print(" ");
lcd.setCursor(15 , 2);
lcd.print((int)(derivative*100.0));

lcd.setCursor(9 , 2);
lcd.print(" ");
lcd.setCursor(9 , 2);
lcd.print((int)(-31*setpoint+31));

lcd.setCursor(9, 0);
lcd.print(" ");
lcd.setCursor(9, 0);
lcd.print((int)(-31*process+31));

//PID Parameters
lcd.setCursor(3 , 3);
lcd.print(" ");
lcd.setCursor(3 , 3);
lcd.print((int)Prop);
lcd.setCursor(11 , 3);
lcd.print(" ");
lcd.setCursor(11 , 3);
lcd.print((int)Integ);
lcd.setCursor(17 , 3);
lcd.print(" ");
lcd.setCursor(17 , 3);
lcd.print(deriv);
lcd.setCursor(0, 0);
lcd.print("P");

return Cont;
}

void printText()// Print Static Text


{

lcd.setCursor(0, 0);
lcd.print("Posit cm ");
lcd.setCursor(0, 1);
lcd.print("C Out % ");
lcd.setCursor(0, 2);
lcd.print("SetPt cm ");

lcd.setCursor(13, 0);
lcd.print("P ");
lcd.setCursor(13, 1);
lcd.print("I ");
lcd.setCursor(13, 2);
lcd.print("D ");

lcd.setCursor(0, 3);
lcd.print("PB= ");
lcd.setCursor(8, 3);
lcd.print("Ti= ");
lcd.setCursor(14, 3);
lcd.print("Td= ");

You might also like