PID auto tune unit test

This commit is contained in:
rusefi 2018-11-22 23:06:06 -05:00
parent a417be192f
commit 64a592e507
4 changed files with 79 additions and 16 deletions

View File

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

View File

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

View File

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

View File

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