klipper icon indicating copy to clipboard operation
klipper copied to clipboard

pid improvements

Open dans98 opened this issue 2 years ago • 52 comments

This PR is related to improving PID control within the constraints Klipper currently operates under. I've made changes to the calibration algorithm as well standard positional form algorithm. Additionally I've added a standard velocity form algorithm, that eliminates to potential for integral windup.

Please see one of the 2 commit messages for greater details, test results, and links to relevant papers.

-Dan S.

dans98 avatar Dec 24 '22 19:12 dans98

I'm using both PID functions since quite a while and have not noticed anything negative. Working stable and nicely.

What I find especially useful is the asymmetry reading, providing an indication between heating capacity and heat loss. This lead to the conclusion that on my two printers the 50W cartridge in combination with the given hotend was too weak. Upgrading both to 70W fixed the asymmetry and are both controlled nicely by the algorithms.

Should @KevinOConnor consider this PR (I hope so), then this should be explained in the documentation.

I wish all of you a happy holiday season!

Sineos avatar Dec 25 '22 08:12 Sineos

I have used that for couple of days, works great, provides much better values than it was. 'pid_v' provides an ability to get rid of first big overshoot. My biggest thanks to author.

The-Futur1st avatar Dec 26 '22 15:12 The-Futur1st

Tried this today.. works well

kejar31 avatar Dec 27 '22 20:12 kejar31

klippy (7).log Getting this when trying to use pid_v: File "/home/pi/klipper/klippy/extras/heaters.py", line 281, in check_busy or abs(self.prev_der) > PID_SETTLE_SLOPE) AttributeError: ControlVelocityPID instance has no attribute 'prev_der'

celtare21 avatar Dec 28 '22 11:12 celtare21

@celtare21 I see it, and i will fix that tonight. it looks like you are the first person to test this that uses m109/m104, as that looks to be what triggered it.

dans98 avatar Dec 28 '22 16:12 dans98

@celtare21 I see it, and i will fix that tonight. it looks like you are the first person to test this thats uses m109/m104, as that looks to be what triggered it.

Yeah I still use the slicer start/end gcode. Waiting for the fix then i'll try the velocity algorithm too, for now using the improved pid algo temps look both more stable and the overshoot is much lower than default

celtare21 avatar Dec 28 '22 20:12 celtare21

@celtare21 you should be able to test it now!

dans98 avatar Dec 28 '22 22:12 dans98

Ich habe nach einem Klipperupdate das Problem das mein Drucker bei ca. 145C mit dem aufheizen abbricht was auch beim PID des Hotends so ist

Maik35 avatar Dec 29 '22 06:12 Maik35

@celtare21 you should be able to test it now!

Can confirm that pid_v now works fine

celtare21 avatar Dec 29 '22 13:12 celtare21

Ich habe nach einem Klipperupdate das Problem das mein Drucker bei ca. 145C mit dem aufheizen abbricht was auch beim PID des Hotends so ist

@Maik35 Hier gehts um was völlig anderes. Am besten du versuchst dein Glück bei Discord in der Klipper Community https://discord.klipper3d.org/

freakydude avatar Dec 29 '22 13:12 freakydude

