PID auto tune unit test
This commit is contained in:
parent
b646c994d7
commit
f1aaf779ce
|
@ -116,7 +116,10 @@ static msg_t etbThread(void *arg) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
percent_t actualThrottlePosition = getTPS();
|
||||||
|
|
||||||
if (engine->etbAutoTune) {
|
if (engine->etbAutoTune) {
|
||||||
|
autoTune.input = actualThrottlePosition;
|
||||||
autoTune.Runtime(&logger);
|
autoTune.Runtime(&logger);
|
||||||
|
|
||||||
etbPwmUp.setSimplePwmDutyCycle(autoTune.output);
|
etbPwmUp.setSimplePwmDutyCycle(autoTune.output);
|
||||||
|
@ -128,7 +131,6 @@ static msg_t etbThread(void *arg) {
|
||||||
|
|
||||||
percent_t targetPosition = getPedalPosition(PASS_ENGINE_PARAMETER_SIGNATURE);
|
percent_t targetPosition = getPedalPosition(PASS_ENGINE_PARAMETER_SIGNATURE);
|
||||||
|
|
||||||
percent_t actualThrottlePosition = getTPS();
|
|
||||||
|
|
||||||
currentEtbDuty = pid.getValue(targetPosition, actualThrottlePosition);
|
currentEtbDuty = pid.getValue(targetPosition, actualThrottlePosition);
|
||||||
|
|
||||||
|
@ -274,7 +276,7 @@ static void setTempOutput(float value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setTempStep(float value) {
|
static void setTempStep(float value) {
|
||||||
autoTune.oStep = value;
|
autoTune.SetOutputStep(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void initElectronicThrottle(void) {
|
void initElectronicThrottle(void) {
|
||||||
|
@ -288,6 +290,7 @@ void initElectronicThrottle(void) {
|
||||||
//
|
//
|
||||||
addConsoleActionF("set_etb", setThrottleDutyCycle);
|
addConsoleActionF("set_etb", setThrottleDutyCycle);
|
||||||
|
|
||||||
|
// this is useful one you do "enable etb_auto"
|
||||||
addConsoleActionF("set_etb_output", setTempOutput);
|
addConsoleActionF("set_etb_output", setTempOutput);
|
||||||
addConsoleActionF("set_etb_step", setTempStep);
|
addConsoleActionF("set_etb_step", setTempStep);
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ Tuning tuningRule[PID_AutoTune::NO_OVERSHOOT_PID + 1] =
|
||||||
PID_AutoTune::PID_AutoTune() {
|
PID_AutoTune::PID_AutoTune() {
|
||||||
running = false;
|
running = false;
|
||||||
|
|
||||||
controlType = ZIEGLER_NICHOLS_PI;
|
controlType = ZIEGLER_NICHOLS_PID;
|
||||||
noiseBand = 0.5;
|
noiseBand = 0.5;
|
||||||
setState(AUTOTUNER_OFF);
|
setState(AUTOTUNER_OFF);
|
||||||
oStep = 10.0;
|
oStep = 10.0;
|
||||||
|
@ -127,7 +127,7 @@ bool PID_AutoTune::Runtime(Logging *logging)
|
||||||
lastPeakTime[0] = now;
|
lastPeakTime[0] = now;
|
||||||
workingNoiseBand = noiseBand;
|
workingNoiseBand = noiseBand;
|
||||||
newWorkingNoiseBand = noiseBand;
|
newWorkingNoiseBand = noiseBand;
|
||||||
workingOstep = oStep;
|
workingOutputstep = oStep;
|
||||||
|
|
||||||
#if defined (AUTOTUNE_RELAY_BIAS)
|
#if defined (AUTOTUNE_RELAY_BIAS)
|
||||||
relayBias = 0.0;
|
relayBias = 0.0;
|
||||||
|
@ -293,9 +293,9 @@ bool PID_AutoTune::Runtime(Logging *logging)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined (AUTOTUNE_RELAY_BIAS)
|
#if defined (AUTOTUNE_RELAY_BIAS)
|
||||||
output = outputStart + workingOstep + relayBias;
|
setOutput(outputStart + workingOstep + relayBias);
|
||||||
#else
|
#else
|
||||||
output = outputStart + workingOstep;
|
setOutput(outputStart + workingOutputstep);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -303,9 +303,9 @@ bool PID_AutoTune::Runtime(Logging *logging)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if defined (AUTOTUNE_RELAY_BIAS)
|
#if defined (AUTOTUNE_RELAY_BIAS)
|
||||||
output = outputStart - workingOstep + relayBias;
|
setOutput(outputStart - workingOstep + relayBias);
|
||||||
#else
|
#else
|
||||||
output = outputStart - workingOstep;
|
setOutput(outputStart - workingOutputstep);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -425,7 +425,7 @@ bool PID_AutoTune::Runtime(Logging *logging)
|
||||||
}
|
}
|
||||||
// else state == STEADY_STATE_AFTER_STEP_UP
|
// else state == STEADY_STATE_AFTER_STEP_UP
|
||||||
// calculate process gain
|
// calculate process gain
|
||||||
K_process = (avgInput - lastPeaks[0]) / workingOstep;
|
K_process = (avgInput - lastPeaks[0]) / workingOutputstep;
|
||||||
|
|
||||||
#if defined (AUTOTUNE_DEBUG)
|
#if defined (AUTOTUNE_DEBUG)
|
||||||
Serial.print(F("Process gain "));
|
Serial.print(F("Process gain "));
|
||||||
|
@ -639,6 +639,8 @@ bool PID_AutoTune::Runtime(Logging *logging)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool tooManyCycles = peakCount >= 20;
|
||||||
|
bool tooLongBetween = ((now - lastPeakTime[0]) > (unsigned long) (AUTOTUNE_MAX_WAIT_MINUTES * 60000));
|
||||||
// if the autotune has not already converged
|
// if the autotune has not already converged
|
||||||
// terminate after 10 cycles
|
// terminate after 10 cycles
|
||||||
// or if too long between peaks
|
// or if too long between peaks
|
||||||
|
@ -649,10 +651,13 @@ bool PID_AutoTune::Runtime(Logging *logging)
|
||||||
((now - lastStepTime[0]) > (unsigned long) (AUTOTUNE_MAX_WAIT_MINUTES * 60000)) ||
|
((now - lastStepTime[0]) > (unsigned long) (AUTOTUNE_MAX_WAIT_MINUTES * 60000)) ||
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
((now - lastPeakTime[0]) > (unsigned long) (AUTOTUNE_MAX_WAIT_MINUTES * 60000)) ||
|
tooLongBetween ||
|
||||||
(peakCount >= 20)
|
tooManyCycles
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
#if EFI_UNIT_TEST
|
||||||
|
printf("tooManyCycles=%d tooLongBetween=%d\r\n", tooManyCycles, tooLongBetween);
|
||||||
|
#endif /* EFI_UNIT_TEST */
|
||||||
setState(FAILED);
|
setState(FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,7 +671,7 @@ bool PID_AutoTune::Runtime(Logging *logging)
|
||||||
|
|
||||||
// autotune algorithm has terminated
|
// autotune algorithm has terminated
|
||||||
// reset autotuner variables
|
// reset autotuner variables
|
||||||
output = outputStart;
|
setOutput( outputStart);
|
||||||
|
|
||||||
if (state == FAILED)
|
if (state == FAILED)
|
||||||
{
|
{
|
||||||
|
@ -684,7 +689,7 @@ bool PID_AutoTune::Runtime(Logging *logging)
|
||||||
// finish up by calculating tuning parameters
|
// finish up by calculating tuning parameters
|
||||||
|
|
||||||
// calculate ultimate gain
|
// calculate ultimate gain
|
||||||
double Ku = 4.0 * workingOstep / (inducedAmplitude * CONST_PI);
|
double Ku = 4.0 * workingOutputstep / (inducedAmplitude * CONST_PI);
|
||||||
|
|
||||||
#if defined (AUTOTUNE_DEBUG)
|
#if defined (AUTOTUNE_DEBUG)
|
||||||
Serial.print(F("ultimate gain "));
|
Serial.print(F("ultimate gain "));
|
||||||
|
@ -762,4 +767,30 @@ float PID_AutoTune::GetKd()
|
||||||
return Kp * Td;
|
return Kp * Td;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PID_AutoTune::setOutput(float output) {
|
||||||
|
this->output = output;
|
||||||
|
#if EFI_UNIT_TEST
|
||||||
|
printf("output=%f\r\n", output);
|
||||||
|
#endif /* EFI_UNIT_TEST */
|
||||||
|
}
|
||||||
|
|
||||||
|
void PID_AutoTune::SetOutputStep(double Step)
|
||||||
|
{
|
||||||
|
oStep = Step;
|
||||||
|
}
|
||||||
|
|
||||||
|
double PID_AutoTune::GetOutputStep()
|
||||||
|
{
|
||||||
|
return oStep;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PID_AutoTune::SetControlType(byte type)
|
||||||
|
{
|
||||||
|
controlType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte PID_AutoTune::GetControlType()
|
||||||
|
{
|
||||||
|
return controlType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -128,11 +128,12 @@ public:
|
||||||
float GetKi(); // computed tuning parameters.
|
float GetKi(); // computed tuning parameters.
|
||||||
float GetKd(); //
|
float GetKd(); //
|
||||||
|
|
||||||
double oStep;
|
|
||||||
byte peakCount;
|
byte peakCount;
|
||||||
float input;
|
float input;
|
||||||
float output;
|
float output;
|
||||||
|
|
||||||
|
void setOutput(float output);
|
||||||
|
|
||||||
#if EFI_UNIT_TEST
|
#if EFI_UNIT_TEST
|
||||||
double absMax;
|
double absMax;
|
||||||
double absMin;
|
double absMin;
|
||||||
|
@ -147,6 +148,7 @@ public:
|
||||||
PidAutoTune_AutoTunerState state; // * state of autotuner finite state machine
|
PidAutoTune_AutoTunerState state; // * state of autotuner finite state machine
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
double oStep;
|
||||||
|
|
||||||
double processValueOffset(double, // * returns an estimate of the process value offset
|
double processValueOffset(double, // * returns an estimate of the process value offset
|
||||||
double); // as a proportion of the amplitude
|
double); // as a proportion of the amplitude
|
||||||
|
@ -165,7 +167,7 @@ private:
|
||||||
float lastInputs[101]; // * process values, most recent in array element 0
|
float lastInputs[101]; // * process values, most recent in array element 0
|
||||||
byte inputCount;
|
byte inputCount;
|
||||||
float workingNoiseBand;
|
float workingNoiseBand;
|
||||||
float workingOstep;
|
float workingOutputstep;
|
||||||
float inducedAmplitude;
|
float inducedAmplitude;
|
||||||
float Kp, Ti, Td;
|
float Kp, Ti, Td;
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ static void testPidAutoZigZagStable() {
|
||||||
|
|
||||||
PID_AutoTune at;
|
PID_AutoTune at;
|
||||||
at.SetLookbackSec(5);
|
at.SetLookbackSec(5);
|
||||||
|
at.SetControlType(PID_AutoTune::ZIEGLER_NICHOLS_PI);
|
||||||
at.sampleTime = 0; // not used in math only used to filter values out
|
at.sampleTime = 0; // not used in math only used to filter values out
|
||||||
assertEqualsM("nLookBack", 20, at.nLookBack);
|
assertEqualsM("nLookBack", 20, at.nLookBack);
|
||||||
|
|
||||||
|
@ -108,7 +109,7 @@ static void testPidAutoZigZagStable() {
|
||||||
bool result = at.Runtime(&logging);
|
bool result = at.Runtime(&logging);
|
||||||
assertEqualsM("should be true", 1, result);
|
assertEqualsM("should be true", 1, result);
|
||||||
|
|
||||||
assertEqualsM("output", 0.0, at.output);
|
assertEqualsM("testPidAutoZigZagStable::output", 0.0, at.output);
|
||||||
|
|
||||||
assertEqualsM("peakCount@80", 5, at.peakCount);
|
assertEqualsM("peakCount@80", 5, at.peakCount);
|
||||||
assertEqualsM("ki", 27.7798, at.GetKi());
|
assertEqualsM("ki", 27.7798, at.GetKi());
|
||||||
|
@ -157,9 +158,35 @@ static void testPidAutoZigZagGrowingOsc() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void testPidAutoZigZagZero() {
|
||||||
|
printf("*************************************************** testPidAutoZigZagGrowingOsc\r\n");
|
||||||
|
|
||||||
|
oscRange = 0;
|
||||||
|
mockTimeMs = 0;
|
||||||
|
|
||||||
|
PID_AutoTune at;
|
||||||
|
at.SetLookbackSec(5);
|
||||||
|
at.sampleTime = 0; // not used in math only used to filter values out
|
||||||
|
|
||||||
|
int startMockMs;
|
||||||
|
|
||||||
|
for (int i =0;i<110;i++) {
|
||||||
|
startMockMs = mockTimeMs;
|
||||||
|
printf("loop=%d %d\r\n", i, startMockMs);
|
||||||
|
for (; mockTimeMs < CYCLE + startMockMs; mockTimeMs++) {
|
||||||
|
at.input = zigZagValue(mockTimeMs);
|
||||||
|
// bool result = at.Runtime(&logging);
|
||||||
|
// assertFalseM("should be false#4", result);
|
||||||
|
}
|
||||||
|
oscRange *= 1.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void testPidAutoZigZag() {
|
void testPidAutoZigZag() {
|
||||||
printf("*************************************************** testPidAutoZigZag\r\n");
|
printf("*************************************************** testPidAutoZigZag\r\n");
|
||||||
|
|
||||||
|
|
||||||
|
testPidAutoZigZagZero();
|
||||||
testPidAutoZigZagStable();
|
testPidAutoZigZagStable();
|
||||||
|
|
||||||
testPidAutoZigZagGrowingOsc();
|
testPidAutoZigZagGrowingOsc();
|
||||||
|
|
Loading…
Reference in New Issue