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

Conversation

t0mpr1c3
Copy link

Brett, there's a lot here so if you want to pull in just a specific feature let me know and I can create a new fork with just that change that you can pull from. The peak detection I think is an improvement because it uses information from both minima and maxima, instead of maxima only, so it potentially converges half a cycle sooner as well as being more accurate if the minima are variable. Lots of variations on Ziegler-Nichols. Slightly different but still a relay tuning method is AMIGOf, a robust algorithm for tuning PI controllers, although the tuning is slower to complete than other methods. Relay bias is useful sometimes so I have put it as a compile option.

  • changes to the peak convergence method
  • peak times and values now recorded for both minima and maxima
    in array peakTime[] and longer array peaks[]
  • new method of assessing convergence for peaks based on
    amplitude over last 1.5 cycles rather than levels of recent maxima
  • new variable inputCount counts number of inputs in lastInputs[]
    so that peaks are not called before lastInputs[] has been filled
  • convergence criterion set by PEAK_AMPLITUDE_TOLERANCE
  • finite state machine
  • new private variable enum AutoTunerState state records current
    state of algorithm
  • Runtime() initiates autotuner immediately first time around
    instead of waiting until next sampleTime
  • enumerated types
  • tuning algorithms selected by enum Control type
  • enum AutoTuneState state used instead of flag variable running
    to indicate autotuner state
  • enum PeakType used to describe whether peaks are maxima or minima
  • enum Mode used to describe whether under Automatic or Manual control
  • enum Direction used to describe sign of gain
  • enum Mode and Direction break dependency with original PID library
    (although this can easily be fixed)
  • changes to private methods and variables
  • minimum value of nLookBack set to 20 in method SetLookbackSec()
  • int variables nLookBack, peakCount changed to byte
  • peakTime[] changed to lastPeakTime[], made shorted, and indexed the same way
    as lastInputs[], etc.
  • got rid of private variable justevaled whose value was never checked
  • private variables justchanged, isMin, isMax, absMax, absMin made
    local to Runtime()
  • private method FinishUp() inlined so that phaseLag and inducedAmplitude
    can be local to Runtime()
  • new tuning rules
  • new tuning rules selectable by setting enum Control type
  • new private variables Kp, Ti, Td for calculation of gain parameters
  • private variables Ku, Kp made local to FinishUp();
  • induced amplitude calculated as average over previous 1.5 or 2 cycles
    used instead of difference between most extreme values ever observed
  • new variables and methods used by the AMIGOF_PI algorithm:
  • private variable K_process estimates the process gain from the steady
    state response to a step up in output
  • private variable originalNoiseBand saves value of noiseBand,
    which is tuned by the AMIGOF_PI algorithm
  • private method CheckStable() checks whether the values in lastInputs[]
    have converged to values within noiseBand of each other
  • implementation of relay bias for non-linear processes/to counter load disturbance
  • compile option to use relay bias code is set to undefined (i.e. do not use relay bias) by default
  • symmetry requirement for relay steps set by STEP_ASYMMETRY_TOLERANCE, tested using
    private variables avgStep1 and avgStep2
  • private arrays lastStepTime[], sumInputSinceLastStep[] and variable stepCount used
    to calculate offset in process variable over last 2 relay cycles
  • process variable offset returned from private method processVariableOffset
  • private variable relayBias calculated from offset in process variable
  • failure cases
  • autotune terminates without setting tuning parameters after 20 peaks or
    after timing out (too long since last peak identification or relay step)
  • time out period set by MAX_WAIT_MINUTES
  • dither
  • may be useful for quantized inputs
  • compile option set undefined (i.e. do not use dither) by default

t0mpr1c3 and others added 22 commits May 2, 2012 16:59
Add Pessen, Some Overshoot, and No Overshoot PID modes
Add Pessen, Some Overshoot, and No Overshoot PID modes
Conflicts:
	PID_AutoTune_v0/PID_AutoTune_v0.cpp
…expanded range of simulations in example sketch
@jhagberg
Copy link

Hej nice commit.

I need to change the controller value to this to get it to compile.
aTune.SetControlType(PID_ATune::AMIGOF_PI);

Is it just typo?

How long will a run of AMIGOF_PI take?

@t0mpr1c3
Copy link
Author

Thanks, can you do a pull request? I'm not exactly sure what the issue is because the firmware compiled OK for me without this.

AMIGOF takes longer than the default Ziegler Nichols because there is an additional step to estimate K_process which can take a while to converge under some conditions. But in my experience the results are far more robust (i.e. remain close to optimal when the process parameters change slightly).

@jhagberg
Copy link

Sure I can!
I am testing all of the autotunes
This far I can get ZIEGLER_NICHOLS_PI and ZIEGLER_NICHOLS_PID to work
Also TYREUS_LUYBEN_PI starts and finds max and min
Now running CIANCONE_MARLIN_PID
Also seems to work good and find max and mins.

I first tried aTune.SetControlType(PID_ATune::AMIGOF_PI);
Had it running all night but nothing really happens. All the other methods Switch the output up and down. But with AMIGOF nothing really happens and output is constant.

Am I doing something wrong or am I missing something? I have cloned your latest git repo!

Added missing "PID_ATune::" to get rid of compile error "was not declared in this scope" on Arduino v 1.0.5
@t0mpr1c3
Copy link
Author

AMIGOF has an extra stage and under certain conditions it fails to converge. (Usually very sluggish processes, in which case Tyreus Luyben PI is probably a good starting point.) You can experiment with the simulations to see which is likely to work best for your process.