Thanks. Very interesting. I have two high-level comments:

  1. On a procedural level, this PR is going to be hard to review and merge as it seems to be mixing functional changes with unrelated changes. (For example, changing the core algorithms in the same commit that renames variables, makes whitespace changes, changes filenames, and similar.) It's important that changes be made in small functional chunks so that we can utilize tools like git bisect and git revert. Viewing these commits right now it appears to be a "rewrite" of the code. It's fine if we ultimately obtain totally new versions of the code after several commits. But in my experience a single bulk replacement of the existing code with new code greatly increases the risk of introducing regressions.
  2. It's unclear to me when I should use a pid or pid_v controller. I suspect other users would be similarly unsure. It's also not clear to me if there are a sufficient number of users that would obtain a real-world benefit to a pid_v controller (some notes on this at https://www.klipper3d.org/CONTRIBUTING.html ). So, for the pid_v commit, I suspect we would need some kind of user facing document detailing the tests a user should run to determine if a pid_v controller should be used and the benefits the user should expect from utilizing it.

Cheers, -Kevin

KevinOConnor avatar Dec 31 '22 03:12 KevinOConnor

+1 On the documentation. Would love to see all of it properly documented, comparisons between options etc. As well as what would a "proper" pid tuning session be like.

celtare21 avatar Dec 31 '22 10:12 celtare21

I totally agree with Kevin. I played around a bit with it. On difference I noticed is, that it takes longer to reach the target temperature but (if it was the calibrated one) it is hold with less tolerance. Nice!

I tried it with the heat bed... Same result but significant longer time to heat up. In my case I would stay with classic pid for it.

Using a target temperature, not calibrated, the algorithm has permanent problems... Classic pid works better in this case ... But can't proof that, just a feeling.

Maybe it helps

freakydude avatar Jan 01 '23 02:01 freakydude

@KevinOConnor

Viewing these commits right now it appears to be a "rewrite" of the code. It's fine if we ultimately obtain totally new versions of the code after several commits. But in my experience a single bulk replacement of the existing code with new code greatly increases the risk of introducing regressions.

To an extent this is the case, but I will be happy to answer any questions about the changes i've made.

  1. It's unclear to me when I should use a pid or pid_v controller. I suspect other users would be similarly unsure. It's also not clear to me if there are a sufficient number of users that would obtain a real-world benefit to a pid_v controller (some notes on this at https://www.klipper3d.org/CONTRIBUTING.html ).

Generally speaking pid_v will almost always be better, because it intrinsically prevents integral wind up. The only time pid_v wouldn't be better would be when used with noisy sensor readings, because it uses a 1st and 2nd derivative. Thankfully it's easy to tell if pid_v will work or not. You do a test run, and if it doesn't settle in it won't work. The only thing you can really change would be to use different pid tuning parameters (more on that in a moment).

Astrom & Hagglund covers velocity at a high level int their books, for example section 3.5 of this one. https://www.ucg.ac.me/skladiste/blog_2146/objava_92847/fajlovi/Astrom.pdf

Here are some comparison graphs from my hotend, using the same pid parameters.

The plot short hand: origonal = the current control algorithm used by klipper updated = the updated version of the original velocity form = the new velocity control algorithm

Plot of the full test runs.

zoomed in showing the initial warm up with no wind-up/overshoot.

This plot shows the summation of absolute variance from the target temp, once they have all settled in. Zero variance would be a perfectly strait horizontal line.

Here is an example of my very noisy AC powered, high thermal mass bed, with a tortures target temperature of 40C. Velocity control just did not work with Ziegler-Nichols parameters, but when i switched to Cohen-Coon as @Sineos recommended I got far better results with positional and velocity form control, but velocity form was better overall.

The plot short hand: positional - the current control algorithm used by klipper velocity - the new velocity control algorithm zn - Ziegler-Nichols cc - Cohen-Coon calibraded - pid parameters generated directly from a calibration run. manual - pid parameters generated from a calibration run that have been manually tweaked to yield better performance.

Plot of the full test runs.

zoomed in showing the initial warm up. Because of the high thermal mass and large delay associated with my bed i always have overshoot, but it's worth noting velocity form always has less.

absolute variance

So, for the pid_v commit, I suspect we would need some kind of user facing document detailing the tests a user should run to determine if a pid_v controller should be used and the benefits the user should expect from utilizing it.

I'm, out of town at the moment, but i'll ty and write something up over the next few days, and i'll run it by the community on discourse.

dans98 avatar Jan 01 '23 07:01 dans98

That explains my observation. Also, I found the rest of your Klipper Discourse mentioned in one of your commits earlier very helpful for understanding.

I didn't realized that you did 3 things:

  • Modified the current PID algorithm
  • Additional implemented a PID Velocity variant
  • Updated the calibration algorithm for both

As I switched to your branch and switched at the same time to pid_v, my extruder and heater bed heat up time inceased. In fact, not really. In my start code, the printer starts to print if the target temp is reached the first time within a tolerance of 2.5%, With PID it overshoots the target temp after that - but starts printing. With PID_V the print starts at a later time point (after the classic PID would be settled down to the target temp).

Maybe it would help people with similiar observation, to describe in the documentation for Config_Reference.md on a high level that pid has high overshots on initial target temp changes in contrast to pid_v which tries to avoid them, resulting in a longer time to reach the target temp (or higher) the first time. But beside of that both algorithms result in a more accurate temperature. In addition I found only in the WRITE_FILE description a word about the TOLERANCE parameter for PID_CALIBRATE. I would give the parameter more attention for people with noisy hardware or similar problems.

And finally, a question I asked myself and maybe you can answer this: Is there a way to calibrate more target temps? As I mentioned earlier - for example changing between PLA and ABS, my target temps would change from 210/65 to 245/115°C. What target temp would result into a more accurate result for both filaments? Just the average like 227.5/90°C?

Anyway, great work. Would really like to see this pull request merged!

(Sorry for my average english level)

freakydude avatar Jan 02 '23 11:01 freakydude

Thanks for the additional information.

Generally speaking pid_v will almost always be better

What does it mean to be "better" in this context? Is it better in the mathematical sense of less deviation from requested, or better in the sense that users will obtain real-world prints with noticeably improved quality?

I do find this interesting. For what it is worth though, all the pid_v graphs look roughly the same to me at a high-level. All the extruder graphs settle at roughly 2 minutes, and the bed graphs (with the exception of "positional zn calibrated") generally settle between 3 to 5 minutes. These times aren't significant when compared to a typical print time of 2-5 hours. So, I'm not sure I'd add a new option to Klipper for pid_v.

Again, I do find this interesting, and I'll try to review your code to better understand it. I'll start with a focus on the pid_calibrate changes.

Cheers, -Kevin

KevinOConnor avatar Jan 04 '23 17:01 KevinOConnor

Hi,

I'm seeing much more stable temperatures in my machine with this patch. I run an 80W heater and a 24 CFM fan, and the upstream code was never able to effectively regulate this combo for me.

I'm not currently using the velocity form.

Best regards, Lasse

dalegaard avatar Jan 05 '23 02:01 dalegaard

What does it mean to be "better" in this context? Is it better in the mathematical sense of less deviation from requested, or better in the sense that users will obtain real-world prints with noticeably improved quality?

These times aren't significant when compared to a typical print time of 2-5 hours. So, I'm not sure I'd add a new option to Klipper for pid_v.

@KevinOConnor

The two points above are linked in my opinion, so I will see if I can answer your question and justify why in my opinion pid_v should exist as an option. I apologize upfront as I’ve had a really 48 hours at work thanks to some major release issue (not my work), so this might get a little rambly.

The most obvious way pid_v is better is that it drastically reduces or completely removes overshoot because of integral wind-up. In the grand scheme of things (as you mentioned), overshoot doesn’t affect print quality, or print time. However,It does help reduce the amount of material you waste printing skirts or using a custom priming routine.

For me that means I'm wasting several meters less filament per spool. I do a lot of small quick prints (less than 30 mins) for prototyping stuff, and I print hot so i get more oozing than others during the warmup.

Where pid_v is better, but in a far less obvious way, is keeping the temp on target.

bang bang, positional pid, velocity pid, etc are all doing the same thing, trying to balance a thermal equation. In the case of a hot end, you have the heater on one side putting heat in. On the other you have ambient temp, print temp, print speed, volumetric flow rate, cooling fan speed etc playing a part in taking heat out.

Each heater has what I like to call a work envelope. At the low end it’s overpowered for the given print parameters and will struggle to hold temp. At the high end, it’s under powered, and will struggle to hold temp. In the middle of the envelope is the sweat spot. Pid_v shines its brightest when you move away from the sweet spot.

Given the plethora of printers, hotends, thermistors, beds, and bed heaters on the market, it would be foolish to say every single user is going to see a marked improvement in print quality. If someone is running their printer with the hot end and bed in the sweet spot they might see a small or no improvement. Someone with their bed or hot end in the sweet spot but not the other should see some improvement. Someone with neither heater in the sweet spot should see a more significant improvment.

On my printer the bed is the most problematic heater. So I’ll use graphs for that.

First I should explain what these graphs are showing in more detail. For each pwm update interval i’m calculating variance as abs(target temp - reported temp). The graph is showing the individual variances summed over time. Thus the higher up the Y axis a curve goes the worse it is at keeping the heater at the target temp.|

my bed calibrated at 40C 40

and again at 75C 75

For both graphs just look at the “positional cc calibrated” & “velocity cc calibrated” curves. At 40C (well outside my beds sweet spot) you can see that velocity pid is far better at keeping the bed on target. At 75C (close to the middle of my beds sweet spot), the two algorithms are on par with each other.

Also take a look at the Y axis, velocity control finished both tests around 300, so it held its level of control relatively constant, while positional control didn’t.

I don’t have any graphs of it on hand, but the same thing will happen as i get close to the upper limit of my bed 110-120C. Velocity control maintains better control than positional control.

Holding tighter temperature control on the bed has very visible effects on print quality. As jslaker mentioned in discourse when the bed temp fluctuates you can get z banding/breathing, because beds do not heat up uniformly. And as he also mentioned cnc kitchen did a nice video on the topic.

The video is talking about bang bang vs pid, but the concept is universal. When the temp of the bed fluctuates, the bed will flex because the bed won't heat uniformly. Depending on what your bed is made from and how it is constrained, the effects can be from mild to extreme.

https://www.youtube.com/watch?v=9JyydfcOcD0

tighter control has positive effects on hot ends as well. if your hot end temp starts fluctuating to much you can get what looks like a case of inconsistent extrusion caused by a clocked nozzle or extruder that slips slightly.

dans98 avatar Jan 05 '23 22:01 dans98

What does it mean to be "better" in this context? Is it better in the mathematical sense of less deviation from requested, or better in the sense that users will obtain real-world prints with noticeably improved quality?

@KevinOConnor

In addition to DanS' comments re: basic print quality, one of the issues I've personally encountered with the existing PID implementation is that auto-tuned variables will essentially never correctly converge for some bed/heater combinations due to overshoot. My suspicion is that the combination of a bed with high thermal mass with a thermistor on the opposite side of the bed from the heater (and therefore considerable lag time in response to saturated heater output) and high heater power is particularly susceptible.

As you noted in #4427, using TEMPERATURE_WAIT instead of M190 can help bandaid over this, but the downside is that bed temperature will continue to oscillate as the PID controller keeps hunting for the set point. In my case, the PID controller was never able to fully recover from overshoot with auto-calibrated terms and would run hot throughout a print.

I was able to get things behaving properly after some extensive manual tuning, but, given the complexity of PID tuning, I'd think that's a pretty big ask of most users.

In my testing, my manual terms still heat more quickly (read: are considerably more aggressive) than what I'm seeing with these changes, but the biggest difference is that it generated terms that would consistently settle at the set point in a reasonable amount of time.

I have seen improvement with my hotend as well, but in that case, it's more "holds setpoint more consistently" rather than "never reaches setpoint." :)

jslaker avatar Jan 05 '23 22:01 jslaker

I use the bambulab hotend which heats up very quick, also the PID tune process is done within one minute. The tune returns almost similar values as the master branch. But as i changed to PID_V algorythm the heater is much more stable, overshoot less and holds the temperature during print within 0,5deg, also the range of pwm is much smaller. With PID it shoots peranently over 50%, with PID_V it is less than 20%. I vote to merge at least the PID_V algo.

Edit: After some more testing my opinion is:

  • The PID_CALIBRATE routine should return additional PID , optional PID values for "Some Overshoot" etc.
  • pid_v should be availible as it gives good improovement, specially in high speed hotend like bambu.

pki791 avatar Jan 07 '23 10:01 pki791

@KevinOConnor

I'm working on the documentation now, is there a place you want me to put the spreadsheet i created? https://klipper.discourse.group/uploads/short-url/oR6MJ0s0I07T2LIXvgZB6iql5DY.zip

I thought about redoing it in pure js, but it seems its not possible to include html/js in md files.

dans98 avatar Jan 25 '23 16:01 dans98

What about a python script? Eventually i can help if You can't do python.

pki791 avatar Jan 26 '23 06:01 pki791

I can for sure do a python script!

dans98 avatar Jan 27 '23 15:01 dans98

Maybe this would be even a way too much around, the PID-TUNE could return all the values calculated in the log.

pki791 avatar Jan 28 '23 13:01 pki791

In my opinion:

  • Klipper main line should return only one set of values for the PID
  • The PR has to choose the best possible, read most commonly applicable, model
    1. Do the tuning
    2. Return values
    3. SAVE_CONFIG
    4. Done
  • Further material / tips / options could be posted on discourse for the interested user to play with

Why?

  • Avoid confusing the users
  • Avoid documentation burden --> Which model to choose when and why
  • Avoid support burden because one thing is 100% certain: Folks will find a way how to mess it up the one or the other way

Sineos avatar Jan 28 '23 14:01 Sineos

I'm working on the documentation now, is there a place you want me to put the spreadsheet i created?

Alas, I'm not sure what I'm looking at with that spreadsheet. I don't recall reading about it on Discourse - got a link?

-Kevin

KevinOConnor avatar Feb 03 '23 23:02 KevinOConnor

I don't recall reading about it on Discourse - got a link?

Sure https://klipper.discourse.group/t/experimental-pid-improvement-changes/3604/63?u=pki

pki791 avatar Feb 05 '23 16:02 pki791

I tried this and had great results!

I have a bed that can't hold under 50C with current PID implementation and auto-tuned parameters, it overshoots and never corrects. This is a problem when printing TPU. The new algorithm using PID_V auto-tuned holds steady down to 35C !

MGunlogson avatar Feb 07 '23 07:02 MGunlogson

@KevinOConnor just an fyi, its going to take me a little while on the documentation. I just got assigned a new project today that's probably going to be 2 or 3 weeks of 10 to 12 hr days, but I'll try and squeeze time in on the weekends.

dans98 avatar Feb 07 '23 19:02 dans98

its going to take me a little while on the documentation

Thanks for the update. I too am struggling with time constraints. Please do not feel the need to rush.

-Kevin

KevinOConnor avatar Feb 09 '23 16:02 KevinOConnor