Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New tuning rules, peak detection method, etc. #11

Open
wants to merge 24 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6329d97
Add dither to smooth quantization errors
t0mpr1c3 May 2, 2012
a6cdc3d
Add dither to smooth quantization errors
t0mpr1c3 May 2, 2012
27a106d
minor edits to dithering
t0mpr1c3 May 2, 2012
29c5dac
C port. Method names changed so longer works with example.
t0mpr1c3 May 13, 2012
e38966d
C port. Method names changed so longer works with example.
t0mpr1c3 May 13, 2012
b6cf56a
Enumerated types
t0mpr1c3 May 15, 2012
b3f1eab
Enumerated types, corrected formula for ultimate gain.
t0mpr1c3 May 15, 2012
d1bfc5a
Enumerated types
t0mpr1c3 May 15, 2012
1d70637
Correct ultimate gain formula, dither option, use enumerated types
May 17, 2012
c30ac5b
Merge branch 'd1bfc5aed467366383dbfe00456d4b8caf4257f8'
t0mpr1c3 May 17, 2012
117e337
Calculate induced amplitude net of dither and expected noise
t0mpr1c3 May 17, 2012
395ecb0
Typo
t0mpr1c3 May 17, 2012
52df065
merged recent changes from br3ttb
t0mpr1c3 Oct 26, 2013
e0724cf
dither as compile option, remove hysteresis from calculation of induc…
t0mpr1c3 Oct 26, 2013
2c8f6f2
AMIGOf PI tuning, rationalized peak detection, finite state machine, …
t0mpr1c3 Oct 27, 2013
f66ea69
implement biased relay
t0mpr1c3 Oct 29, 2013
7ef0d8f
fixup after simulation testing
t0mpr1c3 Oct 29, 2013
7bf0f81
trapezoidal approximation for calculating relay bias
t0mpr1c3 Oct 29, 2013
f83a36b
further debugging after simulations
t0mpr1c3 Oct 29, 2013
ce1ffad
relay bias as compile option, simulation with load disturbance
t0mpr1c3 Oct 30, 2013
683f3e2
corrected calculation of Pu, tuning rule table, removed AMIGOF compil…
t0mpr1c3 Nov 1, 2013
58da68e
relay bias respects output limits
t0mpr1c3 Nov 5, 2013
fbd02de
Update AutoTune_Example.ino
jhagberg Apr 18, 2014
f7ac482
Merge pull request #1 from jhagberg/master
t0mpr1c3 Apr 18, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
249 changes: 249 additions & 0 deletions PID_AutoTune_v0/Examples/AutoTune_Example/AutoTune_Example.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
#include "PID_v1.h"
#include "PID_AutoTune_v0.h"

// set simulation model
// define one, undef the others
#undef SIMULATION_MODEL_LAG_DOMINATED
#undef SIMULATION_MODEL_DELAY_DOMINATED
#define SIMULATION_MODEL_BALANCED_LAG_AND_DELAY
#undef SIMULATION_MODEL_LOAD_DISTURBANCE

// undefine to connect to the real world
#define USE_SIMULATION

// simulation model parameters
double kpmodel, taup, theta[50];
byte deadTime;

// optional white noise variance for simulation
// NB variance of U(0,1) = 1/12
#define SQRT12_DIV_100 0.03464102
double noiseVariance;

// initial state
double input = 80, output=50, setpoint=180;

// default PID tuning
double kp=2, ki=0.5, kd=2;

// autotuner defaults
double outputStart = 5;
double aTuneStep = 30;
double aTuneNoise = 0.5;
unsigned int aTuneLookBack = 5;
boolean tuning = false;

byte ATuneModeRemember;
unsigned long modelTime, serialTime;
int modelStep, tuningStep;

PID myPID(&input, &output, &setpoint, kp, ki, kd, PID::DIRECT);
PID_ATune aTune(&input, &output);

extern Tuning tuningRule[];

void setup()
{

#if !defined (USE_SIMULATION)
for(byte i = 0; i < 50; i++)
{
theta[i] = outputStart;
}
#endif

modelTime = 0;
modelStep = 0;
tuningStep = 0;

// Setup the PID
myPID.SetMode(PID::AUTOMATIC);

// set control type for autotuner
// general considerations:
// ZIEGLER_NICHOLS_PI is the default and is intended for good
// noise rejection rather than servo control
// it is less robust than other rules, often
// with higher proportional gain and lower integral gain and often gives oscillatory results for lag-dominated processes
// TYREUS_LUYBEN_PI is more conservative and considered better for lag-dominated processes
// CIANCONE_MARLIN_PI is suggested for delay-dominated processes
// AMIGOF_PI gives acceptable conservative tunings for most processes
// PI tunings perform well for delay dominated processes
// for lag-dominated processes PID tunings are better because
// the derivative term allows higher integral gain
//aTune.SetControlType(PID_ATune::AMIGOF_PI);
//aTune.SetControlType(PID_ATune::ZIEGLER_NICHOLS_PI);
//aTune.SetControlType(PID_ATune::TYREUS_LUYBEN_PI);
aTune.SetControlType(PID_ATune::ZIEGLER_NICHOLS_PID);
//aTune.SetControlType(PID_ATune::NO_OVERSHOOT_PID);

// set up simulation parameters
#if defined (SIMULATION_MODEL_LAG_DOMINATED)
kpmodel = 1.0;
taup = 100;
deadTime = 5;
noiseVariance = 0.1;
#endif

#if defined (SIMULATION_MODEL_BALANCED_LAG_AND_DELAY) || defined (SIMULATION_MODEL_LOAD_DISTURBANCE)
kpmodel = 1.0;
taup = 50;
deadTime = 30;
noiseVariance = 0.1;
#endif

#if defined (SIMULATION_MODEL_DELAY_DOMINATED)
kpmodel = 1.0;
taup = 20;
deadTime = 50;
noiseVariance = 0.1;
#endif

if (tuning)
{
tuning = false;
changeAutoTune();
tuning = true;
}
serialTime = 0;
Serial.begin(9600);
randomSeed(0);
}

void loop()
{
unsigned long now = millis();

#if !defined (USE_SIMULATION)
// pull the input in from the real world
input = analogRead(0);
#endif

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);

// change set point
setpoint = 130;

}
}
else
{
tuningStep = 0;
myPID.Compute();
}

#if defined (USE_SIMULATION)
theta[deadTime] = output;
if (now >= modelTime)
{
modelTime += 50;
modelStep++;
tuningStep++;
DoModel();

#if defined (SIMULATION_MODEL_LOAD_DISTURBANCE)
if (tuningStep == 50)
{
Serial.println("process disturbed");
kpmodel * 0.9;
}
#endif

}

#else // !defined USE_SIMULATION
analogWrite(0, output);
#endif

//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();
// press '1' to toggle autotuner on and off
if (((b == '1') && !tuning) || ((b != '1') && tuning))
changeAutoTune();
}
}

void DoModel()
{
// cycle the dead time
for (byte i = 0; i < deadTime; i++)
{
theta[i] = theta[i + 1];
}
// compute the input
input = (kpmodel / taup) * (theta[0] - outputStart) + input * (1 - 1 / taup) +
((float)random(-50, 50)) * noiseVariance * SQRT12_DIV_100;
}
Loading