Update AutoTune_Example.ino
@jhagberg
Copy link

Oki but you are supposed to see output changes in the same way as the other? On the serial monitor?

@jhagberg
Copy link

Aha so first you want to hold the process steady at baseline then steady after step up. I turned out debug and it made sense!

@sylvia43
Copy link

Can this be merged then?

@jhagberg
Copy link

I guess that is up to @br3ttb

@rusefi
Copy link

rusefi commented Nov 19, 2018

Just wanted to say "Great work @t0mpr1c3 "

@edgsc
Copy link

edgsc commented Mar 23, 2019

Great work, @t0mpr1c3 !

But I'm having problems to compile it on newer Arduino IDE (1.6.x).

`C:\Users\Acer\Documents\Arduino\libraries\PID_AutoTune_v0\PID_AutoTune_v0.cpp:20:58: error: variable 'tuningRule' must be const in order to be put into read-only section by means of 'attribute((progmem))'

PROGMEM Tuning tuningRule[PID_ATune::NO_OVERSHOOT_PID + 1] =
^`

I tried searching for this error message and I think it's because from IDE 1.0.x to 1.6.x they changed how to use PROGMEM; the code should be adapted (I tried but can't get it to work):
https://github.com/arduino/Arduino/wiki/1.6-Frequently-Asked-Questions#errors-related-to-avr-progmem-changes

Errors related to AVR PROGMEM changes
Q: I get an error message that says: variable 'message' must be const in order to be put into read-only section by means of 'attribute((progmem))': char message[] PROGMEM = "Hello!";. What can I do?
A: The latest avr-gcc compiler (used by Arduino 1.6.x) requires that variables in PROGMEM to be declared as const.

First of all check if an updated version of the libraries used in the sketch has been released. Upgrading libraries is far the best way to solve the problem.

If there are no alternatives you can go to the hard path and change the declaration in your sketch or in your library from

char message[] PROGMEM = "Hello!";

to

const char message[] PROGMEM = "Hello!";

Q: I have a similar error but it seems to be already const! Here's the error: variable 'lotOfMessages' must be const in order to be put into read-only section by means of 'attribute((progmem))': const char* lotOfMessages[] PROGMEM = {
A: In this case you have an array of messages (not just one) and you must tell the compiler that each one of them is const. Here how is it done, change:

const char* lotOfMessages[] PROGMEM = {

to

const char * const lotOfMessages[] PROGMEM = {

And, yes, it's really tricky even for experts.

Anyone having the same problem? How to get it to work?

And congratulations for the great work again!

@edgsc
Copy link

edgsc commented Mar 23, 2019

Great work, @t0mpr1c3 !

But I'm having problems to compile it on newer Arduino IDE (1.6.x).

`C:\Users\Acer\Documents\Arduino\libraries\PID_AutoTune_v0\PID_AutoTune_v0.cpp:20:58: error: variable 'tuningRule' must be const in order to be put into read-only section by means of 'attribute((progmem))'

PROGMEM Tuning tuningRule[PID_ATune::NO_OVERSHOOT_PID + 1] =
^`

I tried searching for this error message and I think it's because from IDE 1.0.x to 1.6.x they changed how to use PROGMEM; the code should be adapted (I tried but can't get it to work):
https://github.com/arduino/Arduino/wiki/1.6-Frequently-Asked-Questions#errors-related-to-avr-progmem-changes

Errors related to AVR PROGMEM changes
Q: I get an error message that says: variable 'message' must be const in order to be put into read-only section by means of 'attribute((progmem))': char message[] PROGMEM = "Hello!";. What can I do?
A: The latest avr-gcc compiler (used by Arduino 1.6.x) requires that variables in PROGMEM to be declared as const.

First of all check if an updated version of the libraries used in the sketch has been released. Upgrading libraries is far the best way to solve the problem.

If there are no alternatives you can go to the hard path and change the declaration in your sketch or in your library from

char message[] PROGMEM = "Hello!";

to

const char message[] PROGMEM = "Hello!";

Q: I have a similar error but it seems to be already const! Here's the error: variable 'lotOfMessages' must be const in order to be put into read-only section by means of 'attribute((progmem))': const char* lotOfMessages[] PROGMEM = {
A: In this case you have an array of messages (not just one) and you must tell the compiler that each one of them is const. Here how is it done, change:

const char* lotOfMessages[] PROGMEM = {

to

const char * const lotOfMessages[] PROGMEM = {

And, yes, it's really tricky even for experts.

Anyone having the same problem? How to get it to work?

And congratulations for the great work again!

Got it to work simply by adding "const" before PROGMEM:
PROGMEM Tuning tuningRule[PID_ATune::NO_OVERSHOOT_PID + 1] =
changed to

const PROGMEM Tuning tuningRule[PID_ATune::NO_OVERSHOOT_PID + 1] =

@skaterdude
Copy link

Hi, just tried to compile this in the latest Arduino IDE and got errors resulting from:
static const double CONST_PI = 3.14159265358979323846;
static const double CONST_SQRT2_DIV_2 = 0.70710678118654752440;
in the .h file. From what I read, it appears that the compiler changed and now flags anything that is not an integer when you declare it this way. Supposedly this is because it is non-standard to the compiler spec. All you have to do is change const to constexpr like so:
static constexpr double CONST_PI = 3.14159265358979323846;
static constexpr double CONST_SQRT2_DIV_2 = 0.70710678118654752440;
and I get a clean compile. I'm using Arduino 1.8.12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants