NOBのArduino日記!

NOBのArduino日記!

趣味は車・バイク・自転車・ラジコン・電子工作です。

PID_AutoTune_v0.hライブラリ(PID_ATune関数の使い方)

■PID_ATune関数
 PID_AutoTune_v0.hライブラリのPID_ATune関数は、PIDライブラリ用のPIDチューニングパラメータを作成するように設計されたオートチューナを作成します。

■使用例
 Arduino IDEで使用するPID_ATune関数の使用例は以下の通りです。
 試しにこのプログラムをArduino UNOで実行すると、DoModel関数で生成したInput値に対してPID関数でPID制御を開始します。
 図1の様に開始直後にシリアルモニター送信欄に「1」と入力し送信すると「Kp,Ki,Kd」の値が消え「tuning mode」と表示されます。
 その後PID_ATune関数が実行され、しばらく(実験では251秒)待つと最適化された「Kp,Ki,Kd」の値がPID関数に適用され図3の様にPCのシリアルモニタ上に出力されます。

#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 AutoTuneHelper(boolean start) {
  if (start)
    ATuneModeRemember = myPID.GetMode();
  else
    myPID.SetMode(ATuneModeRemember);
}

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

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;
  }
}
イメージ 1
図1:プログラム例
 

 イメージ 1
図2:Arduino IDE シリアルモニター(オートチューニング開始)

 

 イメージ 3
図3:Arduino IDE シリアルモニター(オートチューニング中)

 

 イメージ 2
図4:Arduino IDE シリアルモニター(251秒でオートチューニング終了)

 

■構文
 PID(&input,&output)

■パラメータ
 input  :PIDライブラリに入力として接続されているのと同じ変数
 output:PIDライブラリに出力として接続されているのと同じ変数

■戻り値
 ありません。

 
イメージ 1 イメージ 3
励みになりますのでよければクリック下さい(^o^)/

↩【PID制御!】目次に戻る