-
-
Notifications
You must be signed in to change notification settings - Fork 19.5k
Fixes and improvements to PID. #27740
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
Fixes and improvements to PID. #27740
Conversation
Oh, right you are... I just followed my preferred indentation style without much thought. |
Two things I'd appreciate your thoughts on:
|
Okay, first time contributor I think. Fantastic, welcome on board. Just to get it out of the way, a minor comment on coding style: Marlin is strict on the use of white space. No trailing white space (lines 222 and 243 of temperature.h) and one space between Also, whilst improving PID is an excellent thing to do, for a stable hotend MPC is generally better. I mention this just in case you didn't know. Getting to the actual content of this PR, I'll post a detailed follow up comment. Watch this space... |
...starting with the easy change: calculating However I have issues with how |
Before I go on, to respond to your two questions @feldi12, I think a debug message at handover, guarded by I have more to say on the arbitrary limits... |
...second easy(ish) thing to comment on: the uneven heating during handover to PID. The P term really ought to correlate well to If, in reality, PID is not switching well at the boundaries of |
I see what you mean. But in almost all cases the P term is so small, that at handover the heater almost stops, and I term keeps building until it reaches maximum anyway. As you said before, this limit is not computed in particularly good way, so improving this guestimate might solve this. Secondly for the fire scenario - isn't this why we have the safety timers? I actually started digging into that, because the kink at handover kept triggering the safety timer and resetting my printer. P.S: I also run 8-bit. Atmega in anycubic i3 S. I don't think it really adds RAM usage, as PID is called so often, that you would crash sooner or later anyway if this 4 bytes were not available anyway... |
...and, finally, detailed analysis as regards constraining TLDR; The code as originally written in #14373 (i.e. commit 1db7013) is correct. However two bugs were introduced in #14746, one of which is addressed in this PR (well spotted @feldi12). However a later series of changes actually undid #14746 for hotends (but not for beds and chambers). This PR therefore addresses a potential PID bug for beds and chambers. However (I keep using this word!) I think the lower bound used is arbitrary and not necessarily correct. In full... When This all changed in #14746 which introduced what it called But what should the limits be for If we dig into the history, I think there was originally a sensible logic to the calculation of When #14746 added I think the new line should have been So the I component would once again be constrained to prevent I by itself from demanding more than maximum power. Finally, this brings us to what the lower bound for So the right code (with the optimisation that elminates the division) is:
And the In looking into all of this, I have also found another bug: commit e85eca2 removed |
If P has to be really small that implies a lot of latency. I.e. larger P would introduce too much instability. Really, try MPC.
Well spotted. Yes, the protection code should prevent a fire. But that's just a failsafe. If it is ever triggered then by definition the code has a bug or something else has gone wrong.
Oh, good point. But if my last comment is right then this is moot anyway. |
Review comments aside, I am really glad that you're contributing @feldi12. Especially given you have obviously understood the code, which would be beyond most mortals. |
:) Thanks. I run out of brains for now, I'll go through your long comment later... As you guessed this is first time I contribute and as such, i find it is surprisingly time consuming. I'm also gonna 'thank you' right back at ya, as you obviously put a lot of effort in keeping Marlin alive. Cheers. P.S: Oh my... i just saw I accidentally made two separate account for my two main email addresses and used them like one in this discussion... |
Yeah. The basic PR submitting process becomes pretty straightforward after you've done a few. And if the changes are simple then it can sometimes be merged into the bugfix branch quite quickly. Ditto once you get a bit better known. What I have found most time consuming is testing and then responding to bug reports which result from there just being so many different configurations running Marlin. OTOH I think it is so worthwhile. |
Thinking about it, restoring the Further note on submitting PRs: if you're fixing a bug yourself you do not also have to submit a bug report. You can just describe the bug in the PR. That saves some work. |
OK, I went through your comment and I think I have an idea how this would apply... Let's start with theory:
So what I was considering was actually an unsteady state. The PID will have to resolve constantly changing parameters, mostly due to changes in geometry of airflow around nozzle and changes in flow of filament. For example in case of finishing a big part of infill and moving to printing fine detail in the walls, the flow will suddenly reduce by a big amount. In this case a steady state output will cause to overshoot target and integral term will speedup recovery. Now the suggested constrain Now defaults that may lead to bad behaviour links us neatly to the other discussion we had:
By default if someone encounters the repeating failsafe trouble, he will first look at the timer limit: Marlin/Marlin/Configuration_adv.h Lines 322 to 336 in d74ee8c
So we see, that the comment suggest increasing the timer in case of trouble. This is where most people will stop digging, just increasing the limit until it works. And I would argue, that loosening the protection is more dangerous than fixing the source of common trigger. This brings us back to MIN_POW for hot end. This would solve all our troubles, but setting it to sensible value would have to be somehow enforces. For example providing no default value, making it a setting to be mandatory set when creating configuration for a given printer, with a lot of comments on how to approach this and what value is optimal. This failsafe triggering may be a more common problem, then one would think. In my case I'm using a firmware released by @knutwurst , the https://github.com/knutwurst/Marlin-2-0-x-Anycubic-i3-MEGA-S . This is best firmware for my printer I found, and while it still uses PID instead of MPC, I found that after allowing negative I term it keep hotend stable to the extent possible by readout precision. That is plenty good enough in my books. It is however a repo that is particularly well kept for such a niche project and we should be aware, that other might need more persuasion to pay attention and actually take advantage of this kind of improvements. How would you approach the problem of enforcing sensible setting of MIN_POW, and do you see it as crucial as I do? |
I think this is a recipe for oscillations. Check my maths... Power is proportional to the rate of change of temperature. The I component is the integral of temperature. So we have where which is a simple harmonic oscillator.
Enforcing it is not necessary, it's up the the user to use it or not as they prefer. Most users are not looking to solve this problem. For those who are, there are the comments in the config files and #support-chat on the marlin discord. |
I concur that this makes more logical sense, assuming that
You are correct! This was due to the commit being merged very soon after #14746 right after |
MarlinFirmware/Marlin#14746 MarlinFirmware/Marlin#27740 Co-Authored-By: mikeshub <[email protected]>
a73e0c6
to
528e189
Compare
Not all LCD controllers currently use In future it is not guaranteed that vendors will be aware that they should not modify To that end, there is an "editable setting" concept under development as a general part of the Marlin Features class, which would specify valid value ranges, value formatting, etc. These will also deal with values being storable to EEPROM. Once that API has been developed and propagated it should standardize how values are edited on-screen and then we won't have these kinds of special cases. |
@thinkyhead Adding MIN_POWER to the example configs in and of itself is insufficient because all references to it have subsequently been scrubbed from the code. It also needs to be added back to Configuration.h and the default value added back to Conditionals_post.h (removed in #25585) and the instantiation of
|
Should be in latest |
Now that However I agree with @feldi12 that Further, I note that my comments about Finally, I think the changes in https://github.com/tombrazier/Marlin/tree/27740 should be applied to this PR. |
A bit late to the party. Thanks for the shoutout. Yes that MIN_POWER term was there so the handoff to the PID controller would go more smoothly. It has to have some power going through it because there is a powerful fan blowing on the hot end at all times. Definitely proceed with caution on the PID controller. "Perfect is the enemy of good" is very true with the PID controller. These seemingly little changes may improve the performance on a single printer but break things badly for lots of other people. The reason I choose not to let the I term go negative when I did my work way back was because logically it doesn't make sense to me as the lowest a PID loop can go is 0 duty cycle PWM. Imagine if the PID loop has been over temp for long enough to make the I term go negative. Once the temp cools to the set point you want the PID loop to start holding that temperature again. There's going to be a fairly powerful fan cooling the hotend at all times so that filament doesn't melt in the heat break. If the I term is down below zero already then it will just be fighting the P term to get it back up to the correct temperature. If you are in a situation where the PID loop is staying over temp due to wound up I term the better fix is to adjust your P gain up and I term down. Not allowing negative I term should also help with oscillation when the controller ends up with too high of an I gain. The autotuner gets gains close enough to be good enough for anyone to use. That said I haven't printed in a while so it may be improved since I last used it, but I would be surprised if it was perfect. If you want to get better performance out of the PID loop I highly recommend tweaking your gains manually instead of messing with the insides of the PID loop. |
4354891
to
efa1758
Compare
Co-Authored-By: tombrazier <[email protected]>
Thanks for the helpful input @mikeshub I went ahead and brought over Tom's suggestions for review. Take a look and see what you think. |
MarlinFirmware/Marlin#27740 Co-Authored-By: feldi12 <[email protected]>
The remaining changes in this PR seem to be safe, leaving the logic essentially untouched but requiring a little less permanent RAM usage. Let me know if you encounter any anomalies with this modification. I will be putting this through its paces on a BIQU BX while also working on improving SD Card error recovery. I will tag and release 2.1.3-b3 once this testing and tweaking is completed. The final 2.1.3 release will commence next week, so if there are any annoying issues you 'd like to see solved before then, now is the time! |
Description
Following a bug issue #27734 I examined the PID procedure and found, that it does not follow an actual PID algorithm as it constraints I term to only positive values. I also found, that in typical configuration during handover from max heating to PID, there is a pause to heating.
The constraining of the I term to non-negative values, may cause PID to improperly function, particularly when large flow changes are experienced during the print. Normally this term may be negative to offset the differentiating term and proportional term, by limiting it to zero we effectively reduce PID to PD over target temperature.
The uneven heating during handover to PID when heating is due to starting with I term at zero. During handover we come from a temperature outside of PID work range, typically from room temperature. As the I term is limited to max heater power in every iteration of the loop, starting with max I term value allows for smooth handover, and reduces total time to stabilize significantly. It will also reduce occurrence of alarms due to too slow heating, that were sometimes causing print aborts in printers with less powerful hot end heaters. Images comparing heating process are pasted in the issue linked above.
I also moved the max_I_term determining point outside loop - this value changes only when Ki is changed and there is no need to recompute it every iteration.
Requirements
No additional requirements. Couple of extra bytes in programme.
Benefits
Improves time to reach target temperature from room temperature and general temperature stability, particularly when large flow changes are experienced.
Configurations
Change should improve all configurations with PID enabled.
Related Issues
See #27734.