Ovde je objasnjenje principa rada i eliminacija suma u povratnoj sprezi...
Ovo je primer koriscenja biblioteke:
Code:
#include <PID_v1.h>
#include <PID_AutoTune_v0.h>
byte ATuneModeRemember=2;
double input=80, output=50, setpoint=180;
double kp=2,ki=0.5,kd=2;
double kpmodel=1.5, taup=100, theta[50];
double outputStart=5;
double aTuneStep=50, aTuneNoise=1, aTuneStartValue=100;
unsigned int aTuneLookBack=20;
boolean tuning = false;
unsigned long modelTime, serialTime;
PID myPID(&input, &output, &setpoint,kp,ki,kd, DIRECT);
PID_ATune aTune(&input, &output);
//set to false to connect to the real world
boolean useSimulation = true;
void setup()
{
if(useSimulation)
{
for(byte i=0;i<50;i++)
{
theta[i]=outputStart;
}
modelTime = 0;
}
//Setup the pid
myPID.SetMode(AUTOMATIC);
if(tuning)
{
tuning=false;
changeAutoTune();
tuning=true;
}
serialTime = 0;
Serial.begin(9600);
}
void loop()
{
unsigned long now = millis();
if(!useSimulation)
{ //pull the input in from the real world
input = analogRead(0);
}
if(tuning)
{
byte val = (aTune.Runtime());
if (val!=0)
{
tuning = false;
}
if(!tuning)
{ //we're done, set the tuning parameters
kp = aTune.GetKp();
ki = aTune.GetKi();
kd = aTune.GetKd();
myPID.SetTunings(kp,ki,kd);
AutoTuneHelper(false);
}
}
else myPID.Compute();
if(useSimulation)
{
theta[30]=output;
if(now>=modelTime)
{
modelTime +=100;
DoModel();
}
}
else
{
analogWrite(0,output);
}
//send-receive with processing if it's time
if(millis()>serialTime)
{
SerialReceive();
SerialSend();
serialTime+=500;
}
}
void changeAutoTune()
{
if(!tuning)
{
//Set the output to the desired starting frequency.
output=aTuneStartValue;
aTune.SetNoiseBand(aTuneNoise);
aTune.SetOutputStep(aTuneStep);
aTune.SetLookbackSec((int)aTuneLookBack);
AutoTuneHelper(true);
tuning = true;
}
else
{ //cancel autotune
aTune.Cancel();
tuning = false;
AutoTuneHelper(false);
}
}
void AutoTuneHelper(boolean start)
{
if(start)
ATuneModeRemember = myPID.GetMode();
else
myPID.SetMode(ATuneModeRemember);
}
void SerialSend()
{
Serial.print("setpoint: ");Serial.print(setpoint); Serial.print(" ");
Serial.print("input: ");Serial.print(input); Serial.print(" ");
Serial.print("output: ");Serial.print(output); Serial.print(" ");
if(tuning){
Serial.println("tuning mode");
} else {
Serial.print("kp: ");Serial.print(myPID.GetKp());Serial.print(" ");
Serial.print("ki: ");Serial.print(myPID.GetKi());Serial.print(" ");
Serial.print("kd: ");Serial.print(myPID.GetKd());Serial.println();
}
}
void SerialReceive()
{
if(Serial.available())
{
char b = Serial.read();
Serial.flush();
if((b=='1' && !tuning) || (b!='1' && tuning))changeAutoTune();
}
}
void DoModel()
{
//cycle the dead time
for(byte i=0;i<49;i++)
{
theta[i] = theta[i+1];
}
//compute the input
input = (kpmodel / taup) *(theta[0]-outputStart) + input*(1-1/taup) + ((float)random(-10,10))/100;
}
Konkretno sta meni nije jasno:
Po teoriji na objekat upravljanja se dovodi diskretan signal koji zavisi od izmerene vrednosti i zadate vrednosti. Npr na grejac, ukoliko je temperatura manja od zadate grejac je prikljucen na maksimalan napon, ukoliko je temperatura veca od zadate onda se grejac ISKLJUCUJE. Tokom rada meri se maksimalna i minimalna vrednost oscilacija, kao i perioda oscilacija. Na osnovu ovih vrednosti proracunava se Ku i Tu, a zatim se parametri odredjuju na osnovu tabele.
Prvo pitanje da li se grejac ukljucuje na maksimalnu vrednost i iskljucuje ili se napon npr menja 220-100?
Tu je perioda oscilovanja i to je jasno. Prilikom proracuna vrednosti Ku=4*D/(A*PI), vrednost A je razlika maksimalne i minimalne vrednosti povratne sprege, i to je neka vrednost AD konvertora, interesuje me koliko je D, (to se ddefinise na pocetku, ali kako?) Na slici se vide ove vrednosti...