Open t0mpr1c3 opened 11 years ago
I can definitely see benefit to something like a hard-link between the PID and Autotune. at the same time, there's a little dance that happens between pid and autotune when the "autotune" button is pressed, and I don't think that dance will be the same in every application. having a them separate allows for some flexibility on that front.
maybe the solution is a LinkedAutotune class that inherits from the autotuner. it could get passed all the same constructors, along with a pointer to a pid object.
I'll probably code something up in a fork. It may not be for everybody, like you say.
Here is the class I'm using, which combine PID and PID_ATune. Set autoTune = true, and it will adapt the tuned parameters automatically when the tuning process is completed.
`
class PID_enhanced: public PID, public PID_ATune {
private:
byte currentMode = 2;
public:
double Input, Output, Setpoint = 0;
bool autoTune = false;
PID_enhanced(double Kp = 2, double Ki = 5, double Kd = 1,
int ControllerDirection = DIRECT,
int SampleTime = 100,
double OutputLimit_min = 0, double OutputLimit_max = 255,
int controlType = 0)
: PID(&this->Input, &this->Output, &this->Setpoint, Kp, Ki, Kd, ControllerDirection),
PID_ATune(&this->Input, &this->Output){
SetOutputLimits(OutputLimit_min, OutputLimit_max);
SetSampleTime(SampleTime);
SetControlType(controlType);
}
void setup() {
SetMode(AUTOMATIC);
backupMode();
Cancel();
}
int tune() {
int result = 0;
if (autoTune) {
result = PID_ATune::Runtime();
if (result !=0) {
adaptTunedParameters();
Cancel();
autoTune = false;
}
}
return result;
}
int tuneAndCompute() {
if (autoTune) {
return tune();
} else {
Compute();
return 0;
}
}
void backupMode() {
currentMode = GetMode();
}
void restoreMode() {
SetMode(currentMode);
}
double GetOperatingKp()
{
return PID::GetKp();
}
double GetOperatingKi()
{
return PID::GetKi();
}
double GetOperatingKd()
{
return PID::GetKd();
}
double GetTunedKp()
{
return PID_ATune::GetKp();
}
double GetTunedKi()
{
return PID_ATune::GetKi();
}
double GetTunedKd()
{
return PID_ATune::GetKd();
}
void adaptTunedParameters() {
SetTunings(GetTunedKp(), GetTunedKi(), GetTunedKd());
Serial.println("Parameters set to: ");
Serial.print("Kp: ");Serial.print(GetOperatingKp());Serial.print("; ");
Serial.print("Ki: ");Serial.print(GetOperatingKi());Serial.print("; ");
Serial.print("Kd: ");Serial.print(GetOperatingKd());Serial.print("; ");
Serial.println();
}
};
`
I tried using your code, Wei1234c, but it returns me this error:
Archiving built core (caching) in: C:\Users\EDUARD~1\AppData\Local\Temp\arduino_cache_379640\core\core_arduino_avr_uno_0c812875ac70eb4a9b385d8fb077f54c.a
C:\Users\EDUARD~1\AppData\Local\Temp\ccGD3Nq5.ltrans0.ltrans.o: In function `main':
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/main.cpp:43: undefined reference to `setup'
C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino/main.cpp:46: undefined reference to `loop'
collect2.exe: error: ld returned 1 exit status
exit status 1
Has anyone got it to work?
Thanks!
It seems desirable to me to have the entire PID object passed to the auto tune function rather than the individual variables. Probably not possible since I don't see a way to do this that would not break existing programs.